diff options
author | unknown <mskold/marty@linux.site> | 2006-11-30 15:31:20 +0100 |
---|---|---|
committer | unknown <mskold/marty@linux.site> | 2006-11-30 15:31:20 +0100 |
commit | d6e2895da72e79c031c4e0738a565b98c861eaaa (patch) | |
tree | 501aa12882c7189318e5c0edb34c332ecb5aaac0 | |
parent | 9253140b8d7dc129e290f18d21afd8c974a2f50a (diff) | |
parent | a6a0aa42362bf6811150a3d8190f363fc116859a (diff) | |
download | mariadb-git-d6e2895da72e79c031c4e0738a565b98c861eaaa.tar.gz |
Merge mysql.com:/windows/Linux_space/MySQL/mysql-5.1
into mysql.com:/windows/Linux_space/MySQL/mysql-5.1-new-ndb
configure.in:
Auto merged
client/mysqldump.c:
Auto merged
include/my_sys.h:
Auto merged
mysql-test/r/ndb_update.result:
Auto merged
mysql-test/t/ndb_index_ordered.test:
Auto merged
sql/ha_ndbcluster.cc:
Auto merged
sql/ha_ndbcluster_binlog.cc:
Auto merged
sql/sql_class.h:
Auto merged
sql/sql_show.cc:
Auto merged
sql/sql_table.cc:
Auto merged
storage/ndb/include/util/OutputStream.hpp:
Auto merged
storage/ndb/src/common/debugger/EventLogger.cpp:
Auto merged
storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp:
Auto merged
storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp:
Auto merged
storage/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp:
Auto merged
storage/ndb/src/mgmapi/mgmapi.cpp:
Auto merged
storage/ndb/src/mgmclient/CommandInterpreter.cpp:
Auto merged
storage/ndb/src/ndbapi/ClusterMgr.cpp:
Auto merged
storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp:
Auto merged
storage/ndb/src/ndbapi/NdbTransaction.cpp:
Auto merged
storage/ndb/src/ndbapi/Ndbinit.cpp:
Auto merged
storage/ndb/src/ndbapi/ndb_cluster_connection.cpp:
Auto merged
sql/sql_cache.cc:
Merge
596 files changed, 18534 insertions, 7018 deletions
diff --git a/.bzrignore b/.bzrignore index 9c9121c5dc5..bb4cf3a7283 100644 --- a/.bzrignore +++ b/.bzrignore @@ -1252,6 +1252,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/backup.log diff --git a/BUILD/FINISH.sh b/BUILD/FINISH.sh index 51f6e909172..6f0600c9de3 100644 --- a/BUILD/FINISH.sh +++ b/BUILD/FINISH.sh @@ -5,7 +5,7 @@ configure="./configure $base_configs $extra_configs" commands="\ $make -k distclean || true -/bin/rm -rf */.deps/*.P config.cache storage/innobase/config.cache autom4te.cache innobase/autom4te.cache; +/bin/rm -rf */.deps/*.P configure config.cache storage/*/configure storage/*/config.cache autom4te.cache storage/*/autom4te.cache; path=`dirname $0` . \"$path/autorun.sh\"" diff --git a/BUILD/SETUP.sh b/BUILD/SETUP.sh index 87aec7417f1..dfbf1547517 100755 --- a/BUILD/SETUP.sh +++ b/BUILD/SETUP.sh @@ -183,7 +183,7 @@ fi # (http://samba.org/ccache) is installed, use it. # We use 'grep' and hope 'grep' will work as expected # (returns 0 if finds lines) -if ccache -V > /dev/null 2>&1 +if ccache -V > /dev/null 2>&1 && test "$CCACHE_GCOV_VERSION_ENABLED" == "1" then echo "$CC" | grep "ccache" > /dev/null || CC="ccache $CC" echo "$CXX" | grep "ccache" > /dev/null || CXX="ccache $CXX" diff --git a/BUILD/compile-pentium-gcov b/BUILD/compile-pentium-gcov index ca37f78e283..5633efaddf0 100755 --- a/BUILD/compile-pentium-gcov +++ b/BUILD/compile-pentium-gcov @@ -1,12 +1,21 @@ #! /bin/sh +# Need to disable ccache, or we loose the gcov-needed compiler output files. + +CCACHE_GCOV_VERSION_ENABLED=0 +if ccache -V > /dev/null 2>&1 +then + CCACHE_VER=`ccache -V | head -1 | sed s/"ccache version "//` + if test "$CCACHE_VER" == "2.4-gcov" + then + CCACHE_GCOV_VERSION_ENABLED=1 + fi +fi +export CCACHE_GCOV_VERSION_ENABLED + path=`dirname $0` . "$path/SETUP.sh" -# Need to disable ccache, or we loose the gcov-needed compiler output files. -CCACHE_DISABLE=1 -export CCACHE_DISABLE - # GCC4 needs -fprofile-arcs -ftest-coverage on the linker command line (as well # as on the compiler command line), and this requires setting LDFLAGS for BDB. export LDFLAGS="-fprofile-arcs -ftest-coverage" @@ -14,7 +23,7 @@ export LDFLAGS="-fprofile-arcs -ftest-coverage" # The -fprofile-arcs and -ftest-coverage options cause GCC to instrument the # code with profiling information used by gcov. # the -DDISABLE_TAO_ASM is needed to avoid build failures in Yassl. -extra_flags="$pentium_cflags -fprofile-arcs -ftest-coverage -DDISABLE_TAO_ASM -DHAVE_MUTEX_THREAD_ONLY" +extra_flags="$pentium_cflags -fprofile-arcs -ftest-coverage -DDISABLE_TAO_ASM -DHAVE_MUTEX_THREAD_ONLY $debug_extra_flags" extra_configs="$pentium_configs $debug_configs --disable-shared $static_link" extra_configs="$extra_configs $max_configs" diff --git a/BitKeeper/etc/collapsed b/BitKeeper/etc/collapsed index 226f0f1a2e2..f934fa44580 100644 --- a/BitKeeper/etc/collapsed +++ b/BitKeeper/etc/collapsed @@ -17,3 +17,6 @@ 452a92d0-31-8wSzSfZi165fcGcXPA 454a7ef8gdvE_ddMlJyghvOAkKPNOQ 454f8960jsVT_kMKJtZ9OCgXoba0xQ +4561b2ecZbhuAc0TTDdCdultxUYaMw +4561bde4qWhz1I8tkItXKex5uniipA +4562ba016dYH0JzszOqZ8p6psbKfnQ diff --git a/BitKeeper/triggers/post-commit b/BitKeeper/triggers/post-commit index f7b00625264..86f3db012ee 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 09291132e73..4ab92bc557f 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)/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" > $@ # Include the Windows manual.chm in source .tar.gz only if available. # It is not in BitKeeper, but is downloaded from intranet by Bootstrap. diff --git a/Makefile.am b/Makefile.am index a0d19e8271d..c0798fbb5c7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -142,10 +142,15 @@ test-force: 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 # Don't update the files from bitkeeper diff --git a/client/client_priv.h b/client/client_priv.h index bcaa74d3228..78457a4977d 100644 --- a/client/client_priv.h +++ b/client/client_priv.h @@ -58,5 +58,6 @@ enum options_client OPT_IGNORE_TABLE,OPT_INSERT_IGNORE,OPT_SHOW_WARNINGS,OPT_DROP_DATABASE, OPT_TZ_UTC, OPT_AUTO_CLOSE, OPT_CREATE_SLAP_SCHEMA, OPT_MYSQL_REPLACE_INTO, OPT_BASE64_OUTPUT, OPT_SERVER_ID, - OPT_FIX_TABLE_NAMES, OPT_FIX_DB_NAMES, OPT_SSL_VERIFY_SERVER_CERT + OPT_FIX_TABLE_NAMES, OPT_FIX_DB_NAMES, OPT_SSL_VERIFY_SERVER_CERT, + OPT_DEBUG_INFO, OPT_COLUMN_TYPES }; diff --git a/client/mysql.cc b/client/mysql.cc index 486e5bc113c..f3812e12065 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -44,7 +44,7 @@ #include <locale.h> #endif -const char *VER= "14.12"; +const char *VER= "14.13"; /* Don't try to make a nice table if the data is too big */ #define MAX_COLUMN_LENGTH 1024 @@ -140,6 +140,7 @@ static my_bool info_flag=0,ignore_errors=0,wait_flag=0,quick=0, default_charset_used= 0, opt_secure_auth= 0, default_pager_set= 0, opt_sigint_ignore= 0, show_warnings= 0, executing_query= 0, interrupted_query= 0; +static my_bool column_types_flag; static ulong opt_max_allowed_packet, opt_net_buffer_length; static uint verbose=0,opt_silent=0,opt_mysql_port=0, opt_local_infile=0; static my_string opt_mysql_unix_port=0; @@ -545,7 +546,7 @@ sig_handler mysql_end(int sig) my_free(current_prompt,MYF(MY_ALLOW_ZERO_PTR)); mysql_server_end(); free_defaults(defaults_argv); - my_end(info_flag ? MY_CHECK_ERROR | MY_GIVE_INFO : 0); + my_end(info_flag ? MY_CHECK_ERROR : 0); exit(status.exit_status); } @@ -600,12 +601,13 @@ static struct my_option my_long_options[] = {"character-sets-dir", OPT_CHARSETS_DIR, "Directory where character sets are.", (gptr*) &charsets_dir, (gptr*) &charsets_dir, 0, GET_STR, REQUIRED_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}, + {"column-type-info", OPT_COLUMN_TYPES, "Display column type information.", + (gptr*) &column_types_flag, (gptr*) &column_types_flag, + 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"compress", 'C', "Use compression in server/client protocol.", (gptr*) &opt_compress, (gptr*) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + #ifdef DBUG_OFF {"debug", '#', "This is a non-debug version. Catch this and exit", 0,0, 0, GET_DISABLED, OPT_ARG, 0, 0, 0, 0, 0, 0}, @@ -613,8 +615,13 @@ 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", 'T', "Print some debug info at exit.", (gptr*) &info_flag, + (gptr*) &info_flag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"database", 'D', "Database to use.", (gptr*) ¤t_db, (gptr*) ¤t_db, 0, GET_STR_ALLOC, REQUIRED_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}, {"delimiter", OPT_DELIMITER, "Delimiter to be used.", (gptr*) &delimiter_str, (gptr*) &delimiter_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"execute", 'e', "Execute command and quit. (Disables --force and history file)", 0, @@ -711,8 +718,6 @@ static struct my_option my_long_options[] = #include "sslopt-longopts.h" {"table", 't', "Output in table format.", (gptr*) &output_tables, (gptr*) &output_tables, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"debug-info", 'T', "Print some debug info at exit.", (gptr*) &info_flag, - (gptr*) &info_flag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"tee", OPT_TEE, "Append everything into outfile. See interactive help (\\h) also. Does not work in batch mode. Disable with --disable-tee. This option is disabled by default.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, @@ -2085,7 +2090,7 @@ com_go(String *buffer,char *line __attribute__((unused))) time_buff[0]=0; if (result) { - if (!mysql_num_rows(result) && ! quick && !info_flag) + if (!mysql_num_rows(result) && ! quick && !column_types_flag) { strmov(buff, "Empty set"); } @@ -2324,7 +2329,7 @@ print_table_data(MYSQL_RES *result) bool *num_flag; num_flag=(bool*) my_alloca(sizeof(bool)*mysql_num_fields(result)); - if (info_flag) + if (column_types_flag) { print_field_types(result); if (!mysql_num_rows(result)) diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c index 6ec361392c8..46862dd1da6 100644 --- a/client/mysql_upgrade.c +++ b/client/mysql_upgrade.c @@ -16,21 +16,42 @@ #include "client_priv.h" #include <my_dir.h> +#include <my_list.h> +#include <sslopt-vars.h> + +#define UPGRADE_DEFAULTS_NAME "mysql_upgrade_defaults" +#define MYSQL_UPGRADE_INFO_NAME "mysql_upgrade_info" +#define MYSQL_FIX_PRIV_TABLES_NAME "mysql_fix_privilege_tables.sql" + +#define MY_PARENT (1 << 0) +#define MY_ISDIR (1 << 1) +#define MY_SEARCH_SELF (1 << 2) #ifdef __WIN__ const char *mysqlcheck_name= "mysqlcheck.exe"; const char *mysql_name= "mysql.exe"; +const char *mysqld_name= "mysqld.exe"; #else const char *mysqlcheck_name= "mysqlcheck"; const char *mysql_name= "mysql"; +const char *mysqld_name= "mysqld"; #endif /*__WIN__*/ -static my_bool opt_force= 0, opt_verbose= 0, tty_password= 0; +extern TYPELIB sql_protocol_typelib; + +static my_bool opt_force= 0, opt_verbose= 0, opt_compress= 0; static char *user= (char*) "root", *basedir= 0, *datadir= 0, *opt_password= 0; -static my_bool upgrade_defaults_created= 0; -static my_string opt_mysql_port, opt_mysql_unix_port= 0; -static char *default_dbug_option= (char*) "d:t:O,/tmp/comp_err.trace"; -static my_bool info_flag= 0; +static char *current_host= 0; +static char *opt_default_charset= 0, *opt_charsets_dir= 0; +#ifdef HAVE_SMEM +static char *shared_memory_base_name= 0; +#endif +static char *opt_protocol= 0; +static my_string opt_mysql_port= 0, opt_mysql_unix_port= 0; +#ifndef DBUG_OFF +static char *default_dbug_option= (char*) "d:t:O,/tmp/mysql_upgrade.trace"; +#endif +static my_bool info_flag= 0, tty_password= 0; static struct my_option my_long_options[]= { @@ -50,27 +71,51 @@ static struct my_option my_long_options[]= #endif {"debug-info", 'T', "Print some debug info at exit.", (gptr *) & info_flag, (gptr *) & info_flag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"force", 'f', "Continue even if we get an sql-error.", + {"default-character-set", OPT_DEFAULT_CHARSET, + "Set the default character set.", (gptr*) &opt_default_charset, + (gptr*) &opt_default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"force", 'f', "Force execution of mysqlcheck even if mysql_upgrade " + "has already been executed for the current version of MySQL.", (gptr*) &opt_force, (gptr*) &opt_force, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"character-sets-dir", OPT_CHARSETS_DIR, + "Directory where character sets are.", (gptr*) &opt_charsets_dir, + (gptr*) &opt_charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"compress", OPT_COMPRESS, "Use compression in server/client protocol.", + (gptr*) &opt_compress, (gptr*) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0, + 0, 0, 0}, + {"host",'h', "Connect to host.", (gptr*) ¤t_host, + (gptr*) ¤t_host, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"password", 'p', - "Password to use when connecting to server. If password is not given it's solicited on the tty.", - 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, + "Password to use when connecting to server. If password is not given" + " it's solicited on the tty.", 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, +#ifdef __WIN__ + {"pipe", 'W', "Use named pipes to connect to server.", 0, 0, 0, + GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, +#endif {"port", 'P', "Port number to use for connection.", (gptr*) &opt_mysql_port, - (gptr*) &opt_mysql_port, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, - 0}, + (gptr*) &opt_mysql_port, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, +#ifdef HAVE_SMEM + {"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME, + "Base name of shared memory.", (gptr*) &shared_memory_base_name, + (gptr*) &shared_memory_base_name, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, +#endif {"socket", 'S', "Socket file to use for connection.", - (gptr*) &opt_mysql_unix_port, (gptr*) &opt_mysql_unix_port, 0, GET_STR, - REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + (gptr*) &opt_mysql_unix_port, (gptr*) &opt_mysql_unix_port, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"user", 'u', "User for login if not current user.", (gptr*) &user, (gptr*) &user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"verbose", 'v', "Display more output about the process", (gptr*) &opt_verbose, - (gptr *) &opt_verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, +#include <sslopt-longopts.h> + {"verbose", 'v', "Display more output about the process", + (gptr*) &opt_verbose, (gptr*) &opt_verbose, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; + static const char *load_default_groups[]= { "mysql_upgrade", 0 @@ -78,6 +123,81 @@ static const char *load_default_groups[]= #include <help_end.h> +static LIST *extra_defaults= NULL; + +typedef struct _extra_default +{ + int id; + const char *name; + int n_len; + const char *value; + int v_len; +} extra_default_t; + +static inline +void set_extra_default(int id, const struct my_option *opt) +{ + switch (id) { + case 'b': case 'd': /* these are ours */ + case 'f': /* --force is ours */ + case 'u': /* --user passed on cmdline */ + case 'T': /* --debug-info is not accepted by mysqlcheck */ + /* so, do nothing */ + break; + default: + { + LIST *l; + extra_default_t *d; + + /* + Remove any earlier duplicates: they can + refer to invalid memory addresses (stale pointers) + */ + l= extra_defaults; + while (l) + { + LIST *n= l->next; + + d= l->data; + if (d->id == id) + { + extra_defaults= list_delete(extra_defaults, l); + my_free((gptr)l, MYF(0)); + my_free((gptr)d, MYF(0)); + } + l= n; + } + + d= (extra_default_t *)my_malloc(sizeof(extra_default_t), + MYF(MY_FAE|MY_ZEROFILL)); + d->id= id; + d->name= opt->name; + d->n_len= strlen(opt->name); + if (opt->arg_type != NO_ARG) + switch (opt->var_type & GET_TYPE_MASK) { + case GET_BOOL: + if (*((int *)opt->value)) + { + d->value= "true"; + d->v_len= 4; + } + break; + case GET_STR: + case GET_STR_ALLOC: + d->value= *opt->value; + d->v_len= strlen(d->value); + break; + default: + my_printf_error(0, "Error: internal error at %s:%d", MYF(0), + __FILE__, __LINE__); + exit(1); + } + list_push(extra_defaults, d); + } + } +} + + static my_bool get_one_option(int optid, const struct my_option *opt __attribute__ ((unused)), char *argument) @@ -85,16 +205,13 @@ get_one_option(int optid, const struct my_option *opt __attribute__ ((unused)), switch (optid) { case '?': puts - ("MySQL utility script to upgrade database to the current server version"); + ("MySQL utility to upgrade database to the current server version"); puts(""); my_print_help(my_long_options); exit(0); case '#': DBUG_PUSH(argument ? argument : default_dbug_option); break; - case 'f': - opt_force= TRUE; - break; case 'p': tty_password= 1; if (argument) @@ -109,315 +226,412 @@ get_one_option(int optid, const struct my_option *opt __attribute__ ((unused)), tty_password= 0; } break; +#ifdef __WIN__ + case 'W': + my_free(opt_protocol, MYF(MY_ALLOW_ZERO_PTR)); + opt_protocol= my_strdup("pipe", MYF(MY_FAE)); + break; +#endif + case OPT_MYSQL_PROTOCOL: + if (find_type(argument, &sql_protocol_typelib, 0) > 0) + { + my_free(opt_protocol, MYF(MY_ALLOW_ZERO_PTR)); + opt_protocol= my_strdup(argument, MYF(MY_FAE)); + } + else + { + fprintf(stderr, "Unknown option to protocol: %s\n", argument); + exit(1); + } + break; +#include <sslopt-case.h> default:; - }; + } + set_extra_default(opt->id, opt); return 0; } -/* buffer should be not smaller than FN_REFLEN */ -static my_bool test_file_exists_res(const char *dir, const char *fname, - char *buffer, char **buf_end) -{ - MY_STAT stat_info; - - *buf_end= strxnmov(buffer, FN_REFLEN-1, dir, "/", fname, NullS); - unpack_filename(buffer, buffer); - return my_stat(buffer, &stat_info, MYF(0)) != 0; -} - - -static my_bool test_file_exists(const char *dir, const char *fname) -{ - char path[FN_REFLEN]; - char *path_end; - return test_file_exists_res(dir, fname, path, &path_end); -} - - static int create_check_file(const char *path) { - File check_file= my_open(path, O_CREAT | O_WRONLY, MYF(MY_FAE | MY_WME)); - int error; - - if (check_file < 0) - return 1; - - error= my_write(check_file, - MYSQL_SERVER_VERSION, strlen(MYSQL_SERVER_VERSION), + int ret; + File fd; + + fd= my_open(path, O_CREAT | O_WRONLY, MYF(MY_FAE | MY_WME)); + if (fd < 0) { + ret= 1; + goto error; + } + ret= my_write(fd, MYSQL_SERVER_VERSION, + sizeof(MYSQL_SERVER_VERSION) - 1, MYF(MY_WME | MY_FNABP)); - error= my_close(check_file, MYF(MY_FAE | MY_WME)) || error; - return error; + ret|= my_close(fd, MYF(MY_FAE | MY_WME)); +error: + return ret; } -static int create_defaults_file(const char *path, const char *our_defaults_path) +static int create_defaults_file(const char *path, const char *forced_path) { - uint b_read; - File our_defaults_file, defaults_file; - char buffer[512]; - char *buffer_end; - int failed_to_open_count= 0; - int error; - - /* check if the defaults file is needed at all */ - if (!opt_password) - return 0; - -retry_open: + int ret; + uint cnt; + File forced_file, defaults_file; + + DYNAMIC_STRING buf; + extra_default_t *d; + + my_delete(path, MYF(0)); + defaults_file= my_open(path, O_BINARY | O_CREAT | O_WRONLY | O_EXCL, MYF(MY_FAE | MY_WME)); - if (defaults_file < 0) { - if (failed_to_open_count == 0) - { - remove(path); - failed_to_open_count+= 1; - goto retry_open; - } - else - return 1; + ret= 1; + goto out; + } + + if (init_dynamic_string(&buf, NULL, my_getpagesize(), FN_REFLEN)) + { + ret= 1; + goto error; } - upgrade_defaults_created= 1; - if (our_defaults_path) + if (forced_path) { - our_defaults_file= my_open(our_defaults_path, O_RDONLY, - MYF(MY_FAE | MY_WME)); - if (our_defaults_file < 0) - return 1; + forced_file= my_open(forced_path, O_RDONLY, MYF(MY_FAE | MY_WME)); + if (forced_file < 0) + { + ret= 1; + goto error; + } do { - if (((b_read= my_read(our_defaults_file, buffer, - sizeof(buffer), MYF(MY_WME))) == MY_FILE_ERROR) || - my_write(defaults_file, buffer, b_read, MYF(MY_FNABP | MY_WME))) + cnt= my_read(forced_file, buf.str, buf.max_length, MYF(MY_WME)); + if ((cnt == MY_FILE_ERROR) + || my_write(defaults_file, buf.str, cnt, MYF(MY_FNABP | MY_WME))) { - error= 1; - goto close_return; + ret= 1; + my_close(forced_file, MYF(0)); + goto error; } - } while (b_read == sizeof(buffer)); + } while (cnt == buf.max_length); + my_close(forced_file, MYF(0)); } - buffer_end= strnmov(buffer, "\n[client]", sizeof(buffer)); - if (opt_password) - buffer_end= strxnmov(buffer_end, sizeof(buffer), - "\npassword=", opt_password, NullS); - error= my_write(defaults_file, buffer, (int) (buffer_end - buffer), - MYF(MY_WME | MY_FNABP)); -close_return: - return my_close(defaults_file, MYF(MY_WME)) || error; + + dynstr_set(&buf, "\n[client]"); + while (extra_defaults) + { + int len; + + d= extra_defaults->data; + len= d->n_len + d->v_len + 1; + if (buf.length + len >= buf.max_length) /* to avoid realloc() */ + { + if (my_write(defaults_file, buf.str, buf.length, MYF(MY_FNABP | MY_WME))) + { + ret= 1; + goto error; + } + dynstr_set(&buf, NULL); + } + if (dynstr_append_mem(&buf, "\n", 1) + || dynstr_append_mem(&buf, d->name, d->n_len) + || (d->v_len && (dynstr_append_mem(&buf, "=", 1) + || dynstr_append_mem(&buf, d->value, d->v_len)))) + { + ret= 1; + goto error; + } + my_delete((gptr)d, MYF(0)); + list_pop(extra_defaults); /* pop off the head */ + } + if (my_write(defaults_file, buf.str, buf.length, MYF(MY_FNABP | MY_WME))) + { + ret= 1; + goto error; + } + /* everything's all right */ + ret= 0; +error: + dynstr_free(&buf); + + if (defaults_file >= 0) + ret|= my_close(defaults_file, MYF(MY_WME)); + + if (ret) + my_delete(path, MYF(0)); + +out: + return ret; +} + + +/* Compare filenames */ +static int comp_names(struct fileinfo *a, struct fileinfo *b) +{ + return (strcmp(a->name,b->name)); +} + + +static int find_file(const char *name, const char *root, + uint flags, char *result, size_t len, ...) +{ + int ret= 1; + va_list va; + 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; + + va_start(va, len); + subdir= (!(flags & MY_SEARCH_SELF)) ? va_arg(va, char *) : ""; + while (subdir) + { + MY_DIR *dir; + FILEINFO *match; + char *cp1; + + cp1= strnmov(cp, subdir, len - (cp - result) - 1); + + dir= my_dir(result, (flags & MY_ISDIR) ? MY_WANT_STAT : MYF(0)); + if (dir) + { + match= bsearch(&key, dir->dir_entry, dir->number_off_files, + sizeof(FILEINFO), (qsort_cmp)comp_names); + if (match) + { + ret= (flags & MY_ISDIR) ? !MY_S_ISDIR(match->mystat->st_mode) : 0; + if (!ret) + { + if (cp1[-1] != FN_LIBCHAR) + *cp1++= FN_LIBCHAR; + + if (!(flags & MY_PARENT)) + strnmov(cp1, name, len - (cp1 - result)); + else + *cp1= '\0'; + + my_dirend(dir); + break; + } + } + my_dirend(dir); + } + subdir= va_arg(va, char *); + } + va_end(va); + return ret; } int main(int argc, char **argv) { - char bindir[FN_REFLEN]; - char *bindir_end, *buf_end; - char datadir_buf[FN_REFLEN]; - char mysqlcheck_line[FN_REFLEN], *mysqlcheck_end; - char check_file_name[FN_REFLEN]; - int check_file; - char fix_priv_tables_cmd[FN_REFLEN], *fix_cmd_end; - char script_line[FN_REFLEN]; - int error; + int ret; + char *forced_defaults_file; char *forced_extra_defaults; char *defaults_group_suffix; - char upgrade_defaults_path[FN_REFLEN], *defaults_to_use= 0; - char port_socket[100], *port_socket_end; + const char *script_line; + char *upgrade_defaults_path; + char *defaults_to_use= NULL; + int upgrade_defaults_created= 0; + + char path[FN_REFLEN]; + DYNAMIC_STRING cmdline; MY_INIT(argv[0]); #ifdef __NETWARE__ setscreenmode(SCR_AUTOCLOSE_ON_EXIT); #endif + /* Check if we are forced to use specific defaults */ + get_defaults_options(argc, argv, + &forced_defaults_file, &forced_extra_defaults, + &defaults_group_suffix); + load_defaults("my", load_default_groups, &argc, &argv); - if ((error= handle_options(&argc, &argv, my_long_options, get_one_option))) - exit(error); - + if (handle_options(&argc, &argv, my_long_options, get_one_option)) + { + ret= 1; + goto error; + } if (tty_password) opt_password= get_tty_password(NullS); - /* Check if we want to force the use a specific default file */ - get_defaults_options(argc, argv, - &forced_defaults_file, &forced_extra_defaults, - &defaults_group_suffix); - - port_socket_end= port_socket; - if (opt_mysql_port) - port_socket_end= strxnmov(port_socket, sizeof(port_socket) - 1, " --port=", - opt_mysql_port, NullS); - if (opt_mysql_unix_port) - port_socket_end= strxnmov(port_socket_end, - sizeof(port_socket) - - (int)(port_socket_end - port_socket) - 1, - " --socket=", opt_mysql_unix_port, NullS); - *port_socket_end= 0; - - if (basedir) + if (init_dynamic_string(&cmdline, NULL, 2 * FN_REFLEN + 128, FN_REFLEN)) { - bindir_end= strmake(bindir, basedir, sizeof(bindir)-1); + ret= 1; + goto error; } - else + if (!basedir) { - if (test_file_exists("./share/mysql/english", "errmsg.sys") - && (test_file_exists("./bin", "mysqld") || - test_file_exists("./libexec", "mysqld"))) - { - my_getwd(bindir, sizeof(bindir), MYF(0)); - bindir_end= bindir + strlen(bindir); - } - else + my_getwd(path, sizeof(path), MYF(0)); + basedir= my_strdup(path, MYF(0)); + if (find_file("errmsg.sys", basedir, MYF(0), path, sizeof(path), + "share/mysql/english", NullS) + || find_file(mysqld_name, basedir, MYF(0), path, sizeof(path), + "bin", "libexec", NullS)) { - bindir_end= strmake(bindir, DEFAULT_MYSQL_HOME, sizeof(bindir)-1); + my_free((gptr)basedir, MYF(0)); + basedir= (char *)DEFAULT_MYSQL_HOME; } } if (!datadir) { - datadir= datadir_buf; - if (test_file_exists(bindir, "data/mysql")) - { - *strxnmov(datadir_buf, sizeof(datadir_buf)-1, bindir, "/data", NullS)= 0; - } - else if (test_file_exists(bindir, "var/mysql")) - { - *strxnmov(datadir_buf, sizeof(datadir_buf)-1, bindir, "/var", NullS)= 0; - } + if (!find_file("mysql", basedir, MYF(MY_ISDIR|MY_PARENT), + path, sizeof(path), + "data", "var", NullS)) + datadir= my_strdup(path, MYF(0)); else - datadir= (char*) DATADIR; + datadir= (char *)DATADIR; } - - strmake(bindir_end, "/bin", sizeof(bindir) - (int) (bindir_end - bindir)-1); - - if (!test_file_exists_res - (bindir, mysqlcheck_name, mysqlcheck_line, &mysqlcheck_end)) + if (find_file("user.frm", datadir, MYF(0), path, sizeof(path), + "mysql", NullS)) { - printf("Can't find program '%s'\n", mysqlcheck_line); - puts("Please restart with --basedir=mysql-install-directory"); - exit(1); + ret= 1; + puts("Can't find data directory. Please restart with" + " --datadir=path-to-writable-data-dir"); + goto error; } - if (!test_file_exists(datadir, "mysql/user.frm")) + /* + Create the modified defaults file to be used by mysqlcheck + and mysql tools + */ + fn_format(path, UPGRADE_DEFAULTS_NAME, datadir, "", MYF(0)); + upgrade_defaults_path= my_strdup(path, MYF(0)); + + if (extra_defaults) { - puts - ("Can't find data directory. Please restart with --datadir=path-to-data-dir"); - exit(1); - } - - /* create the modified defaults file to be used by mysqlcheck */ - /* and mysql tools */ - *strxnmov(upgrade_defaults_path, sizeof(upgrade_defaults_path)-1, - datadir, "/upgrade_defaults", NullS)= 0; - unpack_filename(upgrade_defaults_path, upgrade_defaults_path); - if ((error= - create_defaults_file(upgrade_defaults_path, forced_extra_defaults))) - goto err_exit; - - defaults_to_use= upgrade_defaults_created ? - upgrade_defaults_path : forced_extra_defaults; + ret= create_defaults_file(upgrade_defaults_path, forced_extra_defaults); + if (ret) + goto error; + + defaults_to_use= upgrade_defaults_path; + upgrade_defaults_created= 1; + } + else + defaults_to_use= forced_extra_defaults; - if (test_file_exists_res(datadir, "mysql_upgrade_info", check_file_name, - &buf_end) && !opt_force) + if (!find_file(MYSQL_UPGRADE_INFO_NAME, datadir, MY_SEARCH_SELF, + path, sizeof(path), NULL, NullS) + && !opt_force) { - char chf_buffer[50]; - int b_read; - check_file= my_open(check_file_name, O_RDONLY, MYF(0)); - b_read= my_read(check_file, chf_buffer, sizeof(chf_buffer)-1, MYF(0)); - chf_buffer[b_read]= 0; - my_close(check_file, MYF(0)); - if (!strcmp(chf_buffer, MYSQL_SERVER_VERSION)) + char buf[sizeof(MYSQL_SERVER_VERSION)]; + int fd, cnt; + + fd= my_open(path, O_RDONLY, MYF(0)); + cnt= my_read(fd, buf, sizeof(buf) - 1, MYF(0)); + my_close(fd, MYF(0)); + buf[cnt]= 0; + if (!strcmp(buf, MYSQL_SERVER_VERSION)) { if (opt_verbose) - puts("mysql_upgrade already done for this version"); + puts("mysql_upgrade has already been done for this version"); goto fix_priv_tables; } } + + if (find_file(mysqlcheck_name, basedir, MYF(0), path, sizeof(path), + "bin", NullS)) + { + ret= 1; + printf("Can't find program '%s'\n", mysqlcheck_name); + puts("Please restart with --basedir=mysql-install-directory"); + goto error; + } + else + dynstr_set(&cmdline, path); if (defaults_to_use) { - mysqlcheck_end= strxnmov(mysqlcheck_end, - sizeof(mysqlcheck_line) - (int) (mysqlcheck_end - - mysqlcheck_line), - " --defaults-extra-file=", defaults_to_use,NullS); + dynstr_append(&cmdline, " --defaults-extra-file="); + dynstr_append(&cmdline, defaults_to_use); } - - mysqlcheck_end= strxnmov(mysqlcheck_end, - sizeof(mysqlcheck_line) - - (int) (mysqlcheck_end - mysqlcheck_line - 1), - " --check-upgrade --all-databases --auto-repair --user=", - user, port_socket, NullS); - *mysqlcheck_end= 0; + + dynstr_append(&cmdline, " --check-upgrade --all-databases" + " --auto-repair --user="); + dynstr_append(&cmdline, user); if (opt_verbose) - printf("Running %s\n", mysqlcheck_line); - if ((error= system(mysqlcheck_line))) + printf("Running %s\n", cmdline.str); + + ret= system(cmdline.str); + if (ret) { - printf("Error executing '%s'\n", mysqlcheck_line); - goto err_exit; + printf("Error executing '%s'\n", cmdline.str); + goto error; } - if ((error= create_check_file(check_file_name))) - goto err_exit; + fn_format(path, MYSQL_UPGRADE_INFO_NAME, datadir, "", MYF(0)); + ret= create_check_file(path); + if (ret) + goto error; fix_priv_tables: - if (!test_file_exists_res(bindir, mysql_name, - fix_priv_tables_cmd, &fix_cmd_end)) + if (find_file(mysql_name, basedir, MYF(0), path, sizeof(path), + "bin", NullS)) { - puts("Could not find MySQL command-line client (mysql)."); - puts - ("Please use --basedir to specify the directory where MySQL is installed."); - error= 1; - goto err_exit; + ret= 1; + puts("Could not find MySQL command-line client (mysql).\n" + "Please use --basedir to specify the directory" + " where MySQL is installed."); + goto error; } - - if (!test_file_exists_res(basedir, - "support_files/mysql_fix_privilege_tables.sql", - script_line, &buf_end) - && !test_file_exists_res(basedir, "share/mysql_fix_privilege_tables.sql", - script_line, &buf_end) - && !test_file_exists_res(basedir, - "share/mysql/mysql_fix_privilege_tables.sql", - script_line, &buf_end) - && !test_file_exists_res(basedir, - "scripts/mysql_fix_privilege_tables.sql", - script_line, &buf_end) - && !test_file_exists_res("/usr/local/mysql/share/mysql", - "mysql_fix_privilege_tables.sql", script_line, - &buf_end)) + else + dynstr_set(&cmdline, path); + + if (find_file(MYSQL_FIX_PRIV_TABLES_NAME, basedir, MYF(0), + path, sizeof(path), + "support_files", "share/mysql", "scripts", + NullS) + && find_file(MYSQL_FIX_PRIV_TABLES_NAME, "/usr/local/mysql", MYF(0), + path, sizeof(path), + "share/mysql", NullS)) { - puts("Could not find file mysql_fix_privilege_tables.sql"); - puts - ("Please use --basedir to specify the directory where MySQL is installed"); - error= 1; - goto err_exit; + ret= 1; + puts("Could not find file " MYSQL_FIX_PRIV_TABLES_NAME "\n" + "Please use --basedir to specify the directory" + " where MySQL is installed"); + goto error; } + else + script_line= my_strdup(path, MYF(0)); if (defaults_to_use) { - fix_cmd_end= strxnmov(fix_cmd_end, - sizeof(fix_priv_tables_cmd) - - (int) (fix_cmd_end - fix_priv_tables_cmd - 1), - " --defaults-extra-file=", defaults_to_use, NullS); + dynstr_append(&cmdline, " --defaults-extra-file="); + dynstr_append(&cmdline, defaults_to_use); } - fix_cmd_end= strxnmov(fix_cmd_end, - sizeof(fix_priv_tables_cmd) - (int) (fix_cmd_end - - fix_priv_tables_cmd), - " --user=", user, port_socket, " mysql < ", script_line, NullS); - *fix_cmd_end= 0; + dynstr_append(&cmdline, " --force --no-auto-rehash --batch --user="); + dynstr_append(&cmdline, user); + dynstr_append(&cmdline, " mysql < "); + dynstr_append(&cmdline, script_line); - if ((error= system(fix_priv_tables_cmd))) - { - /* Problem is that the 'Duplicate column' error */ - /* which is not a bug for the script makes 'mysql' return */ - /* an error */ - /* printf("Error executing '%s'\n", fix_priv_tables_cmd); */ - } + if (opt_verbose) + printf("Running %s\n", cmdline.str); + + ret= system(cmdline.str); + if (ret) + printf("Error executing '%s'\n", cmdline.str); + +error: + dynstr_free(&cmdline); -err_exit: if (upgrade_defaults_created) my_delete(upgrade_defaults_path, MYF(0)); - my_end(info_flag ? MY_CHECK_ERROR | MY_GIVE_INFO : 0); - return error; -} /* main */ + + my_end(info_flag ? MY_CHECK_ERROR : 0); + return ret; +} + diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc index 57ab4e071fb..bde0a5fa143 100644 --- a/client/mysqladmin.cc +++ b/client/mysqladmin.cc @@ -28,7 +28,7 @@ #include "../ndb/src/mgmclient/ndb_mgmclient.h" #endif -#define ADMIN_VERSION "8.41" +#define ADMIN_VERSION "8.42" #define MAX_MYSQL_VAR 256 #define SHUTDOWN_DEF_TIMEOUT 3600 /* Wait for shutdown */ #define MAX_TRUNC_LENGTH 3 @@ -41,7 +41,7 @@ ulonglong last_values[MAX_MYSQL_VAR]; static int interval=0; static my_bool option_force=0,interrupted=0,new_line=0, opt_compress=0, opt_relative=0, opt_verbose=0, opt_vertical=0, - tty_password=0; + tty_password= 0, info_flag= 0; static uint tcp_port = 0, option_wait = 0, option_silent=0, nr_iterations, opt_count_iterations= 0; static ulong opt_connect_timeout, opt_shutdown_timeout; @@ -136,6 +136,8 @@ static struct my_option my_long_options[] = REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.", 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, + {"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}, {"force", 'f', "Don't ask for confirmation on drop database; with multiple commands, continue even if an error occurs.", (gptr*) &option_force, (gptr*) &option_force, 0, GET_BOOL, NO_ARG, 0, 0, @@ -412,7 +414,7 @@ int main(int argc,char *argv[]) my_free(shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR)); #endif free_defaults(save_argv); - my_end(0); + my_end(info_flag ? MY_CHECK_ERROR : 0); exit(error ? 1 : 0); return 0; } diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index ab94c415db7..d3fd7386fb8 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -66,7 +66,7 @@ static bool one_database=0, to_last_remote_log= 0, disable_log_bin= 0; static bool opt_hexdump= 0; static bool opt_base64_output= 0; static const char* database= 0; -static my_bool force_opt= 0, short_form= 0, remote_opt= 0; +static my_bool force_opt= 0, short_form= 0, remote_opt= 0, info_flag; static ulonglong offset = 0; static const char* host = 0; static int port= 0; @@ -716,6 +716,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}, {"disable-log-bin", 'D', "Disable binary log. This is useful, if you " "enabled --to-last-log and are sending the output to the same MySQL server. " "This way you could avoid an endless loop. You would also like to use it " @@ -844,7 +846,7 @@ static void die(const char* fmt, ...) va_end(args); cleanup(); /* We cannot free DBUG, it is used in global destructors after exit(). */ - my_end(MY_DONT_FREE_DBUG); + my_end((info_flag ? MY_CHECK_ERROR : 0) | MY_DONT_FREE_DBUG); exit(1); } @@ -852,7 +854,7 @@ static void die(const char* fmt, ...) static void print_version() { - printf("%s Ver 3.1 for %s at %s\n", my_progname, SYSTEM_TYPE, MACHINE_TYPE); + printf("%s Ver 3.2 for %s at %s\n", my_progname, SYSTEM_TYPE, MACHINE_TYPE); NETWARE_SET_SCREEN_MODE(1); } @@ -1138,7 +1140,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, @@ -1360,6 +1362,21 @@ static int dump_local_log_entries(const char* logname) } else // reading from stdin; { + /* + 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; @@ -1530,7 +1547,7 @@ int main(int argc, char** argv) free_defaults(defaults_argv); my_free_open_file_info(); /* We cannot free DBUG, it is used in global destructors after exit(). */ - my_end(MY_DONT_FREE_DBUG); + my_end((info_flag ? MY_CHECK_ERROR : 0) | MY_DONT_FREE_DBUG); exit(exit_value); DBUG_RETURN(exit_value); // Keep compilers happy } diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c index fdfd9fc36fb..09ddaadf233 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -16,7 +16,7 @@ /* By Jani Tolonen, 2001-04-20, MySQL Development Team */ -#define CHECK_VERSION "2.4.4" +#define CHECK_VERSION "2.4.5" #include "client_priv.h" #include <m_ctype.h> @@ -34,7 +34,7 @@ static my_bool opt_alldbs = 0, opt_check_only_changed = 0, opt_extended = 0, opt_compress = 0, opt_databases = 0, opt_fast = 0, opt_medium_check = 0, opt_quick = 0, opt_all_in_1 = 0, opt_silent = 0, opt_auto_repair = 0, ignore_errors = 0, - tty_password = 0, opt_frm = 0, + tty_password= 0, opt_frm= 0, info_flag= 0, opt_fix_table_names= 0, opt_fix_db_names= 0, opt_upgrade= 0; static uint verbose = 0, opt_mysql_port=0; static my_string opt_mysql_unix_port = 0; @@ -96,6 +96,8 @@ static struct my_option my_long_options[] = {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.", 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, #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}, @@ -761,7 +763,7 @@ int main(int argc, char **argv) */ if (get_options(&argc, &argv)) { - my_end(0); + my_end(info_flag ? MY_CHECK_ERROR : 0); exit(EX_USAGE); } if (dbConnect(current_host, current_user, opt_password)) @@ -803,6 +805,6 @@ int main(int argc, char **argv) #ifdef HAVE_SMEM my_free(shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR)); #endif - my_end(0); + my_end(info_flag ? MY_CHECK_ERROR : 0); return(first_error!=0); } /* main */ diff --git a/client/mysqldump.c b/client/mysqldump.c index 05c28e46eb5..0421f0b70aa 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -37,7 +37,7 @@ ** 10 Jun 2003: SET NAMES and --no-set-names by Alexander Barkov */ -#define DUMP_VERSION "10.10" +#define DUMP_VERSION "10.12" #include <my_global.h> #include <my_sys.h> @@ -103,7 +103,7 @@ static my_bool verbose= 0, opt_no_create_info= 0, opt_no_data= 0, opt_alltspcs=0, opt_notspcs= 0; 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, @@ -111,6 +111,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 @@ -120,7 +121,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 @@ -226,6 +227,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}, @@ -545,8 +548,10 @@ static void write_header(FILE *sql_file, char *db_name) if (opt_xml) { fputs("<?xml version=\"1.0\"?>\n", sql_file); - /* Schema reference. Allows use of xsi:nil for NULL values and - xsi:type to define an element's data type. */ + /* + Schema reference. Allows use of xsi:nil for NULL values and + xsi:type to define an element's data type. + */ fputs("<mysqldump ", sql_file); fputs("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"", sql_file); @@ -649,14 +654,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) @@ -699,6 +696,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); @@ -739,9 +737,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; @@ -817,9 +812,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 (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))) - exit(ho_error); + 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; @@ -831,7 +838,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 */ @@ -841,7 +848,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; @@ -850,14 +857,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, @@ -866,7 +873,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); @@ -941,6 +948,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) @@ -949,18 +973,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); @@ -981,11 +1006,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). @@ -1002,7 +1027,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 @@ -1014,11 +1039,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 */ /* @@ -1543,8 +1568,8 @@ static uint dump_routines_for_db(char *db) if the user has EXECUTE privilege he see routine names, but NOT the 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]))); + DBUG_PRINT("info",("length of body for %s row[2] '%s' is %ld", + routine_name, row[2], (long) strlen(row[2]))); if (strlen(row[2])) { char *query_str= NULL; @@ -1667,7 +1692,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, ""); } @@ -2142,7 +2171,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]; @@ -2330,7 +2359,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) @@ -2638,16 +2667,16 @@ static void dump_table(char *table, char *db) { if (opt_hex_blob && is_blob && length) { - /* Define xsi:type="xs:hexBinary" for hex encoded data */ - print_xml_tag(md_result_file, "\t\t", "", "field", "name=", - field->name, "xsi:type=", "xs:hexBinary", NullS); - print_blob_as_hex(md_result_file, row[i], length); + /* Define xsi:type="xs:hexBinary" for hex encoded data */ + print_xml_tag(md_result_file, "\t\t", "", "field", "name=", + field->name, "xsi:type=", "xs:hexBinary", NullS); + print_blob_as_hex(md_result_file, row[i], length); } else { - print_xml_tag(md_result_file, "\t\t", "", "field", "name=", - field->name, NullS); - print_quoted_xml(md_result_file, row[i], length); + print_xml_tag(md_result_file, "\t\t", "", "field", "name=", + field->name, NullS); + print_quoted_xml(md_result_file, row[i], length); } fputs("</field>\n", md_result_file); } @@ -3097,6 +3126,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)) @@ -3110,7 +3141,7 @@ static int dump_databases(char **db_names) result=1; } } - return result; + DBUG_RETURN(result); } /* dump_databases */ @@ -3125,7 +3156,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 */ @@ -3222,12 +3253,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); } @@ -3236,18 +3266,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 (!strcmp(database, NDB_REP_DB)) /* Skip cluster internal database */ - return 0; 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) @@ -3307,7 +3335,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 */ @@ -3675,7 +3703,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: @@ -3715,8 +3742,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 */ } } @@ -4071,19 +4098,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); @@ -4141,15 +4173,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/mysqlimport.c b/client/mysqlimport.c index 2ef08c9a504..447c3322de7 100644 --- a/client/mysqlimport.c +++ b/client/mysqlimport.c @@ -25,7 +25,7 @@ ** * * ** ************************* */ -#define IMPORT_VERSION "3.5" +#define IMPORT_VERSION "3.6" #include "client_priv.h" #include "mysql_version.h" @@ -50,7 +50,7 @@ static char *add_load_option(char *ptr,const char *object, static my_bool verbose=0,lock_tables=0,ignore_errors=0,opt_delete=0, replace=0,silent=0,ignore=0,opt_compress=0, opt_low_priority= 0, tty_password= 0; -static my_bool opt_use_threads= 0; +static my_bool opt_use_threads= 0, info_flag= 0; static uint opt_local_file=0; static char *opt_password=0, *current_user=0, *current_host=0, *current_db=0, *fields_terminated=0, @@ -88,6 +88,8 @@ static struct my_option my_long_options[] = 0, 0, 0}, {"debug",'#', "Output debug log. Often this is 'd:t:o,filename'.", 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, + {"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}, {"delete", 'd', "First delete all rows from table.", (gptr*) &opt_delete, (gptr*) &opt_delete, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"fields-terminated-by", OPT_FTB, @@ -663,6 +665,6 @@ int main(int argc, char **argv) my_free(shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR)); #endif free_defaults(argv_to_free); - my_end(0); + my_end(info_flag ? MY_CHECK_ERROR : 0); return(exitcode); } diff --git a/client/mysqlshow.c b/client/mysqlshow.c index 40405c53565..153bddc48d7 100644 --- a/client/mysqlshow.c +++ b/client/mysqlshow.c @@ -16,7 +16,7 @@ /* Show databases, tables or columns */ -#define SHOW_VERSION "9.5" +#define SHOW_VERSION "9.6" #include "client_priv.h" #include <my_sys.h> @@ -28,8 +28,8 @@ #include <sslopt-vars.h> static my_string host=0,opt_password=0,user=0; -static my_bool opt_show_keys= 0, opt_compress= 0, opt_count=0, opt_status= 0, - tty_password= 0, opt_table_type= 0; +static my_bool opt_show_keys= 0, opt_compress= 0, opt_count=0, opt_status= 0; +static my_bool tty_password= 0, opt_table_type= 0, info_flag= 0; static uint opt_verbose=0; static char *default_charset= (char*) MYSQL_DEFAULT_CHARSET_NAME; @@ -129,8 +129,7 @@ int main(int argc, char **argv) } mysql.reconnect= 1; - switch (argc) - { + switch (argc) { case 0: error=list_dbs(&mysql,wild); break; case 1: if (opt_status) @@ -151,7 +150,7 @@ int main(int argc, char **argv) #ifdef HAVE_SMEM my_free(shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR)); #endif - my_end(0); + my_end(info_flag ? MY_CHECK_ERROR : 0); exit(error ? 1 : 0); return 0; /* No compiler warnings */ } @@ -177,6 +176,8 @@ static struct my_option my_long_options[] = 0, 0, 0}, {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.", 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, + {"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}, {"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"host", 'h', "Connect to host.", (gptr*) &host, (gptr*) &host, 0, GET_STR, diff --git a/client/mysqlslap.c b/client/mysqlslap.c index 9c8585915a9..cba6f3009be 100644 --- a/client/mysqlslap.c +++ b/client/mysqlslap.c @@ -592,7 +592,7 @@ get_random_string(char *buf) DBUG_ENTER("get_random_string"); for (x= RAND_STRING_SIZE; x > 0; x--) *buf_ptr++= ALPHANUMERICS[random() % ALPHANUMERICS_SIZE]; - DBUG_PRINT("info", ("random string: '%*s'", buf_ptr - buf, buf)); + DBUG_PRINT("info", ("random string: '%*s'", (int) (buf_ptr - buf), buf)); DBUG_RETURN(buf_ptr - buf); } @@ -1031,7 +1031,7 @@ run_scheduler(stats *sptr, statement *stmts, uint concur, ulonglong limit) for (x= 0; x < concur; x++) { int pid; - DBUG_PRINT("info", ("x %d concurrency %d", x, concurrency)); + DBUG_PRINT("info", ("x: %d concurrency: %u", x, *concurrency)); pid= fork(); switch(pid) { diff --git a/client/mysqltest.c b/client/mysqltest.c index aeb86575333..eba682626b4 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -29,6 +29,7 @@ Matt Wagner <matt@mysql.com> Monty Jani + Holyfoot */ #define MTEST_VERSION "3.0" @@ -80,13 +81,14 @@ enum { OPT_SSL_CA, OPT_SSL_CAPATH, OPT_SSL_CIPHER, OPT_PS_PROTOCOL, OPT_SP_PROTOCOL, OPT_CURSOR_PROTOCOL, OPT_VIEW_PROTOCOL, OPT_SSL_VERIFY_SERVER_CERT, OPT_MAX_CONNECT_RETRIES, - OPT_MARK_PROGRESS + OPT_MARK_PROGRESS, OPT_CHARSETS_DIR, OPT_LOG_DIR, OPT_DEBUG_INFO }; static int record= 0, opt_sleep= -1; static char *db= 0, *pass= 0; const char *user= 0, *host= 0, *unix_sock= 0, *opt_basedir= "./"; -const char *opt_include= 0; +const char *opt_logdir= ""; +const char *opt_include= 0, *opt_charsets_dir; static int port= 0; static int opt_max_connect_retries; static my_bool opt_compress= 0, silent= 0, verbose= 0; @@ -97,6 +99,7 @@ static my_bool sp_protocol= 0, sp_protocol_enabled= 0; static my_bool view_protocol= 0, view_protocol_enabled= 0; static my_bool cursor_protocol= 0, cursor_protocol_enabled= 0; static my_bool parsing_disabled= 0; +static my_bool info_flag; static my_bool display_result_vertically= FALSE, display_metadata= FALSE; static my_bool disable_query_log= 0, disable_result_log= 0; static my_bool disable_warnings= 0, disable_ps_warnings= 0; @@ -145,7 +148,6 @@ static struct st_test_file* file_stack_end; static CHARSET_INFO *charset_info= &my_charset_latin1; /* Default charset */ -static const char *charset_name= "latin1"; /* Default character set name */ static const char *embedded_server_groups[]= { @@ -221,6 +223,12 @@ struct st_connection MYSQL* util_mysql; char *name; MYSQL_STMT* stmt; + + const char *cur_query; + int cur_query_len; + pthread_mutex_t mutex; + pthread_cond_t cond; + int query_done; }; struct st_connection connections[128]; struct st_connection* cur_con, *next_con, *connections_end; @@ -459,7 +467,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); @@ -470,7 +477,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) @@ -753,7 +809,7 @@ void die(const char *fmt, ...) /* Clean up and exit */ free_used_memory(); - my_end(MY_CHECK_ERROR); + my_end(info_flag ? MY_CHECK_ERROR | MY_GIVE_INFO : MY_CHECK_ERROR); if (!silent) printf("not ok\n"); @@ -793,7 +849,7 @@ void abort_not_supported_test(const char *fmt, ...) /* Clean up and exit */ free_used_memory(); - my_end(MY_CHECK_ERROR); + my_end(info_flag ? MY_CHECK_ERROR | MY_GIVE_INFO : MY_CHECK_ERROR); if (!silent) printf("skipped\n"); @@ -892,8 +948,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); } @@ -3076,14 +3132,14 @@ 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))); + die("Connection limit exhausted, you can have max %ld connections", + (long) (sizeof(connections)/sizeof(struct st_connection))); if (find_connection_by_name(ds_connection_name.str)) die("Connection %s already exists", ds_connection_name.str); @@ -3093,7 +3149,11 @@ void do_connect(struct st_command *command) if (opt_compress || con_compress) mysql_options(&next_con->mysql, MYSQL_OPT_COMPRESS, NullS); mysql_options(&next_con->mysql, MYSQL_OPT_LOCAL_INFILE, 0); - mysql_options(&next_con->mysql, MYSQL_SET_CHARSET_NAME, charset_name); + mysql_options(&next_con->mysql, MYSQL_SET_CHARSET_NAME, + charset_info->csname); + if (opt_charsets_dir) + mysql_options(&cur_con->mysql, MYSQL_SET_CHARSET_DIR, + opt_charsets_dir); #ifdef HAVE_OPENSSL if (opt_use_ssl || con_ssl) @@ -3779,6 +3839,9 @@ static struct my_option my_long_options[] = 0, 0, 0, 0, 0, 0}, {"basedir", 'b', "Basedir for tests.", (gptr*) &opt_basedir, (gptr*) &opt_basedir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"character-sets-dir", OPT_CHARSETS_DIR, + "Directory where character sets are.", (gptr*) &opt_charsets_dir, + (gptr*) &opt_charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"compress", 'C', "Use the compressed server/client protocol.", (gptr*) &opt_compress, (gptr*) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -3794,12 +3857,16 @@ static struct my_option my_long_options[] = {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.", 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, #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}, {"host", 'h', "Connect to host.", (gptr*) &host, (gptr*) &host, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"include", 'i', "Include SQL before each test case.", (gptr*) &opt_include, (gptr*) &opt_include, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"logdir", OPT_LOG_DIR, "Directory for log files", (gptr*) &opt_logdir, + (gptr*) &opt_logdir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"mark-progress", OPT_MARK_PROGRESS, - "Write linenumber and elapsed time to <testname>.progress ", + "Write linenumber and elapsed time to <testname>.progress", (gptr*) &opt_mark_progress, (gptr*) &opt_mark_progress, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"max-connect-retries", OPT_MAX_CONNECT_RETRIES, @@ -4080,7 +4147,8 @@ void dump_result_to_reject_file(char *buf, int size) void dump_result_to_log_file(char *buf, int size) { char log_file[FN_REFLEN]; - str_to_file(fn_format(log_file, result_file_name, "", ".log", + str_to_file(fn_format(log_file, result_file_name, opt_logdir, ".log", + *opt_logdir ? MY_REPLACE_DIR | MY_REPLACE_EXT: MY_REPLACE_EXT), buf, size); } @@ -4088,8 +4156,9 @@ void dump_result_to_log_file(char *buf, int size) void dump_progress(void) { char log_file[FN_REFLEN]; - str_to_file(fn_format(log_file, result_file_name, "", ".progress", - MY_REPLACE_EXT), + str_to_file(fn_format(log_file, result_file_name, opt_logdir, ".progress", + *opt_logdir ? MY_REPLACE_DIR | MY_REPLACE_EXT: + MY_REPLACE_EXT), ds_progress.str, ds_progress.length); } @@ -4492,7 +4561,6 @@ int append_warnings(DYNAMIC_STRING *ds, MYSQL* mysql) } - /* Run query using MySQL C API @@ -4509,11 +4577,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)); @@ -4524,14 +4593,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; @@ -5022,8 +5103,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; @@ -5180,7 +5262,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) @@ -5511,7 +5593,11 @@ int main(int argc, char **argv) if (opt_compress) mysql_options(&cur_con->mysql,MYSQL_OPT_COMPRESS,NullS); mysql_options(&cur_con->mysql, MYSQL_OPT_LOCAL_INFILE, 0); - mysql_options(&cur_con->mysql, MYSQL_SET_CHARSET_NAME, charset_name); + mysql_options(&cur_con->mysql, MYSQL_SET_CHARSET_NAME, + charset_info->csname); + if (opt_charsets_dir) + mysql_options(&cur_con->mysql, MYSQL_SET_CHARSET_DIR, + opt_charsets_dir); #ifdef HAVE_OPENSSL @@ -5641,7 +5727,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++; @@ -5672,7 +5758,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; @@ -5698,7 +5784,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; @@ -5900,7 +5986,7 @@ int main(int argc, char **argv) timer_output(); free_used_memory(); - my_end(MY_CHECK_ERROR); + my_end(info_flag ? MY_CHECK_ERROR | MY_GIVE_INFO : MY_CHECK_ERROR); /* Yes, if we got this far the test has suceeded! Sakila smiles */ if (!silent) diff --git a/cmd-line-utils/readline/bind.c b/cmd-line-utils/readline/bind.c index 17f61d1df08..3e2a72375d3 100644 --- a/cmd-line-utils/readline/bind.c +++ b/cmd-line-utils/readline/bind.c @@ -434,7 +434,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 +735,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 +766,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 +988,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 +1018,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 +1141,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 +1217,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 +1376,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 +1445,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 +1465,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 +1724,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 +1965,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 +2024,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 +2104,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 +2193,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 ea459b2118c..526c1edb33d 100644 --- a/cmd-line-utils/readline/complete.c +++ b/cmd-line-utils/readline/complete.c @@ -361,15 +361,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 ('*')); } @@ -761,10 +761,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; @@ -872,7 +869,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 @@ -1806,7 +1803,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 @@ -1856,7 +1853,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))) @@ -2092,8 +2089,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..f1822b105a4 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; @@ -333,7 +334,8 @@ history_truncate_file (fname, lines) 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) { close (file); #if defined (EFBIG) 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..4d256f492b8 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 == (unsigned int) 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_ndbcluster.m4 b/config/ac-macros/ha_ndbcluster.m4 index a722f8f1d7d..26cb0394583 100644 --- a/config/ac-macros/ha_ndbcluster.m4 +++ b/config/ac-macros/ha_ndbcluster.m4 @@ -187,7 +187,7 @@ AC_DEFUN([MYSQL_SETUP_NDBCLUSTER], [ ndb_cxxflags_fix="" TEST_NDBCLUSTER="--ndbcluster" - ndbcluster_includes="-I\$(top_builddir)/storage/ndb/include -I\$(top_builddir)/storage/ndb/include/ndbapi -I\$(top_builddir)/storage/ndb/include/mgmapi" + ndbcluster_includes="-I\$(top_builddir)/storage/ndb/include -I\$(top_srcdir)/storage/ndb/include -I\$(top_srcdir)/storage/ndb/include/ndbapi -I\$(top_srcdir)/storage/ndb/include/mgmapi" ndbcluster_libs="\$(top_builddir)/storage/ndb/src/.libs/libndbclient.a" ndbcluster_system_libs="" ndb_mgmclient_libs="\$(top_builddir)/storage/ndb/src/mgmclient/libndbmgmclient.la" diff --git a/config/ac-macros/ssl.m4 b/config/ac-macros/ssl.m4 index 0f2f207c36f..4ee58318a62 100644 --- a/config/ac-macros/ssl.m4 +++ b/config/ac-macros/ssl.m4 @@ -28,10 +28,9 @@ AC_DEFUN([MYSQL_USE_BUNDLED_YASSL], [ yassl_dir="yassl" AC_SUBST([yassl_dir]) - yassl_libs="-L\$(top_srcdir)/extra/yassl/src -lyassl -L\$(top_srcdir)/extra/yassl/taocrypt/src -ltaocrypt" + yassl_libs="\$(top_builddir)/extra/yassl/src/libyassl.la \ + \$(top_builddir)/extra/yassl/taocrypt/src/libtaocrypt.la" AC_SUBST(yassl_libs) - yassl_includes="-I\$(top_srcdir)/extra/yassl/include" - AC_SUBST(yassl_includes) AC_DEFINE([HAVE_OPENSSL], [1], [Defined by configure. Using yaSSL for SSL.]) AC_DEFINE([HAVE_YASSL], [1], [Defined by configure. Using yaSSL for SSL.]) diff --git a/configure.in b/configure.in index be975f8f7fa..f314a9ca754 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.1.13-beta) +AM_INIT_AUTOMAKE(mysql, 5.1.14-beta) AM_CONFIG_HEADER(config.h) PROTOCOL_VERSION=10 @@ -15,7 +15,6 @@ DOT_FRM_VERSION=6 # See the libtool docs for information on how to do shared lib versions. SHARED_LIB_MAJOR_VERSION=15 SHARED_LIB_VERSION=$SHARED_LIB_MAJOR_VERSION:0:0 - # Set all version vars based on $VERSION. How do we do this more elegant ? # Remember that regexps needs to quote [ and ] since this is run through m4 MYSQL_NO_DASH_VERSION=`echo $VERSION | sed -e "s|[[a-z]]*-.*$||"` @@ -2166,10 +2165,6 @@ MYSQL_CHECK_SSL # Has to be done late, as the plugin may need to check for existence of # functions tested above #-------------------------------------------------------------------- -MYSQL_PLUGIN(ftexample, [Simple Parser], - [Simple full-text parser plugin]) -MYSQL_PLUGIN_DIRECTORY(ftexample, [plugin/fulltext]) -MYSQL_PLUGIN_DYNAMIC(ftexample, [mypluglib.la]) MYSQL_STORAGE_ENGINE(partition, partition, [Partition Support], [MySQL Partitioning Support], [max,max-no-ndb]) 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/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/ssl.cpp b/extra/yassl/src/ssl.cpp index a008ea7228b..fe4661b5946 100644 --- a/extra/yassl/src/ssl.cpp +++ b/extra/yassl/src/ssl.cpp @@ -918,7 +918,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); 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/include/algebra.hpp b/extra/yassl/taocrypt/include/algebra.hpp index 07fc405f093..535ce2599c4 100644 --- a/extra/yassl/taocrypt/include/algebra.hpp +++ b/extra/yassl/taocrypt/include/algebra.hpp @@ -75,7 +75,7 @@ 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/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/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/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/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/include/errmsg.h b/include/errmsg.h index dc7adb3b501..f24ea2bf396 100644 --- a/include/errmsg.h +++ b/include/errmsg.h @@ -95,6 +95,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/m_ctype.h b/include/m_ctype.h index 5f946a3b443..0d586030735 100644 --- a/include/m_ctype.h +++ b/include/m_ctype.h @@ -190,8 +190,8 @@ typedef struct my_charset_handler_st const unsigned char *s, const unsigned char *e); /* Functions for case and sort conversion */ - 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, @@ -324,8 +324,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, @@ -415,8 +415,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 a7ec41068b3..c182ef7b799 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -869,9 +869,8 @@ typedef long my_ptrdiff_t; typedef long long my_ptrdiff_t; #endif -#if HAVE_SIZE_T -typedef size_t my_size_t; -#elif SIZEOF_CHARP <= SIZEOF_LONG +/* We can't set my_size_t to size_t as we want my_size_t to be unsigned */ +#if SIZEOF_CHARP <= SIZEOF_LONG typedef unsigned long my_size_t; #else typedef unsigned long long my_size_t; @@ -886,6 +885,22 @@ typedef unsigned long long my_size_t; #define ADD_TO_PTR(ptr,size,type) (type) ((byte*) (ptr)+size) #define PTR_BYTE_DIFF(A,B) (my_ptrdiff_t) ((byte*) (A) - (byte*) (B)) +/* + Custom version of standard offsetof() macro which can be used to get + offsets of members in class for non-POD types (according to the current + version of C++ standard offsetof() macro can't be used in such cases and + attempt to do so causes warnings to be emitted, OTOH in many cases it is + still OK to assume that all instances of the class has the same offsets + for the same members). + + This is temporary solution which should be removed once File_parser class + and related routines are refactored. +*/ + +#define my_offsetof(TYPE, MEMBER) \ + ((size_t)((char *)&(((TYPE *)0x10)->MEMBER) - (char*)0x10)) + + #define NullS (char *) 0 /* Nowdays we do not support MessyDos */ #ifndef NEAR diff --git a/include/my_pthread.h b/include/my_pthread.h index 0cb38d29be8..8a0e1fc2b01 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -130,6 +130,9 @@ void pthread_exit(void *a); /* was #define pthread_exit(A) ExitThread(A)*/ #define my_pthread_setprio(A,B) SetThreadPriority(GetCurrentThread(), (B)) #define pthread_kill(A,B) pthread_dummy(0) +#define pthread_join(A,B) \ + ((WaitForSingleObject((A), INFINITE) != WAIT_OBJECT_0) || !CloseHandle(A)) + /* Dummy defines for easier code */ #define pthread_attr_setdetachstate(A,B) pthread_dummy(0) #define my_pthread_attr_setprio(A,B) pthread_attr_setprio(A,B) diff --git a/include/my_sys.h b/include/my_sys.h index f630ffbebf3..d185913cda1 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -880,7 +880,12 @@ extern int my_getncpus(); #define HAVE_MMAP #endif +#ifndef __NETWARE__ int my_getpagesize(void); +#else +#define my_getpagesize() 8192 +#endif + void *my_mmap(void *, size_t, int, int, int, my_off_t); int my_munmap(void *, size_t); #endif diff --git a/include/my_time.h b/include/my_time.h index 394732236a3..356595cae2c 100644 --- a/include/my_time.h +++ b/include/my_time.h @@ -73,6 +73,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/mysql/plugin.h b/include/mysql/plugin.h index 2b97a134c6f..1385bb502bb 100644 --- a/include/mysql/plugin.h +++ b/include/mysql/plugin.h @@ -29,7 +29,8 @@ #define MYSQL_UDF_PLUGIN 0 /* User-defined function */ #define MYSQL_STORAGE_ENGINE_PLUGIN 1 /* Storage Engine */ #define MYSQL_FTPARSER_PLUGIN 2 /* Full-text parser plugin */ -#define MYSQL_MAX_PLUGIN_TYPE_NUM 3 /* The number of plugin types */ +#define MYSQL_DAEMON_PLUGIN 3 /* The daemon/raw plugin type */ +#define MYSQL_MAX_PLUGIN_TYPE_NUM 4 /* The number of plugin types */ /* We use the following strings to define licenses for plugins */ #define PLUGIN_LICENSE_PROPRIETARY 0 @@ -296,6 +297,13 @@ struct st_mysql_ftparser }; /************************************************************************* + API for Storage Engine plugin. (MYSQL_DAEMON_PLUGIN) +*/ + +/* handlertons of different MySQL releases are incompatible */ +#define MYSQL_DAEMON_INTERFACE_VERSION (MYSQL_VERSION_ID << 8) + +/************************************************************************* API for Storage Engine plugin. (MYSQL_STORAGE_ENGINE_PLUGIN) */ @@ -313,5 +321,15 @@ struct st_mysql_storage_engine int interface_version; }; +/* + Here we define only the descriptor structure, that is referred from + st_mysql_plugin. +*/ + +struct st_mysql_daemon +{ + int interface_version; +}; + #endif 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 e80b142e419..898b583a58b 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -176,16 +176,15 @@ void STDCALL mysql_server_end() end_embedded_server(); #endif /* If library called my_init(), free memory allocated by it */ + finish_client_errs(); if (!org_my_init_done) { my_end(MY_DONT_FREE_DBUG); - /* Remove TRACING, if enabled by mysql_debug() */ + /* Remove TRACING, if enabled by mysql_debug() */ DBUG_POP(); } else mysql_thread_end(); - finish_client_errs(); - free_charsets(); vio_end(); mysql_client_init= org_my_init_done= 0; #ifdef EMBEDDED_SERVER @@ -2094,7 +2093,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); } @@ -2437,10 +2436,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); @@ -2472,6 +2471,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); @@ -2479,16 +2480,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); } @@ -3319,8 +3322,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 @@ -4403,7 +4406,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) { @@ -4763,14 +4766,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 93f5bffdec7..062acccda07 100644 --- a/libmysql_r/Makefile.am +++ b/libmysql_r/Makefile.am @@ -36,12 +36,9 @@ libmysqlclient_r_la_LDFLAGS = $(target_ldflags) # This is called from the toplevel makefile link_sources: set -x; \ - for f in `cd $(top_srcdir)/libmysql && echo *.[ch]`; do \ - rm -f $$f; \ - @LN_CP_F@ $(top_srcdir)/libmysql/$$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 - for f in `cd $(top_builddir)/libmysql && echo *.[ch]`; do \ - rm -f $$f; \ - @LN_CP_F@ $(top_builddir)/libmysql/$$f $$f; \ - done - diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am index 0de37db63e2..cf4f90d99c9 100644 --- a/libmysqld/Makefile.am +++ b/libmysqld/Makefile.am @@ -29,8 +29,8 @@ DEFS = -DEMBEDDED_LIBRARY -DMYSQL_SERVER \ -DSHAREDIR="\"$(MYSQLSHAREdir)\"" \ -DLIBDIR="\"$(MYSQLLIBdir)\"" INCLUDES= -I$(top_builddir)/include -I$(top_srcdir)/include \ - -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@ \ @condition_dependent_plugin_includes@ @@ -94,8 +94,8 @@ INC_LIB= $(top_builddir)/regex/libregex.a \ $(yassl_inc_libs) if HAVE_YASSL -yassl_inc_libs= $(top_srcdir)/extra/yassl/src/.libs/libyassl.a \ - $(top_srcdir)/extra/yassl/taocrypt/src/.libs/libtaocrypt.a +yassl_inc_libs= $(top_builddir)/extra/yassl/src/.libs/libyassl.a \ + $(top_builddir)/extra/yassl/taocrypt/src/.libs/libtaocrypt.a endif # Storage engine specific compilation options @@ -155,16 +155,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; \ if test -n "$(sqlstoragesources)" ; \ then \ diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index b5efd4a82af..9251ddd421a 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 /* @@ -278,24 +279,26 @@ static int emb_stmt_execute(MYSQL_STMT *stmt) DBUG_ENTER("emb_stmt_execute"); char header[5]; 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/mysql-test/Makefile.am b/mysql-test/Makefile.am index f0bc1e9b20a..e8f00902a33 100644 --- a/mysql-test/Makefile.am +++ b/mysql-test/Makefile.am @@ -59,6 +59,7 @@ dist-hook: -$(INSTALL_DATA) $(srcdir)/extra/binlog_tests/*.opt $(distdir)/extra/binlog_tests -$(INSTALL_DATA) $(srcdir)/extra/rpl_tests/*.opt $(distdir)/extra/rpl_tests $(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 @@ -98,6 +99,7 @@ install-data-local: -$(INSTALL_DATA) $(srcdir)/extra/binlog_tests/*.opt $(DESTDIR)$(testdir)/extra/binlog_tests -$(INSTALL_DATA) $(srcdir)/extra/rpl_tests/*.opt $(DESTDIR)$(testdir)/extra/rpl_tests $(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 diff --git a/mysql-test/extra/binlog_tests/binlog.test b/mysql-test/extra/binlog_tests/binlog.test index 81c813e78d0..48d9b859c26 100644 --- a/mysql-test/extra/binlog_tests/binlog.test +++ b/mysql-test/extra/binlog_tests/binlog.test @@ -59,4 +59,17 @@ insert into t1 values(null); select * from t1; drop table t1; +# bug#22027 +create table t1 (a int); +create table if not exists t2 select * from t1; + +# bug#22762 +create temporary table tt1 (a int); +create table if not exists t3 like tt1; + +--replace_column 2 # 5 # +--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\// +show binlog events from 102; +drop table t1,t2,t3,tt1; + -- source extra/binlog_tests/binlog_insert_delayed.test diff --git a/mysql-test/extra/rpl_tests/rpl_deadlock.test b/mysql-test/extra/rpl_tests/rpl_deadlock.test index 64df1f272cc..526925d6a83 100644 --- a/mysql-test/extra/rpl_tests/rpl_deadlock.test +++ b/mysql-test/extra/rpl_tests/rpl_deadlock.test @@ -15,7 +15,8 @@ connection master; eval CREATE TABLE t1 (a INT NOT NULL, KEY(a)) ENGINE=$engine_type; eval CREATE TABLE t2 (a INT NOT NULL, KEY(a)) ENGINE=$engine_type; -eval CREATE TABLE t3 (a INT) ENGINE=$engine_type; +# requiring 'unique' for the timeout part of the test +eval CREATE TABLE t3 (a INT UNIQUE) ENGINE=$engine_type; eval CREATE TABLE t4 (a INT) ENGINE=$engine_type; show variables like 'slave_transaction_retries'; sync_slave_with_master; @@ -30,7 +31,9 @@ stop slave; connection master; begin; # Let's keep BEGIN and the locked statement in two different relay logs. -let $1=200; +insert into t2 values (0); # t2,t1 actors of deadlock in repl-ed ta +#insert into t3 select * from t2 for update; +let $1=10; disable_query_log; while ($1) { @@ -38,16 +41,14 @@ while ($1) dec $1; } enable_query_log; -insert into t3 select * from t2 for update; insert into t1 values(1); commit; save_master_pos; connection slave; begin; -# Let's make our transaction large so that it's slave who is chosen as -# victim -let $1=1000; +# Let's make our transaction large so that it's repl-ed msta that's victim +let $1=100; disable_query_log; while ($1) { @@ -55,14 +56,21 @@ while ($1) dec $1; } enable_query_log; -select * from t1 for update; +select * from t1 for update; # t1,t2 on local slave's start slave; + +# bad option, todo: replicate a non-transactional t_sync with the transaction +# and use wait_until_rows_count macro below --real_sleep 3 # hope that slave is blocked now -insert into t2 values(22); # provoke deadlock, slave should be victim +#let $count=11; +#let $table=t_sync; +#--include wait_until_rows_count.inc + +select * from t2 for update /* dl */; # provoke deadlock, repl-ed should be victim commit; sync_with_master; -select * from t1; # check that slave succeeded finally -select * from t2; +select * from t1; # check that repl-ed succeeded finally +select * from t2 /* must be 1 */; # check that no error is reported --replace_column 1 # 7 # 8 # 9 # 16 # 22 # 23 # 33 # --replace_result $MASTER_MYPORT MASTER_MYPORT @@ -73,14 +81,16 @@ show slave status; # 2) Test lock wait timeout stop slave; -change master to master_log_pos=536; # the BEGIN log event +delete from t3; +change master to master_log_pos=544; # the BEGIN log event begin; select * from t2 for update; # hold lock start slave; ---real_sleep 10 # slave should have blocked, and be retrying +--real_sleep 10 # repl-ed 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 +select * from t1; # check that repl-ed succeeded finally select * from t2; # check that no error is reported --replace_column 1 # 7 # 8 # 9 # 11 # 16 # 22 # 23 # 33 # @@ -96,11 +106,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=536; +delete from t3; +change master to master_log_pos=544; 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; @@ -115,4 +127,4 @@ connection master; drop table t1,t2,t3,t4; sync_slave_with_master; -# End of 4.1 tests +--echo End of 5.1 tests diff --git a/mysql-test/extra/rpl_tests/rpl_extraSlave_Col.test b/mysql-test/extra/rpl_tests/rpl_extraSlave_Col.test new file mode 100644 index 00000000000..34e01b7a675 --- /dev/null +++ b/mysql-test/extra/rpl_tests/rpl_extraSlave_Col.test @@ -0,0 +1,853 @@ +################################################# +# Author: Jeb +# Date: 2006-09-07 +# Purpose: To test having extra columns on the slave. +################################################## + +########### Clean up ################ +--disable_warnings +--disable_query_log +DROP TABLE IF EXISTS t1, t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17; +--enable_query_log +--enable_warnings + +################################################# +############ Different Table Def Test ########### +################################################# +# Purpose: To have different table def on the # +# master and slave. Most of these tests# +# should stop the slave. # +################################################# + +--echo **** Diff Table Def Start **** + +############################################## +### Try to replicate w/ PK on diff columns ### +### Should Stop Slave ### +############################################## + +--echo *** On Slave *** +sync_slave_with_master; +STOP SLAVE; +RESET SLAVE; + +eval CREATE TABLE t1 (a INT, b INT PRIMARY KEY, c CHAR(20), + d FLOAT DEFAULT '2.00', + e CHAR(4) DEFAULT 'TEST') + ENGINE=$engine_type; + +--echo *** Create t1 on Master *** +connection master; +eval CREATE TABLE t1 (a INT PRIMARY KEY, b INT, c CHAR(10) + ) ENGINE=$engine_type; + +RESET MASTER; + +--echo *** Start Slave *** +connection slave; +START SLAVE; + +--echo *** Master Data Insert *** +connection master; + +INSERT INTO t1 () VALUES(1,2,'TEXAS'),(2,1,'AUSTIN'),(3,4,'QA'); +SELECT * FROM t1 ORDER BY a; + +--echo *** Select from slave *** +sync_slave_with_master; +SELECT * FROM t1 ORDER BY a; + +--echo *** Drop t1 *** +connection master; +DROP TABLE t1; +sync_slave_with_master; + +############################################ +### Try to replicate CHAR(10) to CHAR(5) ### +### Should Stop Slave or truncate value ### +############################################ + +## BUG22086 +#--echo *** Create t2 on slave *** +#STOP SLAVE; +#RESET SLAVE; +#eval CREATE TABLE t2 (a INT, b INT PRIMARY KEY, c CHAR(5), +# d FLOAT DEFAULT '2.00', +# e CHAR(5) DEFAULT 'TEST2') +# ENGINE=$engine_type; +# +#--echo *** Create t2 on Master *** +#connection master; +#eval CREATE TABLE t2 (a INT PRIMARY KEY, b INT, c CHAR(10) +# ) ENGINE=$engine_type; +#RESET MASTER; +# +#--echo *** Start Slave *** +#connection slave; +#START SLAVE; +# +#--echo *** Master Data Insert *** +#connection master; +# +#INSERT INTO t2 () VALUES(1,2,'Kyle, TEX'),(2,1,'JOE AUSTIN'),(3,4,'QA TESTING'); +#SELECT * FROM t2 ORDER BY a; + +#--echo *** Select from slave *** +#sync_slave_with_master; +#SELECT * FROM t2 ORDER BY a; + +#--echo *** Drop t2 *** +#connection master; +#DROP TABLE t2; +#sync_slave_with_master; + +#################################### +### Try to replicate BLOB to INT ### +### Should Stop Slave ### +#################################### +--echo *** Create t3 on slave *** +STOP SLAVE; +RESET SLAVE; +eval CREATE TABLE t3 (a INT, b INT PRIMARY KEY, c CHAR(20), + d FLOAT DEFAULT '2.00', + e CHAR(5) DEFAULT 'TEST2') + ENGINE=$engine_type; + +--echo *** Create t3 on Master *** +connection master; +eval CREATE TABLE t3 (a BLOB, b INT PRIMARY KEY, c CHAR(20) + ) ENGINE=$engine_type; +RESET MASTER; + +--echo *** Start Slave *** +connection slave; +START SLAVE; + +--echo *** Master Data Insert *** +connection master; + +set @b1 = 'b1'; +set @b1 = concat(@b1,@b1); + +INSERT INTO t3 () VALUES(@b1,2,'Kyle, TEX'),(@b1,1,'JOE AUSTIN'),(@b1,4,'QA TESTING'); + +--echo ******************************************** +--echo *** Expect slave to fail with Error 1522 *** +--echo ******************************************** +connection slave; +wait_for_slave_to_stop; +--replace_result $MASTER_MYPORT MASTER_PORT +--replace_column 1 # 7 # 8 # 9 # 22 # 23 # 33 # +--query_vertical SHOW SLAVE STATUS +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; +START SLAVE; + +--echo *** Drop t3 *** +connection master; +DROP TABLE t3; +sync_slave_with_master; + +##################################################### +# Columns with different types, more columns at end # +# Expect: proper error message (wrong types) # +##################################################### + +--echo *** Create t4 on slave *** +STOP SLAVE; +RESET SLAVE; +eval CREATE TABLE t4 (a INT, b INT PRIMARY KEY, c CHAR(20), + d FLOAT DEFAULT '2.00', + e CHAR(5) DEFAULT 'TEST2') + ENGINE=$engine_type; + +--echo *** Create t4 on Master *** +connection master; +eval CREATE TABLE t4 (a DECIMAL(8,2), b INT PRIMARY KEY, c CHAR(20) + ) ENGINE=$engine_type; +RESET MASTER; + +--echo *** Start Slave *** +connection slave; +START SLAVE; + +--echo *** Master Data Insert *** +connection master; + +INSERT INTO t4 () VALUES(100.22,2,'Kyle, TEX'),(200.26,1,'JOE AUSTIN'), + (30000.22,4,'QA TESTING'); + +--echo ******************************************** +--echo *** Expect slave to fail with Error 1522 *** +--echo ******************************************** +connection slave; +wait_for_slave_to_stop; +--replace_result $MASTER_MYPORT MASTER_PORT +--replace_column 1 # 7 # 8 # 9 # 22 # 23 # 33 # +--query_vertical SHOW SLAVE STATUS +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; +START SLAVE; + +--echo *** Drop t4 *** +connection master; +DROP TABLE t4; +sync_slave_with_master; + +####################################################### +# Columns with different types, same number of colums # +# Expect: Proper error message # +####################################################### + +--echo *** Create t5 on slave *** +STOP SLAVE; +RESET SLAVE; +eval CREATE TABLE t5 (a INT PRIMARY KEY, b CHAR(5), + c FLOAT, d INT, e DOUBLE, + f DECIMAL(8,2))ENGINE=$engine_type; + +--echo *** Create t5 on Master *** +connection master; +eval CREATE TABLE t5 (a INT PRIMARY KEY, b VARCHAR(6), + c DECIMAL(8,2), d BIT, e BLOB, + f FLOAT) ENGINE=$engine_type; +RESET MASTER; + +--echo *** Start Slave *** +connection slave; +START SLAVE; + +--echo *** Master Data Insert *** +connection master; + +INSERT INTO t5 () VALUES(1,'Kyle',200.23,1,'b1b1',23.00098), + (2,'JOE',300.01,0,'b2b2',1.0000009); + +--echo ******************************************** +--echo *** Expect slave to fail with Error 1522 *** +--echo ******************************************** +connection slave; +wait_for_slave_to_stop; +--replace_result $MASTER_MYPORT MASTER_PORT +--replace_column 1 # 7 # 8 # 9 # 22 # 23 # 33 # +--query_vertical SHOW SLAVE STATUS +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; +START SLAVE; + +--echo *** Drop t5 *** +connection master; +DROP TABLE t5; +sync_slave_with_master; + +####################################################### +################## Continued ########################## +####################################################### +# Columns with different types, same number of colums # +# Expect: Proper error message # +####################################################### + +--echo *** Create t6 on slave *** +STOP SLAVE; +RESET SLAVE; +eval CREATE TABLE t6 (a INT PRIMARY KEY, b CHAR(5), + c FLOAT, d INT)ENGINE=$engine_type; + +--echo *** Create t6 on Master *** +connection master; +eval CREATE TABLE t6 (a INT PRIMARY KEY, b VARCHAR(6), + c DECIMAL(8,2), d BIT + ) ENGINE=$engine_type; +RESET MASTER; + +--echo *** Start Slave *** +connection slave; +START SLAVE; + +--echo *** Master Data Insert *** +connection master; + +INSERT INTO t6 () VALUES(1,'Kyle',200.23,1), + (2,'JOE',300.01,0); + +--echo ******************************************** +--echo *** Expect slave to fail with Error 1522 *** +--echo ******************************************** +connection slave; +wait_for_slave_to_stop; +--replace_result $MASTER_MYPORT MASTER_PORT +--replace_column 1 # 7 # 8 # 9 # 22 # 23 # 33 # +--query_vertical SHOW SLAVE STATUS +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=3; +#START SLAVE; + +--echo *** Drop t6 *** +connection master; +DROP TABLE t6; +connection slave; +DROP TABLE t6; +START SLAVE; +#sync_slave_with_master; + + +--echo **** Diff Table Def End **** + +####################################### +#### Extra Column on Slave Testing #### +####################################### +# Purpose: To test extra colums on the# +# Slave # +####################################### + +--echo **** Extra Colums Start **** + +########################################## +# More columns in slave at end of table, # +# added columns have default values # +# Expect: it should work, default values # +# should be used # +########################################## + +--echo *** Create t7 on slave *** +STOP SLAVE; +RESET SLAVE; +eval CREATE TABLE t7 (a INT KEY, b BLOB, c CHAR(5), + d TIMESTAMP NULL DEFAULT '0000-00-00 00:00:00', + e CHAR(20) DEFAULT 'Extra Column Testing') + ENGINE=$engine_type; + +--echo *** Create t7 on Master *** +connection master; +eval CREATE TABLE t7 (a INT PRIMARY KEY, b BLOB, c CHAR(5) + ) ENGINE=$engine_type; +RESET MASTER; + +--echo *** Start Slave *** +connection slave; +START SLAVE; + +--echo *** Master Data Insert *** +connection master; +set @b1 = 'b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t7 () VALUES(1,@b1,'Kyle'),(2,@b1,'JOE'),(3,@b1,'QA'); +SELECT * FROM t7 ORDER BY a; + +--echo *** Select from slave *** +sync_slave_with_master; +SELECT * FROM t7 ORDER BY a; + +--echo *** Drop t7 *** +connection master; +DROP TABLE t7; +sync_slave_with_master; + +########################################### +# More columns in slave at end of table, # +# added columns do not have default values# +# Expect: Proper error message # +########################################### +# NOTE: This should fail but currently # +# works. BUG#22101 # +########################################### +--echo *** Create t8 on slave *** +STOP SLAVE; +RESET SLAVE; +eval CREATE TABLE t8 (a INT KEY, b BLOB, c CHAR(5), + d TIMESTAMP NULL DEFAULT '0000-00-00 00:00:00', + e INT)ENGINE=$engine_type; + +--echo *** Create t8 on Master *** +connection master; +eval CREATE TABLE t8 (a INT PRIMARY KEY, b BLOB, c CHAR(5) + ) ENGINE=$engine_type; +RESET MASTER; + +--echo *** Start Slave *** +connection slave; +START SLAVE; + +--echo *** Master Data Insert *** +connection master; +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t8 () VALUES(1,@b1,'Kyle'),(2,@b1,'JOE'),(3,@b1,'QA'); + +### Uncomment once bug is fixed + +#connection slave; +#wait_for_slave_to_stop; +#--replace_result $MASTER_MYPORT MASTER_PORT +#--replace_column 1 # 7 # 8 # 9 # 22 # 23 # 33 # +#--query_vertical SHOW SLAVE STATUS +#SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; +#START SLAVE; + +--echo *** Drop t8 *** +connection master; +DROP TABLE t8; +sync_slave_with_master; + +########################################### +############# Continued ################### +# More columns in slave at end of table, # +# added columns do not have default values# +# Expect: Proper error message # +########################################### +# Commented out due to Bug #23907 Extra Slave Col is not +# erroring on extra col with no default values. +######################################################## +#--echo *** Create t9 on slave *** +#STOP SLAVE; +#RESET SLAVE; +#eval CREATE TABLE t9 (a INT KEY, b BLOB, c CHAR(5), +# d TIMESTAMP, +# e INT DEFAULT '1')ENGINE=$engine_type; + +#--echo *** Create t9 on Master *** +#connection master; +#eval CREATE TABLE t9 (a INT PRIMARY KEY, b BLOB, c CHAR(5) +# ) ENGINE=$engine_type; +#RESET MASTER; + +#--echo *** Start Slave *** +#connection slave; +#START SLAVE; + +#--echo *** Master Data Insert *** +#connection master; +#set @b1 = 'b1b1b1b1'; +#set @b1 = concat(@b1,@b1); +#INSERT INTO t9 () VALUES(1,@b1,'Kyle'),(2,@b1,'JOE'),(3,@b1,'QA'); + +#--echo ************************************************* +#--echo ** Currently giving wrong error see bug#22234 *** +#--echo ************************************************* +#sync_slave_with_master; +#connection slave; + +#--echo *** Select from T9 *** +#wait_for_slave_to_stop; +#--replace_result $MASTER_MYPORT MASTER_PORT +#--replace_column 1 # 7 # 8 # 9 # 22 # 23 # 33 # +#--query_vertical SHOW SLAVE STATUS +#SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; +#START SLAVE; + +#--echo *** Drop t9 *** +#connection master; +#DROP TABLE t9; +#sync_slave_with_master; + +############################################ +# More columns in slave at middle of table # +# Expect: Proper error message # +############################################ +--echo *** Create t10 on slave *** +STOP SLAVE; +RESET SLAVE; +eval CREATE TABLE t10 (a INT KEY, b BLOB, f DOUBLE DEFAULT '233', + c CHAR(5), e INT DEFAULT '1')ENGINE=$engine_type; + +--echo *** Create t10 on Master *** +connection master; +eval CREATE TABLE t10 (a INT PRIMARY KEY, b BLOB, c CHAR(5) + ) ENGINE=$engine_type; +RESET MASTER; + +--echo *** Start Slave *** +connection slave; +START SLAVE; + +--echo *** Master Data Insert *** +connection master; +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t10 () VALUES(1,@b1,'Kyle'),(2,@b1,'JOE'),(3,@b1,'QA'); + +--echo ******************************************** +--echo *** Expect slave to fail with Error 1522 *** +--echo ******************************************** +connection slave; +wait_for_slave_to_stop; +--replace_result $MASTER_MYPORT MASTER_PORT +--replace_column 1 # 7 # 8 # 9 # 22 # 23 # 33 # +--query_vertical SHOW SLAVE STATUS +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; +START SLAVE; + +--echo *** Drop t10 *** +connection master; +DROP TABLE t10; +sync_slave_with_master; + +############################################ +############## Continued ################### +############################################ +# More columns in slave at middle of table # +# Expect: Proper error message # +############################################ +--echo *** Create t11 on slave *** +STOP SLAVE; +RESET SLAVE; +eval CREATE TABLE t11 (a INT KEY, b BLOB, f TEXT, + c CHAR(5) DEFAULT 'test', e INT DEFAULT '1')ENGINE=$engine_type; + +--echo *** Create t11 on Master *** +connection master; +eval CREATE TABLE t11 (a INT PRIMARY KEY, b BLOB, c VARCHAR(254) + ) ENGINE=$engine_type; +RESET MASTER; + +--echo *** Start Slave *** +connection slave; +START SLAVE; + +--echo *** Master Data Insert *** +connection master; +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t11 () VALUES(1,@b1,'Kyle'),(2,@b1,'JOE'),(3,@b1,'QA'); + +--echo ******************************************** +--echo *** Expect slave to fail with Error 1522 *** +--echo ******************************************** +connection slave; +wait_for_slave_to_stop; +--replace_result $MASTER_MYPORT MASTER_PORT +--replace_column 1 # 7 # 8 # 9 # 22 # 23 # 33 # +--query_vertical SHOW SLAVE STATUS +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; +START SLAVE; + +--echo *** Drop t11 *** +connection master; +DROP TABLE t11; +sync_slave_with_master; + +############################################ +############## Continued ################### +############################################ +# More columns in slave at middle of table # +# Expect: This one should pass blob-text # +############################################ +--echo *** Create t12 on slave *** +STOP SLAVE; +RESET SLAVE; +eval CREATE TABLE t12 (a INT KEY, b BLOB, f TEXT, + c CHAR(5) DEFAULT 'test', e INT DEFAULT '1')ENGINE=$engine_type; + +--echo *** Create t12 on Master *** +connection master; +eval CREATE TABLE t12 (a INT PRIMARY KEY, b BLOB, c BLOB + ) ENGINE=$engine_type; +RESET MASTER; + +--echo *** Start Slave *** +connection slave; +START SLAVE; + +--echo *** Master Data Insert *** +connection master; +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t12 () VALUES(1,@b1,'Kyle'),(2,@b1,'JOE'),(3,@b1,'QA'); +SELECT * FROM t12 ORDER BY a; + +--echo *** Select on Slave *** +sync_slave_with_master; +SELECT * FROM t12 ORDER BY a; + +--echo *** Drop t12 *** +connection master; +DROP TABLE t12; +sync_slave_with_master; + +--echo **** Extra Colums End **** + +############################### +# BUG#22177 CURRENT_TIMESTAMP # +# Sould work with ^ # +############################### +--echo *** BUG 22177 Start *** +--echo *** Create t13 on slave *** +STOP SLAVE; +RESET SLAVE; +eval CREATE TABLE t13 (a INT KEY, b BLOB, c CHAR(5), + d INT DEFAULT '1', + e TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP + )ENGINE=$engine_type; + +--echo *** Create t13 on Master *** +connection master; +eval CREATE TABLE t13 (a INT PRIMARY KEY, b BLOB, c CHAR(5) + ) ENGINE=$engine_type; +RESET MASTER; + +--echo *** Start Slave *** +connection slave; +START SLAVE; + +--echo *** Master Data Insert *** +connection master; +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t13 () VALUES(1,@b1,'Kyle'),(2,@b1,'JOE'),(3,@b1,'QA'); +SELECT * FROM t13 ORDER BY a; + +--echo *** Select on Slave **** +sync_slave_with_master; +--replace_column 5 CURRENT_TIMESTAMP +SELECT * FROM t13 ORDER BY a; + +--echo *** Drop t13 *** +connection master; +DROP TABLE t13; +sync_slave_with_master; + +--echo *** 22117 END *** + +############################## +# ALTER MASTER TABLE TESTING # +############################## + +--echo *** Alter Master Table Testing Start *** + +#################################################### +# - Alter Master adding columns at middle of table # +# Expect: columns added # +#################################################### + +--echo *** Create t14 on slave *** +STOP SLAVE; +RESET SLAVE; +eval CREATE TABLE t14 (c1 INT KEY, c4 BLOB, c5 CHAR(5), + c6 INT DEFAULT '1', + c7 TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP + )ENGINE=$engine_type; + +--echo *** Create t14 on Master *** +connection master; +eval CREATE TABLE t14 (c1 INT PRIMARY KEY, c4 BLOB, c5 CHAR(5) + ) ENGINE=$engine_type; +RESET MASTER; + +--echo *** Start Slave *** +connection slave; +START SLAVE; + +--echo *** Master Data Insert *** +connection master; +ALTER TABLE t14 ADD COLUMN c2 DECIMAL(8,2) AFTER c1; +ALTER TABLE t14 ADD COLUMN c3 TEXT AFTER c2; +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t14 () VALUES(1,1.00,'Replication Testing Extra Col',@b1,'Kyle'), + (2,2.00,'This Test Should work',@b1,'JOE'), + (3,3.00,'If is does not, I will open a bug',@b1,'QA'); +SELECT * FROM t14 ORDER BY c1; + + +--echo *** Select on Slave **** +sync_slave_with_master; +--replace_column 7 CURRENT_TIMESTAMP +SELECT * FROM t14 ORDER BY c1; + + +#################################################### +# - Alter Master Dropping columns from the middle. # +# Expect: columns dropped # +#################################################### + +--echo *** connect to master and drop columns *** +connection master; +ALTER TABLE t14 DROP COLUMN c2; +ALTER TABLE t14 DROP COLUMN c4; +--echo *** Select from Master *** +SELECT * FROM t14 ORDER BY c1; + +--echo *** Select from Slave *** +sync_slave_with_master; +--replace_column 5 CURRENT_TIMESTAMP +SELECT * FROM t14 ORDER BY c1; + +--echo *** Drop t14 *** +connection master; +DROP TABLE t14; +sync_slave_with_master; + +############################################################## +# - Alter Master adding columns that already exist on slave. # +# Expect: proper error message # +############################################################## + +--echo *** Create t15 on slave *** +STOP SLAVE; +RESET SLAVE; +eval CREATE TABLE t15 (c1 INT KEY, c2 DECIMAL(8,2), c3 TEXT, + c4 BLOB, c5 CHAR(5), + c6 INT DEFAULT '1', + c7 TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP + )ENGINE=$engine_type; + +--echo *** Create t15 on Master *** +connection master; +eval CREATE TABLE t15 (c1 INT PRIMARY KEY, c2 DECIMAL(8,2), c3 TEXT, + c4 BLOB, c5 CHAR(5)) ENGINE=$engine_type; +RESET MASTER; + +--echo *** Start Slave *** +connection slave; +START SLAVE; + +--echo *** Master Data Insert *** +connection master; +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t15 () VALUES(1,1.00,'Replication Testing Extra Col',@b1,'Kyle'), + (2,2.00,'This Test Should work',@b1,'JOE'), + (3,3.00,'If is does not, I will open a bug',@b1,'QA'); +SELECT * FROM t15 ORDER BY c1; + + +--echo *** Select on Slave **** +sync_slave_with_master; +--replace_column 7 CURRENT_TIMESTAMP +SELECT * FROM t15 ORDER BY c1; + +--echo *** Add column on master that is a Extra on Slave *** +connection master; +ALTER TABLE t15 ADD COLUMN c6 INT AFTER c5; + +--echo ******************************************** +--echo *** Expect slave to fail with Error 1060 *** +--echo ******************************************** +connection slave; +wait_for_slave_to_stop; +--replace_result $MASTER_MYPORT MASTER_PORT +--replace_column 1 # 7 # 8 # 9 # 22 # 23 # 33 # +--query_vertical SHOW SLAVE STATUS +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; +START SLAVE; + +--echo *** Try to insert in master **** +connection master; +INSERT INTO t15 () VALUES(5,2.00,'Replication Testing',@b1,'Buda',2); +SELECT * FROM t15 ORDER BY c1; + +--echo *** Try to select from slave **** +sync_slave_with_master; +--replace_column 7 CURRENT_TIMESTAMP +SELECT * FROM t15 ORDER BY c1; + +--echo *** DROP TABLE t15 *** +connection master; +DROP TABLE t15; +sync_slave_with_master; + +#################################### +# - Alter Master and ADD PARTITION # +# Expect:? # +#################################### + +--echo *** Create t16 on slave *** +STOP SLAVE; +RESET SLAVE; +eval CREATE TABLE t16 (c1 INT KEY, c2 DECIMAL(8,2), c3 TEXT, + c4 BLOB, c5 CHAR(5), + c6 INT DEFAULT '1', + c7 TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP + )ENGINE=$engine_type; + +--echo *** Create t16 on Master *** +connection master; +eval CREATE TABLE t16 (c1 INT PRIMARY KEY, c2 DECIMAL(8,2), c3 TEXT, + c4 BLOB, c5 CHAR(5))ENGINE=$engine_type; +RESET MASTER; + +--echo *** Start Slave *** +connection slave; +START SLAVE; + +--echo *** Master Data Insert *** +connection master; +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t16 () VALUES(1,1.00,'Replication Testing Extra Col',@b1,'Kyle'), + (2,2.00,'This Test Should work',@b1,'JOE'), + (3,3.00,'If is does not, I will open a bug',@b1,'QA'); +SELECT * FROM t16 ORDER BY c1; + +--echo *** Select on Slave **** +sync_slave_with_master; +--replace_column 7 CURRENT_TIMESTAMP +SELECT * FROM t16 ORDER BY c1; + +--echo *** Add Partition on master *** +connection master; +ALTER TABLE t16 PARTITION BY KEY(c1) PARTITIONS 4; +INSERT INTO t16 () VALUES(4,1.00,'Replication Rocks',@b1,'Omer'); +SHOW CREATE TABLE t16; + +--echo *** Show table on Slave **** +sync_slave_with_master; +SHOW CREATE TABLE t16; + +--echo *** DROP TABLE t16 *** +connection master; +DROP TABLE t16; +sync_slave_with_master; + +--echo *** Alter Master End *** + +############################################ +### Try to replicate BIGINT to SMALLINT ### +### Should Stop Slave ### +############################################ + +--echo *** Create t17 on slave *** +STOP SLAVE; +RESET SLAVE; +eval CREATE TABLE t17 (a SMALLINT, b INT PRIMARY KEY, c CHAR(5), + d FLOAT DEFAULT '2.00', + e CHAR(5) DEFAULT 'TEST2') + ENGINE=$engine_type; + +--echo *** Create t17 on Master *** +connection master; +eval CREATE TABLE t17 (a BIGINT PRIMARY KEY, b INT, c CHAR(10) + ) ENGINE=$engine_type; +RESET MASTER; + +--echo *** Start Slave *** +connection slave; +START SLAVE; + +--echo *** Master Data Insert *** +connection master; + +INSERT INTO t17 () VALUES(9223372036854775807,2,'Kyle, TEX'); + +--echo ******************************************** +--echo *** Expect slave to fail with Error 1522 *** +--echo ******************************************** +connection slave; +wait_for_slave_to_stop; +--replace_result $MASTER_MYPORT MASTER_PORT +--replace_column 1 # 7 # 8 # 9 # 22 # 23 # 33 # +--query_vertical SHOW SLAVE STATUS +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; +START SLAVE; + +--echo ** DROP table t17 *** +connection master; +DROP TABLE t17; +sync_slave_with_master; + +#### Clean Up #### +--disable_warnings +--disable_query_log +DROP TABLE IF EXISTS t1, t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17; +--enable_query_log +--enable_warnings + +# END 5.1 Test Case + + diff --git a/mysql-test/extra/rpl_tests/rpl_ndb_ddl.test b/mysql-test/extra/rpl_tests/rpl_ndb_ddl.test new file mode 100644 index 00000000000..26c368589ba --- /dev/null +++ b/mysql-test/extra/rpl_tests/rpl_ndb_ddl.test @@ -0,0 +1,507 @@ +######################## rpl_ddl.test ######################## +# # +# DDL statements (sometimes with implicit COMMIT) executed # +# by the master and it's propagation into the slave # +# # +############################################################## + +# +# NOTE, PLEASE BE CAREFUL, WHEN MODIFYING THE TESTS !! +# +# 1. !All! objects to be dropped, renamed, altered ... must be created +# in AUTOCOMMIT= 1 mode before AUTOCOMMIT is set to 0 and the test +# sequences start. +# +# 2. Never use a test object, which was direct or indirect affected by a +# preceeding test sequence again. +# Except table d1.t1 where ONLY DML is allowed. +# +# If one preceeding test sequence hits a (sometimes not good visible, +# because the sql error code of the statement might be 0) bug +# and these rules are ignored, a following test sequence might earn ugly +# effects like failing 'sync_slave_with_master', crashes of the slave or +# abort of the test case etc.. +# +# 3. The assignment of the DDL command to be tested to $my_stmt can +# be a bit difficult. "'" must be avoided, because the test +# routine "include/rpl_stmt_seq.inc" performs a +# eval SELECT CONCAT('######## ','$my_stmt',' ########') as ""; +# + +############################################################### +# Some preparations +############################################################### +# The sync_slave_with_master is needed to make the xids deterministic. +sync_slave_with_master; +connection master; + +SET AUTOCOMMIT = 1; +# +# 1. DROP all objects, which probably already exist, but must be created here +# +--disable_warnings +DROP DATABASE IF EXISTS mysqltest1; +DROP DATABASE IF EXISTS mysqltest2; +DROP DATABASE IF EXISTS mysqltest3; +--enable_warnings +# +# 2. CREATE all objects needed +# working database is mysqltest1 +# working (transactional!) is mysqltest1.t1 +# +CREATE DATABASE mysqltest1; +CREATE DATABASE mysqltest2; +eval CREATE TABLE mysqltest1.t1 (f1 BIGINT) ENGINE=$engine_type; +INSERT INTO mysqltest1.t1 SET f1= 0; +eval CREATE TABLE mysqltest1.t2 (f1 BIGINT) ENGINE=$engine_type; +eval CREATE TABLE mysqltest1.t3 (f1 BIGINT) ENGINE=$engine_type; +eval CREATE TABLE mysqltest1.t4 (f1 BIGINT) ENGINE=$engine_type; +eval CREATE TABLE mysqltest1.t5 (f1 BIGINT) ENGINE=$engine_type; +eval CREATE TABLE mysqltest1.t6 (f1 BIGINT) ENGINE=$engine_type; +CREATE INDEX my_idx6 ON mysqltest1.t6(f1); +eval CREATE TABLE mysqltest1.t7 (f1 BIGINT) ENGINE=$engine_type; +INSERT INTO mysqltest1.t7 SET f1= 0; +eval CREATE TABLE mysqltest1.t8 (f1 BIGINT) ENGINE=$engine_type; +eval CREATE TABLE mysqltest1.t9 (f1 BIGINT) ENGINE=$engine_type; +eval CREATE TABLE mysqltest1.t10 (f1 BIGINT) ENGINE=$engine_type; +eval CREATE TABLE mysqltest1.t11 (f1 BIGINT) ENGINE=$engine_type; +eval CREATE TABLE mysqltest1.t12 (f1 BIGINT) ENGINE=$engine_type; +eval CREATE TABLE mysqltest1.t13 (f1 BIGINT) ENGINE=$engine_type; +eval CREATE TABLE mysqltest1.t14 (f1 BIGINT) ENGINE=$engine_type; +eval CREATE TABLE mysqltest1.t15 (f1 BIGINT) ENGINE=$engine_type; +eval CREATE TABLE mysqltest1.t16 (f1 BIGINT) ENGINE=$engine_type; +eval CREATE TABLE mysqltest1.t17 (f1 BIGINT) ENGINE=$engine_type; +eval CREATE TABLE mysqltest1.t18 (f1 BIGINT) ENGINE=$engine_type; +eval CREATE TABLE mysqltest1.t19 (f1 BIGINT) ENGINE=$engine_type; +CREATE TEMPORARY TABLE mysqltest1.t23 (f1 BIGINT); + +# +# 3. master sessions: never do AUTOCOMMIT +# slave sessions: never do AUTOCOMMIT +# +SET AUTOCOMMIT = 0; +use mysqltest1; +sync_slave_with_master; +connection slave; +--disable_query_log +SELECT '-------- switch to slave --------' as ""; +--enable_query_log +SET AUTOCOMMIT = 0; +use mysqltest1; +connection master; +--disable_query_log +SELECT '-------- switch to master -------' as ""; +--enable_query_log + + +# We don't want to abort the whole test if one statement sent +# to the server gets an error, because the following test +# sequences are nearly independend of the previous statements. +--disable_abort_on_error + +############################################################### +# Banal case: (explicit) COMMIT and ROLLBACK +# Just for checking if the test sequence is usable +############################################################### + +let $my_stmt= COMMIT; +let $my_master_commit= true; +let $my_slave_commit= true; +--source include/rpl_stmt_seq.inc + +let $my_stmt= ROLLBACK; +let $my_master_commit= false; +let $my_slave_commit= false; +--source include/rpl_stmt_seq.inc + +############################################################### +# Cases with commands very similar to COMMIT +############################################################### + +let $my_stmt= SET AUTOCOMMIT=1; +let $my_master_commit= true; +let $my_slave_commit= true; +--source include/rpl_stmt_seq.inc +SET AUTOCOMMIT=0; + +let $my_stmt= START TRANSACTION; +let $my_master_commit= true; +let $my_slave_commit= true; +--source include/rpl_stmt_seq.inc + +let $my_stmt= BEGIN; +let $my_master_commit= true; +let $my_slave_commit= true; +--source include/rpl_stmt_seq.inc + +############################################################### +# Cases with (BASE) TABLES and (UPDATABLE) VIEWs +############################################################### + +let $my_stmt= DROP TABLE mysqltest1.t2; +let $my_master_commit= true; +let $my_slave_commit= true; +--source include/rpl_stmt_seq.inc +SHOW TABLES LIKE 't2'; +connection slave; +--disable_query_log +SELECT '-------- switch to slave --------' as ""; +--enable_query_log +SHOW TABLES LIKE 't2'; +connection master; +--disable_query_log +SELECT '-------- switch to master -------' as ""; +--enable_query_log + +# Note: Since this test is executed with a skip-innodb slave, the +# slave incorrectly commits the insert. One can *not* have InnoDB on +# master and MyISAM on slave and expect that a transactional rollback +# after a CREATE TEMPORARY TABLE should work correctly on the slave. +# For this to work properly the handler on the slave must be able to +# handle transactions (e.g. InnoDB or NDB). +let $my_stmt= DROP TEMPORARY TABLE mysqltest1.t23; +let $my_master_commit= false; +let $my_slave_commit= false; +--source include/rpl_stmt_seq.inc +SHOW TABLES LIKE 't23'; +connection slave; +--disable_query_log +SELECT '-------- switch to slave --------' as ""; +--enable_query_log +SHOW TABLES LIKE 't23'; +connection master; +--disable_query_log +SELECT '-------- switch to master -------' as ""; +--enable_query_log + +let $my_stmt= RENAME TABLE mysqltest1.t3 to mysqltest1.t20; +let $my_master_commit= true; +let $my_slave_commit= true; +--source include/rpl_stmt_seq.inc +SHOW TABLES LIKE 't20'; +connection slave; +--disable_query_log +SELECT '-------- switch to slave --------' as ""; +--enable_query_log +SHOW TABLES LIKE 't20'; +connection master; +--disable_query_log +SELECT '-------- switch to master -------' as ""; +--enable_query_log + +let $my_stmt= ALTER TABLE mysqltest1.t4 ADD column f2 BIGINT; +let $my_master_commit= true; +let $my_slave_commit= true; +--source include/rpl_stmt_seq.inc +describe mysqltest1.t4; +connection slave; +--disable_query_log +SELECT '-------- switch to slave --------' as ""; +--enable_query_log +describe mysqltest1.t4; +connection master; +--disable_query_log +SELECT '-------- switch to master -------' as ""; +--enable_query_log + +let $my_stmt= CREATE TABLE mysqltest1.t21 (f1 BIGINT) ENGINE=; +let $my_master_commit= true; +let $my_slave_commit= true; +--source include/rpl_stmt_seq2.inc + +# Note: Since this test is executed with a skip-innodb slave, the +# slave incorrectly commits the insert. One can *not* have InnoDB on +# master and MyISAM on slave and expect that a transactional rollback +# after a CREATE TEMPORARY TABLE should work correctly on the slave. +# For this to work properly the handler on the slave must be able to +# handle transactions (e.g. InnoDB or NDB). +let $engine=''; +let $eng_type=''; + +let $my_stmt= CREATE TEMPORARY TABLE mysqltest1.t22 (f1 BIGINT); +let $my_master_commit= false; +let $my_slave_commit= false; +--source include/rpl_stmt_seq.inc + +let $my_stmt= TRUNCATE TABLE mysqltest1.t7; +let $my_master_commit= true; +let $my_slave_commit= true; +--source include/rpl_stmt_seq.inc +SELECT * FROM mysqltest1.t7; +--echo -------- switch to slave -------- +sync_slave_with_master; +SELECT * FROM mysqltest1.t7; +--echo -------- switch to master ------- +connection master; + +############################################################### +# Cases with LOCK/UNLOCK +############################################################### + +# MySQL insists in locking mysqltest1.t1, because rpl_stmt_seq performs an +# INSERT into this table. +let $my_stmt= LOCK TABLES mysqltest1.t1 WRITE, mysqltest1.t8 READ; +let $my_master_commit= true; +let $my_slave_commit= true; +--source include/rpl_stmt_seq.inc +UNLOCK TABLES; + +# No prior locking +let $my_stmt= UNLOCK TABLES; +let $my_master_commit= false; +let $my_slave_commit= false; +--source include/rpl_stmt_seq.inc + +# With prior read locking +# Note that this test generate an error since the rpl_stmt_seq.inc +# tries to insert into t1. +LOCK TABLES mysqltest1.t1 READ; +let $my_stmt= UNLOCK TABLES; +let $my_master_commit= false; +let $my_slave_commit= false; +--source include/rpl_stmt_seq.inc + +# With prior write locking +LOCK TABLES mysqltest1.t1 WRITE, mysqltest1.t8 READ; +let $my_stmt= UNLOCK TABLES; +let $my_master_commit= true; +let $my_slave_commit= true; +--source include/rpl_stmt_seq.inc + +############################################################### +# Cases with INDEXES +############################################################### + +let $my_stmt= DROP INDEX my_idx6 ON mysqltest1.t6; +let $my_master_commit= true; +let $my_slave_commit= true; +--source include/rpl_stmt_seq.inc +SHOW INDEX FROM mysqltest1.t6; +connection slave; +--disable_query_log +SELECT '-------- switch to slave --------' as ""; +--enable_query_log +SHOW INDEX FROM mysqltest1.t6; +connection master; +--disable_query_log +SELECT '-------- switch to master -------' as ""; +--enable_query_log + +let $my_stmt= CREATE INDEX my_idx5 ON mysqltest1.t5(f1); +let $my_master_commit= true; +let $my_slave_commit= true; +--source include/rpl_stmt_seq.inc +SHOW INDEX FROM mysqltest1.t5; +connection slave; +--disable_query_log +SELECT '-------- switch to slave --------' as ""; +--enable_query_log +SHOW INDEX FROM mysqltest1.t5; +connection master; +--disable_query_log +SELECT '-------- switch to master -------' as ""; +--enable_query_log + +############################################################### +# Cases with DATABASE +############################################################### + +let $my_stmt= DROP DATABASE mysqltest2; +let $my_master_commit= true; +let $my_slave_commit= true; +--source include/rpl_stmt_seq.inc +SHOW DATABASES LIKE "mysqltest2"; +connection slave; +--disable_query_log +SELECT '-------- switch to slave --------' as ""; +--enable_query_log +SHOW DATABASES LIKE "mysqltest2"; +connection master; +--disable_query_log +SELECT '-------- switch to master -------' as ""; +--enable_query_log + +let $my_stmt= CREATE DATABASE mysqltest3; +let $my_master_commit= true; +let $my_slave_commit= true; +--source include/rpl_stmt_seq.inc +SHOW DATABASES LIKE "mysqltest3"; +connection slave; +--disable_query_log +SELECT '-------- switch to slave --------' as ""; +--enable_query_log +SHOW DATABASES LIKE "mysqltest3"; +connection master; +--disable_query_log +SELECT '-------- switch to master -------' as ""; +--enable_query_log + +# End of 4.1 tests + +############################################################### +# Cases with stored procedures +############################################################### +let $my_stmt= CREATE PROCEDURE p1() READS SQL DATA SELECT "this is p1"; +let $my_master_commit= true; +let $my_slave_commit= true; +--source include/rpl_stmt_seq.inc +--vertical_results +--replace_column 5 # 6 # +SHOW PROCEDURE STATUS LIKE 'p1'; +--disable_query_log +SELECT '-------- switch to slave -------' as ""; +--enable_query_log +connection slave; +--replace_column 5 # 6 # +SHOW PROCEDURE STATUS LIKE 'p1'; +connection master; +--horizontal_results + +let $my_stmt= ALTER PROCEDURE p1 COMMENT "I have been altered"; +let $my_master_commit= true; +let $my_slave_commit= true; +--source include/rpl_stmt_seq.inc +--vertical_results +--replace_column 5 # 6 # +SHOW PROCEDURE STATUS LIKE 'p1'; +--disable_query_log +SELECT '-------- switch to slave -------' as ""; +--enable_query_log +connection slave; +--replace_column 5 # 6 # +SHOW PROCEDURE STATUS LIKE 'p1'; +connection master; +--horizontal_results + +let $my_stmt= DROP PROCEDURE p1; +let $my_master_commit= true; +let $my_slave_commit= true; +--source include/rpl_stmt_seq.inc +--vertical_results +SHOW PROCEDURE STATUS LIKE 'p1'; +--disable_query_log +SELECT '-------- switch to slave -------' as ""; +--enable_query_log +connection slave; +SHOW PROCEDURE STATUS LIKE 'p1'; +connection master; +--horizontal_results + +############################################################### +# Cases with VIEWs +############################################################### +let $my_stmt= CREATE OR REPLACE VIEW v1 as select * from t1; +let $my_master_commit= true; +let $my_slave_commit= true; +--source include/rpl_stmt_seq.inc +SHOW CREATE VIEW v1; +--disable_query_log +SELECT '-------- switch to slave -------' as ""; +--enable_query_log +connection slave; +SHOW CREATE VIEW v1; +connection master; + +let $my_stmt= ALTER VIEW v1 AS select f1 from t1; +let $my_master_commit= true; +let $my_slave_commit= true; +--source include/rpl_stmt_seq.inc +SHOW CREATE VIEW v1; +--disable_query_log +SELECT '-------- switch to slave -------' as ""; +--enable_query_log +connection slave; +SHOW CREATE VIEW v1; +connection master; + +let $my_stmt= DROP VIEW IF EXISTS v1; +let $my_master_commit= true; +let $my_slave_commit= true; +--source include/rpl_stmt_seq.inc +--error 1146 +SHOW CREATE VIEW v1; +--disable_query_log +SELECT '-------- switch to slave -------' as ""; +--enable_query_log +connection slave; +--error 1146 +SHOW CREATE VIEW v1; +connection master; + +############################################################### +# Cases with TRIGGERs +############################################################### +let $my_stmt= CREATE TRIGGER trg1 BEFORE INSERT ON t1 FOR EACH ROW SET @a:=1; +let $my_master_commit= true; +let $my_slave_commit= true; +--source include/rpl_stmt_seq.inc +SHOW TRIGGERS; +--disable_query_log +SELECT '-------- switch to slave -------' as ""; +--enable_query_log +connection slave; +SHOW TRIGGERS; +connection master; + +let $my_stmt= DROP TRIGGER trg1; +let $my_master_commit= true; +let $my_slave_commit= true; +--source include/rpl_stmt_seq.inc +SHOW TRIGGERS; +--disable_query_log +SELECT '-------- switch to slave -------' as ""; +--enable_query_log +connection slave; +SHOW TRIGGERS; +connection master; + +############################################################### +# Cases with USERs +############################################################### +let $my_stmt= CREATE USER user1@localhost; +let $my_master_commit= true; +let $my_slave_commit= true; +--source include/rpl_stmt_seq.inc +SELECT user FROM mysql.user WHERE user = 'user1'; +--disable_query_log +SELECT '-------- switch to slave -------' as ""; +--enable_query_log +connection slave; +SELECT user FROM mysql.user WHERE user = 'user1'; +connection master; + +let $my_stmt= RENAME USER user1@localhost TO rename1@localhost; +let $my_master_commit= true; +let $my_slave_commit= true; +--source include/rpl_stmt_seq.inc +SELECT user FROM mysql.user WHERE user = 'rename1'; +--disable_query_log +SELECT '-------- switch to slave -------' as ""; +--enable_query_log +connection slave; +SELECT user FROM mysql.user WHERE user = 'rename1'; +connection master; + +let $my_stmt= DROP USER rename1@localhost; +let $my_master_commit= true; +let $my_slave_commit= true; +--source include/rpl_stmt_seq.inc +SELECT user FROM mysql.user WHERE user = 'rename1'; +--disable_query_log +SELECT '-------- switch to slave -------' as ""; +--enable_query_log +connection slave; +SELECT user FROM mysql.user WHERE user = 'rename1'; +connection master; + +############################################################### +# Cleanup +############################################################### +--disable_warnings +DROP DATABASE IF EXISTS mysqltest1; +DROP DATABASE IF EXISTS mysqltest2; +DROP DATABASE IF EXISTS mysqltest3; +--enable_warnings + +-- source include/master-slave-end.inc + 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/im_check_env.inc b/mysql-test/include/im_check_env.inc index 019e0984614..883e5d00fe4 100644 --- a/mysql-test/include/im_check_env.inc +++ b/mysql-test/include/im_check_env.inc @@ -22,4 +22,5 @@ SHOW VARIABLES LIKE 'server_id'; # Check that IM understands that mysqld1 is online, while mysqld2 is # offline. +--replace_result starting XXXXX online XXXXX SHOW INSTANCES; diff --git a/mysql-test/include/mix2.inc b/mysql-test/include/mix2.inc index d3980b17d91..8c11f094907 100644 --- a/mysql-test/include/mix2.inc +++ b/mysql-test/include/mix2.inc @@ -1588,7 +1588,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) eval CREATE TABLE t1 ( id INT PRIMARY KEY diff --git a/mysql-test/include/ndb_setup_slave.inc b/mysql-test/include/ndb_setup_slave.inc index b1efeded90b..3cda48755b9 100644 --- a/mysql-test/include/ndb_setup_slave.inc +++ b/mysql-test/include/ndb_setup_slave.inc @@ -7,7 +7,7 @@ # 1. --connection slave --replace_column 1 <the_epoch> -SELECT @the_epoch:=MAX(epoch) FROM cluster.apply_status; +SELECT @the_epoch:=MAX(epoch) FROM mysql.apply_status; --let $the_epoch= `select @the_epoch` # 2. @@ -15,7 +15,7 @@ SELECT @the_epoch:=MAX(epoch) FROM cluster.apply_status; --replace_result $the_epoch <the_epoch> --replace_column 1 <the_pos> eval SELECT @the_pos:=Position,@the_file:=SUBSTRING_INDEX(FILE, '/', -1) - FROM cluster.binlog_index WHERE epoch > $the_epoch ORDER BY epoch ASC LIMIT 1; + FROM mysql.binlog_index WHERE epoch > $the_epoch ORDER BY epoch ASC LIMIT 1; --let $the_pos= `SELECT @the_pos` --let $the_file= `SELECT @the_file` diff --git a/mysql-test/include/query_cache.inc b/mysql-test/include/query_cache.inc index 3b63167a737..0cf2f7cdfe9 100644 --- a/mysql-test/include/query_cache.inc +++ b/mysql-test/include/query_cache.inc @@ -100,4 +100,82 @@ eval set GLOBAL query_cache_size=$save_query_cache_size; --enable_query_log } -# End of 4.1 tests +# +# Test query cache with two interleaving transactions +# + +# Establish connection1 +connect (connection1,localhost,root,,); +eval SET SESSION STORAGE_ENGINE = $engine_type; +SET @@autocommit=1; + +connection default; +--echo connection default +# This should be 'YES'. +SHOW VARIABLES LIKE 'have_query_cache'; + +SET GLOBAL query_cache_size = 200000; +flush status; +SET @@autocommit=1; +eval SET SESSION STORAGE_ENGINE = $engine_type; +CREATE TABLE t2 (s1 int, s2 varchar(1000), key(s1)); +INSERT INTO t2 VALUES (1,repeat('a',10)),(2,repeat('a',10)),(3,repeat('a',10)),(4,repeat('a',10)); +COMMIT; +START TRANSACTION; +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +UPDATE t2 SET s2 = 'w' WHERE s1 = 3; +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +show status like "Qcache_queries_in_cache"; + +connection connection1; +--echo connection connection1 +START TRANSACTION; +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +INSERT INTO t2 VALUES (5,'w'); +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +COMMIT; +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; + +show status like "Qcache_queries_in_cache"; + +connection default; +--echo connection default +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +COMMIT; + +show status like "Qcache_queries_in_cache"; + +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +show status like "Qcache_queries_in_cache"; + +connection connection1; +--echo connection connection1 +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; + +START TRANSACTION; +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +INSERT INTO t2 VALUES (6,'w'); +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; + +connection default; +--echo connection default +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +START TRANSACTION; +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +DELETE from t2 WHERE s1=3; +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +COMMIT; + +connection connection1; +--echo connection connection1 + +COMMIT; +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; + +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; + +# Final cleanup +connection default; +drop table t2; +disconnect connection1; diff --git a/mysql-test/include/report-features.test b/mysql-test/include/report-features.test new file mode 100644 index 00000000000..df395f6e3f0 --- /dev/null +++ b/mysql-test/include/report-features.test @@ -0,0 +1,11 @@ +# +# show server variables +# + +--disable_query_log +--echo ===== ENGINES ===== +show engines; +--echo ===== VARIABLES ===== +show variables; +--echo ===== STOP ===== +--enable_query_log 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 d7c19438836..87ca7e5a530 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/init_db.sql b/mysql-test/lib/init_db.sql index a5736ed4b9b..b7618b3ab46 100644 --- a/mysql-test/lib/init_db.sql +++ b/mysql-test/lib/init_db.sql @@ -634,5 +634,4 @@ CREATE TABLE event ( PRIMARY KEY (db, name) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT 'Events'; -CREATE DATABASE IF NOT EXISTS cluster; -CREATE TABLE IF NOT EXISTS cluster.binlog_index (Position BIGINT UNSIGNED NOT NULL, File VARCHAR(255) NOT NULL, epoch BIGINT UNSIGNED NOT NULL, inserts BIGINT UNSIGNED NOT NULL, updates BIGINT UNSIGNED NOT NULL, deletes BIGINT UNSIGNED NOT NULL, schemaops BIGINT UNSIGNED NOT NULL, PRIMARY KEY(epoch)) ENGINE=MYISAM; +CREATE TABLE IF NOT EXISTS mysql.binlog_index (Position BIGINT UNSIGNED NOT NULL, File VARCHAR(255) NOT NULL, epoch BIGINT UNSIGNED NOT NULL, inserts BIGINT UNSIGNED NOT NULL, updates BIGINT UNSIGNED NOT NULL, deletes BIGINT UNSIGNED NOT NULL, schemaops BIGINT UNSIGNED NOT NULL, PRIMARY KEY(epoch)) ENGINE=MYISAM; 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 984d834486c..5be1d2ffddb 100644 --- a/mysql-test/lib/mtr_io.pl +++ b/mysql-test/lib/mtr_io.pl @@ -39,6 +39,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_process.pl b/mysql-test/lib/mtr_process.pl index 9d0c1f601ba..79285de88a7 100644 --- a/mysql-test/lib/mtr_process.pl +++ b/mysql-test/lib/mtr_process.pl @@ -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"); } diff --git a/mysql-test/lib/mtr_report.pl b/mysql-test/lib/mtr_report.pl index 8d7de9d1a4b..abf9cd066b1 100644 --- a/mysql-test/lib/mtr_report.pl +++ b/mysql-test/lib/mtr_report.pl @@ -38,7 +38,7 @@ sub mtr_show_failed_diff ($) { my $reject_file= "r/$tname.reject"; my $result_file= "r/$tname.result"; - my $log_file= "r/$tname.log"; + my $log_file= "$::opt_vardir/log/$tname.log"; my $eval_file= "r/$tname.eval"; if ( $::opt_suite ne "main" ) @@ -89,10 +89,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 ($) { @@ -243,6 +247,7 @@ sub mtr_report_stats ($) { foreach my $pattern ( "^Warning:", "^Error:", "^==.* at 0x", "InnoDB: Warning", "missing DBUG_RETURN", "mysqld: Warning", + "allocated at line", "Attempting backtrace", "Assertion .* failed" ) { foreach my $errlog ( sort glob("$::opt_vardir/log/*.err") ) 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 99c844b2f78..c6da525c159 100644 --- a/mysql-test/mysql-test-run-shell.sh +++ b/mysql-test/mysql-test-run-shell.sh @@ -129,7 +129,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! @@ -180,18 +180,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 @@ -784,8 +790,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" @@ -882,15 +895,15 @@ fi # Save path and name of mysqldump MYSQL_DUMP_DIR="$MYSQL_DUMP" export MYSQL_DUMP_DIR -MYSQL_CHECK="$MYSQL_CHECK --no-defaults -uroot --socket=$MASTER_MYSOCK --password=$DBPASSWD $EXTRA_MYSQLCHECK_OPT" -MYSQL_DUMP="$MYSQL_DUMP --no-defaults -uroot --socket=$MASTER_MYSOCK --password=$DBPASSWD $EXTRA_MYSQLDUMP_OPT" +MYSQL_CHECK="$MYSQL_CHECK --no-defaults --debug-info -uroot --socket=$MASTER_MYSOCK --password=$DBPASSWD $EXTRA_MYSQLCHECK_OPT" +MYSQL_DUMP="$MYSQL_DUMP --no-defaults --debug-info -uroot --socket=$MASTER_MYSOCK --password=$DBPASSWD $EXTRA_MYSQLDUMP_OPT" MYSQL_SLAP="$MYSQL_SLAP -uroot --socket=$MASTER_MYSOCK --password=$DBPASSWD $EXTRA_MYSQLSLAP_OPT" MYSQL_DUMP_SLAVE="$MYSQL_DUMP_DIR --no-defaults -uroot --socket=$SLAVE_MYSOCK --password=$DBPASSWD $EXTRA_MYSQLDUMP_OPT" -MYSQL_SHOW="$MYSQL_SHOW -uroot --socket=$MASTER_MYSOCK --password=$DBPASSWD $EXTRA_MYSQLSHOW_OPT" -MYSQL_BINLOG="$MYSQL_BINLOG --no-defaults --local-load=$MYSQL_TMP_DIR --character-sets-dir=$CHARSETSDIR $EXTRA_MYSQLBINLOG_OPT" -MYSQL_IMPORT="$MYSQL_IMPORT -uroot --socket=$MASTER_MYSOCK --password=$DBPASSWD $EXTRA_MYSQLDUMP_OPT" +MYSQL_SHOW="$MYSQL_SHOW --no-defaults --debug-info -uroot --socket=$MASTER_MYSOCK --password=$DBPASSWD $EXTRA_MYSQLSHOW_OPT" +MYSQL_BINLOG="$MYSQL_BINLOG --debug-info --no-defaults --local-load=$MYSQL_TMP_DIR --character-sets-dir=$CHARSETSDIR $EXTRA_MYSQLBINLOG_OPT" +MYSQL_IMPORT="$MYSQL_IMPORT --debug-info -uroot --socket=$MASTER_MYSOCK --password=$DBPASSWD $EXTRA_MYSQLDUMP_OPT" MYSQL_FIX_SYSTEM_TABLES="$MYSQL_FIX_SYSTEM_TABLES --no-defaults --host=localhost --port=$MASTER_MYPORT --socket=$MASTER_MYSOCK --user=root --password=$DBPASSWD --basedir=$BASEDIR --bindir=$CLIENT_BINDIR --verbose" -MYSQL="$MYSQL --no-defaults --host=localhost --port=$MASTER_MYPORT --socket=$MASTER_MYSOCK --user=root --password=$DBPASSWD" +MYSQL="$MYSQL --no-defaults --debug-info --host=localhost --port=$MASTER_MYPORT --socket=$MASTER_MYSOCK --user=root --password=$DBPASSWD" export MYSQL MYSQL_CHECK MYSQL_DUMP MYSQL_DUMP_SLAVE MYSQL_SHOW MYSQL_BINLOG MYSQL_FIX_SYSTEM_TABLES MYSQL_IMPORT export CLIENT_BINDIR MYSQL_CLIENT_TEST CHARSETSDIR MYSQL_MY_PRINT_DEFAULTS export MYSQL_SLAP @@ -1263,8 +1276,8 @@ start_ndbcluster() rm_ndbcluster_tables() { - $RM -f $1/cluster/apply_status* - $RM -f $1/cluster/schema* + $RM -f $1/mysql/apply_status* + $RM -f $1/mysql/schema* } stop_ndbcluster() @@ -1406,7 +1419,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; @@ -1563,7 +1576,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; @@ -2164,12 +2177,15 @@ then # Remove files that can cause problems $RM -rf $MYSQL_TEST_DIR/var/ndbcluster $RM -rf $MYSQL_TEST_DIR/var/tmp/snapshot* - $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 fe97c7fa8ad..6ec55c5f4d6 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; @@ -199,6 +198,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; @@ -213,6 +213,11 @@ 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; @@ -220,6 +225,7 @@ our $opt_ndbconnectstring_slave; our $opt_record; our $opt_check_testcases; +my $opt_report_features; our $opt_skip; our $opt_skip_rpl; @@ -312,6 +318,7 @@ our %mysqld_variables; sub main (); sub initial_setup (); sub command_line_setup (); +sub set_mtr_build_thread_ports($); sub datadir_setup (); sub executable_setup (); sub environment_setup (); @@ -426,17 +433,20 @@ sub main () { if ( ! $need_im ) { $opt_skip_im= 1; - } + } initialize_servers(); + if ( $opt_report_features ) { + run_report_features(); + } + run_suite($opt_suite, $tests); } mtr_exit(0); } - ############################################################################## # # Default settings @@ -450,45 +460,17 @@ 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; + $im_port= 9312; + $im_mysqld1_port= 9313; + $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; - } - - 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)"); + set_mtr_build_thread_ports($ENV{'MTR_BUILD_THREAD'}); } # This is needed for test log evaluation in "gen-build-status-page" @@ -540,6 +522,7 @@ 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, @@ -591,9 +574,10 @@ sub command_line_setup () { 'tmpdir=s' => \$opt_tmpdir, 'vardir=s' => \$opt_vardir, 'benchdir=s' => \$glob_mysql_bench_dir, - 'mem' => \$opt_mem, + 'mem:s' => \$opt_mem, # Misc + 'report-features' => \$opt_report_features, 'comment=s' => \$opt_comment, 'debug' => \$opt_debug, 'fast' => \$opt_fast, @@ -621,6 +605,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) @@ -637,7 +630,7 @@ sub command_line_setup () { $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 ) { @@ -645,11 +638,27 @@ 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 ( ! $opt_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; @@ -677,7 +686,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(); @@ -734,24 +744,25 @@ sub command_line_setup () { # -------------------------------------------------------------------------- # Check if we should speed up tests by trying to run on tmpfs # -------------------------------------------------------------------------- - if ( $opt_mem ) + if ( defined $opt_mem ) { mtr_error("Can't use --mem and --vardir at the same time ") if $opt_vardir; mtr_error("Can't use --mem and --tmpdir at the same time ") if $opt_tmpdir; - # Use /dev/shm as the preferred location for vardir and - # thus implicitly also tmpdir. Add other locations to list - my @tmpfs_locations= ($opt_mem, "/dev/shm"); - # One could maybe use "mount" to find tmpfs location(s) + # Search through list of locations that are known + # to be "fast disks" to list to find a suitable location + # Use --mem=<dir> as first location to look. + my @tmpfs_locations= ($opt_mem, "/dev/shm", "/tmp"); + foreach my $fs (@tmpfs_locations) { if ( -d $fs ) { 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; } } @@ -793,6 +804,13 @@ sub command_line_setup () { $opt_vardir= "$glob_mysql_test_dir/$opt_vardir"; } + # Ensure a proper error message + mkpath("$opt_vardir"); + unless ( -d $opt_vardir and -w $opt_vardir ) + { + mtr_error("Writable 'var' directory is needed, use the '--vardir' option"); + } + # -------------------------------------------------------------------------- # Set tmpdir # -------------------------------------------------------------------------- @@ -1199,6 +1217,43 @@ sub command_line_setup () { $path_snapshot= "$opt_tmpdir/snapshot_$opt_master_myport/"; } +# +# 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; + + # 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 () { # Make a list of all data_dirs @@ -1314,7 +1369,9 @@ sub executable_setup_im () { $exe_im= mtr_exe_maybe_exists( "$glob_basedir/server-tools/instance-manager/mysqlmanager", - "$glob_basedir/libexec/mysqlmanager"); + "$glob_basedir/libexec/mysqlmanager", + "$glob_basedir/bin/mysqlmanager", + "$glob_basedir/sbin/mysqlmanager"); return ($exe_im eq ""); } @@ -1466,7 +1523,7 @@ sub executable_setup () { $exe_mysql_client_test= mtr_exe_maybe_exists(vs_config_dirs('tests', 'mysql_client_test'), "$glob_basedir/tests/mysql_client_test", - "$glob_basedir/bin"); + "$glob_basedir/bin/mysql_client_test"); } } @@ -1474,7 +1531,7 @@ sub executable_setup () { sub generate_cmdline_mysqldump ($) { my($mysqld) = @_; return - "$exe_mysqldump --no-defaults -uroot " . + "$exe_mysqldump --no-defaults --debug-info -uroot " . "--port=$mysqld->{'port'} " . "--socket=$mysqld->{'path_sock'} --password="; } @@ -1543,7 +1600,8 @@ sub environment_setup () { if ( $opt_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 { @@ -1614,7 +1672,7 @@ sub environment_setup () { $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; @@ -1675,7 +1733,7 @@ sub environment_setup () { # Setup env so childs can execute mysqlcheck # ---------------------------------------------------- my $cmdline_mysqlcheck= - "$exe_mysqlcheck --no-defaults -uroot " . + "$exe_mysqlcheck --no-defaults --debug-info -uroot " . "--port=$master->[0]->{'port'} " . "--socket=$master->[0]->{'path_sock'} --password="; @@ -1726,7 +1784,7 @@ sub environment_setup () { # Setup env so childs can execute mysqlimport # ---------------------------------------------------- my $cmdline_mysqlimport= - "$exe_mysqlimport -uroot " . + "$exe_mysqlimport --debug-info -uroot " . "--port=$master->[0]->{'port'} " . "--socket=$master->[0]->{'path_sock'} --password="; @@ -1742,7 +1800,7 @@ sub environment_setup () { # Setup env so childs can execute mysqlshow # ---------------------------------------------------- my $cmdline_mysqlshow= - "$exe_mysqlshow -uroot " . + "$exe_mysqlshow --debug-info -uroot " . "--port=$master->[0]->{'port'} " . "--socket=$master->[0]->{'path_sock'} --password="; @@ -1758,7 +1816,7 @@ sub environment_setup () { # ---------------------------------------------------- my $cmdline_mysqlbinlog= "$exe_mysqlbinlog" . - " --no-defaults --local-load=$opt_tmpdir"; + " --no-defaults --debug-info --local-load=$opt_tmpdir"; if ( $mysql_version_id >= 50000 ) { $cmdline_mysqlbinlog .=" --character-sets-dir=$path_charsetsdir"; @@ -1775,7 +1833,7 @@ sub environment_setup () { # Setup env so childs can execute mysql # ---------------------------------------------------- my $cmdline_mysql= - "$exe_mysql --no-defaults --host=localhost --user=root --password= " . + "$exe_mysql --no-defaults --debug-info --host=localhost --user=root --password= " . "--port=$master->[0]->{'port'} " . "--socket=$master->[0]->{'path_sock'} ". "--character-sets-dir=$path_charsetsdir"; @@ -2012,6 +2070,12 @@ sub cleanup_stale_files () { } closedir(DIR); } + + # Remove old log files + foreach my $name (glob("r/*.progress r/*.log r/*.warnings")) + { + unlink($name); + } } @@ -2392,8 +2456,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); } @@ -2953,10 +3017,6 @@ sub do_after_run_mysqltest($) # Save info from this testcase run to mysqltest.log mtr_appendfile_to_file($path_timefile, $path_mysqltest_log) if -f $path_timefile; - - # Remove the file that mysqltest writes info to - unlink($path_timefile); - } @@ -2964,14 +3024,14 @@ 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; @@ -2996,9 +3056,9 @@ sub analyze_testcase_failure_sync_with_master($) mtr_add_arg($args, "--no-defaults"); mtr_add_arg($args, "--silent"); - mtr_add_arg($args, "-v"); mtr_add_arg($args, "--skip-safemalloc"); mtr_add_arg($args, "--tmpdir=%s", $opt_tmpdir); + mtr_add_arg($args, "--character-sets-dir=%s", $path_charsetsdir); mtr_add_arg($args, "--socket=%s", $master->[0]->{'path_sock'}); mtr_add_arg($args, "--port=%d", $master->[0]->{'port'}); @@ -3106,6 +3166,9 @@ sub run_testcase ($) { my $res= run_mysqltest($tinfo); mtr_report_test_name($tinfo); + + do_after_run_mysqltest($tinfo); + if ( $res == 0 ) { mtr_report_test_passed($tinfo); @@ -3139,10 +3202,11 @@ sub run_testcase ($) { "mysqltest returned unexpected code $res, it has probably crashed"; report_failure_and_restart($tinfo); } - - do_after_run_mysqltest($tinfo); } + # Remove the file that mysqltest writes info to + unlink($path_timefile); + # ---------------------------------------------------------------------- # Stop Instance Manager if we are processing an IM-test case. # ---------------------------------------------------------------------- @@ -4063,12 +4127,12 @@ 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; } } @@ -4181,9 +4245,9 @@ sub run_check_testcase ($$) { mtr_add_arg($args, "--no-defaults"); mtr_add_arg($args, "--silent"); - mtr_add_arg($args, "-v"); mtr_add_arg($args, "--skip-safemalloc"); mtr_add_arg($args, "--tmpdir=%s", $opt_tmpdir); + mtr_add_arg($args, "--character-sets-dir=%s", $path_charsetsdir); mtr_add_arg($args, "--socket=%s", $mysqld->{'path_sock'}); mtr_add_arg($args, "--port=%d", $mysqld->{'port'}); @@ -4216,6 +4280,43 @@ sub run_check_testcase ($$) { return $res; } +############################################################################## +# +# Report the features that were compiled in +# +############################################################################## + +sub run_report_features () { + my $args; + + if ( ! $glob_use_embedded_server ) + { + mysqld_start($master->[0],[],[]); + if ( ! $master->[0]->{'pid'} ) + { + mtr_error("Can't start the mysqld server"); + } + mysqld_wait_started($master->[0]); + } + + my $tinfo = {}; + $tinfo->{'name'} = 'report features'; + $tinfo->{'result_file'} = undef; + $tinfo->{'component_id'} = 'mysqld'; + $tinfo->{'path'} = 'include/report-features.test'; + $tinfo->{'timezone'}= "GMT-3"; + $tinfo->{'slave_num'} = 0; + $tinfo->{'master_opt'} = []; + $tinfo->{'slave_opt'} = []; + $tinfo->{'slave_mi'} = []; + $tinfo->{'comment'} = 'report server features'; + run_mysqltest($tinfo); + + if ( ! $glob_use_embedded_server ) + { + stop_all_servers(); + } +} sub run_mysqltest ($) { @@ -4227,9 +4328,10 @@ sub run_mysqltest ($) { mtr_add_arg($args, "--no-defaults"); mtr_add_arg($args, "--silent"); - mtr_add_arg($args, "-v"); mtr_add_arg($args, "--skip-safemalloc"); mtr_add_arg($args, "--tmpdir=%s", $opt_tmpdir); + mtr_add_arg($args, "--character-sets-dir=%s", $path_charsetsdir); + mtr_add_arg($args, "--logdir=%s/log", $opt_vardir); if ($tinfo->{'component_id'} eq 'im') { @@ -4314,13 +4416,11 @@ sub run_mysqltest ($) { if ( $opt_ssl ) { # Turn on SSL for _all_ test cases if option --ssl was used - mtr_add_arg($args, "--ssl", - $glob_mysql_test_dir); + mtr_add_arg($args, "--ssl"); } elsif ( $opt_ssl_supported ) { - mtr_add_arg($args, "--skip-ssl", - $glob_mysql_test_dir); + mtr_add_arg($args, "--skip-ssl"); } # ---------------------------------------------------------------------- @@ -4355,8 +4455,10 @@ sub run_mysqltest ($) { mtr_add_arg($args, "--test-file"); mtr_add_arg($args, $tinfo->{'path'}); - mtr_add_arg($args, "--result-file"); - mtr_add_arg($args, $tinfo->{'result_file'}); + if ( defined $tinfo->{'result_file'} ) { + mtr_add_arg($args, "--result-file"); + mtr_add_arg($args, $tinfo->{'result_file'}); + } if ( $opt_record ) { @@ -4654,9 +4756,12 @@ Options to control directories to use vardir=DIR The directory where files generated from the test run is stored (default: ./var). Specifying a ramdisk or tmpfs will speed up tests. - mem Run testsuite in "memory" using tmpfs if - available(default: /dev/shm) - reads path from MTR_MEM environment variable + mem[=DIR] Run testsuite in "memory" using tmpfs or ramdisk + Attempts to use DIR first if specified else + uses as builtin list of standard locations + for tmpfs (/dev/shm) + The option can also be set using environment + variable MTR_MEM=[DIR] Options to control what test suites or cases to run @@ -4681,6 +4786,8 @@ 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 diff --git a/mysql-test/r/1st.result b/mysql-test/r/1st.result new file mode 100644 index 00000000000..7e35f1a7ce6 --- /dev/null +++ b/mysql-test/r/1st.result @@ -0,0 +1,29 @@ +show databases; +Database +information_schema +mysql +test +show tables in mysql; +Tables_in_mysql +binlog_index +columns_priv +db +event +func +general_log +help_category +help_keyword +help_relation +help_topic +host +plugin +proc +procs_priv +slow_log +tables_priv +time_zone +time_zone_leap_second +time_zone_name +time_zone_transition +time_zone_transition_type +user diff --git a/mysql-test/r/archive.result b/mysql-test/r/archive.result index 1dfec8ff713..bf730908d35 100644 --- a/mysql-test/r/archive.result +++ b/mysql-test/r/archive.result @@ -13820,4 +13820,31 @@ i v 2 abc 4 3r4f 5 lmn +DROP TABLE t5; +CREATE TABLE `t5` ( +`a` int(11) NOT NULL auto_increment, +b varchar(250), +c varchar(800), +KEY (`a`) +) ENGINE=ARCHIVE DEFAULT CHARSET=latin1; +INSERT INTO t5 VALUES (NULL, "foo", "grok this!"); +INSERT INTO t5 VALUES (NULL, "We the people", NULL); +INSERT INTO t5 VALUES (NULL, "in order to form a more peefect union", "secure the blessing of liberty"); +INSERT INTO t5 VALUES (NULL, "establish justice", "to ourselves and"); +INSERT INTO t5 VALUES (32, "ensure domestic tranquility", NULL); +INSERT INTO t5 VALUES (23, "provide for the common defense", "posterity"); +INSERT INTO t5 VALUES (NULL, "promote the general welfare", "do ordain"); +INSERT INTO t5 VALUES (NULL, "abcdeghijklmnopqrstuvwxyzabcdeghijklmnopqrstuvwxyzabcdeghijklmnopqrstuvwxyzabcdeghijklmnopqrstuvwxyzabcdeghijklmnopqrstuvwxyzabcdeghijklmnopqrstuvwxyzabcdeghijklmnopqrstuvwxyzabcdeghijklmnopqrstuvwxyzabcdeghijklmnopqrstuvwxyzabcdeghijklmnopqrstuvwxyzabc", "do ordain"); +Warnings: +Warning 1265 Data truncated for column 'b' at row 1 +SELECT * FROM t5; +a b c +1 foo grok this! +2 We the people NULL +3 in order to form a more peefect union secure the blessing of liberty +4 establish justice to ourselves and +32 ensure domestic tranquility NULL +23 provide for the common defense posterity +33 promote the general welfare do ordain +34 abcdeghijklmnopqrstuvwxyzabcdeghijklmnopqrstuvwxyzabcdeghijklmnopqrstuvwxyzabcdeghijklmnopqrstuvwxyzabcdeghijklmnopqrstuvwxyzabcdeghijklmnopqrstuvwxyzabcdeghijklmnopqrstuvwxyzabcdeghijklmnopqrstuvwxyzabcdeghijklmnopqrstuvwxyzabcdeghijklmnopqrstuvwxyz do ordain drop table t1, t2, t4, t5; diff --git a/mysql-test/r/binlog_row_binlog.result b/mysql-test/r/binlog_row_binlog.result index 7cbfa525798..aee270bd7f6 100644 --- a/mysql-test/r/binlog_row_binlog.result +++ b/mysql-test/r/binlog_row_binlog.result @@ -245,6 +245,24 @@ select * from t1; id 127 drop table t1; +create table t1 (a int); +create table if not exists t2 select * from t1; +create temporary table tt1 (a int); +create table if not exists t3 like tt1; +show binlog events from 102; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query 1 # use `test`; create table t1 (id tinyint auto_increment primary key) +master-bin.000001 # Table_map 1 # table_id: # (test.t1) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Query 1 # use `test`; drop table t1 +master-bin.000001 # Query 1 # use `test`; create table t1 (a int) +master-bin.000001 # Query 1 # use `test`; CREATE TABLE IF NOT EXISTS `t2` ( + `a` int(11) DEFAULT NULL +) +master-bin.000001 # Query 1 # use `test`; CREATE TABLE IF NOT EXISTS `t3` ( + `a` int(11) DEFAULT NULL +) +drop table t1,t2,t3,tt1; create table t1 (a int not null auto_increment, primary key (a)) engine=myisam; set @@session.auto_increment_increment=1, @@session.auto_increment_offset=1; insert delayed into t1 values (207); @@ -256,6 +274,14 @@ master-bin.000001 # Query 1 # use `test`; create table t1 (id tinyint auto_incre master-bin.000001 # Table_map 1 # table_id: # (test.t1) master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F master-bin.000001 # Query 1 # use `test`; drop table t1 +master-bin.000001 # Query 1 # use `test`; create table t1 (a int) +master-bin.000001 # Query 1 # use `test`; CREATE TABLE IF NOT EXISTS `t2` ( + `a` int(11) DEFAULT NULL +) +master-bin.000001 # Query 1 # use `test`; CREATE TABLE IF NOT EXISTS `t3` ( + `a` int(11) DEFAULT NULL +) +master-bin.000001 # Query 1 # use `test`; DROP TABLE `t1`,`t2`,`t3` /* generated by server */ master-bin.000001 # Query 1 # use `test`; create table t1 (a int not null auto_increment, primary key (a)) engine=myisam master-bin.000001 # Table_map 1 # table_id: # (test.t1) master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F diff --git a/mysql-test/r/binlog_stm_binlog.result b/mysql-test/r/binlog_stm_binlog.result index eed2df28d1f..a9b3f69ecee 100644 --- a/mysql-test/r/binlog_stm_binlog.result +++ b/mysql-test/r/binlog_stm_binlog.result @@ -155,6 +155,21 @@ select * from t1; id 127 drop table t1; +create table t1 (a int); +create table if not exists t2 select * from t1; +create temporary table tt1 (a int); +create table if not exists t3 like tt1; +show binlog events from 102; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query 1 # use `test`; create table t1 (id tinyint auto_increment primary key) +master-bin.000001 # Intvar 1 # INSERT_ID=127 +master-bin.000001 # Query 1 # use `test`; insert into t1 values(null) +master-bin.000001 # Query 1 # use `test`; drop table t1 +master-bin.000001 # Query 1 # use `test`; create table t1 (a int) +master-bin.000001 # Query 1 # use `test`; create table if not exists t2 select * from t1 +master-bin.000001 # Query 1 # use `test`; create temporary table tt1 (a int) +master-bin.000001 # Query 1 # use `test`; create table if not exists t3 like tt1 +drop table t1,t2,t3,tt1; create table t1 (a int not null auto_increment, primary key (a)) engine=myisam; set @@session.auto_increment_increment=1, @@session.auto_increment_offset=1; insert delayed into t1 values (207); @@ -166,6 +181,11 @@ master-bin.000001 # Query 1 # use `test`; create table t1 (id tinyint auto_incre master-bin.000001 # Intvar 1 # INSERT_ID=127 master-bin.000001 # Query 1 # use `test`; insert into t1 values(null) master-bin.000001 # Query 1 # use `test`; drop table t1 +master-bin.000001 # Query 1 # use `test`; create table t1 (a int) +master-bin.000001 # Query 1 # use `test`; create table if not exists t2 select * from t1 +master-bin.000001 # Query 1 # use `test`; create temporary table tt1 (a int) +master-bin.000001 # Query 1 # use `test`; create table if not exists t3 like tt1 +master-bin.000001 # Query 1 # use `test`; drop table t1,t2,t3,tt1 master-bin.000001 # Query 1 # use `test`; create table t1 (a int not null auto_increment, primary key (a)) engine=myisam master-bin.000001 # Table_map 1 # table_id: # (test.t1) master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F diff --git a/mysql-test/r/cache_innodb.result b/mysql-test/r/cache_innodb.result index 7f9b3e279a9..17cfcd69ec3 100644 --- a/mysql-test/r/cache_innodb.result +++ b/mysql-test/r/cache_innodb.result @@ -128,3 +128,94 @@ select t1.* from t1, t2, t3 where t3.state & 1 = 0 and t3.t1_id = t1.id and t3.t id a 1 me drop table t3,t2,t1; +SET SESSION STORAGE_ENGINE = InnoDB; +SET @@autocommit=1; +connection default +SHOW VARIABLES LIKE 'have_query_cache'; +Variable_name Value +have_query_cache YES +SET GLOBAL query_cache_size = 200000; +flush status; +SET @@autocommit=1; +SET SESSION STORAGE_ENGINE = InnoDB; +CREATE TABLE t2 (s1 int, s2 varchar(1000), key(s1)); +INSERT INTO t2 VALUES (1,repeat('a',10)),(2,repeat('a',10)),(3,repeat('a',10)),(4,repeat('a',10)); +COMMIT; +START TRANSACTION; +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +count(*) +0 +UPDATE t2 SET s2 = 'w' WHERE s1 = 3; +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +count(*) +1 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +connection connection1 +START TRANSACTION; +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +count(*) +0 +INSERT INTO t2 VALUES (5,'w'); +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +count(*) +1 +COMMIT; +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +count(*) +1 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +connection default +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +count(*) +1 +COMMIT; +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +count(*) +2 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +connection connection1 +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +count(*) +2 +START TRANSACTION; +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +count(*) +2 +INSERT INTO t2 VALUES (6,'w'); +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +count(*) +3 +connection default +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +count(*) +2 +START TRANSACTION; +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +count(*) +2 +DELETE from t2 WHERE s1=3; +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +count(*) +1 +COMMIT; +connection connection1 +COMMIT; +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +count(*) +2 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 2 +drop table t2; diff --git a/mysql-test/r/connect.result b/mysql-test/r/connect.result index 862260346f5..08710217afc 100644 --- a/mysql-test/r/connect.result +++ b/mysql-test/r/connect.result @@ -1,6 +1,7 @@ drop table if exists t1,t2; show tables; Tables_in_mysql +binlog_index columns_priv db event @@ -32,6 +33,7 @@ grant ALL on *.* to test@localhost identified by "gambling"; grant ALL on *.* to test@127.0.0.1 identified by "gambling"; show tables; Tables_in_mysql +binlog_index columns_priv db event @@ -71,6 +73,7 @@ ERROR HY000: Password hash should be a 41-digit hexadecimal number set password=old_password('gambling3'); show tables; Tables_in_mysql +binlog_index columns_priv db event diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index 5bc28e9eee5..7bef6c2efba 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -820,3 +820,19 @@ SELECT * from t2; a b 1 1 drop table t1,t2; +CREATE DATABASE aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; +ERROR 42000: Incorrect database name 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' +DROP DATABASE aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; +ERROR 42000: Incorrect database name 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' +RENAME DATABASE aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa TO a; +ERROR 42000: Unknown database 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' +RENAME DATABASE mysqltest TO aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; +ERROR 42000: Incorrect database name 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' +create database mysqltest; +RENAME DATABASE mysqltest TO aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; +ERROR 42000: Incorrect database name 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' +drop database mysqltest; +USE aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; +ERROR 42000: Incorrect database name 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' +SHOW CREATE DATABASE aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; +ERROR 42000: Incorrect database name 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' diff --git a/mysql-test/r/ctype_cp1250_ch.result b/mysql-test/r/ctype_cp1250_ch.result index 007d6103b8a..4b02fa2182a 100644 --- a/mysql-test/r/ctype_cp1250_ch.result +++ b/mysql-test/r/ctype_cp1250_ch.result @@ -1,4 +1,5 @@ drop table if exists t1; +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_create.result b/mysql-test/r/ctype_create.result index 8a81991ea78..35461fce45a 100644 --- a/mysql-test/r/ctype_create.result +++ b/mysql-test/r/ctype_create.result @@ -72,3 +72,7 @@ mysqltest2 CREATE DATABASE `mysqltest2` /*!40100 DEFAULT CHARACTER SET latin2 */ drop database mysqltest2; ALTER DATABASE DEFAULT CHARACTER SET latin2; ERROR 3D000: No database selected +ALTER DATABASE aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa DEFAULT CHARACTER SET latin2; +ERROR 42000: Incorrect database name 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' +ALTER DATABASE `` DEFAULT CHARACTER SET latin2; +ERROR 42000: Incorrect database name '' diff --git a/mysql-test/r/ctype_recoding.result b/mysql-test/r/ctype_recoding.result index d0087b03c17..e85d379c932 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 4f08b97492f..a65b19695ec 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 4ae19fc8f7c..4aa22944b9b 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/drop.result b/mysql-test/r/drop.result index 24f1b654733..ff11905aa34 100644 --- a/mysql-test/r/drop.result +++ b/mysql-test/r/drop.result @@ -47,7 +47,6 @@ create database mysqltest; show databases; Database information_schema -cluster mysql mysqltest test @@ -59,7 +58,6 @@ drop database mysqltest; show databases; Database information_schema -cluster mysql test drop database mysqltest; diff --git a/mysql-test/r/events.result b/mysql-test/r/events.result index abf6879fc3c..af864c57efa 100644 --- a/mysql-test/r/events.result +++ b/mysql-test/r/events.result @@ -394,4 +394,10 @@ create trigger t1_ai after insert on t1 for each row show create event e1; ERROR 0A000: Not allowed to return a result set from a trigger drop table t1; drop event e1; +SHOW EVENTS FROM aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; +ERROR 42000: Incorrect database name 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' +SHOW EVENTS FROM ``; +ERROR 42000: Incorrect database name '' +SHOW EVENTS FROM `events\\test`; +Db Name Definer Type Execute at Interval value Interval field Starts Ends Status drop database events_test; diff --git a/mysql-test/r/fulltext.result b/mysql-test/r/fulltext.result index 457155b4299..829cf25a896 100644 --- a/mysql-test/r/fulltext.result +++ b/mysql-test/r/fulltext.result @@ -381,10 +381,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 619c8dafeae..57b0a2aec25 100644 --- a/mysql-test/r/func_gconcat.result +++ b/mysql-test/r/func_gconcat.result @@ -664,3 +664,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 40ca0a38db2..8158cab4323 100644 --- a/mysql-test/r/func_group.result +++ b/mysql-test/r/func_group.result @@ -1020,3 +1020,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 b88e5a66f96..6578af7cd8b 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); @@ -343,6 +351,7 @@ some_id 1 2 drop table t1; +End of 5.0 tests create table t1(f1 char(1)); insert into t1 values ('a'),('b'),('1'); select f1 from t1 where f1 in ('a',1); @@ -411,3 +420,4 @@ explain select f2 from t2 where f2 in (1,'b'); id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 index NULL t2f2 5 NULL 3 Using where; Using index drop table t1, t2; +End of 5.1 tests diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index d85d3eabe5e..4e63d4d8482 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -813,11 +813,231 @@ drop table t7; select substring_index("1abcd;2abcd;3abcd;4abcd", ';', 2),substring_index("1abcd;2abcd;3abcd;4abcd", ';', -2); substring_index("1abcd;2abcd;3abcd;4abcd", ';', 2) substring_index("1abcd;2abcd;3abcd;4abcd", ';', -2) 1abcd;2abcd 3abcd;4abcd -explain extended select md5('hello'), sha('abc'), sha1('abc'), soundex(''), 'mood' sounds like 'mud', aes_decrypt(aes_encrypt('abc','1'),'1'),concat('*',space(5),'*'), reverse('abc'), rpad('a',4,'1'), lpad('a',4,'1'), concat_ws(',','',NULL,'a'),make_set(255,_latin2'a',_latin2'b',_latin2'c'),elt(2,1),locate("a","b",2),format(130,10),char(0),conv(130,16,10),hex(130),binary 'HE', export_set(255,_latin2'y',_latin2'n',_latin2' '),FIELD('b' COLLATE latin1_bin,'A','B'),FIND_IN_SET(_latin1'B',_latin1'a,b,c,d'),collation(conv(130,16,10)), coercibility(conv(130,16,10)),length('\n\t\r\b\0\_\%\\'),bit_length('\n\t\r\b\0\_\%\\'),bit_length('\n\t\r\b\0\_\%\\'),concat('monty',' was here ','again'),length('hello'),char(ascii('h')),ord('h'),quote(1/0),crc32("123"),replace('aaaa','a','b'),insert('txs',2,1,'hi'),left(_latin2'a',1),right(_latin2'a',1),lcase(_latin2'a'),ucase(_latin2'a'),SUBSTR('abcdefg',3,2),substring_index("1abcd;2abcd;3abcd;4abcd", ';', 2),trim(_latin2' a '),ltrim(_latin2' a '),rtrim(_latin2' a '), decode(encode(repeat("a",100000),"monty"),"monty"); +explain extended select md5('hello'); id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: -Note 1003 select md5(_latin1'hello') AS `md5('hello')`,sha(_latin1'abc') AS `sha('abc')`,sha(_latin1'abc') AS `sha1('abc')`,soundex(_latin1'') AS `soundex('')`,(soundex(_latin1'mood') = soundex(_latin1'mud')) AS `'mood' sounds like 'mud'`,aes_decrypt(aes_encrypt(_latin1'abc',_latin1'1'),_latin1'1') AS `aes_decrypt(aes_encrypt('abc','1'),'1')`,concat(_latin1'*',repeat(_latin1' ',5),_latin1'*') AS `concat('*',space(5),'*')`,reverse(_latin1'abc') AS `reverse('abc')`,rpad(_latin1'a',4,_latin1'1') AS `rpad('a',4,'1')`,lpad(_latin1'a',4,_latin1'1') AS `lpad('a',4,'1')`,concat_ws(_latin1',',_latin1'',NULL,_latin1'a') AS `concat_ws(',','',NULL,'a')`,make_set(255,_latin2'a',_latin2'b',_latin2'c') AS `make_set(255,_latin2'a',_latin2'b',_latin2'c')`,elt(2,1) AS `elt(2,1)`,locate(_latin1'a',_latin1'b',2) AS `locate("a","b",2)`,format(130,10) AS `format(130,10)`,char(0) AS `char(0)`,conv(130,16,10) AS `conv(130,16,10)`,hex(130) AS `hex(130)`,cast(_latin1'HE' as char charset binary) AS `binary 'HE'`,export_set(255,_latin2'y',_latin2'n',_latin2' ') AS `export_set(255,_latin2'y',_latin2'n',_latin2' ')`,field((_latin1'b' collate latin1_bin),_latin1'A',_latin1'B') AS `FIELD('b' COLLATE latin1_bin,'A','B')`,find_in_set(_latin1'B',_latin1'a,b,c,d') AS `FIND_IN_SET(_latin1'B',_latin1'a,b,c,d')`,collation(conv(130,16,10)) AS `collation(conv(130,16,10))`,coercibility(conv(130,16,10)) AS `coercibility(conv(130,16,10))`,length(_latin1'\n \r\0\\_\\%\\') AS `length('\n\t\r\b\0\_\%\\')`,bit_length(_latin1'\n \r\0\\_\\%\\') AS `bit_length('\n\t\r\b\0\_\%\\')`,bit_length(_latin1'\n \r\0\\_\\%\\') AS `bit_length('\n\t\r\b\0\_\%\\')`,concat(_latin1'monty',_latin1' was here ',_latin1'again') AS `concat('monty',' was here ','again')`,length(_latin1'hello') AS `length('hello')`,char(ascii(_latin1'h')) AS `char(ascii('h'))`,ord(_latin1'h') AS `ord('h')`,quote((1 / 0)) AS `quote(1/0)`,crc32(_latin1'123') AS `crc32("123")`,replace(_latin1'aaaa',_latin1'a',_latin1'b') AS `replace('aaaa','a','b')`,insert(_latin1'txs',2,1,_latin1'hi') AS `insert('txs',2,1,'hi')`,left(_latin2'a',1) AS `left(_latin2'a',1)`,right(_latin2'a',1) AS `right(_latin2'a',1)`,lcase(_latin2'a') AS `lcase(_latin2'a')`,ucase(_latin2'a') AS `ucase(_latin2'a')`,substr(_latin1'abcdefg',3,2) AS `SUBSTR('abcdefg',3,2)`,substring_index(_latin1'1abcd;2abcd;3abcd;4abcd',_latin1';',2) AS `substring_index("1abcd;2abcd;3abcd;4abcd", ';', 2)`,trim(_latin2' a ') AS `trim(_latin2' a ')`,ltrim(_latin2' a ') AS `ltrim(_latin2' a ')`,rtrim(_latin2' a ') AS `rtrim(_latin2' a ')`,decode(encode(repeat(_latin1'a',100000))) AS `decode(encode(repeat("a",100000),"monty"),"monty")` +Note 1003 select md5(_latin1'hello') AS `md5('hello')` +explain extended select sha('abc'); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select sha(_latin1'abc') AS `sha('abc')` +explain extended select sha1('abc'); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select sha(_latin1'abc') AS `sha1('abc')` +explain extended select soundex(''); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select soundex(_latin1'') AS `soundex('')` +explain extended select 'mood' sounds like 'mud'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select (soundex(_latin1'mood') = soundex(_latin1'mud')) AS `'mood' sounds like 'mud'` +explain extended select aes_decrypt(aes_encrypt('abc','1'),'1'); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select aes_decrypt(aes_encrypt(_latin1'abc',_latin1'1'),_latin1'1') AS `aes_decrypt(aes_encrypt('abc','1'),'1')` +explain extended select concat('*',space(5),'*'); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select concat(_latin1'*',repeat(_latin1' ',5),_latin1'*') AS `concat('*',space(5),'*')` +explain extended select reverse('abc'); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select reverse(_latin1'abc') AS `reverse('abc')` +explain extended select rpad('a',4,'1'); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select rpad(_latin1'a',4,_latin1'1') AS `rpad('a',4,'1')` +explain extended select lpad('a',4,'1'); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select lpad(_latin1'a',4,_latin1'1') AS `lpad('a',4,'1')` +explain extended select concat_ws(',','',NULL,'a'); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select concat_ws(_latin1',',_latin1'',NULL,_latin1'a') AS `concat_ws(',','',NULL,'a')` +explain extended select make_set(255,_latin2'a', _latin2'b', _latin2'c'); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select make_set(255,_latin2'a',_latin2'b',_latin2'c') AS `make_set(255,_latin2'a', _latin2'b', _latin2'c')` +explain extended select elt(2,1); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select elt(2,1) AS `elt(2,1)` +explain extended select locate("a","b",2); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select locate(_latin1'a',_latin1'b',2) AS `locate("a","b",2)` +explain extended select format(130,10); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select format(130,10) AS `format(130,10)` +explain extended select char(0); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select char(0) AS `char(0)` +explain extended select conv(130,16,10); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select conv(130,16,10) AS `conv(130,16,10)` +explain extended select hex(130); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select hex(130) AS `hex(130)` +explain extended select binary 'HE'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select cast(_latin1'HE' as char charset binary) AS `binary 'HE'` +explain extended select export_set(255,_latin2'y', _latin2'n', _latin2' '); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select export_set(255,_latin2'y',_latin2'n',_latin2' ') AS `export_set(255,_latin2'y', _latin2'n', _latin2' ')` +explain extended select FIELD('b' COLLATE latin1_bin,'A','B'); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select field((_latin1'b' collate latin1_bin),_latin1'A',_latin1'B') AS `FIELD('b' COLLATE latin1_bin,'A','B')` +explain extended select FIND_IN_SET(_latin1'B', _latin1'a,b,c,d'); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select find_in_set(_latin1'B',_latin1'a,b,c,d') AS `FIND_IN_SET(_latin1'B', _latin1'a,b,c,d')` +explain extended select collation(conv(130,16,10)); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select collation(conv(130,16,10)) AS `collation(conv(130,16,10))` +explain extended select coercibility(conv(130,16,10)); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select coercibility(conv(130,16,10)) AS `coercibility(conv(130,16,10))` +explain extended select length('\n\t\r\b\0\_\%\\'); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select length(_latin1'\n \r\0\\_\\%\\') AS `length('\n\t\r\b\0\_\%\\')` +explain extended select bit_length('\n\t\r\b\0\_\%\\'); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select bit_length(_latin1'\n \r\0\\_\\%\\') AS `bit_length('\n\t\r\b\0\_\%\\')` +explain extended select bit_length('\n\t\r\b\0\_\%\\'); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select bit_length(_latin1'\n \r\0\\_\\%\\') AS `bit_length('\n\t\r\b\0\_\%\\')` +explain extended select concat('monty',' was here ','again'); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select concat(_latin1'monty',_latin1' was here ',_latin1'again') AS `concat('monty',' was here ','again')` +explain extended select length('hello'); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select length(_latin1'hello') AS `length('hello')` +explain extended select char(ascii('h')); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select char(ascii(_latin1'h')) AS `char(ascii('h'))` +explain extended select ord('h'); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select ord(_latin1'h') AS `ord('h')` +explain extended select quote(1/0); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select quote((1 / 0)) AS `quote(1/0)` +explain extended select crc32("123"); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select crc32(_latin1'123') AS `crc32("123")` +explain extended select replace('aaaa','a','b'); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select replace(_latin1'aaaa',_latin1'a',_latin1'b') AS `replace('aaaa','a','b')` +explain extended select insert('txs',2,1,'hi'); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select insert(_latin1'txs',2,1,_latin1'hi') AS `insert('txs',2,1,'hi')` +explain extended select left(_latin2'a',1); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select left(_latin2'a',1) AS `left(_latin2'a',1)` +explain extended select right(_latin2'a',1); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select right(_latin2'a',1) AS `right(_latin2'a',1)` +explain extended select lcase(_latin2'a'); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select lcase(_latin2'a') AS `lcase(_latin2'a')` +explain extended select ucase(_latin2'a'); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select ucase(_latin2'a') AS `ucase(_latin2'a')` +explain extended select SUBSTR('abcdefg',3,2); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select substr(_latin1'abcdefg',3,2) AS `SUBSTR('abcdefg',3,2)` +explain extended select substring_index("1abcd;2abcd;3abcd;4abcd", ';', 2); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select substring_index(_latin1'1abcd;2abcd;3abcd;4abcd',_latin1';',2) AS `substring_index("1abcd;2abcd;3abcd;4abcd", ';', 2)` +explain extended select trim(_latin2' a '); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select trim(_latin2' a ') AS `trim(_latin2' a ')` +explain extended select ltrim(_latin2' a '); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select ltrim(_latin2' a ') AS `ltrim(_latin2' a ')` +explain extended select rtrim(_latin2' a '); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select rtrim(_latin2' a ') AS `rtrim(_latin2' a ')` +explain extended select decode(encode(repeat("a",100000),"monty"),"monty"); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select decode(encode(repeat(_latin1'a',100000),_latin1'monty'),_latin1'monty') AS `decode(encode(repeat("a",100000),"monty"),"monty")` SELECT lpad(12345, 5, "#"); lpad(12345, 5, "#") 12345 @@ -1148,4 +1368,885 @@ id select_type table type possible_keys key key_len ref rows filtered Extra Warnings: Note 1003 select `test`.`t1`.`code` AS `code`,`test`.`t2`.`id` AS `id` from `test`.`t1` join `test`.`t2` where ((`test`.`t1`.`code` = _latin1'a12') and (length(`test`.`t1`.`code`) = 5)) DROP TABLE t1,t2; +select encode(NULL, NULL); +encode(NULL, NULL) +NULL +select encode("data", NULL); +encode("data", NULL) +NULL +select encode(NULL, "password"); +encode(NULL, "password") +NULL +select decode(NULL, NULL); +decode(NULL, NULL) +NULL +select decode("data", NULL); +decode("data", NULL) +NULL +select decode(NULL, "password"); +decode(NULL, "password") +NULL +select format(NULL, NULL); +format(NULL, NULL) +NULL +select format(pi(), NULL); +format(pi(), NULL) +NULL +select format(NULL, 2); +format(NULL, 2) +NULL +select benchmark(NULL, NULL); +benchmark(NULL, NULL) +NULL +select benchmark(0, NULL); +benchmark(0, NULL) +0 +select benchmark(100, NULL); +benchmark(100, NULL) +0 +select benchmark(NULL, 1+1); +benchmark(NULL, 1+1) +NULL +set @password="password"; +set @my_data="clear text to encode"; +select md5(encode(@my_data, "password")); +md5(encode(@my_data, "password")) +44320fd2b4a0ec92faa2da2122def917 +select md5(encode(@my_data, _utf8 "password")); +md5(encode(@my_data, _utf8 "password")) +44320fd2b4a0ec92faa2da2122def917 +select md5(encode(@my_data, binary "password")); +md5(encode(@my_data, binary "password")) +44320fd2b4a0ec92faa2da2122def917 +select md5(encode(@my_data, _latin1 "password")); +md5(encode(@my_data, _latin1 "password")) +44320fd2b4a0ec92faa2da2122def917 +select md5(encode(@my_data, _koi8r "password")); +md5(encode(@my_data, _koi8r "password")) +44320fd2b4a0ec92faa2da2122def917 +select md5(encode(@my_data, (select "password" from dual))); +md5(encode(@my_data, (select "password" from dual))) +44320fd2b4a0ec92faa2da2122def917 +select md5(encode(@my_data, concat("pass", "word"))); +md5(encode(@my_data, concat("pass", "word"))) +44320fd2b4a0ec92faa2da2122def917 +select md5(encode(@my_data, @password)); +md5(encode(@my_data, @password)) +44320fd2b4a0ec92faa2da2122def917 +set @my_data="binary encoded data"; +select md5(decode(@my_data, "password")); +md5(decode(@my_data, "password")) +5bea8c394368dbc03b76684483b7756b +select md5(decode(@my_data, _utf8 "password")); +md5(decode(@my_data, _utf8 "password")) +5bea8c394368dbc03b76684483b7756b +select md5(decode(@my_data, binary "password")); +md5(decode(@my_data, binary "password")) +5bea8c394368dbc03b76684483b7756b +select md5(decode(@my_data, _latin1 "password")); +md5(decode(@my_data, _latin1 "password")) +5bea8c394368dbc03b76684483b7756b +select md5(decode(@my_data, _koi8r "password")); +md5(decode(@my_data, _koi8r "password")) +5bea8c394368dbc03b76684483b7756b +select md5(decode(@my_data, (select "password" from dual))); +md5(decode(@my_data, (select "password" from dual))) +5bea8c394368dbc03b76684483b7756b +select md5(decode(@my_data, concat("pass", "word"))); +md5(decode(@my_data, concat("pass", "word"))) +5bea8c394368dbc03b76684483b7756b +select md5(decode(@my_data, @password)); +md5(decode(@my_data, @password)) +5bea8c394368dbc03b76684483b7756b +set @dec=5; +select format(pi(), (1+1)); +format(pi(), (1+1)) +3.14 +select format(pi(), (select 3 from dual)); +format(pi(), (select 3 from dual)) +3.142 +select format(pi(), @dec); +format(pi(), @dec) +3.14159 +set @bench_count=10; +select benchmark(10, pi()); +benchmark(10, pi()) +0 +select benchmark(5+5, pi()); +benchmark(5+5, pi()) +0 +select benchmark((select 10 from dual), pi()); +benchmark((select 10 from dual), pi()) +0 +select benchmark(@bench_count, pi()); +benchmark(@bench_count, pi()) +0 +select locate('he','hello',-2); +locate('he','hello',-2) +0 +select locate('lo','hello',-4294967295); +locate('lo','hello',-4294967295) +0 +select locate('lo','hello',4294967295); +locate('lo','hello',4294967295) +0 +select locate('lo','hello',-4294967296); +locate('lo','hello',-4294967296) +0 +select locate('lo','hello',4294967296); +locate('lo','hello',4294967296) +0 +select locate('lo','hello',-4294967297); +locate('lo','hello',-4294967297) +0 +select locate('lo','hello',4294967297); +locate('lo','hello',4294967297) +0 +select locate('lo','hello',-18446744073709551615); +locate('lo','hello',-18446744073709551615) +0 +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +select locate('lo','hello',18446744073709551615); +locate('lo','hello',18446744073709551615) +0 +select locate('lo','hello',-18446744073709551616); +locate('lo','hello',-18446744073709551616) +0 +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +select locate('lo','hello',18446744073709551616); +locate('lo','hello',18446744073709551616) +0 +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +select locate('lo','hello',-18446744073709551617); +locate('lo','hello',-18446744073709551617) +0 +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +select locate('lo','hello',18446744073709551617); +locate('lo','hello',18446744073709551617) +0 +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +select left('hello', 10); +left('hello', 10) +hello +select left('hello', 0); +left('hello', 0) + +select left('hello', -1); +left('hello', -1) + +select left('hello', -4294967295); +left('hello', -4294967295) + +select left('hello', 4294967295); +left('hello', 4294967295) +hello +select left('hello', -4294967296); +left('hello', -4294967296) + +select left('hello', 4294967296); +left('hello', 4294967296) +hello +select left('hello', -4294967297); +left('hello', -4294967297) + +select left('hello', 4294967297); +left('hello', 4294967297) +hello +select left('hello', -18446744073709551615); +left('hello', -18446744073709551615) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select left('hello', 18446744073709551615); +left('hello', 18446744073709551615) +hello +select left('hello', -18446744073709551616); +left('hello', -18446744073709551616) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select left('hello', 18446744073709551616); +left('hello', 18446744073709551616) +hello +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select left('hello', -18446744073709551617); +left('hello', -18446744073709551617) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select left('hello', 18446744073709551617); +left('hello', 18446744073709551617) +hello +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select right('hello', 10); +right('hello', 10) +hello +select right('hello', 0); +right('hello', 0) + +select right('hello', -1); +right('hello', -1) + +select right('hello', -4294967295); +right('hello', -4294967295) + +select right('hello', 4294967295); +right('hello', 4294967295) +hello +select right('hello', -4294967296); +right('hello', -4294967296) + +select right('hello', 4294967296); +right('hello', 4294967296) +hello +select right('hello', -4294967297); +right('hello', -4294967297) + +select right('hello', 4294967297); +right('hello', 4294967297) +hello +select right('hello', -18446744073709551615); +right('hello', -18446744073709551615) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select right('hello', 18446744073709551615); +right('hello', 18446744073709551615) +hello +select right('hello', -18446744073709551616); +right('hello', -18446744073709551616) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select right('hello', 18446744073709551616); +right('hello', 18446744073709551616) +hello +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select right('hello', -18446744073709551617); +right('hello', -18446744073709551617) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select right('hello', 18446744073709551617); +right('hello', 18446744073709551617) +hello +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select substring('hello', 2, -1); +substring('hello', 2, -1) + +select substring('hello', -1, 1); +substring('hello', -1, 1) +o +select substring('hello', -2, 1); +substring('hello', -2, 1) +l +select substring('hello', -4294967295, 1); +substring('hello', -4294967295, 1) + +select substring('hello', 4294967295, 1); +substring('hello', 4294967295, 1) + +select substring('hello', -4294967296, 1); +substring('hello', -4294967296, 1) + +select substring('hello', 4294967296, 1); +substring('hello', 4294967296, 1) + +select substring('hello', -4294967297, 1); +substring('hello', -4294967297, 1) + +select substring('hello', 4294967297, 1); +substring('hello', 4294967297, 1) + +select substring('hello', -18446744073709551615, 1); +substring('hello', -18446744073709551615, 1) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select substring('hello', 18446744073709551615, 1); +substring('hello', 18446744073709551615, 1) + +select substring('hello', -18446744073709551616, 1); +substring('hello', -18446744073709551616, 1) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select substring('hello', 18446744073709551616, 1); +substring('hello', 18446744073709551616, 1) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select substring('hello', -18446744073709551617, 1); +substring('hello', -18446744073709551617, 1) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select substring('hello', 18446744073709551617, 1); +substring('hello', 18446744073709551617, 1) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select substring('hello', 1, -1); +substring('hello', 1, -1) + +select substring('hello', 1, -4294967295); +substring('hello', 1, -4294967295) + +select substring('hello', 1, 4294967295); +substring('hello', 1, 4294967295) +hello +select substring('hello', 1, -4294967296); +substring('hello', 1, -4294967296) + +select substring('hello', 1, 4294967296); +substring('hello', 1, 4294967296) +hello +select substring('hello', 1, -4294967297); +substring('hello', 1, -4294967297) + +select substring('hello', 1, 4294967297); +substring('hello', 1, 4294967297) +hello +select substring('hello', 1, -18446744073709551615); +substring('hello', 1, -18446744073709551615) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select substring('hello', 1, 18446744073709551615); +substring('hello', 1, 18446744073709551615) +hello +select substring('hello', 1, -18446744073709551616); +substring('hello', 1, -18446744073709551616) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select substring('hello', 1, 18446744073709551616); +substring('hello', 1, 18446744073709551616) +hello +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select substring('hello', 1, -18446744073709551617); +substring('hello', 1, -18446744073709551617) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select substring('hello', 1, 18446744073709551617); +substring('hello', 1, 18446744073709551617) +hello +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select substring('hello', -1, -1); +substring('hello', -1, -1) + +select substring('hello', -4294967295, -4294967295); +substring('hello', -4294967295, -4294967295) + +select substring('hello', 4294967295, 4294967295); +substring('hello', 4294967295, 4294967295) + +select substring('hello', -4294967296, -4294967296); +substring('hello', -4294967296, -4294967296) + +select substring('hello', 4294967296, 4294967296); +substring('hello', 4294967296, 4294967296) + +select substring('hello', -4294967297, -4294967297); +substring('hello', -4294967297, -4294967297) + +select substring('hello', 4294967297, 4294967297); +substring('hello', 4294967297, 4294967297) + +select substring('hello', -18446744073709551615, -18446744073709551615); +substring('hello', -18446744073709551615, -18446744073709551615) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select substring('hello', 18446744073709551615, 18446744073709551615); +substring('hello', 18446744073709551615, 18446744073709551615) + +select substring('hello', -18446744073709551616, -18446744073709551616); +substring('hello', -18446744073709551616, -18446744073709551616) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select substring('hello', 18446744073709551616, 18446744073709551616); +substring('hello', 18446744073709551616, 18446744073709551616) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select substring('hello', -18446744073709551617, -18446744073709551617); +substring('hello', -18446744073709551617, -18446744073709551617) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select substring('hello', 18446744073709551617, 18446744073709551617); +substring('hello', 18446744073709551617, 18446744073709551617) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select insert('hello', -1, 1, 'hi'); +insert('hello', -1, 1, 'hi') +hello +select insert('hello', -4294967295, 1, 'hi'); +insert('hello', -4294967295, 1, 'hi') +hello +select insert('hello', 4294967295, 1, 'hi'); +insert('hello', 4294967295, 1, 'hi') +hello +select insert('hello', -4294967296, 1, 'hi'); +insert('hello', -4294967296, 1, 'hi') +hello +select insert('hello', 4294967296, 1, 'hi'); +insert('hello', 4294967296, 1, 'hi') +hello +select insert('hello', -4294967297, 1, 'hi'); +insert('hello', -4294967297, 1, 'hi') +hello +select insert('hello', 4294967297, 1, 'hi'); +insert('hello', 4294967297, 1, 'hi') +hello +select insert('hello', -18446744073709551615, 1, 'hi'); +insert('hello', -18446744073709551615, 1, 'hi') +hello +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +select insert('hello', 18446744073709551615, 1, 'hi'); +insert('hello', 18446744073709551615, 1, 'hi') +hello +select insert('hello', -18446744073709551616, 1, 'hi'); +insert('hello', -18446744073709551616, 1, 'hi') +hello +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +select insert('hello', 18446744073709551616, 1, 'hi'); +insert('hello', 18446744073709551616, 1, 'hi') +hello +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +select insert('hello', -18446744073709551617, 1, 'hi'); +insert('hello', -18446744073709551617, 1, 'hi') +hello +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +select insert('hello', 18446744073709551617, 1, 'hi'); +insert('hello', 18446744073709551617, 1, 'hi') +hello +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +select insert('hello', 1, -1, 'hi'); +insert('hello', 1, -1, 'hi') +hi +select insert('hello', 1, -4294967295, 'hi'); +insert('hello', 1, -4294967295, 'hi') +hi +select insert('hello', 1, 4294967295, 'hi'); +insert('hello', 1, 4294967295, 'hi') +hi +select insert('hello', 1, -4294967296, 'hi'); +insert('hello', 1, -4294967296, 'hi') +hi +select insert('hello', 1, 4294967296, 'hi'); +insert('hello', 1, 4294967296, 'hi') +hi +select insert('hello', 1, -4294967297, 'hi'); +insert('hello', 1, -4294967297, 'hi') +hi +select insert('hello', 1, 4294967297, 'hi'); +insert('hello', 1, 4294967297, 'hi') +hi +select insert('hello', 1, -18446744073709551615, 'hi'); +insert('hello', 1, -18446744073709551615, 'hi') +hi +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +select insert('hello', 1, 18446744073709551615, 'hi'); +insert('hello', 1, 18446744073709551615, 'hi') +hi +select insert('hello', 1, -18446744073709551616, 'hi'); +insert('hello', 1, -18446744073709551616, 'hi') +hi +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +select insert('hello', 1, 18446744073709551616, 'hi'); +insert('hello', 1, 18446744073709551616, 'hi') +hi +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +select insert('hello', 1, -18446744073709551617, 'hi'); +insert('hello', 1, -18446744073709551617, 'hi') +hi +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +select insert('hello', 1, 18446744073709551617, 'hi'); +insert('hello', 1, 18446744073709551617, 'hi') +hi +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +select insert('hello', -1, -1, 'hi'); +insert('hello', -1, -1, 'hi') +hello +select insert('hello', -4294967295, -4294967295, 'hi'); +insert('hello', -4294967295, -4294967295, 'hi') +hello +select insert('hello', 4294967295, 4294967295, 'hi'); +insert('hello', 4294967295, 4294967295, 'hi') +hello +select insert('hello', -4294967296, -4294967296, 'hi'); +insert('hello', -4294967296, -4294967296, 'hi') +hello +select insert('hello', 4294967296, 4294967296, 'hi'); +insert('hello', 4294967296, 4294967296, 'hi') +hello +select insert('hello', -4294967297, -4294967297, 'hi'); +insert('hello', -4294967297, -4294967297, 'hi') +hello +select insert('hello', 4294967297, 4294967297, 'hi'); +insert('hello', 4294967297, 4294967297, 'hi') +hello +select insert('hello', -18446744073709551615, -18446744073709551615, 'hi'); +insert('hello', -18446744073709551615, -18446744073709551615, 'hi') +hello +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select insert('hello', 18446744073709551615, 18446744073709551615, 'hi'); +insert('hello', 18446744073709551615, 18446744073709551615, 'hi') +hello +select insert('hello', -18446744073709551616, -18446744073709551616, 'hi'); +insert('hello', -18446744073709551616, -18446744073709551616, 'hi') +hello +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select insert('hello', 18446744073709551616, 18446744073709551616, 'hi'); +insert('hello', 18446744073709551616, 18446744073709551616, 'hi') +hello +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select insert('hello', -18446744073709551617, -18446744073709551617, 'hi'); +insert('hello', -18446744073709551617, -18446744073709551617, 'hi') +hello +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select insert('hello', 18446744073709551617, 18446744073709551617, 'hi'); +insert('hello', 18446744073709551617, 18446744073709551617, 'hi') +hello +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select repeat('hello', -1); +repeat('hello', -1) + +select repeat('hello', -4294967295); +repeat('hello', -4294967295) + +select repeat('hello', 4294967295); +repeat('hello', 4294967295) +NULL +Warnings: +Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated +select repeat('hello', -4294967296); +repeat('hello', -4294967296) + +select repeat('hello', 4294967296); +repeat('hello', 4294967296) +NULL +Warnings: +Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated +select repeat('hello', -4294967297); +repeat('hello', -4294967297) + +select repeat('hello', 4294967297); +repeat('hello', 4294967297) +NULL +Warnings: +Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated +select repeat('hello', -18446744073709551615); +repeat('hello', -18446744073709551615) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select repeat('hello', 18446744073709551615); +repeat('hello', 18446744073709551615) +NULL +Warnings: +Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated +select repeat('hello', -18446744073709551616); +repeat('hello', -18446744073709551616) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select repeat('hello', 18446744073709551616); +repeat('hello', 18446744073709551616) +NULL +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated +select repeat('hello', -18446744073709551617); +repeat('hello', -18446744073709551617) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select repeat('hello', 18446744073709551617); +repeat('hello', 18446744073709551617) +NULL +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated +select space(-1); +space(-1) + +select space(-4294967295); +space(-4294967295) + +select space(4294967295); +space(4294967295) +NULL +Warnings: +Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated +select space(-4294967296); +space(-4294967296) + +select space(4294967296); +space(4294967296) +NULL +Warnings: +Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated +select space(-4294967297); +space(-4294967297) + +select space(4294967297); +space(4294967297) +NULL +Warnings: +Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated +select space(-18446744073709551615); +space(-18446744073709551615) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select space(18446744073709551615); +space(18446744073709551615) +NULL +Warnings: +Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated +select space(-18446744073709551616); +space(-18446744073709551616) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select space(18446744073709551616); +space(18446744073709551616) +NULL +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated +select space(-18446744073709551617); +space(-18446744073709551617) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select space(18446744073709551617); +space(18446744073709551617) +NULL +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated +select rpad('hello', -1, '1'); +rpad('hello', -1, '1') +NULL +select rpad('hello', -4294967295, '1'); +rpad('hello', -4294967295, '1') +NULL +select rpad('hello', 4294967295, '1'); +rpad('hello', 4294967295, '1') +NULL +Warnings: +Warning 1301 Result of rpad() was larger than max_allowed_packet (1048576) - truncated +select rpad('hello', -4294967296, '1'); +rpad('hello', -4294967296, '1') +NULL +select rpad('hello', 4294967296, '1'); +rpad('hello', 4294967296, '1') +NULL +Warnings: +Warning 1301 Result of rpad() was larger than max_allowed_packet (1048576) - truncated +select rpad('hello', -4294967297, '1'); +rpad('hello', -4294967297, '1') +NULL +select rpad('hello', 4294967297, '1'); +rpad('hello', 4294967297, '1') +NULL +Warnings: +Warning 1301 Result of rpad() was larger than max_allowed_packet (1048576) - truncated +select rpad('hello', -18446744073709551615, '1'); +rpad('hello', -18446744073709551615, '1') +NULL +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select rpad('hello', 18446744073709551615, '1'); +rpad('hello', 18446744073709551615, '1') +NULL +Warnings: +Warning 1301 Result of rpad() was larger than max_allowed_packet (1048576) - truncated +select rpad('hello', -18446744073709551616, '1'); +rpad('hello', -18446744073709551616, '1') +NULL +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select rpad('hello', 18446744073709551616, '1'); +rpad('hello', 18446744073709551616, '1') +NULL +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +Warning 1301 Result of rpad() was larger than max_allowed_packet (1048576) - truncated +select rpad('hello', -18446744073709551617, '1'); +rpad('hello', -18446744073709551617, '1') +NULL +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select rpad('hello', 18446744073709551617, '1'); +rpad('hello', 18446744073709551617, '1') +NULL +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +Warning 1301 Result of rpad() was larger than max_allowed_packet (1048576) - truncated +select lpad('hello', -1, '1'); +lpad('hello', -1, '1') +NULL +select lpad('hello', -4294967295, '1'); +lpad('hello', -4294967295, '1') +NULL +select lpad('hello', 4294967295, '1'); +lpad('hello', 4294967295, '1') +NULL +Warnings: +Warning 1301 Result of lpad() was larger than max_allowed_packet (1048576) - truncated +select lpad('hello', -4294967296, '1'); +lpad('hello', -4294967296, '1') +NULL +select lpad('hello', 4294967296, '1'); +lpad('hello', 4294967296, '1') +NULL +Warnings: +Warning 1301 Result of lpad() was larger than max_allowed_packet (1048576) - truncated +select lpad('hello', -4294967297, '1'); +lpad('hello', -4294967297, '1') +NULL +select lpad('hello', 4294967297, '1'); +lpad('hello', 4294967297, '1') +NULL +Warnings: +Warning 1301 Result of lpad() was larger than max_allowed_packet (1048576) - truncated +select lpad('hello', -18446744073709551615, '1'); +lpad('hello', -18446744073709551615, '1') +NULL +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select lpad('hello', 18446744073709551615, '1'); +lpad('hello', 18446744073709551615, '1') +NULL +Warnings: +Warning 1301 Result of lpad() was larger than max_allowed_packet (1048576) - truncated +select lpad('hello', -18446744073709551616, '1'); +lpad('hello', -18446744073709551616, '1') +NULL +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select lpad('hello', 18446744073709551616, '1'); +lpad('hello', 18446744073709551616, '1') +NULL +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 +select lpad('hello', -18446744073709551617, '1'); +lpad('hello', -18446744073709551617, '1') +NULL +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select lpad('hello', 18446744073709551617, '1'); +lpad('hello', 18446744073709551617, '1') +NULL +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/gis-rtree.result b/mysql-test/r/gis-rtree.result index dbd6783fe76..95211ad9133 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/im_cmd_line.result b/mysql-test/r/im_cmd_line.result index a4c21c36415..a862d465904 100644 --- a/mysql-test/r/im_cmd_line.result +++ b/mysql-test/r/im_cmd_line.result @@ -3,7 +3,7 @@ Variable_name Value server_id 1 SHOW INSTANCES; instance_name state -mysqld1 starting +mysqld1 XXXXX mysqld2 offline --> Listing users... im_admin diff --git a/mysql-test/r/im_daemon_life_cycle.result b/mysql-test/r/im_daemon_life_cycle.result index 397f4d5d503..a2baeac5f14 100644 --- a/mysql-test/r/im_daemon_life_cycle.result +++ b/mysql-test/r/im_daemon_life_cycle.result @@ -3,10 +3,10 @@ Variable_name Value server_id 1 SHOW INSTANCES; instance_name state -mysqld1 online +mysqld1 XXXXX 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_instance_conf.result b/mysql-test/r/im_instance_conf.result index 597a1be428e..d04ae0270ab 100644 --- a/mysql-test/r/im_instance_conf.result +++ b/mysql-test/r/im_instance_conf.result @@ -3,7 +3,7 @@ Variable_name Value server_id 1 SHOW INSTANCES; instance_name state -mysqld1 online +mysqld1 XXXXX mysqld2 offline -------------------------------------------------------------------- server_id = 1 diff --git a/mysql-test/r/im_life_cycle.result b/mysql-test/r/im_life_cycle.result index c403411c399..dcabc8cf4f3 100644 --- a/mysql-test/r/im_life_cycle.result +++ b/mysql-test/r/im_life_cycle.result @@ -3,7 +3,7 @@ Variable_name Value server_id 1 SHOW INSTANCES; instance_name state -mysqld1 online +mysqld1 XXXXX mysqld2 offline -------------------------------------------------------------------- @@ -39,7 +39,7 @@ ERROR HY000: Unknown instance name -- 1.1.6. -------------------------------------------------------------------- Killing the process... -Sleeping... +Waiting... Success: the process was restarted. SHOW INSTANCES; instance_name state @@ -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/im_utils.result b/mysql-test/r/im_utils.result index 6e40c9bb1c0..b7c68965ada 100644 --- a/mysql-test/r/im_utils.result +++ b/mysql-test/r/im_utils.result @@ -3,7 +3,7 @@ Variable_name Value server_id 1 SHOW INSTANCES; instance_name state -mysqld1 online +mysqld1 XXXXX mysqld2 offline SHOW INSTANCE OPTIONS mysqld1; option_name value diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index 305e89f0325..d910be98cf4 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -14,7 +14,6 @@ NULL test latin1 latin1_swedish_ci NULL select schema_name from information_schema.schemata; schema_name information_schema -cluster mysql test show databases like 't%'; @@ -23,7 +22,6 @@ test show databases; Database information_schema -cluster mysql test show databases where `database` = 't%'; @@ -35,7 +33,7 @@ create table t3(a int, KEY a_data (a)); create table mysqltest.t4(a int); create table t5 (id int auto_increment primary key); insert into t5 values (10); -create view v1 (c) as select table_name from information_schema.TABLES where table_schema!='cluster'; +create view v1 (c) as select table_name from information_schema.TABLES where table_name<>'binlog_index' AND table_name<>'apply_status'; select * from v1; c CHARACTER_SETS @@ -352,7 +350,6 @@ create view v0 (c) as select schema_name from information_schema.schemata; select * from v0; c information_schema -cluster mysql test explain select * from v0; @@ -852,7 +849,7 @@ VIEWS TABLE_NAME select delete from mysql.user where user='mysqltest_4'; delete from mysql.db where user='mysqltest_4'; flush privileges; -SELECT table_schema, count(*) FROM information_schema.TABLES where TABLE_SCHEMA!='cluster' GROUP BY TABLE_SCHEMA; +SELECT table_schema, count(*) FROM information_schema.TABLES where table_name<>'binlog_index' AND table_name<>'apply_status' GROUP BY TABLE_SCHEMA; table_schema count(*) information_schema 27 mysql 21 @@ -1329,6 +1326,21 @@ 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 0 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; End of 5.0 tests. select * from information_schema.engines WHERE ENGINE="MyISAM"; ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS diff --git a/mysql-test/r/log_tables.result b/mysql-test/r/log_tables.result index 2836b96d7b5..d9d754c91e6 100644 --- a/mysql-test/r/log_tables.result +++ b/mysql-test/r/log_tables.result @@ -280,6 +280,7 @@ create table general_log_new like general_log; create table slow_log_new like slow_log; show tables like "%log%"; Tables_in_mysql (%log%) +binlog_index general_log general_log_new slow_log diff --git a/mysql-test/r/lowercase_table.result b/mysql-test/r/lowercase_table.result index 7705961d08d..464f423fa92 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/mysqlcheck.result b/mysql-test/r/mysqlcheck.result index c34aa995b2b..d6149981f37 100644 --- a/mysql-test/r/mysqlcheck.result +++ b/mysql-test/r/mysqlcheck.result @@ -2,7 +2,7 @@ drop database if exists client_test_db; DROP SCHEMA test; CREATE SCHEMA test; use test; -cluster.binlog_index OK +mysql.binlog_index OK mysql.columns_priv OK mysql.db OK mysql.event OK @@ -26,6 +26,7 @@ mysql.time_zone_name OK mysql.time_zone_transition OK mysql.time_zone_transition_type OK mysql.user OK +mysql.binlog_index OK mysql.columns_priv OK mysql.db OK mysql.event OK diff --git a/mysql-test/r/ndb_binlog_basic.result b/mysql-test/r/ndb_binlog_basic.result index a8f88c2192e..43c19278d2c 100644 --- a/mysql-test/r/ndb_binlog_basic.result +++ b/mysql-test/r/ndb_binlog_basic.result @@ -6,7 +6,7 @@ drop database mysqltest; use test; create table t1 (a int primary key) engine=ndb; insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); -select @max_epoch:=max(epoch)-1 from cluster.binlog_index; +select @max_epoch:=max(epoch)-1 from mysql.binlog_index; @max_epoch:=max(epoch)-1 # delete from t1; @@ -19,19 +19,19 @@ update t2 set b=1 where a=3; delete from t2 where a=4; commit; drop table t2; -select inserts from cluster.binlog_index where epoch > @max_epoch and inserts > 5; +select inserts from mysql.binlog_index where epoch > @max_epoch and inserts > 5; inserts 10 -select deletes from cluster.binlog_index where epoch > @max_epoch and deletes > 5; +select deletes from mysql.binlog_index where epoch > @max_epoch and deletes > 5; deletes 10 select inserts,updates,deletes from -cluster.binlog_index where epoch > @max_epoch and updates > 0; +mysql.binlog_index where epoch > @max_epoch and updates > 0; inserts updates deletes 2 1 1 flush logs; purge master logs before now(); -select count(*) from cluster.binlog_index; +select count(*) from mysql.binlog_index; count(*) 0 create table t1 (a int primary key, b int) engine=ndb; @@ -40,12 +40,12 @@ use mysqltest; create table t1 (c int, d int primary key) engine=ndb; use test; insert into mysqltest.t1 values (2,1),(2,2); -select @max_epoch:=max(epoch)-1 from cluster.binlog_index; +select @max_epoch:=max(epoch)-1 from mysql.binlog_index; @max_epoch:=max(epoch)-1 # drop table t1; drop database mysqltest; select inserts,updates,deletes from -cluster.binlog_index where epoch > @max_epoch and inserts > 0; +mysql.binlog_index where epoch > @max_epoch and inserts > 0; inserts updates deletes 2 0 0 diff --git a/mysql-test/r/ndb_binlog_ddl_multi.result b/mysql-test/r/ndb_binlog_ddl_multi.result index 19414cf75c5..ff9c3bdc3e4 100644 --- a/mysql-test/r/ndb_binlog_ddl_multi.result +++ b/mysql-test/r/ndb_binlog_ddl_multi.result @@ -23,7 +23,7 @@ reset master; alter table t2 add column (b int); show binlog events from <binlog_start>; Log_name Pos Event_type Server_id End_log_pos Info -master-bin1.000001 # Query # # use `test`; alter table t2 add column (b int) +master-bin.000001 # Query # # use `test`; alter table t2 add column (b int) reset master; reset master; ALTER DATABASE mysqltest CHARACTER SET latin1; @@ -44,7 +44,7 @@ show binlog events from <binlog_start>; Log_name Pos Event_type Server_id End_log_pos Info master-bin1.000001 # Query # # BEGIN master-bin1.000001 # Table_map # # table_id: # (test.t2) -master-bin1.000001 # Table_map # # table_id: # (cluster.apply_status) +master-bin1.000001 # Table_map # # table_id: # (mysql.apply_status) master-bin1.000001 # Write_rows # # table_id: # master-bin1.000001 # Write_rows # # table_id: # flags: STMT_END_F master-bin1.000001 # Query # # COMMIT @@ -180,14 +180,14 @@ Log_name Pos Event_type Server_id End_log_pos Info master-bin1.000001 # Query # # use `test`; create table t1 (a int key) engine=ndb master-bin1.000001 # Query # # BEGIN master-bin1.000001 # Table_map # # table_id: # (test.t1) -master-bin1.000001 # Table_map # # table_id: # (cluster.apply_status) +master-bin1.000001 # Table_map # # table_id: # (mysql.apply_status) master-bin1.000001 # Write_rows # # table_id: # master-bin1.000001 # Write_rows # # table_id: # flags: STMT_END_F master-bin1.000001 # Query # # COMMIT master-bin1.000001 # Query # # use `test`; rename table `test.t1` to `test.t2` master-bin1.000001 # Query # # BEGIN master-bin1.000001 # Table_map # # table_id: # (test.t2) -master-bin1.000001 # Table_map # # table_id: # (cluster.apply_status) +master-bin1.000001 # Table_map # # table_id: # (mysql.apply_status) master-bin1.000001 # Write_rows # # table_id: # master-bin1.000001 # Write_rows # # table_id: # flags: STMT_END_F master-bin1.000001 # Query # # COMMIT diff --git a/mysql-test/r/ndb_binlog_discover.result b/mysql-test/r/ndb_binlog_discover.result index 01e15dc1c39..e81d5cfc6f3 100644 --- a/mysql-test/r/ndb_binlog_discover.result +++ b/mysql-test/r/ndb_binlog_discover.result @@ -5,7 +5,7 @@ show binlog events from <binlog_start>; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 # Query # # BEGIN master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Table_map # # table_id: # (cluster.apply_status) +master-bin.000001 # Table_map # # table_id: # (mysql.apply_status) master-bin.000001 # Write_rows # # table_id: # master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F master-bin.000001 # Query # # COMMIT diff --git a/mysql-test/r/ndb_binlog_multi.result b/mysql-test/r/ndb_binlog_multi.result index 119174039f9..ffd0b44484b 100644 --- a/mysql-test/r/ndb_binlog_multi.result +++ b/mysql-test/r/ndb_binlog_multi.result @@ -11,7 +11,7 @@ Log_name Pos Event_type Server_id End_log_pos Info master-bin1.000001 # Query # # use `test`; CREATE TABLE t2 (a INT PRIMARY KEY, b int) ENGINE = NDB master-bin1.000001 # Query # # BEGIN master-bin1.000001 # Table_map # # table_id: # (test.t2) -master-bin1.000001 # Table_map # # table_id: # (cluster.apply_status) +master-bin1.000001 # Table_map # # table_id: # (mysql.apply_status) master-bin1.000001 # Write_rows # # table_id: # master-bin1.000001 # Write_rows # # table_id: # flags: STMT_END_F master-bin1.000001 # Query # # COMMIT @@ -20,7 +20,7 @@ a b 1 1 2 2 SELECT @the_epoch:=epoch,inserts,updates,deletes,schemaops FROM -cluster.binlog_index ORDER BY epoch DESC LIMIT 1; +mysql.binlog_index ORDER BY epoch DESC LIMIT 1; @the_epoch:=epoch inserts updates deletes schemaops <the_epoch> 2 0 0 0 SELECT * FROM t2 ORDER BY a; @@ -33,13 +33,13 @@ Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 # Query # # use `test`; CREATE TABLE t2 (a INT PRIMARY KEY, b int) ENGINE = NDB master-bin.000001 # Query # # BEGIN master-bin.000001 # Table_map # # table_id: # (test.t2) -master-bin.000001 # Table_map # # table_id: # (cluster.apply_status) +master-bin.000001 # Table_map # # table_id: # (mysql.apply_status) master-bin.000001 # Write_rows # # table_id: # master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F master-bin.000001 # Query # # COMMIT master-bin.000001 # Query # # use `test`; DROP TABLE t2 SELECT inserts,updates,deletes,schemaops FROM -cluster.binlog_index WHERE epoch=<the_epoch>; +mysql.binlog_index WHERE epoch=<the_epoch>; inserts updates deletes schemaops 2 0 0 0 reset master; @@ -51,16 +51,16 @@ Log_name Pos Event_type Server_id End_log_pos Info master-bin1.000001 # Query # # use `test`; CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE = NDB master-bin1.000001 # Query # # BEGIN master-bin1.000001 # Table_map # # table_id: # (test.t1) -master-bin1.000001 # Table_map # # table_id: # (cluster.apply_status) +master-bin1.000001 # Table_map # # table_id: # (mysql.apply_status) master-bin1.000001 # Write_rows # # table_id: # master-bin1.000001 # Write_rows # # table_id: # flags: STMT_END_F master-bin1.000001 # Query # # COMMIT SELECT @the_epoch2:=epoch,inserts,updates,deletes,schemaops FROM -cluster.binlog_index ORDER BY epoch DESC LIMIT 1; +mysql.binlog_index ORDER BY epoch DESC LIMIT 1; @the_epoch2:=epoch inserts updates deletes schemaops <the_epoch2> 2 0 0 0 SELECT inserts,updates,deletes,schemaops FROM -cluster.binlog_index WHERE epoch > <the_epoch> AND epoch <= <the_epoch2>; +mysql.binlog_index WHERE epoch > <the_epoch> AND epoch <= <the_epoch2>; inserts updates deletes schemaops 2 0 0 0 drop table t1; @@ -69,12 +69,12 @@ Log_name Pos Event_type Server_id End_log_pos Info master-bin1.000001 # Query # # use `test`; CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE = NDB master-bin1.000001 # Query # # BEGIN master-bin1.000001 # Table_map # # table_id: # (test.t1) -master-bin1.000001 # Table_map # # table_id: # (cluster.apply_status) +master-bin1.000001 # Table_map # # table_id: # (mysql.apply_status) master-bin1.000001 # Write_rows # # table_id: # master-bin1.000001 # Write_rows # # table_id: # flags: STMT_END_F master-bin1.000001 # Query # # COMMIT master-bin1.000001 # Query # # use `test`; drop table t1 SELECT inserts,updates,deletes,schemaops FROM -cluster.binlog_index WHERE epoch > <the_epoch> AND epoch <= <the_epoch2>; +mysql.binlog_index WHERE epoch > <the_epoch> AND epoch <= <the_epoch2>; inserts updates deletes schemaops 2 0 0 0 diff --git a/mysql-test/r/ndb_restore_compat.result b/mysql-test/r/ndb_restore_compat.result index 358ca36b2df..595c582e3b7 100644 --- a/mysql-test/r/ndb_restore_compat.result +++ b/mysql-test/r/ndb_restore_compat.result @@ -44,7 +44,7 @@ SELECT * FROM SYSTEM_VALUES ORDER BY SYSTEM_VALUES_ID; SYSTEM_VALUES_ID VALUE 0 2039 1 3 -SELECT * FROM cluster.apply_status WHERE server_id=0; +SELECT * FROM mysql.apply_status WHERE server_id=0; server_id epoch 0 151 TRUNCATE GL; @@ -98,7 +98,7 @@ SELECT * FROM SYSTEM_VALUES ORDER BY SYSTEM_VALUES_ID; SYSTEM_VALUES_ID VALUE 0 2297 1 5 -SELECT * FROM cluster.apply_status WHERE server_id=0; +SELECT * FROM mysql.apply_status WHERE server_id=0; server_id epoch 0 331 DROP DATABASE BANK; diff --git a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result index 6461696b0d0..e5cc47fd9d2 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/parser.result b/mysql-test/r/parser.result index afd78561898..df446e01601 100644 --- a/mysql-test/r/parser.result +++ b/mysql-test/r/parser.result @@ -296,11 +296,6 @@ select atan(); ERROR 42000: Incorrect parameter count in the call to native function 'atan' select atan2(1, 2, 3); ERROR 42000: Incorrect parameter count in the call to native function 'atan2' -select benchmark(10, 1+1); -benchmark(10, 1+1) -0 -select benchmark(5+5, 2); -ERROR 42000: Incorrect parameters in the call to native function 'BENCHMARK' select concat(); ERROR 42000: Incorrect parameter count in the call to native function 'concat' select concat("foo"); @@ -310,11 +305,6 @@ select concat_ws(); ERROR 42000: Incorrect parameter count in the call to native function 'concat_ws' select concat_ws("foo"); ERROR 42000: Incorrect parameter count in the call to native function 'concat_ws' -set @pwd="my password"; -select encode("secret", @pwd); -ERROR 42000: Incorrect parameters in the call to native function 'ENCODE' -select decode("encoded-secret", @pwd); -ERROR 42000: Incorrect parameters in the call to native function 'DECODE' select encrypt(); ERROR 42000: Incorrect parameter count in the call to native function 'encrypt' select encrypt(1, 2, 3); @@ -339,9 +329,6 @@ select field(); ERROR 42000: Incorrect parameter count in the call to native function 'field' select field("p1"); ERROR 42000: Incorrect parameter count in the call to native function 'field' -set @dec=2; -select format(pi(), @dec); -ERROR 42000: Incorrect parameters in the call to native function 'FORMAT' select from_unixtime(); ERROR 42000: Incorrect parameter count in the call to native function 'from_unixtime' select from_unixtime(1, 2, 3); diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 617e289d30d..e968d3de6e9 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -796,12 +796,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 @@ -820,67 +820,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"; @@ -888,13 +891,19 @@ 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 +select @@max_prepared_stmt_count; +@@max_prepared_stmt_count +3 +show status like 'prepared_stmt_count'; +Variable_name Value +Prepared_stmt_count 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); @@ -2090,14 +2099,6 @@ v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VI deallocate prepare abc; drop view v1; drop table t1; -create procedure proc_1() install plugin my_plug soname '/root/some_plugin.so'; -call proc_1(); -ERROR HY000: No paths allowed for shared library -call proc_1(); -ERROR HY000: No paths allowed for shared library -call proc_1(); -ERROR HY000: No paths allowed for shared library -drop procedure proc_1; create procedure proc_1() install plugin my_plug soname 'some_plugin.so'; call proc_1(); ERROR HY000: Can't open shared library @@ -2112,12 +2113,6 @@ select func_1(), func_1(), func_1() from dual; ERROR 42000: FUNCTION test.func_1 does not exist drop function func_1; ERROR 42000: FUNCTION test.func_1 does not exist -prepare abc from "install plugin my_plug soname '/root/some_plugin.so'"; -execute abc; -ERROR HY000: No paths allowed for shared library -execute abc; -ERROR HY000: No paths allowed for shared library -deallocate prepare abc; prepare abc from "install plugin my_plug soname 'some_plugin.so'"; deallocate prepare abc; create procedure proc_1() uninstall plugin my_plug; @@ -2391,3 +2386,49 @@ Level Code Message Note 1051 Unknown table 't1' Note 1051 Unknown table 't2' deallocate prepare abc; +set @my_password="password"; +set @my_data="clear text to encode"; +prepare stmt1 from 'select decode(encode(?, ?), ?)'; +execute stmt1 using @my_data, @my_password, @my_password; +decode(encode(?, ?), ?) +clear text to encode +set @my_data="more text to encode"; +execute stmt1 using @my_data, @my_password, @my_password; +decode(encode(?, ?), ?) +more text to encode +set @my_password="new password"; +execute stmt1 using @my_data, @my_password, @my_password; +decode(encode(?, ?), ?) +more text to encode +deallocate prepare stmt1; +set @to_format="123456789.123456789"; +set @dec=0; +prepare stmt2 from 'select format(?, ?)'; +execute stmt2 using @to_format, @dec; +format(?, ?) +123,456,789 +set @dec=4; +execute stmt2 using @to_format, @dec; +format(?, ?) +123,456,789.1235 +set @dec=6; +execute stmt2 using @to_format, @dec; +format(?, ?) +123,456,789.123457 +set @dec=2; +execute stmt2 using @to_format, @dec; +format(?, ?) +123,456,789.12 +set @to_format="100"; +execute stmt2 using @to_format, @dec; +format(?, ?) +100.00 +set @to_format="1000000"; +execute stmt2 using @to_format, @dec; +format(?, ?) +1,000,000.00 +set @to_format="10000"; +execute stmt2 using @to_format, @dec; +format(?, ?) +10,000.00 +deallocate prepare stmt2; diff --git a/mysql-test/r/ps_1general.result b/mysql-test/r/ps_1general.result index 67959920248..762ceeaa03b 100644 --- a/mysql-test/r/ps_1general.result +++ b/mysql-test/r/ps_1general.result @@ -259,7 +259,6 @@ prepare stmt4 from ' show databases '; execute stmt4; Database information_schema -cluster mysql test prepare stmt4 from ' show tables from test like ''t2%'' '; diff --git a/mysql-test/r/ps_not_windows.result b/mysql-test/r/ps_not_windows.result new file mode 100644 index 00000000000..e58b6ec5cad --- /dev/null +++ b/mysql-test/r/ps_not_windows.result @@ -0,0 +1,14 @@ +create procedure proc_1() install plugin my_plug soname '/root/some_plugin.so'; +call proc_1(); +ERROR HY000: No paths allowed for shared library +call proc_1(); +ERROR HY000: No paths allowed for shared library +call proc_1(); +ERROR HY000: No paths allowed for shared library +drop procedure proc_1; +prepare abc from "install plugin my_plug soname '/root/some_plugin.so'"; +execute abc; +ERROR HY000: No paths allowed for shared library +execute abc; +ERROR HY000: No paths allowed for shared library +deallocate prepare abc; diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result index d5996ee8163..fac026047de 100644 --- a/mysql-test/r/query_cache.result +++ b/mysql-test/r/query_cache.result @@ -1276,3 +1276,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/rpl_create_database.result b/mysql-test/r/rpl_create_database.result index 0593501f623..0cfd44bc58c 100644 --- a/mysql-test/r/rpl_create_database.result +++ b/mysql-test/r/rpl_create_database.result @@ -23,7 +23,6 @@ ALTER DATABASE mysqltest_bob CHARACTER SET latin1; SHOW DATABASES; Database information_schema -cluster mysql mysqltest_bob mysqltest_prometheus @@ -32,7 +31,6 @@ test SHOW DATABASES; Database information_schema -cluster mysql mysqltest_prometheus mysqltest_sisyfos @@ -47,7 +45,6 @@ CREATE TABLE t2 (a INT); SHOW DATABASES; Database information_schema -cluster mysql mysqltest_bob mysqltest_prometheus @@ -56,7 +53,6 @@ test SHOW DATABASES; Database information_schema -cluster mysql mysqltest_prometheus mysqltest_sisyfos diff --git a/mysql-test/r/rpl_deadlock_innodb.result b/mysql-test/r/rpl_deadlock_innodb.result index b9a23950ed8..9a67391cd4d 100644 --- a/mysql-test/r/rpl_deadlock_innodb.result +++ b/mysql-test/r/rpl_deadlock_innodb.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 @@ -28,21 +28,22 @@ Variable_name Value slave_transaction_retries 2 stop slave; begin; -insert into t3 select * from t2 for update; +insert into t2 values (0); insert into t1 values(1); commit; begin; select * from t1 for update; a start slave; -insert into t2 values(22); +select * from t2 for update /* dl */; +a commit; select * from t1; a 1 -select * from t2; +select * from t2 /* must be 1 */; a -22 +0 show slave status; Slave_IO_State # Master_Host 127.0.0.1 @@ -78,12 +79,16 @@ Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master # stop slave; -change master to master_log_pos=536; +delete from t3; +change master to master_log_pos=544; begin; select * from t2 for update; a -22 +0 start slave; +select count(*) from t3 /* must be zero */; +count(*) +0 commit; select * from t1; a @@ -91,7 +96,8 @@ a 1 select * from t2; a -22 +0 +0 show slave status; Slave_IO_State # Master_Host 127.0.0.1 @@ -128,12 +134,17 @@ Master_SSL_Key Seconds_Behind_Master # set global max_relay_log_size=0; stop slave; -change master to master_log_pos=536; +delete from t3; +change master to master_log_pos=544; begin; select * from t2 for update; a -22 +0 +0 start slave; +select count(*) from t3 /* must be zero */; +count(*) +0 commit; select * from t1; a @@ -142,7 +153,9 @@ a 1 select * from t2; a -22 +0 +0 +0 show slave status; Slave_IO_State # Master_Host 127.0.0.1 @@ -178,3 +191,4 @@ Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master # drop table t1,t2,t3,t4; +End of 5.1 tests diff --git a/mysql-test/r/rpl_do_grant.result b/mysql-test/r/rpl_do_grant.result index 8bf8e615448..50d181be0ca 100644 --- a/mysql-test/r/rpl_do_grant.result +++ b/mysql-test/r/rpl_do_grant.result @@ -23,6 +23,8 @@ password<>_binary'' delete from mysql.user where user=_binary'rpl_do_grant'; delete from mysql.db where user=_binary'rpl_do_grant'; flush privileges; +delete from mysql.user where user=_binary'rpl_do_grant'; +delete from mysql.db where user=_binary'rpl_do_grant'; flush privileges; show grants for rpl_do_grant@localhost; ERROR 42000: There is no such grant defined for user 'rpl_do_grant' on host 'localhost' diff --git a/mysql-test/r/rpl_extraCol_innodb.result b/mysql-test/r/rpl_extraCol_innodb.result new file mode 100644 index 00000000000..7f681aef4be --- /dev/null +++ b/mysql-test/r/rpl_extraCol_innodb.result @@ -0,0 +1,741 @@ +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; +**** Diff Table Def Start **** +*** On Slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t1 (a INT, b INT PRIMARY KEY, c CHAR(20), +d FLOAT DEFAULT '2.00', +e CHAR(4) DEFAULT 'TEST') +ENGINE='InnoDB'; +*** Create t1 on Master *** +CREATE TABLE t1 (a INT PRIMARY KEY, b INT, c CHAR(10) +) ENGINE='InnoDB'; +RESET MASTER; +*** Start Slave *** +START SLAVE; +*** Master Data Insert *** +INSERT INTO t1 () VALUES(1,2,'TEXAS'),(2,1,'AUSTIN'),(3,4,'QA'); +SELECT * FROM t1 ORDER BY a; +a b c +1 2 TEXAS +2 1 AUSTIN +3 4 QA +*** Select from slave *** +SELECT * FROM t1 ORDER BY a; +a b c d e +1 2 TEXAS 2 TEST +2 1 AUSTIN 2 TEST +3 4 QA 2 TEST +*** Drop t1 *** +DROP TABLE t1; +*** Create t3 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t3 (a INT, b INT PRIMARY KEY, c CHAR(20), +d FLOAT DEFAULT '2.00', +e CHAR(5) DEFAULT 'TEST2') +ENGINE='InnoDB'; +*** Create t3 on Master *** +CREATE TABLE t3 (a BLOB, b INT PRIMARY KEY, c CHAR(20) +) ENGINE='InnoDB'; +RESET MASTER; +*** Start Slave *** +START SLAVE; +*** Master Data Insert *** +set @b1 = 'b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t3 () VALUES(@b1,2,'Kyle, TEX'),(@b1,1,'JOE AUSTIN'),(@b1,4,'QA TESTING'); +******************************************** +*** Expect slave to fail with Error 1522 *** +******************************************** +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 1522 +Last_Error Column 0 type mismatch - received type 252, test.t3 has type 3 +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; +START SLAVE; +*** Drop t3 *** +DROP TABLE t3; +*** Create t4 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t4 (a INT, b INT PRIMARY KEY, c CHAR(20), +d FLOAT DEFAULT '2.00', +e CHAR(5) DEFAULT 'TEST2') +ENGINE='InnoDB'; +*** Create t4 on Master *** +CREATE TABLE t4 (a DECIMAL(8,2), b INT PRIMARY KEY, c CHAR(20) +) ENGINE='InnoDB'; +RESET MASTER; +*** Start Slave *** +START SLAVE; +*** Master Data Insert *** +INSERT INTO t4 () VALUES(100.22,2,'Kyle, TEX'),(200.26,1,'JOE AUSTIN'), +(30000.22,4,'QA TESTING'); +******************************************** +*** Expect slave to fail with Error 1522 *** +******************************************** +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 1522 +Last_Error Column 0 type mismatch - received type 246, test.t4 has type 3 +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; +START SLAVE; +*** Drop t4 *** +DROP TABLE t4; +*** Create t5 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t5 (a INT PRIMARY KEY, b CHAR(5), +c FLOAT, d INT, e DOUBLE, +f DECIMAL(8,2))ENGINE='InnoDB'; +*** Create t5 on Master *** +CREATE TABLE t5 (a INT PRIMARY KEY, b VARCHAR(6), +c DECIMAL(8,2), d BIT, e BLOB, +f FLOAT) ENGINE='InnoDB'; +RESET MASTER; +*** Start Slave *** +START SLAVE; +*** Master Data Insert *** +INSERT INTO t5 () VALUES(1,'Kyle',200.23,1,'b1b1',23.00098), +(2,'JOE',300.01,0,'b2b2',1.0000009); +******************************************** +*** Expect slave to fail with Error 1522 *** +******************************************** +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 1522 +Last_Error Column 5 type mismatch - received type 4, test.t5 has type 246 +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; +START SLAVE; +*** Drop t5 *** +DROP TABLE t5; +*** Create t6 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t6 (a INT PRIMARY KEY, b CHAR(5), +c FLOAT, d INT)ENGINE='InnoDB'; +*** Create t6 on Master *** +CREATE TABLE t6 (a INT PRIMARY KEY, b VARCHAR(6), +c DECIMAL(8,2), d BIT +) ENGINE='InnoDB'; +RESET MASTER; +*** Start Slave *** +START SLAVE; +*** Master Data Insert *** +INSERT INTO t6 () VALUES(1,'Kyle',200.23,1), +(2,'JOE',300.01,0); +******************************************** +*** Expect slave to fail with Error 1522 *** +******************************************** +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 1522 +Last_Error Column 3 type mismatch - received type 16, test.t6 has type 3 +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=3; +*** Drop t6 *** +DROP TABLE t6; +DROP TABLE t6; +START SLAVE; +**** Diff Table Def End **** +**** Extra Colums Start **** +*** Create t7 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t7 (a INT KEY, b BLOB, c CHAR(5), +d TIMESTAMP NULL DEFAULT '0000-00-00 00:00:00', +e CHAR(20) DEFAULT 'Extra Column Testing') +ENGINE='InnoDB'; +*** Create t7 on Master *** +CREATE TABLE t7 (a INT PRIMARY KEY, b BLOB, c CHAR(5) +) ENGINE='InnoDB'; +RESET MASTER; +*** Start Slave *** +START SLAVE; +*** Master Data Insert *** +set @b1 = 'b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t7 () VALUES(1,@b1,'Kyle'),(2,@b1,'JOE'),(3,@b1,'QA'); +SELECT * FROM t7 ORDER BY a; +a b c +1 b1b1 Kyle +2 b1b1 JOE +3 b1b1 QA +*** Select from slave *** +SELECT * FROM t7 ORDER BY a; +a b c d e +1 b1b1 Kyle 0000-00-00 00:00:00 Extra Column Testing +2 b1b1 JOE 0000-00-00 00:00:00 Extra Column Testing +3 b1b1 QA 0000-00-00 00:00:00 Extra Column Testing +*** Drop t7 *** +DROP TABLE t7; +*** Create t8 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t8 (a INT KEY, b BLOB, c CHAR(5), +d TIMESTAMP NULL DEFAULT '0000-00-00 00:00:00', +e INT)ENGINE='InnoDB'; +*** Create t8 on Master *** +CREATE TABLE t8 (a INT PRIMARY KEY, b BLOB, c CHAR(5) +) ENGINE='InnoDB'; +RESET MASTER; +*** Start Slave *** +START SLAVE; +*** Master Data Insert *** +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t8 () VALUES(1,@b1,'Kyle'),(2,@b1,'JOE'),(3,@b1,'QA'); +*** Drop t8 *** +DROP TABLE t8; +*** Create t10 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t10 (a INT KEY, b BLOB, f DOUBLE DEFAULT '233', +c CHAR(5), e INT DEFAULT '1')ENGINE='InnoDB'; +*** Create t10 on Master *** +CREATE TABLE t10 (a INT PRIMARY KEY, b BLOB, c CHAR(5) +) ENGINE='InnoDB'; +RESET MASTER; +*** Start Slave *** +START SLAVE; +*** Master Data Insert *** +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t10 () VALUES(1,@b1,'Kyle'),(2,@b1,'JOE'),(3,@b1,'QA'); +******************************************** +*** Expect slave to fail with Error 1522 *** +******************************************** +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 1522 +Last_Error Column 2 type mismatch - received type 254, test.t10 has type 5 +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; +START SLAVE; +*** Drop t10 *** +DROP TABLE t10; +*** Create t11 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t11 (a INT KEY, b BLOB, f TEXT, +c CHAR(5) DEFAULT 'test', e INT DEFAULT '1')ENGINE='InnoDB'; +*** Create t11 on Master *** +CREATE TABLE t11 (a INT PRIMARY KEY, b BLOB, c VARCHAR(254) +) ENGINE='InnoDB'; +RESET MASTER; +*** Start Slave *** +START SLAVE; +*** Master Data Insert *** +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t11 () VALUES(1,@b1,'Kyle'),(2,@b1,'JOE'),(3,@b1,'QA'); +******************************************** +*** Expect slave to fail with Error 1522 *** +******************************************** +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 1522 +Last_Error Column 2 type mismatch - received type 15, test.t11 has type 252 +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; +START SLAVE; +*** Drop t11 *** +DROP TABLE t11; +*** Create t12 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t12 (a INT KEY, b BLOB, f TEXT, +c CHAR(5) DEFAULT 'test', e INT DEFAULT '1')ENGINE='InnoDB'; +*** Create t12 on Master *** +CREATE TABLE t12 (a INT PRIMARY KEY, b BLOB, c BLOB +) ENGINE='InnoDB'; +RESET MASTER; +*** Start Slave *** +START SLAVE; +*** Master Data Insert *** +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t12 () VALUES(1,@b1,'Kyle'),(2,@b1,'JOE'),(3,@b1,'QA'); +SELECT * FROM t12 ORDER BY a; +a b c +1 b1b1b1b1b1b1b1b1 Kyle +2 b1b1b1b1b1b1b1b1 JOE +3 b1b1b1b1b1b1b1b1 QA +*** Select on Slave *** +SELECT * FROM t12 ORDER BY a; +a b f c e +1 b1b1b1b1b1b1b1b1 Kyle test 1 +2 b1b1b1b1b1b1b1b1 JOE test 1 +3 b1b1b1b1b1b1b1b1 QA test 1 +*** Drop t12 *** +DROP TABLE t12; +**** Extra Colums End **** +*** BUG 22177 Start *** +*** Create t13 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t13 (a INT KEY, b BLOB, c CHAR(5), +d INT DEFAULT '1', +e TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP +)ENGINE='InnoDB'; +*** Create t13 on Master *** +CREATE TABLE t13 (a INT PRIMARY KEY, b BLOB, c CHAR(5) +) ENGINE='InnoDB'; +RESET MASTER; +*** Start Slave *** +START SLAVE; +*** Master Data Insert *** +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t13 () VALUES(1,@b1,'Kyle'),(2,@b1,'JOE'),(3,@b1,'QA'); +SELECT * FROM t13 ORDER BY a; +a b c +1 b1b1b1b1b1b1b1b1 Kyle +2 b1b1b1b1b1b1b1b1 JOE +3 b1b1b1b1b1b1b1b1 QA +*** Select on Slave **** +SELECT * FROM t13 ORDER BY a; +a b c d e +1 b1b1b1b1b1b1b1b1 Kyle 1 CURRENT_TIMESTAMP +2 b1b1b1b1b1b1b1b1 JOE 1 CURRENT_TIMESTAMP +3 b1b1b1b1b1b1b1b1 QA 1 CURRENT_TIMESTAMP +*** Drop t13 *** +DROP TABLE t13; +*** 22117 END *** +*** Alter Master Table Testing Start *** +*** Create t14 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t14 (c1 INT KEY, c4 BLOB, c5 CHAR(5), +c6 INT DEFAULT '1', +c7 TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP +)ENGINE='InnoDB'; +*** Create t14 on Master *** +CREATE TABLE t14 (c1 INT PRIMARY KEY, c4 BLOB, c5 CHAR(5) +) ENGINE='InnoDB'; +RESET MASTER; +*** Start Slave *** +START SLAVE; +*** Master Data Insert *** +ALTER TABLE t14 ADD COLUMN c2 DECIMAL(8,2) AFTER c1; +ALTER TABLE t14 ADD COLUMN c3 TEXT AFTER c2; +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t14 () VALUES(1,1.00,'Replication Testing Extra Col',@b1,'Kyle'), +(2,2.00,'This Test Should work',@b1,'JOE'), +(3,3.00,'If is does not, I will open a bug',@b1,'QA'); +SELECT * FROM t14 ORDER BY c1; +c1 c2 c3 c4 c5 +1 1.00 Replication Testing Extra Col b1b1b1b1b1b1b1b1 Kyle +2 2.00 This Test Should work b1b1b1b1b1b1b1b1 JOE +3 3.00 If is does not, I will open a bug b1b1b1b1b1b1b1b1 QA +*** Select on Slave **** +SELECT * FROM t14 ORDER BY c1; +c1 c2 c3 c4 c5 c6 c7 +1 1.00 Replication Testing Extra Col b1b1b1b1b1b1b1b1 Kyle 1 CURRENT_TIMESTAMP +2 2.00 This Test Should work b1b1b1b1b1b1b1b1 JOE 1 CURRENT_TIMESTAMP +3 3.00 If is does not, I will open a bug b1b1b1b1b1b1b1b1 QA 1 CURRENT_TIMESTAMP +*** connect to master and drop columns *** +ALTER TABLE t14 DROP COLUMN c2; +ALTER TABLE t14 DROP COLUMN c4; +*** Select from Master *** +SELECT * FROM t14 ORDER BY c1; +c1 c3 c5 +1 Replication Testing Extra Col Kyle +2 This Test Should work JOE +3 If is does not, I will open a bug QA +*** Select from Slave *** +SELECT * FROM t14 ORDER BY c1; +c1 c3 c5 c6 c7 +1 Replication Testing Extra Col Kyle 1 CURRENT_TIMESTAMP +2 This Test Should work JOE 1 CURRENT_TIMESTAMP +3 If is does not, I will open a bug QA 1 CURRENT_TIMESTAMP +*** Drop t14 *** +DROP TABLE t14; +*** Create t15 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t15 (c1 INT KEY, c2 DECIMAL(8,2), c3 TEXT, +c4 BLOB, c5 CHAR(5), +c6 INT DEFAULT '1', +c7 TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP +)ENGINE='InnoDB'; +*** Create t15 on Master *** +CREATE TABLE t15 (c1 INT PRIMARY KEY, c2 DECIMAL(8,2), c3 TEXT, +c4 BLOB, c5 CHAR(5)) ENGINE='InnoDB'; +RESET MASTER; +*** Start Slave *** +START SLAVE; +*** Master Data Insert *** +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t15 () VALUES(1,1.00,'Replication Testing Extra Col',@b1,'Kyle'), +(2,2.00,'This Test Should work',@b1,'JOE'), +(3,3.00,'If is does not, I will open a bug',@b1,'QA'); +SELECT * FROM t15 ORDER BY c1; +c1 c2 c3 c4 c5 +1 1.00 Replication Testing Extra Col b1b1b1b1b1b1b1b1 Kyle +2 2.00 This Test Should work b1b1b1b1b1b1b1b1 JOE +3 3.00 If is does not, I will open a bug b1b1b1b1b1b1b1b1 QA +*** Select on Slave **** +SELECT * FROM t15 ORDER BY c1; +c1 c2 c3 c4 c5 c6 c7 +1 1.00 Replication Testing Extra Col b1b1b1b1b1b1b1b1 Kyle 1 CURRENT_TIMESTAMP +2 2.00 This Test Should work b1b1b1b1b1b1b1b1 JOE 1 CURRENT_TIMESTAMP +3 3.00 If is does not, I will open a bug b1b1b1b1b1b1b1b1 QA 1 CURRENT_TIMESTAMP +*** Add column on master that is a Extra on Slave *** +ALTER TABLE t15 ADD COLUMN c6 INT AFTER c5; +******************************************** +*** Expect slave to fail with Error 1060 *** +******************************************** +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 1060 +Last_Error Error 'Duplicate column name 'c6'' on query. Default database: 'test'. Query: 'ALTER TABLE t15 ADD COLUMN c6 INT AFTER c5' +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; +START SLAVE; +*** Try to insert in master **** +INSERT INTO t15 () VALUES(5,2.00,'Replication Testing',@b1,'Buda',2); +SELECT * FROM t15 ORDER BY c1; +c1 c2 c3 c4 c5 c6 +1 1.00 Replication Testing Extra Col b1b1b1b1b1b1b1b1 Kyle NULL +2 2.00 This Test Should work b1b1b1b1b1b1b1b1 JOE NULL +3 3.00 If is does not, I will open a bug b1b1b1b1b1b1b1b1 QA NULL +5 2.00 Replication Testing b1b1b1b1b1b1b1b1 Buda 2 +*** Try to select from slave **** +SELECT * FROM t15 ORDER BY c1; +c1 c2 c3 c4 c5 c6 c7 +1 1.00 Replication Testing Extra Col b1b1b1b1b1b1b1b1 Kyle 1 CURRENT_TIMESTAMP +2 2.00 This Test Should work b1b1b1b1b1b1b1b1 JOE 1 CURRENT_TIMESTAMP +3 3.00 If is does not, I will open a bug b1b1b1b1b1b1b1b1 QA 1 CURRENT_TIMESTAMP +*** DROP TABLE t15 *** +DROP TABLE t15; +*** Create t16 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t16 (c1 INT KEY, c2 DECIMAL(8,2), c3 TEXT, +c4 BLOB, c5 CHAR(5), +c6 INT DEFAULT '1', +c7 TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP +)ENGINE='InnoDB'; +*** Create t16 on Master *** +CREATE TABLE t16 (c1 INT PRIMARY KEY, c2 DECIMAL(8,2), c3 TEXT, +c4 BLOB, c5 CHAR(5))ENGINE='InnoDB'; +RESET MASTER; +*** Start Slave *** +START SLAVE; +*** Master Data Insert *** +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t16 () VALUES(1,1.00,'Replication Testing Extra Col',@b1,'Kyle'), +(2,2.00,'This Test Should work',@b1,'JOE'), +(3,3.00,'If is does not, I will open a bug',@b1,'QA'); +SELECT * FROM t16 ORDER BY c1; +c1 c2 c3 c4 c5 +1 1.00 Replication Testing Extra Col b1b1b1b1b1b1b1b1 Kyle +2 2.00 This Test Should work b1b1b1b1b1b1b1b1 JOE +3 3.00 If is does not, I will open a bug b1b1b1b1b1b1b1b1 QA +*** Select on Slave **** +SELECT * FROM t16 ORDER BY c1; +c1 c2 c3 c4 c5 c6 c7 +1 1.00 Replication Testing Extra Col b1b1b1b1b1b1b1b1 Kyle 1 CURRENT_TIMESTAMP +2 2.00 This Test Should work b1b1b1b1b1b1b1b1 JOE 1 CURRENT_TIMESTAMP +3 3.00 If is does not, I will open a bug b1b1b1b1b1b1b1b1 QA 1 CURRENT_TIMESTAMP +*** Add Partition on master *** +ALTER TABLE t16 PARTITION BY KEY(c1) PARTITIONS 4; +INSERT INTO t16 () VALUES(4,1.00,'Replication Rocks',@b1,'Omer'); +SHOW CREATE TABLE t16; +Table Create Table +t16 CREATE TABLE `t16` ( + `c1` int(11) NOT NULL, + `c2` decimal(8,2) DEFAULT NULL, + `c3` text, + `c4` blob, + `c5` char(5) DEFAULT NULL, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 /*!50100 PARTITION BY KEY (c1) PARTITIONS 4 */ +*** Show table on Slave **** +SHOW CREATE TABLE t16; +Table Create Table +t16 CREATE TABLE `t16` ( + `c1` int(11) NOT NULL, + `c2` decimal(8,2) DEFAULT NULL, + `c3` text, + `c4` blob, + `c5` char(5) DEFAULT NULL, + `c6` int(11) DEFAULT '1', + `c7` timestamp NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 /*!50100 PARTITION BY KEY (c1) PARTITIONS 4 */ +*** DROP TABLE t16 *** +DROP TABLE t16; +*** Alter Master End *** +*** Create t17 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t17 (a SMALLINT, b INT PRIMARY KEY, c CHAR(5), +d FLOAT DEFAULT '2.00', +e CHAR(5) DEFAULT 'TEST2') +ENGINE='InnoDB'; +*** Create t17 on Master *** +CREATE TABLE t17 (a BIGINT PRIMARY KEY, b INT, c CHAR(10) +) ENGINE='InnoDB'; +RESET MASTER; +*** Start Slave *** +START SLAVE; +*** Master Data Insert *** +INSERT INTO t17 () VALUES(9223372036854775807,2,'Kyle, TEX'); +******************************************** +*** Expect slave to fail with Error 1522 *** +******************************************** +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 1522 +Last_Error Column 0 type mismatch - received type 8, test.t17 has type 2 +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; +START SLAVE; +** DROP table t17 *** +DROP TABLE t17; diff --git a/mysql-test/r/rpl_extraCol_myisam.result b/mysql-test/r/rpl_extraCol_myisam.result new file mode 100644 index 00000000000..3c0d1fae4a8 --- /dev/null +++ b/mysql-test/r/rpl_extraCol_myisam.result @@ -0,0 +1,741 @@ +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; +**** Diff Table Def Start **** +*** On Slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t1 (a INT, b INT PRIMARY KEY, c CHAR(20), +d FLOAT DEFAULT '2.00', +e CHAR(4) DEFAULT 'TEST') +ENGINE='MyISAM'; +*** Create t1 on Master *** +CREATE TABLE t1 (a INT PRIMARY KEY, b INT, c CHAR(10) +) ENGINE='MyISAM'; +RESET MASTER; +*** Start Slave *** +START SLAVE; +*** Master Data Insert *** +INSERT INTO t1 () VALUES(1,2,'TEXAS'),(2,1,'AUSTIN'),(3,4,'QA'); +SELECT * FROM t1 ORDER BY a; +a b c +1 2 TEXAS +2 1 AUSTIN +3 4 QA +*** Select from slave *** +SELECT * FROM t1 ORDER BY a; +a b c d e +1 2 TEXAS 2 TEST +2 1 AUSTIN 2 TEST +3 4 QA 2 TEST +*** Drop t1 *** +DROP TABLE t1; +*** Create t3 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t3 (a INT, b INT PRIMARY KEY, c CHAR(20), +d FLOAT DEFAULT '2.00', +e CHAR(5) DEFAULT 'TEST2') +ENGINE='MyISAM'; +*** Create t3 on Master *** +CREATE TABLE t3 (a BLOB, b INT PRIMARY KEY, c CHAR(20) +) ENGINE='MyISAM'; +RESET MASTER; +*** Start Slave *** +START SLAVE; +*** Master Data Insert *** +set @b1 = 'b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t3 () VALUES(@b1,2,'Kyle, TEX'),(@b1,1,'JOE AUSTIN'),(@b1,4,'QA TESTING'); +******************************************** +*** Expect slave to fail with Error 1522 *** +******************************************** +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 1522 +Last_Error Column 0 type mismatch - received type 252, test.t3 has type 3 +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; +START SLAVE; +*** Drop t3 *** +DROP TABLE t3; +*** Create t4 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t4 (a INT, b INT PRIMARY KEY, c CHAR(20), +d FLOAT DEFAULT '2.00', +e CHAR(5) DEFAULT 'TEST2') +ENGINE='MyISAM'; +*** Create t4 on Master *** +CREATE TABLE t4 (a DECIMAL(8,2), b INT PRIMARY KEY, c CHAR(20) +) ENGINE='MyISAM'; +RESET MASTER; +*** Start Slave *** +START SLAVE; +*** Master Data Insert *** +INSERT INTO t4 () VALUES(100.22,2,'Kyle, TEX'),(200.26,1,'JOE AUSTIN'), +(30000.22,4,'QA TESTING'); +******************************************** +*** Expect slave to fail with Error 1522 *** +******************************************** +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 1522 +Last_Error Column 0 type mismatch - received type 246, test.t4 has type 3 +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; +START SLAVE; +*** Drop t4 *** +DROP TABLE t4; +*** Create t5 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t5 (a INT PRIMARY KEY, b CHAR(5), +c FLOAT, d INT, e DOUBLE, +f DECIMAL(8,2))ENGINE='MyISAM'; +*** Create t5 on Master *** +CREATE TABLE t5 (a INT PRIMARY KEY, b VARCHAR(6), +c DECIMAL(8,2), d BIT, e BLOB, +f FLOAT) ENGINE='MyISAM'; +RESET MASTER; +*** Start Slave *** +START SLAVE; +*** Master Data Insert *** +INSERT INTO t5 () VALUES(1,'Kyle',200.23,1,'b1b1',23.00098), +(2,'JOE',300.01,0,'b2b2',1.0000009); +******************************************** +*** Expect slave to fail with Error 1522 *** +******************************************** +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 1522 +Last_Error Column 5 type mismatch - received type 4, test.t5 has type 246 +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; +START SLAVE; +*** Drop t5 *** +DROP TABLE t5; +*** Create t6 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t6 (a INT PRIMARY KEY, b CHAR(5), +c FLOAT, d INT)ENGINE='MyISAM'; +*** Create t6 on Master *** +CREATE TABLE t6 (a INT PRIMARY KEY, b VARCHAR(6), +c DECIMAL(8,2), d BIT +) ENGINE='MyISAM'; +RESET MASTER; +*** Start Slave *** +START SLAVE; +*** Master Data Insert *** +INSERT INTO t6 () VALUES(1,'Kyle',200.23,1), +(2,'JOE',300.01,0); +******************************************** +*** Expect slave to fail with Error 1522 *** +******************************************** +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 1522 +Last_Error Column 3 type mismatch - received type 16, test.t6 has type 3 +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=3; +*** Drop t6 *** +DROP TABLE t6; +DROP TABLE t6; +START SLAVE; +**** Diff Table Def End **** +**** Extra Colums Start **** +*** Create t7 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t7 (a INT KEY, b BLOB, c CHAR(5), +d TIMESTAMP NULL DEFAULT '0000-00-00 00:00:00', +e CHAR(20) DEFAULT 'Extra Column Testing') +ENGINE='MyISAM'; +*** Create t7 on Master *** +CREATE TABLE t7 (a INT PRIMARY KEY, b BLOB, c CHAR(5) +) ENGINE='MyISAM'; +RESET MASTER; +*** Start Slave *** +START SLAVE; +*** Master Data Insert *** +set @b1 = 'b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t7 () VALUES(1,@b1,'Kyle'),(2,@b1,'JOE'),(3,@b1,'QA'); +SELECT * FROM t7 ORDER BY a; +a b c +1 b1b1 Kyle +2 b1b1 JOE +3 b1b1 QA +*** Select from slave *** +SELECT * FROM t7 ORDER BY a; +a b c d e +1 b1b1 Kyle 0000-00-00 00:00:00 Extra Column Testing +2 b1b1 JOE 0000-00-00 00:00:00 Extra Column Testing +3 b1b1 QA 0000-00-00 00:00:00 Extra Column Testing +*** Drop t7 *** +DROP TABLE t7; +*** Create t8 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t8 (a INT KEY, b BLOB, c CHAR(5), +d TIMESTAMP NULL DEFAULT '0000-00-00 00:00:00', +e INT)ENGINE='MyISAM'; +*** Create t8 on Master *** +CREATE TABLE t8 (a INT PRIMARY KEY, b BLOB, c CHAR(5) +) ENGINE='MyISAM'; +RESET MASTER; +*** Start Slave *** +START SLAVE; +*** Master Data Insert *** +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t8 () VALUES(1,@b1,'Kyle'),(2,@b1,'JOE'),(3,@b1,'QA'); +*** Drop t8 *** +DROP TABLE t8; +*** Create t10 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t10 (a INT KEY, b BLOB, f DOUBLE DEFAULT '233', +c CHAR(5), e INT DEFAULT '1')ENGINE='MyISAM'; +*** Create t10 on Master *** +CREATE TABLE t10 (a INT PRIMARY KEY, b BLOB, c CHAR(5) +) ENGINE='MyISAM'; +RESET MASTER; +*** Start Slave *** +START SLAVE; +*** Master Data Insert *** +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t10 () VALUES(1,@b1,'Kyle'),(2,@b1,'JOE'),(3,@b1,'QA'); +******************************************** +*** Expect slave to fail with Error 1522 *** +******************************************** +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 1522 +Last_Error Column 2 type mismatch - received type 254, test.t10 has type 5 +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; +START SLAVE; +*** Drop t10 *** +DROP TABLE t10; +*** Create t11 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t11 (a INT KEY, b BLOB, f TEXT, +c CHAR(5) DEFAULT 'test', e INT DEFAULT '1')ENGINE='MyISAM'; +*** Create t11 on Master *** +CREATE TABLE t11 (a INT PRIMARY KEY, b BLOB, c VARCHAR(254) +) ENGINE='MyISAM'; +RESET MASTER; +*** Start Slave *** +START SLAVE; +*** Master Data Insert *** +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t11 () VALUES(1,@b1,'Kyle'),(2,@b1,'JOE'),(3,@b1,'QA'); +******************************************** +*** Expect slave to fail with Error 1522 *** +******************************************** +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 1522 +Last_Error Column 2 type mismatch - received type 15, test.t11 has type 252 +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; +START SLAVE; +*** Drop t11 *** +DROP TABLE t11; +*** Create t12 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t12 (a INT KEY, b BLOB, f TEXT, +c CHAR(5) DEFAULT 'test', e INT DEFAULT '1')ENGINE='MyISAM'; +*** Create t12 on Master *** +CREATE TABLE t12 (a INT PRIMARY KEY, b BLOB, c BLOB +) ENGINE='MyISAM'; +RESET MASTER; +*** Start Slave *** +START SLAVE; +*** Master Data Insert *** +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t12 () VALUES(1,@b1,'Kyle'),(2,@b1,'JOE'),(3,@b1,'QA'); +SELECT * FROM t12 ORDER BY a; +a b c +1 b1b1b1b1b1b1b1b1 Kyle +2 b1b1b1b1b1b1b1b1 JOE +3 b1b1b1b1b1b1b1b1 QA +*** Select on Slave *** +SELECT * FROM t12 ORDER BY a; +a b f c e +1 b1b1b1b1b1b1b1b1 Kyle test 1 +2 b1b1b1b1b1b1b1b1 JOE test 1 +3 b1b1b1b1b1b1b1b1 QA test 1 +*** Drop t12 *** +DROP TABLE t12; +**** Extra Colums End **** +*** BUG 22177 Start *** +*** Create t13 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t13 (a INT KEY, b BLOB, c CHAR(5), +d INT DEFAULT '1', +e TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP +)ENGINE='MyISAM'; +*** Create t13 on Master *** +CREATE TABLE t13 (a INT PRIMARY KEY, b BLOB, c CHAR(5) +) ENGINE='MyISAM'; +RESET MASTER; +*** Start Slave *** +START SLAVE; +*** Master Data Insert *** +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t13 () VALUES(1,@b1,'Kyle'),(2,@b1,'JOE'),(3,@b1,'QA'); +SELECT * FROM t13 ORDER BY a; +a b c +1 b1b1b1b1b1b1b1b1 Kyle +2 b1b1b1b1b1b1b1b1 JOE +3 b1b1b1b1b1b1b1b1 QA +*** Select on Slave **** +SELECT * FROM t13 ORDER BY a; +a b c d e +1 b1b1b1b1b1b1b1b1 Kyle 1 CURRENT_TIMESTAMP +2 b1b1b1b1b1b1b1b1 JOE 1 CURRENT_TIMESTAMP +3 b1b1b1b1b1b1b1b1 QA 1 CURRENT_TIMESTAMP +*** Drop t13 *** +DROP TABLE t13; +*** 22117 END *** +*** Alter Master Table Testing Start *** +*** Create t14 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t14 (c1 INT KEY, c4 BLOB, c5 CHAR(5), +c6 INT DEFAULT '1', +c7 TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP +)ENGINE='MyISAM'; +*** Create t14 on Master *** +CREATE TABLE t14 (c1 INT PRIMARY KEY, c4 BLOB, c5 CHAR(5) +) ENGINE='MyISAM'; +RESET MASTER; +*** Start Slave *** +START SLAVE; +*** Master Data Insert *** +ALTER TABLE t14 ADD COLUMN c2 DECIMAL(8,2) AFTER c1; +ALTER TABLE t14 ADD COLUMN c3 TEXT AFTER c2; +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t14 () VALUES(1,1.00,'Replication Testing Extra Col',@b1,'Kyle'), +(2,2.00,'This Test Should work',@b1,'JOE'), +(3,3.00,'If is does not, I will open a bug',@b1,'QA'); +SELECT * FROM t14 ORDER BY c1; +c1 c2 c3 c4 c5 +1 1.00 Replication Testing Extra Col b1b1b1b1b1b1b1b1 Kyle +2 2.00 This Test Should work b1b1b1b1b1b1b1b1 JOE +3 3.00 If is does not, I will open a bug b1b1b1b1b1b1b1b1 QA +*** Select on Slave **** +SELECT * FROM t14 ORDER BY c1; +c1 c2 c3 c4 c5 c6 c7 +1 1.00 Replication Testing Extra Col b1b1b1b1b1b1b1b1 Kyle 1 CURRENT_TIMESTAMP +2 2.00 This Test Should work b1b1b1b1b1b1b1b1 JOE 1 CURRENT_TIMESTAMP +3 3.00 If is does not, I will open a bug b1b1b1b1b1b1b1b1 QA 1 CURRENT_TIMESTAMP +*** connect to master and drop columns *** +ALTER TABLE t14 DROP COLUMN c2; +ALTER TABLE t14 DROP COLUMN c4; +*** Select from Master *** +SELECT * FROM t14 ORDER BY c1; +c1 c3 c5 +1 Replication Testing Extra Col Kyle +2 This Test Should work JOE +3 If is does not, I will open a bug QA +*** Select from Slave *** +SELECT * FROM t14 ORDER BY c1; +c1 c3 c5 c6 c7 +1 Replication Testing Extra Col Kyle 1 CURRENT_TIMESTAMP +2 This Test Should work JOE 1 CURRENT_TIMESTAMP +3 If is does not, I will open a bug QA 1 CURRENT_TIMESTAMP +*** Drop t14 *** +DROP TABLE t14; +*** Create t15 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t15 (c1 INT KEY, c2 DECIMAL(8,2), c3 TEXT, +c4 BLOB, c5 CHAR(5), +c6 INT DEFAULT '1', +c7 TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP +)ENGINE='MyISAM'; +*** Create t15 on Master *** +CREATE TABLE t15 (c1 INT PRIMARY KEY, c2 DECIMAL(8,2), c3 TEXT, +c4 BLOB, c5 CHAR(5)) ENGINE='MyISAM'; +RESET MASTER; +*** Start Slave *** +START SLAVE; +*** Master Data Insert *** +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t15 () VALUES(1,1.00,'Replication Testing Extra Col',@b1,'Kyle'), +(2,2.00,'This Test Should work',@b1,'JOE'), +(3,3.00,'If is does not, I will open a bug',@b1,'QA'); +SELECT * FROM t15 ORDER BY c1; +c1 c2 c3 c4 c5 +1 1.00 Replication Testing Extra Col b1b1b1b1b1b1b1b1 Kyle +2 2.00 This Test Should work b1b1b1b1b1b1b1b1 JOE +3 3.00 If is does not, I will open a bug b1b1b1b1b1b1b1b1 QA +*** Select on Slave **** +SELECT * FROM t15 ORDER BY c1; +c1 c2 c3 c4 c5 c6 c7 +1 1.00 Replication Testing Extra Col b1b1b1b1b1b1b1b1 Kyle 1 CURRENT_TIMESTAMP +2 2.00 This Test Should work b1b1b1b1b1b1b1b1 JOE 1 CURRENT_TIMESTAMP +3 3.00 If is does not, I will open a bug b1b1b1b1b1b1b1b1 QA 1 CURRENT_TIMESTAMP +*** Add column on master that is a Extra on Slave *** +ALTER TABLE t15 ADD COLUMN c6 INT AFTER c5; +******************************************** +*** Expect slave to fail with Error 1060 *** +******************************************** +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 1060 +Last_Error Error 'Duplicate column name 'c6'' on query. Default database: 'test'. Query: 'ALTER TABLE t15 ADD COLUMN c6 INT AFTER c5' +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; +START SLAVE; +*** Try to insert in master **** +INSERT INTO t15 () VALUES(5,2.00,'Replication Testing',@b1,'Buda',2); +SELECT * FROM t15 ORDER BY c1; +c1 c2 c3 c4 c5 c6 +1 1.00 Replication Testing Extra Col b1b1b1b1b1b1b1b1 Kyle NULL +2 2.00 This Test Should work b1b1b1b1b1b1b1b1 JOE NULL +3 3.00 If is does not, I will open a bug b1b1b1b1b1b1b1b1 QA NULL +5 2.00 Replication Testing b1b1b1b1b1b1b1b1 Buda 2 +*** Try to select from slave **** +SELECT * FROM t15 ORDER BY c1; +c1 c2 c3 c4 c5 c6 c7 +1 1.00 Replication Testing Extra Col b1b1b1b1b1b1b1b1 Kyle 1 CURRENT_TIMESTAMP +2 2.00 This Test Should work b1b1b1b1b1b1b1b1 JOE 1 CURRENT_TIMESTAMP +3 3.00 If is does not, I will open a bug b1b1b1b1b1b1b1b1 QA 1 CURRENT_TIMESTAMP +*** DROP TABLE t15 *** +DROP TABLE t15; +*** Create t16 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t16 (c1 INT KEY, c2 DECIMAL(8,2), c3 TEXT, +c4 BLOB, c5 CHAR(5), +c6 INT DEFAULT '1', +c7 TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP +)ENGINE='MyISAM'; +*** Create t16 on Master *** +CREATE TABLE t16 (c1 INT PRIMARY KEY, c2 DECIMAL(8,2), c3 TEXT, +c4 BLOB, c5 CHAR(5))ENGINE='MyISAM'; +RESET MASTER; +*** Start Slave *** +START SLAVE; +*** Master Data Insert *** +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t16 () VALUES(1,1.00,'Replication Testing Extra Col',@b1,'Kyle'), +(2,2.00,'This Test Should work',@b1,'JOE'), +(3,3.00,'If is does not, I will open a bug',@b1,'QA'); +SELECT * FROM t16 ORDER BY c1; +c1 c2 c3 c4 c5 +1 1.00 Replication Testing Extra Col b1b1b1b1b1b1b1b1 Kyle +2 2.00 This Test Should work b1b1b1b1b1b1b1b1 JOE +3 3.00 If is does not, I will open a bug b1b1b1b1b1b1b1b1 QA +*** Select on Slave **** +SELECT * FROM t16 ORDER BY c1; +c1 c2 c3 c4 c5 c6 c7 +1 1.00 Replication Testing Extra Col b1b1b1b1b1b1b1b1 Kyle 1 CURRENT_TIMESTAMP +2 2.00 This Test Should work b1b1b1b1b1b1b1b1 JOE 1 CURRENT_TIMESTAMP +3 3.00 If is does not, I will open a bug b1b1b1b1b1b1b1b1 QA 1 CURRENT_TIMESTAMP +*** Add Partition on master *** +ALTER TABLE t16 PARTITION BY KEY(c1) PARTITIONS 4; +INSERT INTO t16 () VALUES(4,1.00,'Replication Rocks',@b1,'Omer'); +SHOW CREATE TABLE t16; +Table Create Table +t16 CREATE TABLE `t16` ( + `c1` int(11) NOT NULL, + `c2` decimal(8,2) DEFAULT NULL, + `c3` text, + `c4` blob, + `c5` char(5) DEFAULT NULL, + PRIMARY KEY (`c1`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 /*!50100 PARTITION BY KEY (c1) PARTITIONS 4 */ +*** Show table on Slave **** +SHOW CREATE TABLE t16; +Table Create Table +t16 CREATE TABLE `t16` ( + `c1` int(11) NOT NULL, + `c2` decimal(8,2) DEFAULT NULL, + `c3` text, + `c4` blob, + `c5` char(5) DEFAULT NULL, + `c6` int(11) DEFAULT '1', + `c7` timestamp NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`c1`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 /*!50100 PARTITION BY KEY (c1) PARTITIONS 4 */ +*** DROP TABLE t16 *** +DROP TABLE t16; +*** Alter Master End *** +*** Create t17 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t17 (a SMALLINT, b INT PRIMARY KEY, c CHAR(5), +d FLOAT DEFAULT '2.00', +e CHAR(5) DEFAULT 'TEST2') +ENGINE='MyISAM'; +*** Create t17 on Master *** +CREATE TABLE t17 (a BIGINT PRIMARY KEY, b INT, c CHAR(10) +) ENGINE='MyISAM'; +RESET MASTER; +*** Start Slave *** +START SLAVE; +*** Master Data Insert *** +INSERT INTO t17 () VALUES(9223372036854775807,2,'Kyle, TEX'); +******************************************** +*** Expect slave to fail with Error 1522 *** +******************************************** +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 1522 +Last_Error Column 0 type mismatch - received type 8, test.t17 has type 2 +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; +START SLAVE; +** DROP table t17 *** +DROP TABLE t17; 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_load_from_master.result b/mysql-test/r/rpl_load_from_master.result index c279ee6e0aa..08b45ec1db0 100644 --- a/mysql-test/r/rpl_load_from_master.result +++ b/mysql-test/r/rpl_load_from_master.result @@ -33,7 +33,6 @@ create database mysqltest; show databases; Database information_schema -cluster mysql mysqltest mysqltest2 @@ -51,7 +50,6 @@ set sql_log_bin = 1; show databases; Database information_schema -cluster mysql test create database mysqltest2; @@ -71,7 +69,6 @@ load data from master; show databases; Database information_schema -cluster mysql mysqltest mysqltest2 diff --git a/mysql-test/r/rpl_loaddata_m.result b/mysql-test/r/rpl_loaddata_m.result index ec2f788a5e1..9dbae6d38c4 100644 --- a/mysql-test/r/rpl_loaddata_m.result +++ b/mysql-test/r/rpl_loaddata_m.result @@ -21,7 +21,6 @@ COUNT(*) SHOW DATABASES; Database information_schema -cluster mysql mysqltest test diff --git a/mysql-test/r/rpl_ndb_bank.result b/mysql-test/r/rpl_ndb_bank.result index 62ab3f18d37..06c005427d1 100644 --- a/mysql-test/r/rpl_ndb_bank.result +++ b/mysql-test/r/rpl_ndb_bank.result @@ -47,17 +47,17 @@ CREATE DATABASE IF NOT EXISTS BANK; DROP DATABASE BANK; CREATE DATABASE BANK; RESET MASTER; -CREATE TABLE IF NOT EXISTS cluster.backup_info (id INT, backup_id INT) ENGINE = HEAP; -DELETE FROM cluster.backup_info; -LOAD DATA INFILE '../tmp.dat' INTO TABLE cluster.backup_info FIELDS TERMINATED BY ','; -SELECT @the_backup_id:=backup_id FROM cluster.backup_info; +CREATE TABLE IF NOT EXISTS mysql.backup_info (id INT, backup_id INT) ENGINE = HEAP; +DELETE FROM mysql.backup_info; +LOAD DATA INFILE '../tmp.dat' INTO TABLE mysql.backup_info FIELDS TERMINATED BY ','; +SELECT @the_backup_id:=backup_id FROM mysql.backup_info; @the_backup_id:=backup_id <the_backup_id> -SELECT @the_epoch:=MAX(epoch) FROM cluster.apply_status; +SELECT @the_epoch:=MAX(epoch) FROM mysql.apply_status; @the_epoch:=MAX(epoch) <the_epoch> SELECT @the_pos:=Position,@the_file:=SUBSTRING_INDEX(FILE, '/', -1) -FROM cluster.binlog_index WHERE epoch > <the_epoch> ORDER BY epoch ASC LIMIT 1; +FROM mysql.binlog_index WHERE epoch > <the_epoch> ORDER BY epoch ASC LIMIT 1; @the_pos:=Position @the_file:=SUBSTRING_INDEX(FILE, '/', -1) <the_pos> master-bin.000001 CHANGE MASTER TO diff --git a/mysql-test/r/rpl_ndb_dd_advance.result b/mysql-test/r/rpl_ndb_dd_advance.result index bbc67a04027..c52fe7114c4 100644 --- a/mysql-test/r/rpl_ndb_dd_advance.result +++ b/mysql-test/r/rpl_ndb_dd_advance.result @@ -326,12 +326,12 @@ COUNT(*) **** Must make sure slave is clean ***** STOP SLAVE; RESET SLAVE; -DROP PROCEDURE tpcb.load; -DROP PROCEDURE tpcb.trans; -DROP TABLE tpcb.account; -DROP TABLE tpcb.teller; -DROP TABLE tpcb.branch; -DROP TABLE tpcb.history; +DROP PROCEDURE IF EXISTS tpcb.load; +DROP PROCEDURE IF EXISTS tpcb.trans; +DROP TABLE IF EXISTS tpcb.account; +DROP TABLE IF EXISTS tpcb.teller; +DROP TABLE IF EXISTS tpcb.branch; +DROP TABLE IF EXISTS tpcb.history; DROP DATABASE tpcb; ALTER TABLESPACE ts1 DROP DATAFILE 'datafile.dat' @@ -355,13 +355,13 @@ COUNT(*) SELECT COUNT(*) FROM history; COUNT(*) 2000 -CREATE TEMPORARY TABLE IF NOT EXISTS cluster.backup_info (id INT, backup_id INT) ENGINE = HEAP; -DELETE FROM cluster.backup_info; -LOAD DATA INFILE '../tmp.dat' INTO TABLE cluster.backup_info FIELDS TERMINATED BY ','; -SELECT @the_backup_id:=backup_id FROM cluster.backup_info; +CREATE TEMPORARY TABLE IF NOT EXISTS mysql.backup_info (id INT, backup_id INT) ENGINE = HEAP; +DELETE FROM mysql.backup_info; +LOAD DATA INFILE '../tmp.dat' INTO TABLE mysql.backup_info FIELDS TERMINATED BY ','; +SELECT @the_backup_id:=backup_id FROM mysql.backup_info; @the_backup_id:=backup_id <the_backup_id> -DROP TABLE IF EXISTS cluster.backup_info; +DROP TABLE IF EXISTS mysql.backup_info; ************ Restore the slave ************************ CREATE DATABASE tpcb; ***** Check a few slave restore values *************** @@ -392,8 +392,8 @@ COUNT(*) 4050 *** DUMP MASTER & SLAVE FOR COMPARE ******** *************** TEST 2 CLEANUP SECTION ******************** -DROP PROCEDURE tpcb.load; -DROP PROCEDURE tpcb.trans; +DROP PROCEDURE IF EXISTS tpcb.load; +DROP PROCEDURE IF EXISTS tpcb.trans; DROP TABLE tpcb.account; DROP TABLE tpcb.teller; DROP TABLE tpcb.branch; diff --git a/mysql-test/r/rpl_ndb_dd_basic.result b/mysql-test/r/rpl_ndb_dd_basic.result index bb5919193eb..75323767427 100644 --- a/mysql-test/r/rpl_ndb_dd_basic.result +++ b/mysql-test/r/rpl_ndb_dd_basic.result @@ -57,7 +57,7 @@ tablespace ts1 storage disk engine ndb master-bin.000001 # Query # # BEGIN master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Table_map # # table_id: # (cluster.apply_status) +master-bin.000001 # Table_map # # table_id: # (mysql.apply_status) master-bin.000001 # Write_rows # # table_id: # master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F master-bin.000001 # Query # # COMMIT diff --git a/mysql-test/r/rpl_ndb_ddl.result b/mysql-test/r/rpl_ndb_ddl.result index de35175bf18..f5d8073be94 100644 --- a/mysql-test/r/rpl_ndb_ddl.result +++ b/mysql-test/r/rpl_ndb_ddl.result @@ -359,8 +359,6 @@ MAX(f1) -------- switch to master ------- ROLLBACK; -Warnings: -Warning 1196 Some non-transactional changed tables couldn't be rolled back SELECT MAX(f1) FROM t1; MAX(f1) 5 @@ -370,9 +368,9 @@ TEST-INFO: MASTER: The INSERT is not committed (Succeeded) -------- switch to slave -------- SELECT MAX(f1) FROM t1; MAX(f1) -6 +5 -TEST-INFO: SLAVE: The INSERT is committed (Succeeded) +TEST-INFO: SLAVE: The INSERT is not committed (Succeeded) -------- switch to master ------- flush logs; @@ -401,7 +399,7 @@ MAX(f1) -------- switch to slave -------- SELECT MAX(f1) FROM t1; MAX(f1) -6 +5 -------- switch to master ------- RENAME TABLE mysqltest1.t3 to mysqltest1.t20; @@ -506,7 +504,7 @@ f2 bigint(20) YES NULL -------- switch to master ------- -######## CREATE TABLE mysqltest1.t21 (f1 BIGINT) ENGINE= "InnoDB" ######## +######## CREATE TABLE mysqltest1.t21 (f1 BIGINT) ENGINE= "NDB" ######## -------- switch to master ------- INSERT INTO t1 SET f1= 7 + 1; @@ -520,7 +518,7 @@ MAX(f1) 7 -------- switch to master ------- -CREATE TABLE mysqltest1.t21 (f1 BIGINT) ENGINE= "InnoDB"; +CREATE TABLE mysqltest1.t21 (f1 BIGINT) ENGINE= "NDB"; SELECT MAX(f1) FROM t1; MAX(f1) 8 @@ -579,8 +577,6 @@ MAX(f1) -------- switch to master ------- ROLLBACK; -Warnings: -Warning 1196 Some non-transactional changed tables couldn't be rolled back SELECT MAX(f1) FROM t1; MAX(f1) 8 @@ -590,9 +586,9 @@ TEST-INFO: MASTER: The INSERT is not committed (Succeeded) -------- switch to slave -------- SELECT MAX(f1) FROM t1; MAX(f1) -9 +8 -TEST-INFO: SLAVE: The INSERT is committed (Succeeded) +TEST-INFO: SLAVE: The INSERT is not committed (Succeeded) -------- switch to master ------- flush logs; @@ -613,7 +609,7 @@ MAX(f1) -------- switch to slave -------- SELECT MAX(f1) FROM t1; MAX(f1) -9 +8 -------- switch to master ------- TRUNCATE TABLE mysqltest1.t7; @@ -650,11 +646,9 @@ flush logs; -------- switch to master ------- SELECT * FROM mysqltest1.t7; f1 - -------- switch to slave -------- SELECT * FROM mysqltest1.t7; f1 - -------- switch to master ------- ######## LOCK TABLES mysqltest1.t1 WRITE, mysqltest1.t8 READ ######## @@ -957,7 +951,7 @@ t5 1 my_idx5 1 f1 A 0 NULL NULL YES BTREE -------- switch to slave -------- SHOW INDEX FROM mysqltest1.t5; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment -t5 1 my_idx5 1 f1 A NULL NULL NULL YES BTREE +t5 1 my_idx5 1 f1 A 0 NULL NULL YES BTREE -------- switch to master ------- @@ -1691,3 +1685,4 @@ user DROP DATABASE IF EXISTS mysqltest1; DROP DATABASE IF EXISTS mysqltest2; DROP DATABASE IF EXISTS mysqltest3; +ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction diff --git a/mysql-test/r/rpl_ndb_extraCol.result b/mysql-test/r/rpl_ndb_extraCol.result new file mode 100644 index 00000000000..e51fae29c54 --- /dev/null +++ b/mysql-test/r/rpl_ndb_extraCol.result @@ -0,0 +1,742 @@ +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; +**** Diff Table Def Start **** +*** On Slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t1 (a INT, b INT PRIMARY KEY, c CHAR(20), +d FLOAT DEFAULT '2.00', +e CHAR(4) DEFAULT 'TEST') +ENGINE='NDB'; +*** Create t1 on Master *** +CREATE TABLE t1 (a INT PRIMARY KEY, b INT, c CHAR(10) +) ENGINE='NDB'; +RESET MASTER; +*** Start Slave *** +START SLAVE; +*** Master Data Insert *** +INSERT INTO t1 () VALUES(1,2,'TEXAS'),(2,1,'AUSTIN'),(3,4,'QA'); +SELECT * FROM t1 ORDER BY a; +a b c +1 2 TEXAS +2 1 AUSTIN +3 4 QA +*** Select from slave *** +SELECT * FROM t1 ORDER BY a; +a b c d e +1 2 TEXAS 2 TEST +2 1 AUSTIN 2 TEST +3 4 QA 2 TEST +*** Drop t1 *** +DROP TABLE t1; +*** Create t3 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t3 (a INT, b INT PRIMARY KEY, c CHAR(20), +d FLOAT DEFAULT '2.00', +e CHAR(5) DEFAULT 'TEST2') +ENGINE='NDB'; +*** Create t3 on Master *** +CREATE TABLE t3 (a BLOB, b INT PRIMARY KEY, c CHAR(20) +) ENGINE='NDB'; +RESET MASTER; +*** Start Slave *** +START SLAVE; +*** Master Data Insert *** +set @b1 = 'b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t3 () VALUES(@b1,2,'Kyle, TEX'),(@b1,1,'JOE AUSTIN'),(@b1,4,'QA TESTING'); +******************************************** +*** Expect slave to fail with Error 1522 *** +******************************************** +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 1522 +Last_Error Column 0 type mismatch - received type 252, test.t3 has type 3 +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; +START SLAVE; +*** Drop t3 *** +DROP TABLE t3; +*** Create t4 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t4 (a INT, b INT PRIMARY KEY, c CHAR(20), +d FLOAT DEFAULT '2.00', +e CHAR(5) DEFAULT 'TEST2') +ENGINE='NDB'; +*** Create t4 on Master *** +CREATE TABLE t4 (a DECIMAL(8,2), b INT PRIMARY KEY, c CHAR(20) +) ENGINE='NDB'; +RESET MASTER; +*** Start Slave *** +START SLAVE; +*** Master Data Insert *** +INSERT INTO t4 () VALUES(100.22,2,'Kyle, TEX'),(200.26,1,'JOE AUSTIN'), +(30000.22,4,'QA TESTING'); +******************************************** +*** Expect slave to fail with Error 1522 *** +******************************************** +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 1522 +Last_Error Column 0 type mismatch - received type 246, test.t4 has type 3 +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; +START SLAVE; +*** Drop t4 *** +DROP TABLE t4; +*** Create t5 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t5 (a INT PRIMARY KEY, b CHAR(5), +c FLOAT, d INT, e DOUBLE, +f DECIMAL(8,2))ENGINE='NDB'; +*** Create t5 on Master *** +CREATE TABLE t5 (a INT PRIMARY KEY, b VARCHAR(6), +c DECIMAL(8,2), d BIT, e BLOB, +f FLOAT) ENGINE='NDB'; +RESET MASTER; +*** Start Slave *** +START SLAVE; +*** Master Data Insert *** +INSERT INTO t5 () VALUES(1,'Kyle',200.23,1,'b1b1',23.00098), +(2,'JOE',300.01,0,'b2b2',1.0000009); +******************************************** +*** Expect slave to fail with Error 1522 *** +******************************************** +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 1522 +Last_Error Column 5 type mismatch - received type 4, test.t5 has type 246 +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; +START SLAVE; +*** Drop t5 *** +DROP TABLE t5; +*** Create t6 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t6 (a INT PRIMARY KEY, b CHAR(5), +c FLOAT, d INT)ENGINE='NDB'; +*** Create t6 on Master *** +CREATE TABLE t6 (a INT PRIMARY KEY, b VARCHAR(6), +c DECIMAL(8,2), d BIT +) ENGINE='NDB'; +RESET MASTER; +*** Start Slave *** +START SLAVE; +*** Master Data Insert *** +INSERT INTO t6 () VALUES(1,'Kyle',200.23,1), +(2,'JOE',300.01,0); +******************************************** +*** Expect slave to fail with Error 1522 *** +******************************************** +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 1522 +Last_Error Column 3 type mismatch - received type 16, test.t6 has type 3 +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=3; +*** Drop t6 *** +DROP TABLE t6; +DROP TABLE t6; +START SLAVE; +**** Diff Table Def End **** +**** Extra Colums Start **** +*** Create t7 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t7 (a INT KEY, b BLOB, c CHAR(5), +d TIMESTAMP NULL DEFAULT '0000-00-00 00:00:00', +e CHAR(20) DEFAULT 'Extra Column Testing') +ENGINE='NDB'; +*** Create t7 on Master *** +CREATE TABLE t7 (a INT PRIMARY KEY, b BLOB, c CHAR(5) +) ENGINE='NDB'; +RESET MASTER; +*** Start Slave *** +START SLAVE; +*** Master Data Insert *** +set @b1 = 'b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t7 () VALUES(1,@b1,'Kyle'),(2,@b1,'JOE'),(3,@b1,'QA'); +SELECT * FROM t7 ORDER BY a; +a b c +1 b1b1 Kyle +2 b1b1 JOE +3 b1b1 QA +*** Select from slave *** +SELECT * FROM t7 ORDER BY a; +a b c d e +1 b1b1 Kyle 0000-00-00 00:00:00 Extra Column Testing +2 b1b1 JOE 0000-00-00 00:00:00 Extra Column Testing +3 b1b1 QA 0000-00-00 00:00:00 Extra Column Testing +*** Drop t7 *** +DROP TABLE t7; +*** Create t8 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t8 (a INT KEY, b BLOB, c CHAR(5), +d TIMESTAMP NULL DEFAULT '0000-00-00 00:00:00', +e INT)ENGINE='NDB'; +*** Create t8 on Master *** +CREATE TABLE t8 (a INT PRIMARY KEY, b BLOB, c CHAR(5) +) ENGINE='NDB'; +RESET MASTER; +*** Start Slave *** +START SLAVE; +*** Master Data Insert *** +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t8 () VALUES(1,@b1,'Kyle'),(2,@b1,'JOE'),(3,@b1,'QA'); +*** Drop t8 *** +DROP TABLE t8; +*** Create t10 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t10 (a INT KEY, b BLOB, f DOUBLE DEFAULT '233', +c CHAR(5), e INT DEFAULT '1')ENGINE='NDB'; +*** Create t10 on Master *** +CREATE TABLE t10 (a INT PRIMARY KEY, b BLOB, c CHAR(5) +) ENGINE='NDB'; +RESET MASTER; +*** Start Slave *** +START SLAVE; +*** Master Data Insert *** +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t10 () VALUES(1,@b1,'Kyle'),(2,@b1,'JOE'),(3,@b1,'QA'); +******************************************** +*** Expect slave to fail with Error 1522 *** +******************************************** +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 1522 +Last_Error Column 2 type mismatch - received type 254, test.t10 has type 5 +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; +START SLAVE; +*** Drop t10 *** +DROP TABLE t10; +*** Create t11 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t11 (a INT KEY, b BLOB, f TEXT, +c CHAR(5) DEFAULT 'test', e INT DEFAULT '1')ENGINE='NDB'; +*** Create t11 on Master *** +CREATE TABLE t11 (a INT PRIMARY KEY, b BLOB, c VARCHAR(254) +) ENGINE='NDB'; +RESET MASTER; +*** Start Slave *** +START SLAVE; +*** Master Data Insert *** +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t11 () VALUES(1,@b1,'Kyle'),(2,@b1,'JOE'),(3,@b1,'QA'); +******************************************** +*** Expect slave to fail with Error 1522 *** +******************************************** +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 1522 +Last_Error Column 2 type mismatch - received type 15, test.t11 has type 252 +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; +START SLAVE; +*** Drop t11 *** +DROP TABLE t11; +*** Create t12 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t12 (a INT KEY, b BLOB, f TEXT, +c CHAR(5) DEFAULT 'test', e INT DEFAULT '1')ENGINE='NDB'; +*** Create t12 on Master *** +CREATE TABLE t12 (a INT PRIMARY KEY, b BLOB, c BLOB +) ENGINE='NDB'; +RESET MASTER; +*** Start Slave *** +START SLAVE; +*** Master Data Insert *** +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t12 () VALUES(1,@b1,'Kyle'),(2,@b1,'JOE'),(3,@b1,'QA'); +SELECT * FROM t12 ORDER BY a; +a b c +1 b1b1b1b1b1b1b1b1 Kyle +2 b1b1b1b1b1b1b1b1 JOE +3 b1b1b1b1b1b1b1b1 QA +*** Select on Slave *** +SELECT * FROM t12 ORDER BY a; +a b f c e +1 b1b1b1b1b1b1b1b1 Kyle test 1 +2 b1b1b1b1b1b1b1b1 JOE test 1 +3 b1b1b1b1b1b1b1b1 QA test 1 +*** Drop t12 *** +DROP TABLE t12; +**** Extra Colums End **** +*** BUG 22177 Start *** +*** Create t13 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t13 (a INT KEY, b BLOB, c CHAR(5), +d INT DEFAULT '1', +e TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP +)ENGINE='NDB'; +*** Create t13 on Master *** +CREATE TABLE t13 (a INT PRIMARY KEY, b BLOB, c CHAR(5) +) ENGINE='NDB'; +RESET MASTER; +*** Start Slave *** +START SLAVE; +*** Master Data Insert *** +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t13 () VALUES(1,@b1,'Kyle'),(2,@b1,'JOE'),(3,@b1,'QA'); +SELECT * FROM t13 ORDER BY a; +a b c +1 b1b1b1b1b1b1b1b1 Kyle +2 b1b1b1b1b1b1b1b1 JOE +3 b1b1b1b1b1b1b1b1 QA +*** Select on Slave **** +SELECT * FROM t13 ORDER BY a; +a b c d e +1 b1b1b1b1b1b1b1b1 Kyle 1 CURRENT_TIMESTAMP +2 b1b1b1b1b1b1b1b1 JOE 1 CURRENT_TIMESTAMP +3 b1b1b1b1b1b1b1b1 QA 1 CURRENT_TIMESTAMP +*** Drop t13 *** +DROP TABLE t13; +*** 22117 END *** +*** Alter Master Table Testing Start *** +*** Create t14 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t14 (c1 INT KEY, c4 BLOB, c5 CHAR(5), +c6 INT DEFAULT '1', +c7 TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP +)ENGINE='NDB'; +*** Create t14 on Master *** +CREATE TABLE t14 (c1 INT PRIMARY KEY, c4 BLOB, c5 CHAR(5) +) ENGINE='NDB'; +RESET MASTER; +*** Start Slave *** +START SLAVE; +*** Master Data Insert *** +ALTER TABLE t14 ADD COLUMN c2 DECIMAL(8,2) AFTER c1; +ALTER TABLE t14 ADD COLUMN c3 TEXT AFTER c2; +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t14 () VALUES(1,1.00,'Replication Testing Extra Col',@b1,'Kyle'), +(2,2.00,'This Test Should work',@b1,'JOE'), +(3,3.00,'If is does not, I will open a bug',@b1,'QA'); +SELECT * FROM t14 ORDER BY c1; +c1 c2 c3 c4 c5 +1 1.00 Replication Testing Extra Col b1b1b1b1b1b1b1b1 Kyle +2 2.00 This Test Should work b1b1b1b1b1b1b1b1 JOE +3 3.00 If is does not, I will open a bug b1b1b1b1b1b1b1b1 QA +*** Select on Slave **** +SELECT * FROM t14 ORDER BY c1; +c1 c2 c3 c4 c5 c6 c7 +1 1.00 Replication Testing Extra Col b1b1b1b1b1b1b1b1 Kyle 1 CURRENT_TIMESTAMP +2 2.00 This Test Should work b1b1b1b1b1b1b1b1 JOE 1 CURRENT_TIMESTAMP +3 3.00 If is does not, I will open a bug b1b1b1b1b1b1b1b1 QA 1 CURRENT_TIMESTAMP +*** connect to master and drop columns *** +ALTER TABLE t14 DROP COLUMN c2; +ALTER TABLE t14 DROP COLUMN c4; +*** Select from Master *** +SELECT * FROM t14 ORDER BY c1; +c1 c3 c5 +1 Replication Testing Extra Col Kyle +2 This Test Should work JOE +3 If is does not, I will open a bug QA +*** Select from Slave *** +SELECT * FROM t14 ORDER BY c1; +c1 c3 c5 c6 c7 +1 Replication Testing Extra Col Kyle 1 CURRENT_TIMESTAMP +2 This Test Should work JOE 1 CURRENT_TIMESTAMP +3 If is does not, I will open a bug QA 1 CURRENT_TIMESTAMP +*** Drop t14 *** +DROP TABLE t14; +*** Create t15 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t15 (c1 INT KEY, c2 DECIMAL(8,2), c3 TEXT, +c4 BLOB, c5 CHAR(5), +c6 INT DEFAULT '1', +c7 TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP +)ENGINE='NDB'; +*** Create t15 on Master *** +CREATE TABLE t15 (c1 INT PRIMARY KEY, c2 DECIMAL(8,2), c3 TEXT, +c4 BLOB, c5 CHAR(5)) ENGINE='NDB'; +RESET MASTER; +*** Start Slave *** +START SLAVE; +*** Master Data Insert *** +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t15 () VALUES(1,1.00,'Replication Testing Extra Col',@b1,'Kyle'), +(2,2.00,'This Test Should work',@b1,'JOE'), +(3,3.00,'If is does not, I will open a bug',@b1,'QA'); +SELECT * FROM t15 ORDER BY c1; +c1 c2 c3 c4 c5 +1 1.00 Replication Testing Extra Col b1b1b1b1b1b1b1b1 Kyle +2 2.00 This Test Should work b1b1b1b1b1b1b1b1 JOE +3 3.00 If is does not, I will open a bug b1b1b1b1b1b1b1b1 QA +*** Select on Slave **** +SELECT * FROM t15 ORDER BY c1; +c1 c2 c3 c4 c5 c6 c7 +1 1.00 Replication Testing Extra Col b1b1b1b1b1b1b1b1 Kyle 1 CURRENT_TIMESTAMP +2 2.00 This Test Should work b1b1b1b1b1b1b1b1 JOE 1 CURRENT_TIMESTAMP +3 3.00 If is does not, I will open a bug b1b1b1b1b1b1b1b1 QA 1 CURRENT_TIMESTAMP +*** Add column on master that is a Extra on Slave *** +ALTER TABLE t15 ADD COLUMN c6 INT AFTER c5; +******************************************** +*** Expect slave to fail with Error 1060 *** +******************************************** +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 1060 +Last_Error Error 'Duplicate column name 'c6'' on query. Default database: 'test'. Query: 'ALTER TABLE t15 ADD COLUMN c6 INT AFTER c5' +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; +START SLAVE; +*** Try to insert in master **** +INSERT INTO t15 () VALUES(5,2.00,'Replication Testing',@b1,'Buda',2); +SELECT * FROM t15 ORDER BY c1; +c1 c2 c3 c4 c5 c6 +1 1.00 Replication Testing Extra Col b1b1b1b1b1b1b1b1 Kyle NULL +2 2.00 This Test Should work b1b1b1b1b1b1b1b1 JOE NULL +3 3.00 If is does not, I will open a bug b1b1b1b1b1b1b1b1 QA NULL +5 2.00 Replication Testing b1b1b1b1b1b1b1b1 Buda 2 +*** Try to select from slave **** +SELECT * FROM t15 ORDER BY c1; +c1 c2 c3 c4 c5 c6 c7 +1 1.00 Replication Testing Extra Col b1b1b1b1b1b1b1b1 Kyle 1 CURRENT_TIMESTAMP +2 2.00 This Test Should work b1b1b1b1b1b1b1b1 JOE 1 CURRENT_TIMESTAMP +3 3.00 If is does not, I will open a bug b1b1b1b1b1b1b1b1 QA 1 CURRENT_TIMESTAMP +5 2.00 Replication Testing b1b1b1b1b1b1b1b1 Buda 2 CURRENT_TIMESTAMP +*** DROP TABLE t15 *** +DROP TABLE t15; +*** Create t16 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t16 (c1 INT KEY, c2 DECIMAL(8,2), c3 TEXT, +c4 BLOB, c5 CHAR(5), +c6 INT DEFAULT '1', +c7 TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP +)ENGINE='NDB'; +*** Create t16 on Master *** +CREATE TABLE t16 (c1 INT PRIMARY KEY, c2 DECIMAL(8,2), c3 TEXT, +c4 BLOB, c5 CHAR(5))ENGINE='NDB'; +RESET MASTER; +*** Start Slave *** +START SLAVE; +*** Master Data Insert *** +set @b1 = 'b1b1b1b1'; +set @b1 = concat(@b1,@b1); +INSERT INTO t16 () VALUES(1,1.00,'Replication Testing Extra Col',@b1,'Kyle'), +(2,2.00,'This Test Should work',@b1,'JOE'), +(3,3.00,'If is does not, I will open a bug',@b1,'QA'); +SELECT * FROM t16 ORDER BY c1; +c1 c2 c3 c4 c5 +1 1.00 Replication Testing Extra Col b1b1b1b1b1b1b1b1 Kyle +2 2.00 This Test Should work b1b1b1b1b1b1b1b1 JOE +3 3.00 If is does not, I will open a bug b1b1b1b1b1b1b1b1 QA +*** Select on Slave **** +SELECT * FROM t16 ORDER BY c1; +c1 c2 c3 c4 c5 c6 c7 +1 1.00 Replication Testing Extra Col b1b1b1b1b1b1b1b1 Kyle 1 CURRENT_TIMESTAMP +2 2.00 This Test Should work b1b1b1b1b1b1b1b1 JOE 1 CURRENT_TIMESTAMP +3 3.00 If is does not, I will open a bug b1b1b1b1b1b1b1b1 QA 1 CURRENT_TIMESTAMP +*** Add Partition on master *** +ALTER TABLE t16 PARTITION BY KEY(c1) PARTITIONS 4; +INSERT INTO t16 () VALUES(4,1.00,'Replication Rocks',@b1,'Omer'); +SHOW CREATE TABLE t16; +Table Create Table +t16 CREATE TABLE `t16` ( + `c1` int(11) NOT NULL, + `c2` decimal(8,2) DEFAULT NULL, + `c3` text, + `c4` blob, + `c5` char(5) DEFAULT NULL, + PRIMARY KEY (`c1`) +) ENGINE=ndbcluster DEFAULT CHARSET=latin1 /*!50100 PARTITION BY KEY (c1) PARTITIONS 4 */ +*** Show table on Slave **** +SHOW CREATE TABLE t16; +Table Create Table +t16 CREATE TABLE `t16` ( + `c1` int(11) NOT NULL, + `c2` decimal(8,2) DEFAULT NULL, + `c3` text, + `c4` blob, + `c5` char(5) DEFAULT NULL, + `c6` int(11) DEFAULT '1', + `c7` timestamp NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`c1`) +) ENGINE=ndbcluster DEFAULT CHARSET=latin1 /*!50100 PARTITION BY KEY (c1) PARTITIONS 4 */ +*** DROP TABLE t16 *** +DROP TABLE t16; +*** Alter Master End *** +*** Create t17 on slave *** +STOP SLAVE; +RESET SLAVE; +CREATE TABLE t17 (a SMALLINT, b INT PRIMARY KEY, c CHAR(5), +d FLOAT DEFAULT '2.00', +e CHAR(5) DEFAULT 'TEST2') +ENGINE='NDB'; +*** Create t17 on Master *** +CREATE TABLE t17 (a BIGINT PRIMARY KEY, b INT, c CHAR(10) +) ENGINE='NDB'; +RESET MASTER; +*** Start Slave *** +START SLAVE; +*** Master Data Insert *** +INSERT INTO t17 () VALUES(9223372036854775807,2,'Kyle, TEX'); +******************************************** +*** Expect slave to fail with Error 1522 *** +******************************************** +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 1522 +Last_Error Column 0 type mismatch - received type 8, test.t17 has type 2 +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; +START SLAVE; +** DROP table t17 *** +DROP TABLE t17; diff --git a/mysql-test/r/rpl_ndb_idempotent.result b/mysql-test/r/rpl_ndb_idempotent.result index 1ba23e703c2..e8a96aec137 100644 --- a/mysql-test/r/rpl_ndb_idempotent.result +++ b/mysql-test/r/rpl_ndb_idempotent.result @@ -9,14 +9,14 @@ INSERT INTO t1 VALUES ("row1","will go away",1); SELECT * FROM t1 ORDER BY c3; c1 c2 c3 row1 will go away 1 -SELECT @the_epoch:=MAX(epoch) FROM cluster.apply_status; +SELECT @the_epoch:=MAX(epoch) FROM mysql.apply_status; @the_epoch:=MAX(epoch) <the_epoch> SELECT * FROM t1 ORDER BY c3; c1 c2 c3 row1 will go away 1 SELECT @the_pos:=Position,@the_file:=SUBSTRING_INDEX(FILE, '/', -1) -FROM cluster.binlog_index WHERE epoch = <the_epoch> ; +FROM mysql.binlog_index WHERE epoch = <the_epoch> ; @the_pos:=Position @the_file:=SUBSTRING_INDEX(FILE, '/', -1) <the_pos> master-bin.000001 INSERT INTO t1 VALUES ("row2","will go away",2),("row3","will change",3),("row4","D",4); diff --git a/mysql-test/r/rpl_ndb_log.result b/mysql-test/r/rpl_ndb_log.result index e0135a94c63..a594fa6c1dc 100644 --- a/mysql-test/r/rpl_ndb_log.result +++ b/mysql-test/r/rpl_ndb_log.result @@ -22,7 +22,7 @@ master-bin.000001 # Format_desc 1 # Server ver: VERSION, Binlog ver: 4 master-bin.000001 # Query 1 # use `test`; create table t1(n int not null auto_increment primary key)ENGINE=NDB master-bin.000001 # Query 1 # BEGIN master-bin.000001 # Table_map 1 # table_id: # (test.t1) -master-bin.000001 # Table_map 1 # table_id: # (cluster.apply_status) +master-bin.000001 # Table_map 1 # table_id: # (mysql.apply_status) master-bin.000001 # Write_rows 1 # table_id: # master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F master-bin.000001 # Query 1 # COMMIT @@ -30,7 +30,7 @@ master-bin.000001 # Query 1 # use `test`; drop table t1 master-bin.000001 # Query 1 # use `test`; create table t1 (word char(20) not null)ENGINE=NDB master-bin.000001 # Query 1 # BEGIN master-bin.000001 # Table_map 1 # table_id: # (test.t1) -master-bin.000001 # Table_map 1 # table_id: # (cluster.apply_status) +master-bin.000001 # Table_map 1 # table_id: # (mysql.apply_status) master-bin.000001 # Write_rows 1 # table_id: # master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F master-bin.000001 # Query 1 # COMMIT @@ -61,7 +61,7 @@ master-bin.000001 # Format_desc 1 # Server ver: VERSION, Binlog ver: 4 master-bin.000001 # Query 1 # use `test`; create table t1(n int not null auto_increment primary key)ENGINE=NDB master-bin.000001 # Query 1 # BEGIN master-bin.000001 # Table_map 1 # table_id: # (test.t1) -master-bin.000001 # Table_map 1 # table_id: # (cluster.apply_status) +master-bin.000001 # Table_map 1 # table_id: # (mysql.apply_status) master-bin.000001 # Write_rows 1 # table_id: # master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F master-bin.000001 # Query 1 # COMMIT @@ -69,7 +69,7 @@ master-bin.000001 # Query 1 # use `test`; drop table t1 master-bin.000001 # Query 1 # use `test`; create table t1 (word char(20) not null)ENGINE=NDB master-bin.000001 # Query 1 # BEGIN master-bin.000001 # Table_map 1 # table_id: # (test.t1) -master-bin.000001 # Table_map 1 # table_id: # (cluster.apply_status) +master-bin.000001 # Table_map 1 # table_id: # (mysql.apply_status) master-bin.000001 # Write_rows 1 # table_id: # master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F master-bin.000001 # Query 1 # COMMIT @@ -81,18 +81,18 @@ master-bin.000002 # Query 1 # use `test`; create table t3 (a int)ENGINE=NDB master-bin.000002 # Query 1 # use `test`; create table t2 (n int)ENGINE=NDB master-bin.000002 # Query 1 # BEGIN master-bin.000002 # Table_map 1 # table_id: # (test.t2) -master-bin.000002 # Table_map 1 # table_id: # (cluster.apply_status) +master-bin.000002 # Table_map 1 # table_id: # (mysql.apply_status) master-bin.000002 # Write_rows 1 # table_id: # master-bin.000002 # Write_rows 1 # table_id: # flags: STMT_END_F master-bin.000002 # Query 1 # COMMIT show binary logs; Log_name File_size -master-bin.000001 1698 -master-bin.000002 591 +master-bin.000001 1694 +master-bin.000002 589 start slave; show binary logs; Log_name File_size -slave-bin.000001 1793 +slave-bin.000001 1789 slave-bin.000002 198 show binlog events in 'slave-bin.000001' from 4; Log_name Pos Event_type Server_id End_log_pos Info @@ -100,7 +100,7 @@ slave-bin.000001 # Format_desc 2 # Server ver: VERSION, Binlog ver: 4 slave-bin.000001 # Query 1 # use `test`; create table t1(n int not null auto_increment primary key)ENGINE=NDB slave-bin.000001 # Query 2 # BEGIN slave-bin.000001 # Table_map 2 # table_id: # (test.t1) -slave-bin.000001 # Table_map 2 # table_id: # (cluster.apply_status) +slave-bin.000001 # Table_map 2 # table_id: # (mysql.apply_status) slave-bin.000001 # Write_rows 2 # table_id: # slave-bin.000001 # Write_rows 2 # table_id: # flags: STMT_END_F slave-bin.000001 # Query 2 # COMMIT @@ -108,7 +108,7 @@ slave-bin.000001 # Query 1 # use `test`; drop table t1 slave-bin.000001 # Query 1 # use `test`; create table t1 (word char(20) not null)ENGINE=NDB slave-bin.000001 # Query 2 # BEGIN slave-bin.000001 # Table_map 2 # table_id: # (test.t1) -slave-bin.000001 # Table_map 2 # table_id: # (cluster.apply_status) +slave-bin.000001 # Table_map 2 # table_id: # (mysql.apply_status) slave-bin.000001 # Write_rows 2 # table_id: # slave-bin.000001 # Write_rows 2 # table_id: # flags: STMT_END_F slave-bin.000001 # Query 2 # COMMIT @@ -120,13 +120,13 @@ slave-bin.000002 # Format_desc 2 # Server ver: VERSION, Binlog ver: 4 slave-bin.000002 # Query 1 # use `test`; create table t2 (n int)ENGINE=NDB slave-bin.000002 # Query 2 # BEGIN slave-bin.000002 # Table_map 2 # table_id: # (test.t2) -slave-bin.000002 # Table_map 2 # table_id: # (cluster.apply_status) +slave-bin.000002 # Table_map 2 # table_id: # (mysql.apply_status) slave-bin.000002 # Write_rows 2 # table_id: # slave-bin.000002 # Write_rows 2 # table_id: # flags: STMT_END_F slave-bin.000002 # Query 2 # COMMIT show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master -# 127.0.0.1 root MASTER_PORT 1 master-bin.000002 591 # # master-bin.000002 Yes Yes # 0 0 591 # None 0 No # +# 127.0.0.1 root MASTER_PORT 1 master-bin.000002 589 # # master-bin.000002 Yes Yes # 0 0 589 # None 0 No # show binlog events in 'slave-bin.000005' from 4; ERROR HY000: Error when executing command SHOW BINLOG EVENTS: Could not find target log DROP TABLE t1; diff --git a/mysql-test/r/rpl_ndb_multi.result b/mysql-test/r/rpl_ndb_multi.result index 13751060ed3..74e06b5ff38 100644 --- a/mysql-test/r/rpl_ndb_multi.result +++ b/mysql-test/r/rpl_ndb_multi.result @@ -16,7 +16,7 @@ row1 will go away 1 SELECT * FROM t1 ORDER BY c3; c1 c2 c3 row1 will go away 1 -SELECT @the_epoch:=MAX(epoch) FROM cluster.apply_status; +SELECT @the_epoch:=MAX(epoch) FROM mysql.apply_status; @the_epoch:=MAX(epoch) <the_epoch> SELECT * FROM t1 ORDER BY c3; @@ -24,7 +24,7 @@ c1 c2 c3 row1 will go away 1 stop slave; SELECT @the_pos:=Position,@the_file:=SUBSTRING_INDEX(FILE, '/', -1) -FROM cluster.binlog_index WHERE epoch = <the_epoch> ; +FROM mysql.binlog_index WHERE epoch = <the_epoch> ; @the_pos:=Position @the_file:=SUBSTRING_INDEX(FILE, '/', -1) 102 master-bin1.000001 CHANGE MASTER TO diff --git a/mysql-test/r/rpl_ndb_sync.result b/mysql-test/r/rpl_ndb_sync.result index 4ca73167603..2b9ca24fca0 100644 --- a/mysql-test/r/rpl_ndb_sync.result +++ b/mysql-test/r/rpl_ndb_sync.result @@ -60,11 +60,11 @@ hex(c2) hex(c3) c1 0 1 BCDEF 1 0 CD 0 0 DEFGHIJKL -SELECT @the_epoch:=MAX(epoch) FROM cluster.apply_status; +SELECT @the_epoch:=MAX(epoch) FROM mysql.apply_status; @the_epoch:=MAX(epoch) <the_epoch> SELECT @the_pos:=Position,@the_file:=SUBSTRING_INDEX(FILE, '/', -1) -FROM cluster.binlog_index WHERE epoch > <the_epoch> ORDER BY epoch ASC LIMIT 1; +FROM mysql.binlog_index WHERE epoch > <the_epoch> ORDER BY epoch ASC LIMIT 1; @the_pos:=Position @the_file:=SUBSTRING_INDEX(FILE, '/', -1) <the_pos> master-bin.000001 CHANGE MASTER TO @@ -89,8 +89,8 @@ hex(c2) hex(c3) c1 DROP DATABASE ndbsynctest; STOP SLAVE; reset master; -select * from cluster.binlog_index; +select * from mysql.binlog_index; Position File epoch inserts updates deletes schemaops reset slave; -select * from cluster.apply_status; +select * from mysql.apply_status; server_id epoch 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_row_basic_11bugs.result b/mysql-test/r/rpl_row_basic_11bugs.result index e49facd2d70..8af2e8639aa 100644 --- a/mysql-test/r/rpl_row_basic_11bugs.result +++ b/mysql-test/r/rpl_row_basic_11bugs.result @@ -9,7 +9,6 @@ CREATE DATABASE test_ignore; SHOW DATABASES; Database information_schema -cluster mysql test test_ignore @@ -34,7 +33,6 @@ master-bin.000001 235 Write_rows 1 282 table_id: # flags: STMT_END_F SHOW DATABASES; Database information_schema -cluster mysql test USE test; diff --git a/mysql-test/r/rpl_trigger.result b/mysql-test/r/rpl_trigger.result index 50bcd071d23..815a87eede5 100644 --- a/mysql-test/r/rpl_trigger.result +++ b/mysql-test/r/rpl_trigger.result @@ -944,3 +944,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/rpl_truncate_7ndb.result b/mysql-test/r/rpl_truncate_7ndb.result index 0e1b21d31aa..c57eb2e1dae 100644 --- a/mysql-test/r/rpl_truncate_7ndb.result +++ b/mysql-test/r/rpl_truncate_7ndb.result @@ -33,12 +33,12 @@ master-bin.000001 4 Format_desc 1 102 Server ver: SERVER_VERSION, Binlog ver: 4 master-bin.000001 102 Query 1 219 use `test`; CREATE TABLE t1 (a INT PRIMARY KEY, b LONG) ENGINE=NDB master-bin.000001 219 Query 1 283 BEGIN master-bin.000001 283 Table_map 1 40 table_id: # (test.t1) -master-bin.000001 323 Table_map 1 93 table_id: # (cluster.apply_status) -master-bin.000001 376 Write_rows 1 135 table_id: # -master-bin.000001 418 Write_rows 1 182 table_id: # flags: STMT_END_F -master-bin.000001 465 Query 1 530 COMMIT -master-bin.000001 530 Query 1 610 use `test`; TRUNCATE TABLE t1 -master-bin.000001 610 Query 1 686 use `test`; DROP TABLE t1 +master-bin.000001 323 Table_map 1 91 table_id: # (mysql.apply_status) +master-bin.000001 374 Write_rows 1 133 table_id: # +master-bin.000001 416 Write_rows 1 180 table_id: # flags: STMT_END_F +master-bin.000001 463 Query 1 528 COMMIT +master-bin.000001 528 Query 1 608 use `test`; TRUNCATE TABLE t1 +master-bin.000001 608 Query 1 684 use `test`; DROP TABLE t1 **** On Master **** CREATE TABLE t1 (a INT PRIMARY KEY, b LONG) ENGINE=NDB; INSERT INTO t1 VALUES (1,1), (2,2); @@ -69,23 +69,23 @@ master-bin.000001 4 Format_desc 1 102 Server ver: SERVER_VERSION, Binlog ver: 4 master-bin.000001 102 Query 1 219 use `test`; CREATE TABLE t1 (a INT PRIMARY KEY, b LONG) ENGINE=NDB master-bin.000001 219 Query 1 283 BEGIN master-bin.000001 283 Table_map 1 40 table_id: # (test.t1) -master-bin.000001 323 Table_map 1 93 table_id: # (cluster.apply_status) -master-bin.000001 376 Write_rows 1 135 table_id: # -master-bin.000001 418 Write_rows 1 182 table_id: # flags: STMT_END_F -master-bin.000001 465 Query 1 530 COMMIT -master-bin.000001 530 Query 1 610 use `test`; TRUNCATE TABLE t1 -master-bin.000001 610 Query 1 686 use `test`; DROP TABLE t1 -master-bin.000001 686 Query 1 803 use `test`; CREATE TABLE t1 (a INT PRIMARY KEY, b LONG) ENGINE=NDB -master-bin.000001 803 Query 1 867 BEGIN -master-bin.000001 867 Table_map 1 40 table_id: # (test.t1) -master-bin.000001 907 Table_map 1 93 table_id: # (cluster.apply_status) -master-bin.000001 960 Write_rows 1 135 table_id: # -master-bin.000001 1002 Write_rows 1 182 table_id: # flags: STMT_END_F -master-bin.000001 1049 Query 1 1114 COMMIT -master-bin.000001 1114 Query 1 1178 BEGIN -master-bin.000001 1178 Table_map 1 40 table_id: # (test.t1) -master-bin.000001 1218 Table_map 1 93 table_id: # (cluster.apply_status) -master-bin.000001 1271 Write_rows 1 135 table_id: # -master-bin.000001 1313 Delete_rows 1 174 table_id: # flags: STMT_END_F -master-bin.000001 1352 Query 1 1417 COMMIT -master-bin.000001 1417 Query 1 1493 use `test`; DROP TABLE t1 +master-bin.000001 323 Table_map 1 91 table_id: # (mysql.apply_status) +master-bin.000001 374 Write_rows 1 133 table_id: # +master-bin.000001 416 Write_rows 1 180 table_id: # flags: STMT_END_F +master-bin.000001 463 Query 1 528 COMMIT +master-bin.000001 528 Query 1 608 use `test`; TRUNCATE TABLE t1 +master-bin.000001 608 Query 1 684 use `test`; DROP TABLE t1 +master-bin.000001 684 Query 1 801 use `test`; CREATE TABLE t1 (a INT PRIMARY KEY, b LONG) ENGINE=NDB +master-bin.000001 801 Query 1 865 BEGIN +master-bin.000001 865 Table_map 1 40 table_id: # (test.t1) +master-bin.000001 905 Table_map 1 91 table_id: # (mysql.apply_status) +master-bin.000001 956 Write_rows 1 133 table_id: # +master-bin.000001 998 Write_rows 1 180 table_id: # flags: STMT_END_F +master-bin.000001 1045 Query 1 1110 COMMIT +master-bin.000001 1110 Query 1 1174 BEGIN +master-bin.000001 1174 Table_map 1 40 table_id: # (test.t1) +master-bin.000001 1214 Table_map 1 91 table_id: # (mysql.apply_status) +master-bin.000001 1265 Write_rows 1 133 table_id: # +master-bin.000001 1307 Delete_rows 1 172 table_id: # flags: STMT_END_F +master-bin.000001 1346 Query 1 1411 COMMIT +master-bin.000001 1411 Query 1 1487 use `test`; DROP TABLE t1 diff --git a/mysql-test/r/rpl_truncate_7ndb_2.result b/mysql-test/r/rpl_truncate_7ndb_2.result index 0e1b21d31aa..ca323e193fa 100644 --- a/mysql-test/r/rpl_truncate_7ndb_2.result +++ b/mysql-test/r/rpl_truncate_7ndb_2.result @@ -33,7 +33,7 @@ master-bin.000001 4 Format_desc 1 102 Server ver: SERVER_VERSION, Binlog ver: 4 master-bin.000001 102 Query 1 219 use `test`; CREATE TABLE t1 (a INT PRIMARY KEY, b LONG) ENGINE=NDB master-bin.000001 219 Query 1 283 BEGIN master-bin.000001 283 Table_map 1 40 table_id: # (test.t1) -master-bin.000001 323 Table_map 1 93 table_id: # (cluster.apply_status) +master-bin.000001 323 Table_map 1 93 table_id: # (mysql.apply_status) master-bin.000001 376 Write_rows 1 135 table_id: # master-bin.000001 418 Write_rows 1 182 table_id: # flags: STMT_END_F master-bin.000001 465 Query 1 530 COMMIT @@ -69,7 +69,7 @@ master-bin.000001 4 Format_desc 1 102 Server ver: SERVER_VERSION, Binlog ver: 4 master-bin.000001 102 Query 1 219 use `test`; CREATE TABLE t1 (a INT PRIMARY KEY, b LONG) ENGINE=NDB master-bin.000001 219 Query 1 283 BEGIN master-bin.000001 283 Table_map 1 40 table_id: # (test.t1) -master-bin.000001 323 Table_map 1 93 table_id: # (cluster.apply_status) +master-bin.000001 323 Table_map 1 93 table_id: # (mysql.apply_status) master-bin.000001 376 Write_rows 1 135 table_id: # master-bin.000001 418 Write_rows 1 182 table_id: # flags: STMT_END_F master-bin.000001 465 Query 1 530 COMMIT @@ -78,13 +78,13 @@ master-bin.000001 610 Query 1 686 use `test`; DROP TABLE t1 master-bin.000001 686 Query 1 803 use `test`; CREATE TABLE t1 (a INT PRIMARY KEY, b LONG) ENGINE=NDB master-bin.000001 803 Query 1 867 BEGIN master-bin.000001 867 Table_map 1 40 table_id: # (test.t1) -master-bin.000001 907 Table_map 1 93 table_id: # (cluster.apply_status) +master-bin.000001 907 Table_map 1 93 table_id: # (mysql.apply_status) master-bin.000001 960 Write_rows 1 135 table_id: # master-bin.000001 1002 Write_rows 1 182 table_id: # flags: STMT_END_F master-bin.000001 1049 Query 1 1114 COMMIT master-bin.000001 1114 Query 1 1178 BEGIN master-bin.000001 1178 Table_map 1 40 table_id: # (test.t1) -master-bin.000001 1218 Table_map 1 93 table_id: # (cluster.apply_status) +master-bin.000001 1218 Table_map 1 93 table_id: # (mysql.apply_status) master-bin.000001 1271 Write_rows 1 135 table_id: # master-bin.000001 1313 Delete_rows 1 174 table_id: # flags: STMT_END_F master-bin.000001 1352 Query 1 1417 COMMIT diff --git a/mysql-test/r/schema.result b/mysql-test/r/schema.result index 8ed1a587588..538abd8d039 100644 --- a/mysql-test/r/schema.result +++ b/mysql-test/r/schema.result @@ -6,7 +6,6 @@ foo CREATE DATABASE `foo` /*!40100 DEFAULT CHARACTER SET latin1 */ show schemas; Database information_schema -cluster foo mysql test diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result index 7a1ef7cedcf..8b04155f2b9 100644 --- a/mysql-test/r/show_check.result +++ b/mysql-test/r/show_check.result @@ -53,7 +53,6 @@ Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length I show databases; Database information_schema -cluster mysql test show databases like "test%"; diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index aeccfd9c951..60363b06ea0 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -2178,6 +2178,7 @@ set @stamped_time=in_time; set x=2; end if; end| +set time_zone='+03:00'; call bug3426(1000, @i)| select @i, from_unixtime(@stamped_time, '%d-%m-%Y %h:%i:%s') as time| @i time @@ -5627,4 +5628,111 @@ Called B drop procedure proc_21462_a| drop procedure proc_21462_b| End of 5.0 tests +Begin of 5.1 tests +drop function if exists pi; +create function pi() returns varchar(50) +return "pie, my favorite desert."; +Warnings: +Note 1578 This function 'pi' has the same name as a native function. +SET @save_sql_mode=@@sql_mode; +SET SQL_MODE='IGNORE_SPACE'; +select pi(), pi (); +pi() pi () +3.141593 3.141593 +select test.pi(), test.pi (); +test.pi() test.pi () +pie, my favorite desert. pie, my favorite desert. +SET SQL_MODE=''; +select pi(), pi (); +pi() pi () +3.141593 3.141593 +select test.pi(), test.pi (); +test.pi() test.pi () +pie, my favorite desert. pie, my favorite desert. +SET @@sql_mode=@save_sql_mode; +drop function pi; +drop function if exists test.database; +drop function if exists test.current_user; +drop function if exists test.md5; +create database nowhere; +use nowhere; +drop database nowhere; +SET @save_sql_mode=@@sql_mode; +SET SQL_MODE='IGNORE_SPACE'; +select database(), database (); +database() database () +NULL NULL +select current_user(), current_user (); +current_user() current_user () +root@localhost root@localhost +select md5("aaa"), md5 ("aaa"); +md5("aaa") md5 ("aaa") +47bce5c74f589f4867dbd57e9ca9f808 47bce5c74f589f4867dbd57e9ca9f808 +SET SQL_MODE=''; +select database(), database (); +database() database () +NULL NULL +select current_user(), current_user (); +current_user() current_user () +root@localhost root@localhost +select md5("aaa"), md5 ("aaa"); +md5("aaa") md5 ("aaa") +47bce5c74f589f4867dbd57e9ca9f808 47bce5c74f589f4867dbd57e9ca9f808 +use test; +create function `database`() returns varchar(50) +return "Stored function database"; +Warnings: +Note 1578 This function 'database' has the same name as a native function. +create function `current_user`() returns varchar(50) +return "Stored function current_user"; +Warnings: +Note 1578 This function 'current_user' has the same name as a native function. +create function md5(x varchar(50)) returns varchar(50) +return "Stored function md5"; +Warnings: +Note 1578 This function 'md5' has the same name as a native function. +SET SQL_MODE='IGNORE_SPACE'; +select database(), database (); +database() database () +test test +select current_user(), current_user (); +current_user() current_user () +root@localhost root@localhost +select md5("aaa"), md5 ("aaa"); +md5("aaa") md5 ("aaa") +47bce5c74f589f4867dbd57e9ca9f808 47bce5c74f589f4867dbd57e9ca9f808 +select test.database(), test.database (); +test.database() test.database () +Stored function database Stored function database +select test.current_user(), test.current_user (); +test.current_user() test.current_user () +Stored function current_user Stored function current_user +select test.md5("aaa"), test.md5 ("aaa"); +test.md5("aaa") test.md5 ("aaa") +Stored function md5 Stored function md5 +SET SQL_MODE=''; +select database(), database (); +database() database () +test test +select current_user(), current_user (); +current_user() current_user () +root@localhost root@localhost +select md5("aaa"), md5 ("aaa"); +md5("aaa") md5 ("aaa") +47bce5c74f589f4867dbd57e9ca9f808 47bce5c74f589f4867dbd57e9ca9f808 +select test.database(), test.database (); +test.database() test.database () +Stored function database Stored function database +select test.current_user(), test.current_user (); +test.current_user() test.current_user () +Stored function current_user Stored function current_user +select test.md5("aaa"), test.md5 ("aaa"); +test.md5("aaa") test.md5 ("aaa") +Stored function md5 Stored function md5 +SET @@sql_mode=@save_sql_mode; +drop function test.database; +drop function test.current_user; +drop function md5; +use test; +End of 5.1 tests drop table t1,t2; diff --git a/mysql-test/r/sp_gis.result b/mysql-test/r/sp_gis.result new file mode 100644 index 00000000000..ea2cdd0d29d --- /dev/null +++ b/mysql-test/r/sp_gis.result @@ -0,0 +1,30 @@ +use test; +drop function if exists a; +drop function if exists x; +drop function if exists y; +create function a() returns int +return 1; +create function x() returns int +return 2; +Warnings: +Note 1578 This function 'x' has the same name as a native function. +create function y() returns int +return 3; +Warnings: +Note 1578 This function 'y' has the same name as a native function. +select a(); +a() +1 +select x(); +ERROR 42000: Incorrect parameter count in the call to native function 'x' +select y(); +ERROR 42000: Incorrect parameter count in the call to native function 'y' +select x(PointFromText("POINT(10 20)")), y(PointFromText("POINT(10 20)")); +x(PointFromText("POINT(10 20)")) y(PointFromText("POINT(10 20)")) +10 20 +select test.a(), test.x(), test.y(); +test.a() test.x() test.y() +1 2 3 +drop function a; +drop function x; +drop function y; diff --git a/mysql-test/r/strict_autoinc_1myisam.result b/mysql-test/r/strict_autoinc_1myisam.result index dcda74a19cd..afcccb1c40f 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 9e90ab886f3..e534286e2a2 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 d22054eb59d..0a31da04460 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 48ebe196baf..2e8980e435b 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 debc7242e15..ea6e5ffc741 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 ecd9762dd24..a4c666dd876 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 filtered Extra 3 DEPENDENT UNION NULL NULL NULL NULL NULL NULL NULL NULL No tables used NULL UNION RESULT <union2,3> ALL NULL 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 filtered Extra 2 DEPENDENT SUBQUERY t2 ref_or_null a a 5 func 2 100.00 Using where; Using index 2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 3 100.00 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 filtered Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 8 100.00 2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 9 100.00 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 filtered Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 8 100.00 Using where 2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 9 100.00 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 filtered Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 8 100.00 2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 9 100.00 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..10cc2729f3e --- /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 filtered Extra +1 PRIMARY t2 ALL NULL NULL NULL NULL 5 100.00 +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 6 100.00 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 filtered Extra +1 PRIMARY t2 ALL NULL NULL NULL NULL 5 100.00 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 6 100.00 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 filtered Extra +1 PRIMARY t3 ALL NULL NULL NULL NULL 2 100.00 +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 6 100.00 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 filtered Extra +1 PRIMARY t2 ALL NULL NULL NULL NULL 4 100.00 +2 DEPENDENT SUBQUERY t1 index_subquery a a 5 func 2 100.00 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 filtered Extra +1 PRIMARY t3 ALL NULL NULL NULL NULL 3 100.00 +2 DEPENDENT SUBQUERY t1 ref_or_null a a 5 func 4 100.00 Using where +2 DEPENDENT SUBQUERY t2 ref a a 5 test.t1.b 1 100.00 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/synchronization.result b/mysql-test/r/synchronization.result index 4543a829494..5d8585f1f88 100644 --- a/mysql-test/r/synchronization.result +++ b/mysql-test/r/synchronization.result @@ -1,4 +1,4 @@ -drop table if exists t1; +drop table if exists t1,t2; CREATE TABLE t1 (x1 int); ALTER TABLE t1 CHANGE x1 x2 int; CREATE TABLE t2 LIKE t1; diff --git a/mysql-test/r/system_mysql_db.result b/mysql-test/r/system_mysql_db.result index b9d3504993c..ab140fe2782 100644 --- a/mysql-test/r/system_mysql_db.result +++ b/mysql-test/r/system_mysql_db.result @@ -1,6 +1,7 @@ drop table if exists t1,t1aa,t2aa; show tables; Tables_in_db +binlog_index columns_priv db event diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result index 52123885772..e302f5def1b 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_datetime.result b/mysql-test/r/type_datetime.result index 04b37f7ae86..a8d5388097d 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 595c15afcc2..901297288af 100644 --- a/mysql-test/r/type_newdecimal.result +++ b/mysql-test/r/type_newdecimal.result @@ -1420,6 +1420,14 @@ 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(143.481 as decimal(4,1)); cast(143.481 as decimal(4,1)) 143.5 @@ -1447,3 +1455,8 @@ Error 1264 Out of range value for column 'cast(-13.4 as decimal(2,1))' at row 1 select cast(98.6 as decimal(2,0)); cast(98.6 as decimal(2,0)) 99 +select cast(19999999999999999999 as unsigned); +cast(19999999999999999999 as unsigned) +18446744073709551615 +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' diff --git a/mysql-test/r/udf.result b/mysql-test/r/udf.result index a552282fece..1308980ca96 100644 --- a/mysql-test/r/udf.result +++ b/mysql-test/r/udf.result @@ -105,7 +105,102 @@ 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 filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 +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 filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 +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 filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 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 filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 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 filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 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 filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 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 if exists pi; +CREATE FUNCTION pi RETURNS STRING SONAME "should_not_parse.so"; +ERROR HY000: This function 'pi' has the same name as a native function. +DROP FUNCTION IF EXISTS metaphon; +CREATE FUNCTION metaphon(a int) RETURNS int +return 0; +CREATE FUNCTION metaphon RETURNS STRING SONAME "UDF_EXAMPLE_LIB"; +ERROR HY000: Function 'metaphon' already exists +DROP FUNCTION metaphon; +CREATE FUNCTION metaphon RETURNS STRING SONAME "UDF_EXAMPLE_LIB"; +CREATE FUNCTION metaphon(a int) RETURNS int +return 0; +ERROR HY000: Function 'metaphon' already exists +CREATE FUNCTION test.metaphon(a int) RETURNS int +return 0; +ERROR HY000: Function 'metaphon' already exists DROP FUNCTION metaphon; DROP FUNCTION myfunc_double; DROP FUNCTION myfunc_nonexist; diff --git a/mysql-test/r/upgrade.result b/mysql-test/r/upgrade.result index 8a2249480e9..76e0359c405 100644 --- a/mysql-test/r/upgrade.result +++ b/mysql-test/r/upgrade.result @@ -57,3 +57,5 @@ s1 1 drop table `txu@0023p@0023p1`; drop table `txu#p#p1`; +truncate t1; +drop table t1; diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 501d15efa82..4bc122cc97b 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -3015,3 +3015,22 @@ i j DROP VIEW v1, v2; DROP TABLE t1; End of 5.0 tests. +DROP DATABASE IF EXISTS `d-1`; +CREATE DATABASE `d-1`; +USE `d-1`; +CREATE TABLE `t-1` (c1 INT); +CREATE VIEW `v-1` AS SELECT c1 FROM `t-1`; +SHOW TABLES; +Tables_in_d-1 +t-1 +v-1 +RENAME TABLE `t-1` TO `t-2`; +RENAME TABLE `v-1` TO `v-2`; +SHOW TABLES; +Tables_in_d-1 +t-2 +v-2 +DROP TABLE `t-2`; +DROP VIEW `v-2`; +DROP DATABASE `d-1`; +USE test; diff --git a/mysql-test/r/warnings.result b/mysql-test/r/warnings.result index d07f90d41b9..d03c5ed2f54 100644 --- a/mysql-test/r/warnings.result +++ b/mysql-test/r/warnings.result @@ -166,10 +166,10 @@ show variables like 'max_error_count'; Variable_name Value max_error_count 10 drop table t1; -create table t1 (id int) engine=merge; +create table t1 (id int) engine=NDB; Warnings: Warning 1266 Using storage engine MyISAM for table 't1' -alter table t1 engine=merge; +alter table t1 engine=NDB; Warnings: Warning 1266 Using storage engine MyISAM for table 't1' drop table t1; diff --git a/mysql-test/r/windows.result b/mysql-test/r/windows.result index 039c5b1476e..e8c3c81a44e 100644 --- a/mysql-test/r/windows.result +++ b/mysql-test/r/windows.result @@ -6,3 +6,17 @@ use prn; ERROR 42000: Unknown database 'prn' create table nu (a int); drop table nu; +create procedure proc_1() install plugin my_plug soname '\\root\\some_plugin.dll'; +call proc_1(); +ERROR HY000: No paths allowed for shared library +call proc_1(); +ERROR HY000: No paths allowed for shared library +call proc_1(); +ERROR HY000: No paths allowed for shared library +drop procedure proc_1; +prepare abc from "install plugin my_plug soname '\\\\root\\\\some_plugin.dll'"; +execute abc; +ERROR HY000: No paths allowed for shared library +execute abc; +ERROR HY000: No paths allowed for shared library +deallocate prepare abc; diff --git a/mysql-test/r/xml.result b/mysql-test/r/xml.result index efe7d14095d..bb7f84d0287 100644 --- a/mysql-test/r/xml.result +++ b/mysql-test/r/xml.result @@ -736,3 +736,76 @@ test select extractValue('<x.-_:>test</x.-_:>','//*'); extractValue('<x.-_:>test</x.-_:>','//*') test +set @xml= "<entry><id>pt10</id><pt>10</pt></entry><entry><id>pt50</id><pt>50</pt></entry>"; +select ExtractValue(@xml, "/entry[(pt=10)]/id"); +ExtractValue(@xml, "/entry[(pt=10)]/id") +pt10 +select ExtractValue(@xml, "/entry[(pt!=10)]/id"); +ExtractValue(@xml, "/entry[(pt!=10)]/id") +pt50 +select ExtractValue(@xml, "/entry[(pt<10)]/id"); +ExtractValue(@xml, "/entry[(pt<10)]/id") + +select ExtractValue(@xml, "/entry[(pt<=10)]/id"); +ExtractValue(@xml, "/entry[(pt<=10)]/id") +pt10 +select ExtractValue(@xml, "/entry[(pt>10)]/id"); +ExtractValue(@xml, "/entry[(pt>10)]/id") +pt50 +select ExtractValue(@xml, "/entry[(pt>=10)]/id"); +ExtractValue(@xml, "/entry[(pt>=10)]/id") +pt10 pt50 +select ExtractValue(@xml, "/entry[(pt=50)]/id"); +ExtractValue(@xml, "/entry[(pt=50)]/id") +pt50 +select ExtractValue(@xml, "/entry[(pt!=50)]/id"); +ExtractValue(@xml, "/entry[(pt!=50)]/id") +pt10 +select ExtractValue(@xml, "/entry[(pt<50)]/id"); +ExtractValue(@xml, "/entry[(pt<50)]/id") +pt10 +select ExtractValue(@xml, "/entry[(pt<=50)]/id"); +ExtractValue(@xml, "/entry[(pt<=50)]/id") +pt10 pt50 +select ExtractValue(@xml, "/entry[(pt>50)]/id"); +ExtractValue(@xml, "/entry[(pt>50)]/id") + +select ExtractValue(@xml, "/entry[(pt>=50)]/id"); +ExtractValue(@xml, "/entry[(pt>=50)]/id") +pt50 +select ExtractValue(@xml, "/entry[(10=pt)]/id"); +ExtractValue(@xml, "/entry[(10=pt)]/id") +pt10 +select ExtractValue(@xml, "/entry[(10!=pt)]/id"); +ExtractValue(@xml, "/entry[(10!=pt)]/id") +pt50 +select ExtractValue(@xml, "/entry[(10>pt)]/id"); +ExtractValue(@xml, "/entry[(10>pt)]/id") + +select ExtractValue(@xml, "/entry[(10>=pt)]/id"); +ExtractValue(@xml, "/entry[(10>=pt)]/id") +pt10 +select ExtractValue(@xml, "/entry[(10<pt)]/id"); +ExtractValue(@xml, "/entry[(10<pt)]/id") +pt50 +select ExtractValue(@xml, "/entry[(10<=pt)]/id"); +ExtractValue(@xml, "/entry[(10<=pt)]/id") +pt10 pt50 +select ExtractValue(@xml, "/entry[(50=pt)]/id"); +ExtractValue(@xml, "/entry[(50=pt)]/id") +pt50 +select ExtractValue(@xml, "/entry[(50!=pt)]/id"); +ExtractValue(@xml, "/entry[(50!=pt)]/id") +pt10 +select ExtractValue(@xml, "/entry[(50>pt)]/id"); +ExtractValue(@xml, "/entry[(50>pt)]/id") +pt10 +select ExtractValue(@xml, "/entry[(50>=pt)]/id"); +ExtractValue(@xml, "/entry[(50>=pt)]/id") +pt10 pt50 +select ExtractValue(@xml, "/entry[(50<pt)]/id"); +ExtractValue(@xml, "/entry[(50<pt)]/id") + +select ExtractValue(@xml, "/entry[(50<=pt)]/id"); +ExtractValue(@xml, "/entry[(50<=pt)]/id") +pt50 diff --git a/mysql-test/std_data/old_table-323.frm b/mysql-test/std_data/old_table-323.frm Binary files differnew file mode 100644 index 00000000000..316dfd76050 --- /dev/null +++ b/mysql-test/std_data/old_table-323.frm diff --git a/mysql-test/t/1st.test b/mysql-test/t/1st.test new file mode 100644 index 00000000000..6b93efee944 --- /dev/null +++ b/mysql-test/t/1st.test @@ -0,0 +1,5 @@ +# +# Check that we haven't any strange new tables or databases +# +show databases; +show tables in mysql; diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test index 168d011a2ac..78bbd23adf1 100644 --- a/mysql-test/t/alter_table.test +++ b/mysql-test/t/alter_table.test @@ -535,4 +535,3 @@ INSERT INTO `@0023sql1` VALUES (2); SHOW CREATE TABLE `#sql2`; SHOW CREATE TABLE `@0023sql1`; DROP TABLE `#sql2`, `@0023sql1`; - diff --git a/mysql-test/t/archive.test b/mysql-test/t/archive.test index 0dccd8f111a..497cd717ae2 100644 --- a/mysql-test/t/archive.test +++ b/mysql-test/t/archive.test @@ -1492,6 +1492,27 @@ select * from t1 where i between 2 and 4 and v in ('def','3r4f','lmn'); alter table t1 data directory="$MYSQLTEST_VARDIR/tmp"; select * from t1; +# Testing cleared row key +DROP TABLE t5; + +CREATE TABLE `t5` ( +`a` int(11) NOT NULL auto_increment, +b varchar(250), +c varchar(800), +KEY (`a`) +) ENGINE=ARCHIVE DEFAULT CHARSET=latin1; + +INSERT INTO t5 VALUES (NULL, "foo", "grok this!"); +INSERT INTO t5 VALUES (NULL, "We the people", NULL); +INSERT INTO t5 VALUES (NULL, "in order to form a more peefect union", "secure the blessing of liberty"); +INSERT INTO t5 VALUES (NULL, "establish justice", "to ourselves and"); +INSERT INTO t5 VALUES (32, "ensure domestic tranquility", NULL); +INSERT INTO t5 VALUES (23, "provide for the common defense", "posterity"); +INSERT INTO t5 VALUES (NULL, "promote the general welfare", "do ordain"); +INSERT INTO t5 VALUES (NULL, "abcdeghijklmnopqrstuvwxyzabcdeghijklmnopqrstuvwxyzabcdeghijklmnopqrstuvwxyzabcdeghijklmnopqrstuvwxyzabcdeghijklmnopqrstuvwxyzabcdeghijklmnopqrstuvwxyzabcdeghijklmnopqrstuvwxyzabcdeghijklmnopqrstuvwxyzabcdeghijklmnopqrstuvwxyzabcdeghijklmnopqrstuvwxyzabc", "do ordain"); + +SELECT * FROM t5; + # # Cleanup, test is over # diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test index aebee0b0c6f..a2853ca3191 100644 --- a/mysql-test/t/create.test +++ b/mysql-test/t/create.test @@ -554,7 +554,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; @@ -567,7 +567,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) @@ -575,7 +575,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) @@ -583,7 +583,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) @@ -591,7 +591,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) @@ -599,7 +599,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) @@ -613,7 +613,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, @@ -621,20 +621,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, @@ -711,3 +711,24 @@ TRUNCATE table t2; INSERT INTO t2 select * from t1; SELECT * from t2; drop table t1,t2; + +# +# Test incorrect database names +# + +--error 1102 +CREATE DATABASE aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; +--error 1102 +DROP DATABASE aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; +--error 1049 +RENAME DATABASE aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa TO a; +--error 1102 +RENAME DATABASE mysqltest TO aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; +create database mysqltest; +--error 1102 +RENAME DATABASE mysqltest TO aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; +drop database mysqltest; +--error 1102 +USE aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; +--error 1102 +SHOW CREATE DATABASE aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; diff --git a/mysql-test/t/csv.test b/mysql-test/t/csv.test index 82102a6078e..60d38394fc0 100644 --- a/mysql-test/t/csv.test +++ b/mysql-test/t/csv.test @@ -1508,27 +1508,27 @@ DROP TABLE test_repair_table5; 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 89f82d1a758..7b7018d5901 100644 --- a/mysql-test/t/ctype_cp1250_ch.test +++ b/mysql-test/t/ctype_cp1250_ch.test @@ -3,6 +3,10 @@ drop table if exists t1; --enable_warnings +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + SHOW COLLATION LIKE 'cp1250_czech_cs'; # diff --git a/mysql-test/t/ctype_create.test b/mysql-test/t/ctype_create.test index e88004bbb8c..060c09a0459 100644 --- a/mysql-test/t/ctype_create.test +++ b/mysql-test/t/ctype_create.test @@ -100,3 +100,8 @@ drop database mysqltest2; ALTER DATABASE DEFAULT CHARACTER SET latin2; # End of 4.1 tests + +--error 1102 +ALTER DATABASE aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa DEFAULT CHARACTER SET latin2; +--error 1102 +ALTER DATABASE `` DEFAULT CHARACTER SET latin2; 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 65ee82fff23..804b17ab6bb 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -1229,6 +1229,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 0d3b7cdfdeb..e48108af9ce 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -16,6 +16,9 @@ concurrent_innodb : BUG#21579 2006-08-11 mleich innodb_concurrent random ndb_autodiscover : BUG#18952 2006-02-16 jmiller Needs to be fixed w.r.t binlog ndb_autodiscover2 : BUG#18952 2006-02-16 jmiller Needs to be fixed w.r.t binlog ndb_load : BUG#17233 2006-05-04 tomas failed load data from infile causes mysqld dbug_assert, binlog not flushed +ndb_restore_partition : Problem with cluster/def/schema table that is in std_data/ndb_backup51; Pekka will schdule this to someone +rpl_ndb_sync : Problem with cluster/def/schema table that is in std_data/ndb_backup51; Pekka will schdule this to someone + partition_03ndb : BUG#16385 2006-03-24 mikael Partitions: crash when updating a range partitioned NDB table ps_7ndb : BUG#18950 2006-02-16 jmiller create table like does not obtain LOCK_open rpl_ndb_2innodb : BUG#19227 2006-04-20 pekka pk delete apparently not replicated @@ -27,6 +30,7 @@ rpl_ndb_myisam2ndb : Bug #19710 Cluster replication to partition table fa rpl_row_blob_innodb : BUG#18980 2006-04-10 kent Test fails randomly rpl_sp : BUG#16456 2006-02-16 jmiller rpl_multi_engine : BUG#22583 2006-09-23 lars +synchronization : Bug#24529 Test 'synchronization' fails on Mac pushbuild; Also on Linux 64 bit. # the below testcase have been reworked to avoid the bug, test contains comment, keep bug open #ndb_binlog_ddl_multi : BUG#18976 2006-04-10 kent CRBR: multiple binlog, second binlog may miss schema log events diff --git a/mysql-test/t/events.test b/mysql-test/t/events.test index 32863308687..6eb514fc13c 100644 --- a/mysql-test/t/events.test +++ b/mysql-test/t/events.test @@ -395,4 +395,15 @@ drop event e1; ##show processlist; ##select count(*) from mysql.event; +# +# Test wrong syntax +# + +--error 1102 +SHOW EVENTS FROM aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; +--error 1102 +SHOW EVENTS FROM ``; + +SHOW EVENTS FROM `events\\test`; + drop database events_test; diff --git a/mysql-test/t/events_bugs.test b/mysql-test/t/events_bugs.test index 6223395bfd9..81988818809 100644 --- a/mysql-test/t/events_bugs.test +++ b/mysql-test/t/events_bugs.test @@ -280,7 +280,7 @@ create event e22830_3 on schedule every 1 hour do alter event e22830_3 on schedu create event e22830_4 on schedule every 1 hour do alter event e22830_4 on schedule every (select f22830() from dual) hour; select event_name, event_definition, interval_value, interval_field from information_schema.events order by event_name; set global event_scheduler=on; ---sleep 0.7 +--sleep 2.0 set global event_scheduler=off; select event_name, event_definition, interval_value, interval_field from information_schema.events order by event_name; drop function f22830; 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/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 db3536c6d36..cde9c1fcea3 100644 --- a/mysql-test/t/func_gconcat.test +++ b/mysql-test/t/func_gconcat.test @@ -461,3 +461,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 78393ee1104..b41f6cd71c8 100644 --- a/mysql-test/t/func_group.test +++ b/mysql-test/t/func_group.test @@ -707,3 +707,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 906747c2f78..ee344d0958b 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) @@ -233,6 +254,10 @@ 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); drop table t1; + +--echo End of 5.0 tests + + # # Bug#18360: Type aggregation for IN and CASE may lead to a wrong result # @@ -256,3 +281,6 @@ explain select f2 from t2 where f2 in ('a','b'); select f2 from t2 where f2 in (1,'b'); explain select f2 from t2 where f2 in (1,'b'); drop table t1, t2; + + +--echo End of 5.1 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 45415882ac7..2ec1afc70ee 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 @@ -460,7 +468,51 @@ drop table t7; select substring_index("1abcd;2abcd;3abcd;4abcd", ';', 2),substring_index("1abcd;2abcd;3abcd;4abcd", ';', -2); -explain extended select md5('hello'), sha('abc'), sha1('abc'), soundex(''), 'mood' sounds like 'mud', aes_decrypt(aes_encrypt('abc','1'),'1'),concat('*',space(5),'*'), reverse('abc'), rpad('a',4,'1'), lpad('a',4,'1'), concat_ws(',','',NULL,'a'),make_set(255,_latin2'a',_latin2'b',_latin2'c'),elt(2,1),locate("a","b",2),format(130,10),char(0),conv(130,16,10),hex(130),binary 'HE', export_set(255,_latin2'y',_latin2'n',_latin2' '),FIELD('b' COLLATE latin1_bin,'A','B'),FIND_IN_SET(_latin1'B',_latin1'a,b,c,d'),collation(conv(130,16,10)), coercibility(conv(130,16,10)),length('\n\t\r\b\0\_\%\\'),bit_length('\n\t\r\b\0\_\%\\'),bit_length('\n\t\r\b\0\_\%\\'),concat('monty',' was here ','again'),length('hello'),char(ascii('h')),ord('h'),quote(1/0),crc32("123"),replace('aaaa','a','b'),insert('txs',2,1,'hi'),left(_latin2'a',1),right(_latin2'a',1),lcase(_latin2'a'),ucase(_latin2'a'),SUBSTR('abcdefg',3,2),substring_index("1abcd;2abcd;3abcd;4abcd", ';', 2),trim(_latin2' a '),ltrim(_latin2' a '),rtrim(_latin2' a '), decode(encode(repeat("a",100000),"monty"),"monty"); +explain extended select md5('hello'); +explain extended select sha('abc'); +explain extended select sha1('abc'); +explain extended select soundex(''); +explain extended select 'mood' sounds like 'mud'; +explain extended select aes_decrypt(aes_encrypt('abc','1'),'1'); +explain extended select concat('*',space(5),'*'); +explain extended select reverse('abc'); +explain extended select rpad('a',4,'1'); +explain extended select lpad('a',4,'1'); +explain extended select concat_ws(',','',NULL,'a'); +explain extended select make_set(255,_latin2'a', _latin2'b', _latin2'c'); +explain extended select elt(2,1); +explain extended select locate("a","b",2); +explain extended select format(130,10); +explain extended select char(0); +explain extended select conv(130,16,10); +explain extended select hex(130); +explain extended select binary 'HE'; +explain extended select export_set(255,_latin2'y', _latin2'n', _latin2' '); +explain extended select FIELD('b' COLLATE latin1_bin,'A','B'); +explain extended select FIND_IN_SET(_latin1'B', _latin1'a,b,c,d'); +explain extended select collation(conv(130,16,10)); +explain extended select coercibility(conv(130,16,10)); +explain extended select length('\n\t\r\b\0\_\%\\'); +explain extended select bit_length('\n\t\r\b\0\_\%\\'); +explain extended select bit_length('\n\t\r\b\0\_\%\\'); +explain extended select concat('monty',' was here ','again'); +explain extended select length('hello'); +explain extended select char(ascii('h')); +explain extended select ord('h'); +explain extended select quote(1/0); +explain extended select crc32("123"); +explain extended select replace('aaaa','a','b'); +explain extended select insert('txs',2,1,'hi'); +explain extended select left(_latin2'a',1); +explain extended select right(_latin2'a',1); +explain extended select lcase(_latin2'a'); +explain extended select ucase(_latin2'a'); +explain extended select SUBSTR('abcdefg',3,2); +explain extended select substring_index("1abcd;2abcd;3abcd;4abcd", ';', 2); +explain extended select trim(_latin2' a '); +explain extended select ltrim(_latin2' a '); +explain extended select rtrim(_latin2' a '); +explain extended select decode(encode(repeat("a",100000),"monty"),"monty"); # # lpad returns incorrect result (Bug #2182) @@ -780,4 +832,271 @@ SELECT * FROM t1 INNER JOIN t2 ON code=id DROP TABLE t1,t2; +# +# Bug#22684: The Functions ENCODE, DECODE and FORMAT are not real functions +# + +select encode(NULL, NULL); +select encode("data", NULL); +select encode(NULL, "password"); + +select decode(NULL, NULL); +select decode("data", NULL); +select decode(NULL, "password"); + +select format(NULL, NULL); +select format(pi(), NULL); +select format(NULL, 2); + +select benchmark(NULL, NULL); +select benchmark(0, NULL); +select benchmark(100, NULL); +select benchmark(NULL, 1+1); + +# +# Please note: +# 1) The collation of the password is irrelevant, the encryption uses +# the binary representation of the string without charset/collation. +# 2) These tests can not print the encoded text directly, because it's binary, +# and doing this would cause problems with source control. +# Instead, an md5() checksum is used, to verify the result indirectly. +# 3) Each md5() result must be identical. +# 4) The md5() result must never change, and must be stable across releases. +# +set @password="password"; +set @my_data="clear text to encode"; +select md5(encode(@my_data, "password")); +select md5(encode(@my_data, _utf8 "password")); +select md5(encode(@my_data, binary "password")); +select md5(encode(@my_data, _latin1 "password")); +select md5(encode(@my_data, _koi8r "password")); +select md5(encode(@my_data, (select "password" from dual))); +select md5(encode(@my_data, concat("pass", "word"))); +select md5(encode(@my_data, @password)); + +set @my_data="binary encoded data"; +select md5(decode(@my_data, "password")); +select md5(decode(@my_data, _utf8 "password")); +select md5(decode(@my_data, binary "password")); +select md5(decode(@my_data, _latin1 "password")); +select md5(decode(@my_data, _koi8r "password")); +select md5(decode(@my_data, (select "password" from dual))); +select md5(decode(@my_data, concat("pass", "word"))); +select md5(decode(@my_data, @password)); + +set @dec=5; +select format(pi(), (1+1)); +select format(pi(), (select 3 from dual)); +select format(pi(), @dec); + +set @bench_count=10; +select benchmark(10, pi()); +select benchmark(5+5, pi()); +select benchmark((select 10 from dual), pi()); +select benchmark(@bench_count, pi()); + + +# +# Bug #10963 +# 4294967296 18446744073709551616 + +select locate('he','hello',-2); +select locate('lo','hello',-4294967295); +select locate('lo','hello',4294967295); +select locate('lo','hello',-4294967296); +select locate('lo','hello',4294967296); +select locate('lo','hello',-4294967297); +select locate('lo','hello',4294967297); +select locate('lo','hello',-18446744073709551615); +select locate('lo','hello',18446744073709551615); +select locate('lo','hello',-18446744073709551616); +select locate('lo','hello',18446744073709551616); +select locate('lo','hello',-18446744073709551617); +select locate('lo','hello',18446744073709551617); + +select left('hello', 10); +select left('hello', 0); +select left('hello', -1); +select left('hello', -4294967295); +select left('hello', 4294967295); +select left('hello', -4294967296); +select left('hello', 4294967296); +select left('hello', -4294967297); +select left('hello', 4294967297); +select left('hello', -18446744073709551615); +select left('hello', 18446744073709551615); +select left('hello', -18446744073709551616); +select left('hello', 18446744073709551616); +select left('hello', -18446744073709551617); +select left('hello', 18446744073709551617); + +select right('hello', 10); +select right('hello', 0); +select right('hello', -1); +select right('hello', -4294967295); +select right('hello', 4294967295); +select right('hello', -4294967296); +select right('hello', 4294967296); +select right('hello', -4294967297); +select right('hello', 4294967297); +select right('hello', -18446744073709551615); +select right('hello', 18446744073709551615); +select right('hello', -18446744073709551616); +select right('hello', 18446744073709551616); +select right('hello', -18446744073709551617); +select right('hello', 18446744073709551617); + +select substring('hello', 2, -1); + +select substring('hello', -1, 1); +select substring('hello', -2, 1); +select substring('hello', -4294967295, 1); +select substring('hello', 4294967295, 1); +select substring('hello', -4294967296, 1); +select substring('hello', 4294967296, 1); +select substring('hello', -4294967297, 1); +select substring('hello', 4294967297, 1); +select substring('hello', -18446744073709551615, 1); +select substring('hello', 18446744073709551615, 1); +select substring('hello', -18446744073709551616, 1); +select substring('hello', 18446744073709551616, 1); +select substring('hello', -18446744073709551617, 1); +select substring('hello', 18446744073709551617, 1); +select substring('hello', 1, -1); +select substring('hello', 1, -4294967295); +select substring('hello', 1, 4294967295); +select substring('hello', 1, -4294967296); +select substring('hello', 1, 4294967296); +select substring('hello', 1, -4294967297); +select substring('hello', 1, 4294967297); +select substring('hello', 1, -18446744073709551615); +select substring('hello', 1, 18446744073709551615); +select substring('hello', 1, -18446744073709551616); +select substring('hello', 1, 18446744073709551616); +select substring('hello', 1, -18446744073709551617); +select substring('hello', 1, 18446744073709551617); +select substring('hello', -1, -1); +select substring('hello', -4294967295, -4294967295); +select substring('hello', 4294967295, 4294967295); +select substring('hello', -4294967296, -4294967296); +select substring('hello', 4294967296, 4294967296); +select substring('hello', -4294967297, -4294967297); +select substring('hello', 4294967297, 4294967297); +select substring('hello', -18446744073709551615, -18446744073709551615); +select substring('hello', 18446744073709551615, 18446744073709551615); +select substring('hello', -18446744073709551616, -18446744073709551616); +select substring('hello', 18446744073709551616, 18446744073709551616); +select substring('hello', -18446744073709551617, -18446744073709551617); +select substring('hello', 18446744073709551617, 18446744073709551617); + +select insert('hello', -1, 1, 'hi'); +select insert('hello', -4294967295, 1, 'hi'); +select insert('hello', 4294967295, 1, 'hi'); +select insert('hello', -4294967296, 1, 'hi'); +select insert('hello', 4294967296, 1, 'hi'); +select insert('hello', -4294967297, 1, 'hi'); +select insert('hello', 4294967297, 1, 'hi'); +select insert('hello', -18446744073709551615, 1, 'hi'); +select insert('hello', 18446744073709551615, 1, 'hi'); +select insert('hello', -18446744073709551616, 1, 'hi'); +select insert('hello', 18446744073709551616, 1, 'hi'); +select insert('hello', -18446744073709551617, 1, 'hi'); +select insert('hello', 18446744073709551617, 1, 'hi'); +select insert('hello', 1, -1, 'hi'); +select insert('hello', 1, -4294967295, 'hi'); +select insert('hello', 1, 4294967295, 'hi'); +select insert('hello', 1, -4294967296, 'hi'); +select insert('hello', 1, 4294967296, 'hi'); +select insert('hello', 1, -4294967297, 'hi'); +select insert('hello', 1, 4294967297, 'hi'); +select insert('hello', 1, -18446744073709551615, 'hi'); +select insert('hello', 1, 18446744073709551615, 'hi'); +select insert('hello', 1, -18446744073709551616, 'hi'); +select insert('hello', 1, 18446744073709551616, 'hi'); +select insert('hello', 1, -18446744073709551617, 'hi'); +select insert('hello', 1, 18446744073709551617, 'hi'); +select insert('hello', -1, -1, 'hi'); +select insert('hello', -4294967295, -4294967295, 'hi'); +select insert('hello', 4294967295, 4294967295, 'hi'); +select insert('hello', -4294967296, -4294967296, 'hi'); +select insert('hello', 4294967296, 4294967296, 'hi'); +select insert('hello', -4294967297, -4294967297, 'hi'); +select insert('hello', 4294967297, 4294967297, 'hi'); +select insert('hello', -18446744073709551615, -18446744073709551615, 'hi'); +select insert('hello', 18446744073709551615, 18446744073709551615, 'hi'); +select insert('hello', -18446744073709551616, -18446744073709551616, 'hi'); +select insert('hello', 18446744073709551616, 18446744073709551616, 'hi'); +select insert('hello', -18446744073709551617, -18446744073709551617, 'hi'); +select insert('hello', 18446744073709551617, 18446744073709551617, 'hi'); + +select repeat('hello', -1); +select repeat('hello', -4294967295); +select repeat('hello', 4294967295); +select repeat('hello', -4294967296); +select repeat('hello', 4294967296); +select repeat('hello', -4294967297); +select repeat('hello', 4294967297); +select repeat('hello', -18446744073709551615); +select repeat('hello', 18446744073709551615); +select repeat('hello', -18446744073709551616); +select repeat('hello', 18446744073709551616); +select repeat('hello', -18446744073709551617); +select repeat('hello', 18446744073709551617); + +select space(-1); +select space(-4294967295); +select space(4294967295); +select space(-4294967296); +select space(4294967296); +select space(-4294967297); +select space(4294967297); +select space(-18446744073709551615); +select space(18446744073709551615); +select space(-18446744073709551616); +select space(18446744073709551616); +select space(-18446744073709551617); +select space(18446744073709551617); + +select rpad('hello', -1, '1'); +select rpad('hello', -4294967295, '1'); +select rpad('hello', 4294967295, '1'); +select rpad('hello', -4294967296, '1'); +select rpad('hello', 4294967296, '1'); +select rpad('hello', -4294967297, '1'); +select rpad('hello', 4294967297, '1'); +select rpad('hello', -18446744073709551615, '1'); +select rpad('hello', 18446744073709551615, '1'); +select rpad('hello', -18446744073709551616, '1'); +select rpad('hello', 18446744073709551616, '1'); +select rpad('hello', -18446744073709551617, '1'); +select rpad('hello', 18446744073709551617, '1'); + +select lpad('hello', -1, '1'); +select lpad('hello', -4294967295, '1'); +select lpad('hello', 4294967295, '1'); +select lpad('hello', -4294967296, '1'); +select lpad('hello', 4294967296, '1'); +select lpad('hello', -4294967297, '1'); +select lpad('hello', 4294967297, '1'); +select lpad('hello', -18446744073709551615, '1'); +select lpad('hello', 18446744073709551615, '1'); +select lpad('hello', -18446744073709551616, '1'); +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/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..4feca43ae1a 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): --- --- 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 +# 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_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 11ba6885dd1..f9ac3a625cc 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 extended select distinct a1,a2,b,c from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121'); @@ -502,7 +502,7 @@ explain extended select distinct a1,a2,b,c from t2 where (a2 >= 'b') and (b = 'a 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 extended 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 extended 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 extended 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 extended 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 extended select a1,a2,count(a2) from t1 where (a1 > 'a') group by a1,a2,b; explain extended select sum(ord(a1)) from t1 where (a1 > 'a') group by a1,a2,b; @@ -790,24 +790,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)) diff --git a/mysql-test/t/im_daemon_life_cycle.imtest b/mysql-test/t/im_daemon_life_cycle.imtest index fd19b6f8527..c5b8ee16d9a 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_NUMBER 4 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_options.imtest b/mysql-test/t/im_options.imtest index b3932c446da..8f9bed16473 100644 --- a/mysql-test/t/im_options.imtest +++ b/mysql-test/t/im_options.imtest @@ -32,33 +32,7 @@ # ########################################################################### ---source include/im_check_os.inc - -########################################################################### -# -# Check starting conditions. -# -########################################################################### - -# - check the configuration file; - ---echo -------------------------------------------------------------------- ---exec grep '^server_id[^a-zA-Z0-9_-]' $MYSQLTEST_VARDIR/im.cnf ; ---echo -------------------------------------------------------------------- - -# - check the running instances. - ---connect (mysql1_con,localhost,root,,mysql,$IM_MYSQLD1_PORT,$IM_MYSQLD1_SOCK) - ---connection mysql1_con - -SHOW VARIABLES LIKE 'server_id'; - ---connection default - -# - check the internal cache. - -SHOW INSTANCES; +--source include/im_check_env.inc ########################################################################### # 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 4ae88736b98..cec140a5e63 100644 --- a/mysql-test/t/information_schema.test +++ b/mysql-test/t/information_schema.test @@ -37,7 +37,7 @@ create table t3(a int, KEY a_data (a)); create table mysqltest.t4(a int); create table t5 (id int auto_increment primary key); insert into t5 values (10); -create view v1 (c) as select table_name from information_schema.TABLES where table_schema!='cluster'; +create view v1 (c) as select table_name from information_schema.TABLES where table_name<>'binlog_index' AND table_name<>'apply_status'; select * from v1; select c,table_name from v1 @@ -528,7 +528,7 @@ flush privileges; # Bug #9404 information_schema: Weird error messages # with SELECT SUM() ... GROUP BY queries # -SELECT table_schema, count(*) FROM information_schema.TABLES where TABLE_SCHEMA!='cluster' GROUP BY TABLE_SCHEMA; +SELECT table_schema, count(*) FROM information_schema.TABLES where table_name<>'binlog_index' AND table_name<>'apply_status' GROUP BY TABLE_SCHEMA; # @@ -974,6 +974,20 @@ SELECT COLUMN_NAME, MD5(COLUMN_DEFAULT), LENGTH(COLUMN_DEFAULT), COLUMN_DEFAULT= DROP TABLE bug23037; 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; + --echo End of 5.0 tests. # # Show engines 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 1a2afad3b44..7e9a0e1ed18 100644 --- a/mysql-test/t/innodb.test +++ b/mysql-test/t/innodb.test @@ -1475,7 +1475,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 d0005f3b8f7..f39938ec52c 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,17 +481,17 @@ 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 +select * from t1 natural join (t3 cross join t4); # works in Oracle - bug -- error 1052 -select * from (t3 cross join t4) natural join t1; -- works in Oracle - bug +select * from (t3 cross join t4) natural join t1; # works in Oracle - bug -- error 1052 select * from t1 join (t2, t3) using (b); -- error 1052 @@ -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 @@ -579,12 +579,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_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 cf7789428b2..2eb4e6cbbb2 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 765da1ee18d..6c89a8b4a7b 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/mysql.test b/mysql-test/t/mysql.test index c06e52e2d78..cb4a5593de7 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 diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index 1f1c8a44dbe..05b15cdad17 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -1394,6 +1394,9 @@ revoke all privileges on mysqldump_myDB.* from myDB_User@localhost; drop user myDB_User; drop database mysqldump_myDB; use test; +connection default; +disconnect root; +disconnect user1; --echo # --echo # BUG#13926: --order-by-primary fails if PKEY contains quote character diff --git a/mysql-test/t/ndb_binlog_basic.test b/mysql-test/t/ndb_binlog_basic.test index 3886900037d..c2a36423445 100644 --- a/mysql-test/t/ndb_binlog_basic.test +++ b/mysql-test/t/ndb_binlog_basic.test @@ -19,7 +19,7 @@ create table t1 (a int primary key) engine=ndb; insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); save_master_pos; --replace_column 1 # -select @max_epoch:=max(epoch)-1 from cluster.binlog_index; +select @max_epoch:=max(epoch)-1 from mysql.binlog_index; delete from t1; alter table t1 add (b int); @@ -38,10 +38,10 @@ drop table t2; # (save_master_pos waits for last gcp to complete, ensuring that we have # the expected data in the binlog) save_master_pos; -select inserts from cluster.binlog_index where epoch > @max_epoch and inserts > 5; -select deletes from cluster.binlog_index where epoch > @max_epoch and deletes > 5; +select inserts from mysql.binlog_index where epoch > @max_epoch and inserts > 5; +select deletes from mysql.binlog_index where epoch > @max_epoch and deletes > 5; select inserts,updates,deletes from - cluster.binlog_index where epoch > @max_epoch and updates > 0; + mysql.binlog_index where epoch > @max_epoch and updates > 0; # # check that purge clears the binlog_index @@ -49,7 +49,7 @@ select inserts,updates,deletes from flush logs; --sleep 1 purge master logs before now(); -select count(*) from cluster.binlog_index; +select count(*) from mysql.binlog_index; # # several tables in different databases @@ -64,9 +64,9 @@ use test; insert into mysqltest.t1 values (2,1),(2,2); save_master_pos; --replace_column 1 # -select @max_epoch:=max(epoch)-1 from cluster.binlog_index; +select @max_epoch:=max(epoch)-1 from mysql.binlog_index; drop table t1; drop database mysqltest; select inserts,updates,deletes from - cluster.binlog_index where epoch > @max_epoch and inserts > 0; + mysql.binlog_index where epoch > @max_epoch and inserts > 0; diff --git a/mysql-test/t/ndb_binlog_ddl_multi.test b/mysql-test/t/ndb_binlog_ddl_multi.test index 78cec137159..064bd88764a 100644 --- a/mysql-test/t/ndb_binlog_ddl_multi.test +++ b/mysql-test/t/ndb_binlog_ddl_multi.test @@ -45,7 +45,7 @@ reset master; --connection server2 alter table t2 add column (b int); ---connections server1 +--connection server1 --source include/show_binlog_events.inc # alter database diff --git a/mysql-test/t/ndb_binlog_multi.test b/mysql-test/t/ndb_binlog_multi.test index e023a54b61c..1c6a1063fea 100644 --- a/mysql-test/t/ndb_binlog_multi.test +++ b/mysql-test/t/ndb_binlog_multi.test @@ -38,7 +38,7 @@ INSERT INTO t2 VALUES (1,1),(2,2); select * from t2 order by a; --replace_column 1 <the_epoch> SELECT @the_epoch:=epoch,inserts,updates,deletes,schemaops FROM - cluster.binlog_index ORDER BY epoch DESC LIMIT 1; + mysql.binlog_index ORDER BY epoch DESC LIMIT 1; let $the_epoch= `SELECT @the_epoch`; # see if we got something on server1 @@ -50,7 +50,7 @@ DROP TABLE t2; --source include/show_binlog_events.inc --replace_result $the_epoch <the_epoch> eval SELECT inserts,updates,deletes,schemaops FROM - cluster.binlog_index WHERE epoch=$the_epoch; + mysql.binlog_index WHERE epoch=$the_epoch; # reset for next test connection server1; @@ -65,12 +65,12 @@ INSERT INTO t1 VALUES (1),(2); --source include/show_binlog_events.inc --replace_column 1 <the_epoch2> SELECT @the_epoch2:=epoch,inserts,updates,deletes,schemaops FROM - cluster.binlog_index ORDER BY epoch DESC LIMIT 1; + mysql.binlog_index ORDER BY epoch DESC LIMIT 1; let $the_epoch2= `SELECT @the_epoch2`; --replace_result $the_epoch <the_epoch> $the_epoch2 <the_epoch2> eval SELECT inserts,updates,deletes,schemaops FROM - cluster.binlog_index WHERE epoch > $the_epoch AND epoch <= $the_epoch2; + mysql.binlog_index WHERE epoch > $the_epoch AND epoch <= $the_epoch2; # now see that we have the events on the other server connection server2; @@ -80,4 +80,4 @@ drop table t1; --source include/show_binlog_events.inc --replace_result $the_epoch <the_epoch> $the_epoch2 <the_epoch2> eval SELECT inserts,updates,deletes,schemaops FROM - cluster.binlog_index WHERE epoch > $the_epoch AND epoch <= $the_epoch2; + mysql.binlog_index WHERE epoch > $the_epoch AND epoch <= $the_epoch2; diff --git a/mysql-test/t/ndb_blob_partition.test b/mysql-test/t/ndb_blob_partition.test index 6173c9d9851..35df57b96ba 100644 --- a/mysql-test/t/ndb_blob_partition.test +++ b/mysql-test/t/ndb_blob_partition.test @@ -36,15 +36,15 @@ set @s0 = 'rggurloniukyehuxdbfkkyzlceixzrehqhvxvxbpwizzvjzpucqmzrhzxzfau'; set @s1 = 'ykyymbzqgqlcjhlhmyqelfoaaohvtbekvifukdtnvcrrjveevfakxarxexomz'; set @s2 = 'dbnfqyzgtqxalcrwtfsqabknvtfcbpoonxsjiqvmhnfikxxhcgoexlkoezvah'; -set @v1 = repeat(@s0, 100); -- 1d42dd9090cf78314a06665d4ea938c35cc760f4 -set @v2 = repeat(@s1, 200); -- 10d3c783026b310218d10b7188da96a2401648c6 -set @v3 = repeat(@s2, 300); -- a33549d9844092289a58ac348dd59f09fc28406a -set @v4 = repeat(@s0, 400); -- daa61c6de36a0526f0d47dc29d6b9de7e6d2630c -set @v5 = repeat(@s1, 500); -- 70fc9a7d08beebc522258bfb02000a30c77a8f1d -set @v6 = repeat(@s2, 600); -- 090565c580809efed3d369481a4bbb168b20713e -set @v7 = repeat(@s0, 700); -- 1e0070bec426871a46291de27b9bd6e4255ab4e5 -set @v8 = repeat(@s1, 800); -- acbaba01bc2e682f015f40e79d9cbe475db3002e -set @v9 = repeat(@s2, 900); -- 9ee30d99162574f79c66ae95cdf132dcf9cbc259 +set @v1 = repeat(@s0, 100); # 1d42dd9090cf78314a06665d4ea938c35cc760f4 +set @v2 = repeat(@s1, 200); # 10d3c783026b310218d10b7188da96a2401648c6 +set @v3 = repeat(@s2, 300); # a33549d9844092289a58ac348dd59f09fc28406a +set @v4 = repeat(@s0, 400); # daa61c6de36a0526f0d47dc29d6b9de7e6d2630c +set @v5 = repeat(@s1, 500); # 70fc9a7d08beebc522258bfb02000a30c77a8f1d +set @v6 = repeat(@s2, 600); # 090565c580809efed3d369481a4bbb168b20713e +set @v7 = repeat(@s0, 700); # 1e0070bec426871a46291de27b9bd6e4255ab4e5 +set @v8 = repeat(@s1, 800); # acbaba01bc2e682f015f40e79d9cbe475db3002e +set @v9 = repeat(@s2, 900); # 9ee30d99162574f79c66ae95cdf132dcf9cbc259 --enable_query_log # -- insert -- diff --git a/mysql-test/t/ndb_index_ordered.test b/mysql-test/t/ndb_index_ordered.test index 85eb9149a6d..bba0c5ca53f 100644 --- a/mysql-test/t/ndb_index_ordered.test +++ b/mysql-test/t/ndb_index_ordered.test @@ -50,7 +50,7 @@ update t1 set c = 13 where b <= 3; select * from t1 order by a; update t1 set b = b + 1 where b > 4 and b < 7; select * from t1 order by a; --- Update primary key +# Update primary key update t1 set a = a + 10 where b > 1 and b < 7; select * from t1 order by a; diff --git a/mysql-test/t/ndb_restore_compat.test b/mysql-test/t/ndb_restore_compat.test index 774011e362d..ee55e827d0e 100644 --- a/mysql-test/t/ndb_restore_compat.test +++ b/mysql-test/t/ndb_restore_compat.test @@ -21,7 +21,7 @@ SELECT * FROM GL ORDER BY TIME,ACCOUNT_TYPE; SELECT * FROM ACCOUNT ORDER BY ACCOUNT_ID; SELECT COUNT(*) FROM TRANSACTION; SELECT * FROM SYSTEM_VALUES ORDER BY SYSTEM_VALUES_ID; -SELECT * FROM cluster.apply_status WHERE server_id=0; +SELECT * FROM mysql.apply_status WHERE server_id=0; # # verify restore of 5.0 backup @@ -39,5 +39,5 @@ SELECT * FROM GL ORDER BY TIME,ACCOUNT_TYPE; SELECT * FROM ACCOUNT ORDER BY ACCOUNT_ID; SELECT COUNT(*) FROM TRANSACTION; SELECT * FROM SYSTEM_VALUES ORDER BY SYSTEM_VALUES_ID; -SELECT * FROM cluster.apply_status WHERE server_id=0; +SELECT * FROM mysql.apply_status WHERE server_id=0; DROP DATABASE BANK; diff --git a/mysql-test/t/ndb_update.test b/mysql-test/t/ndb_update.test index 5472dd95e9f..ebcc6995d74 100644 --- a/mysql-test/t/ndb_update.test +++ b/mysql-test/t/ndb_update.test @@ -29,6 +29,7 @@ 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/parser.test b/mysql-test/t/parser.test index 11af7c691d8..39c8d8e2bf4 100644 --- a/mysql-test/t/parser.test +++ b/mysql-test/t/parser.test @@ -399,11 +399,6 @@ select atan(); -- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT select atan2(1, 2, 3); -select benchmark(10, 1+1); - --- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT -select benchmark(5+5, 2); - -- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT select concat(); select concat("foo"); @@ -413,12 +408,6 @@ select concat_ws(); -- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT select concat_ws("foo"); -set @pwd="my password"; --- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT -select encode("secret", @pwd); --- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT -select decode("encoded-secret", @pwd); - -- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT select encrypt(); -- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT @@ -448,10 +437,6 @@ select field(); -- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT select field("p1"); -set @dec=2; --- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT -select format(pi(), @dec); - -- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT select from_unixtime(); -- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index 1a19355406a..39e4e65c6bf 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -849,6 +849,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; # @@ -858,17 +861,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; @@ -882,12 +885,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; @@ -895,47 +892,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; @@ -944,26 +944,31 @@ 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`; +let $query= select variable_value from information_schema.global_status + where variable_name = 'prepared_stmt_count'; +let $count= `$query`; if ($count) { ---sleep 2 - let $count= `select @@prepared_stmt_count`; +--sleep 1 + let $count= `$query`; } -select @@max_prepared_stmt_count, @@prepared_stmt_count; +select @@max_prepared_stmt_count; +show status like '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" @@ -2092,14 +2097,6 @@ drop view v1; drop table t1; -create procedure proc_1() install plugin my_plug soname '/root/some_plugin.so'; ---error ER_UDF_NO_PATHS -call proc_1(); ---error ER_UDF_NO_PATHS -call proc_1(); ---error ER_UDF_NO_PATHS -call proc_1(); -drop procedure proc_1; create procedure proc_1() install plugin my_plug soname 'some_plugin.so'; --replace_regex /(Can\'t open shared library).*$/\1/ --error ER_CANT_OPEN_LIBRARY @@ -2119,12 +2116,6 @@ delimiter ;| select func_1(), func_1(), func_1() from dual; --error ER_SP_DOES_NOT_EXIST drop function func_1; -prepare abc from "install plugin my_plug soname '/root/some_plugin.so'"; ---error ER_UDF_NO_PATHS -execute abc; ---error ER_UDF_NO_PATHS -execute abc; -deallocate prepare abc; prepare abc from "install plugin my_plug soname 'some_plugin.so'"; deallocate prepare abc; @@ -2414,3 +2405,38 @@ execute abc; drop table if exists t1, t2; execute abc; deallocate prepare abc; + +# +# Bug#22684: The Functions ENCODE, DECODE and FORMAT are not real functions +# + +set @my_password="password"; +set @my_data="clear text to encode"; + +prepare stmt1 from 'select decode(encode(?, ?), ?)'; +execute stmt1 using @my_data, @my_password, @my_password; +set @my_data="more text to encode"; +execute stmt1 using @my_data, @my_password, @my_password; +set @my_password="new password"; +execute stmt1 using @my_data, @my_password, @my_password; +deallocate prepare stmt1; + +set @to_format="123456789.123456789"; +set @dec=0; + +prepare stmt2 from 'select format(?, ?)'; +execute stmt2 using @to_format, @dec; +set @dec=4; +execute stmt2 using @to_format, @dec; +set @dec=6; +execute stmt2 using @to_format, @dec; +set @dec=2; +execute stmt2 using @to_format, @dec; +set @to_format="100"; +execute stmt2 using @to_format, @dec; +set @to_format="1000000"; +execute stmt2 using @to_format, @dec; +set @to_format="10000"; +execute stmt2 using @to_format, @dec; +deallocate prepare stmt2; + diff --git a/mysql-test/t/ps_not_windows.test b/mysql-test/t/ps_not_windows.test new file mode 100644 index 00000000000..0d97df96285 --- /dev/null +++ b/mysql-test/t/ps_not_windows.test @@ -0,0 +1,23 @@ +# Non-windows specific ps tests. +--source include/not_windows.inc + +# +# Bug #20665: All commands supported in Stored Procedures should work in +# Prepared Statements +# + +create procedure proc_1() install plugin my_plug soname '/root/some_plugin.so'; +--error ER_UDF_NO_PATHS +call proc_1(); +--error ER_UDF_NO_PATHS +call proc_1(); +--error ER_UDF_NO_PATHS +call proc_1(); +drop procedure proc_1; + +prepare abc from "install plugin my_plug soname '/root/some_plugin.so'"; +--error ER_UDF_NO_PATHS +execute abc; +--error ER_UDF_NO_PATHS +execute abc; +deallocate prepare abc; diff --git a/mysql-test/t/query_cache.test b/mysql-test/t/query_cache.test index 67c4c4cb20b..cb4e5f97c3a 100644 --- a/mysql-test/t/query_cache.test +++ b/mysql-test/t/query_cache.test @@ -877,3 +877,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/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/rpl_do_grant.test b/mysql-test/t/rpl_do_grant.test index 8d6f99e4bf1..4e398114269 100644 --- a/mysql-test/t/rpl_do_grant.test +++ b/mysql-test/t/rpl_do_grant.test @@ -39,11 +39,11 @@ connection master; delete from mysql.user where user=_binary'rpl_do_grant'; delete from mysql.db where user=_binary'rpl_do_grant'; flush privileges; -save_master_pos; -connection slave; -sync_with_master; -# no need to delete manually, as the DELETEs must have done some real job on -# master (updated binlog) +sync_slave_with_master; +# The mysql database is not replicated, so we have to do the deletes +# manually on the slave as well. +delete from mysql.user where user=_binary'rpl_do_grant'; +delete from mysql.db where user=_binary'rpl_do_grant'; flush privileges; # End of 4.1 tests diff --git a/mysql-test/t/rpl_extraCol_innodb-master.opt b/mysql-test/t/rpl_extraCol_innodb-master.opt new file mode 100644 index 00000000000..627becdbfb5 --- /dev/null +++ b/mysql-test/t/rpl_extraCol_innodb-master.opt @@ -0,0 +1 @@ +--innodb diff --git a/mysql-test/t/rpl_extraCol_innodb-slave.opt b/mysql-test/t/rpl_extraCol_innodb-slave.opt new file mode 100644 index 00000000000..627becdbfb5 --- /dev/null +++ b/mysql-test/t/rpl_extraCol_innodb-slave.opt @@ -0,0 +1 @@ +--innodb diff --git a/mysql-test/t/rpl_extraCol_innodb.test b/mysql-test/t/rpl_extraCol_innodb.test new file mode 100644 index 00000000000..e9685baf01b --- /dev/null +++ b/mysql-test/t/rpl_extraCol_innodb.test @@ -0,0 +1,13 @@ +########################################### +# Author: Jeb +# Date: 2006-09-08 +# Purpose: Wapper for rpl_extraSlave_Col.test +# Using innodb +########################################### +-- source include/have_binlog_format_row.inc +-- source include/have_innodb.inc +-- source include/master-slave.inc +let $engine_type = 'InnoDB'; +-- source extra/rpl_tests/rpl_extraSlave_Col.test + + diff --git a/mysql-test/t/rpl_extraCol_myisam.test b/mysql-test/t/rpl_extraCol_myisam.test new file mode 100644 index 00000000000..d56df394ccf --- /dev/null +++ b/mysql-test/t/rpl_extraCol_myisam.test @@ -0,0 +1,12 @@ +########################################### +# Author: Jeb +# Date: 2006-09-07 +# Purpose: Wapper for rpl_extraSlave_Col.test +# Using MyISAM +########################################### +-- source include/have_binlog_format_row.inc +-- source include/master-slave.inc +let $engine_type = 'MyISAM'; +-- source extra/rpl_tests/rpl_extraSlave_Col.test + + 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 84b0a4cde38..10c75db0b70 100644 --- a/mysql-test/t/rpl_ignore_table.test +++ b/mysql-test/t/rpl_ignore_table.test @@ -28,3 +28,27 @@ connection master; DROP TABLE t1; DROP TABLE t4; sync_slave_with_master; + +# +# bug#22877 replication character sets get out of sync +# using replicate-wild-ignore-table +# +connection master; +--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; +sync_slave_with_master; diff --git a/mysql-test/t/rpl_ndb_bank.test b/mysql-test/t/rpl_ndb_bank.test index d6a10e4ccac..9174d09484b 100644 --- a/mysql-test/t/rpl_ndb_bank.test +++ b/mysql-test/t/rpl_ndb_bank.test @@ -118,12 +118,12 @@ RESET MASTER; # there is no neat way to find the backupid, this is a hack to find it... --exec $NDB_TOOLS_DIR/ndb_select_all --ndb-connectstring="localhost:$NDBCLUSTER_PORT" -d sys --delimiter=',' SYSTAB_0 | grep 520093696 > $MYSQLTEST_VARDIR/tmp.dat -CREATE TABLE IF NOT EXISTS cluster.backup_info (id INT, backup_id INT) ENGINE = HEAP; -DELETE FROM cluster.backup_info; -LOAD DATA INFILE '../tmp.dat' INTO TABLE cluster.backup_info FIELDS TERMINATED BY ','; +CREATE TABLE IF NOT EXISTS mysql.backup_info (id INT, backup_id INT) ENGINE = HEAP; +DELETE FROM mysql.backup_info; +LOAD DATA INFILE '../tmp.dat' INTO TABLE mysql.backup_info FIELDS TERMINATED BY ','; --exec rm $MYSQLTEST_VARDIR/tmp.dat || true --replace_column 1 <the_backup_id> -SELECT @the_backup_id:=backup_id FROM cluster.backup_info; +SELECT @the_backup_id:=backup_id FROM mysql.backup_info; let the_backup_id=`select @the_backup_id`; # restore on slave, first check that nothing is there diff --git a/mysql-test/t/rpl_ndb_dd_advance.test b/mysql-test/t/rpl_ndb_dd_advance.test index 1fe36ecd8a1..4730951cb47 100644 --- a/mysql-test/t/rpl_ndb_dd_advance.test +++ b/mysql-test/t/rpl_ndb_dd_advance.test @@ -385,12 +385,12 @@ while ($j) --connection slave STOP SLAVE; RESET SLAVE; -DROP PROCEDURE tpcb.load; -DROP PROCEDURE tpcb.trans; -DROP TABLE tpcb.account; -DROP TABLE tpcb.teller; -DROP TABLE tpcb.branch; -DROP TABLE tpcb.history; +DROP PROCEDURE IF EXISTS tpcb.load; +DROP PROCEDURE IF EXISTS tpcb.trans; +DROP TABLE IF EXISTS tpcb.account; +DROP TABLE IF EXISTS tpcb.teller; +DROP TABLE IF EXISTS tpcb.branch; +DROP TABLE IF EXISTS tpcb.history; DROP DATABASE tpcb; ALTER TABLESPACE ts1 @@ -436,19 +436,19 @@ SELECT COUNT(*) FROM history; --exec $NDB_TOOLS_DIR/ndb_select_all --ndb-connectstring="localhost:$NDBCLUSTER_PORT" -d sys --delimiter=',' SYSTAB_0 | grep 520093696 > $MYSQLTEST_VARDIR/tmp.dat -CREATE TEMPORARY TABLE IF NOT EXISTS cluster.backup_info (id INT, backup_id INT) ENGINE = HEAP; +CREATE TEMPORARY TABLE IF NOT EXISTS mysql.backup_info (id INT, backup_id INT) ENGINE = HEAP; -DELETE FROM cluster.backup_info; +DELETE FROM mysql.backup_info; -LOAD DATA INFILE '../tmp.dat' INTO TABLE cluster.backup_info FIELDS TERMINATED BY ','; +LOAD DATA INFILE '../tmp.dat' INTO TABLE mysql.backup_info FIELDS TERMINATED BY ','; --exec rm $MYSQLTEST_VARDIR/tmp.dat || true --replace_column 1 <the_backup_id> -SELECT @the_backup_id:=backup_id FROM cluster.backup_info; +SELECT @the_backup_id:=backup_id FROM mysql.backup_info; let the_backup_id=`select @the_backup_id`; -DROP TABLE IF EXISTS cluster.backup_info; +DROP TABLE IF EXISTS mysql.backup_info; #RESET MASTER; --echo ************ Restore the slave ************************ @@ -534,8 +534,8 @@ SELECT COUNT(*) FROM history; --echo *************** TEST 2 CLEANUP SECTION ******************** connection master; -DROP PROCEDURE tpcb.load; -DROP PROCEDURE tpcb.trans; +DROP PROCEDURE IF EXISTS tpcb.load; +DROP PROCEDURE IF EXISTS tpcb.trans; DROP TABLE tpcb.account; DROP TABLE tpcb.teller; DROP TABLE tpcb.branch; diff --git a/mysql-test/t/rpl_ndb_ddl.test b/mysql-test/t/rpl_ndb_ddl.test index b3d32232518..0c503e56c9c 100644 --- a/mysql-test/t/rpl_ndb_ddl.test +++ b/mysql-test/t/rpl_ndb_ddl.test @@ -31,4 +31,5 @@ --source include/have_ndb.inc --source include/master-slave.inc let $engine_type= "NDB"; --- source extra/rpl_tests/rpl_ddl.test +-- source extra/rpl_tests/rpl_ndb_ddl.test + diff --git a/mysql-test/t/rpl_ndb_extraCol.test b/mysql-test/t/rpl_ndb_extraCol.test new file mode 100644 index 00000000000..cf0501c490a --- /dev/null +++ b/mysql-test/t/rpl_ndb_extraCol.test @@ -0,0 +1,13 @@ +########################################### +# Author: Jeb +# Date: 2006-09-08 +# Purpose: Wapper for rpl_extraSlave_Col.test +# Using NDB +########################################### +-- source include/have_binlog_format_row.inc +--source include/have_ndb.inc +-- source include/master-slave.inc +let $engine_type = 'NDB'; +-- source extra/rpl_tests/rpl_extraSlave_Col.test + + diff --git a/mysql-test/t/rpl_ndb_idempotent.test b/mysql-test/t/rpl_ndb_idempotent.test index eb47ec08695..477e7ff02e5 100644 --- a/mysql-test/t/rpl_ndb_idempotent.test +++ b/mysql-test/t/rpl_ndb_idempotent.test @@ -4,7 +4,7 @@ # # Currently test only works with ndb since it retrieves "old" -# binlog positions with cluster.binlog_index and apply_status; +# binlog positions with mysql.binlog_index and apply_status; # # create a table with one row @@ -15,7 +15,7 @@ SELECT * FROM t1 ORDER BY c3; # sync slave and retrieve epoch sync_slave_with_master; --replace_column 1 <the_epoch> -SELECT @the_epoch:=MAX(epoch) FROM cluster.apply_status; +SELECT @the_epoch:=MAX(epoch) FROM mysql.apply_status; let $the_epoch= `select @the_epoch` ; SELECT * FROM t1 ORDER BY c3; @@ -24,7 +24,7 @@ connection master; --replace_result $the_epoch <the_epoch> --replace_column 1 <the_pos> eval SELECT @the_pos:=Position,@the_file:=SUBSTRING_INDEX(FILE, '/', -1) - FROM cluster.binlog_index WHERE epoch = $the_epoch ; + FROM mysql.binlog_index WHERE epoch = $the_epoch ; let $the_pos= `SELECT @the_pos` ; let $the_file= `SELECT @the_file` ; diff --git a/mysql-test/t/rpl_ndb_multi.test b/mysql-test/t/rpl_ndb_multi.test index fc7ecab00ac..630668ad369 100644 --- a/mysql-test/t/rpl_ndb_multi.test +++ b/mysql-test/t/rpl_ndb_multi.test @@ -7,7 +7,7 @@ # # Currently test only works with ndb since it retrieves "old" -# binlog positions with cluster.binlog_index and apply_status; +# binlog positions with mysql.binlog_index and apply_status; # # create a table with one row, and make sure the other "master" gets it @@ -25,7 +25,7 @@ SELECT * FROM t1 ORDER BY c3; connection master; sync_slave_with_master; --replace_column 1 <the_epoch> -SELECT @the_epoch:=MAX(epoch) FROM cluster.apply_status; +SELECT @the_epoch:=MAX(epoch) FROM mysql.apply_status; let $the_epoch= `select @the_epoch` ; SELECT * FROM t1 ORDER BY c3; stop slave; @@ -34,7 +34,7 @@ stop slave; connection server2; --replace_result $the_epoch <the_epoch> eval SELECT @the_pos:=Position,@the_file:=SUBSTRING_INDEX(FILE, '/', -1) - FROM cluster.binlog_index WHERE epoch = $the_epoch ; + FROM mysql.binlog_index WHERE epoch = $the_epoch ; let $the_pos= `SELECT @the_pos` ; let $the_file= `SELECT @the_file` ; diff --git a/mysql-test/t/rpl_ndb_sync.test b/mysql-test/t/rpl_ndb_sync.test index 20d4f5707f8..10f7dd534a3 100644 --- a/mysql-test/t/rpl_ndb_sync.test +++ b/mysql-test/t/rpl_ndb_sync.test @@ -6,7 +6,7 @@ # # Currently test only works with ndb since it retrieves "old" -# binlog positions with cluster.binlog_index and apply_status; +# binlog positions with mysql.binlog_index and apply_status; # # stop the save @@ -94,11 +94,11 @@ STOP SLAVE; --connection master reset master; # should now contain nothing -select * from cluster.binlog_index; +select * from mysql.binlog_index; --connection slave reset slave; # should now contain nothing -select * from cluster.apply_status; +select * from mysql.apply_status; # End 5.1 Test 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_trigger.test b/mysql-test/t/rpl_trigger.test index 6ec0021635a..9f5f6fc9b4c 100644 --- a/mysql-test/t/rpl_trigger.test +++ b/mysql-test/t/rpl_trigger.test @@ -431,6 +431,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 bc0dfd6de76..79049353950 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -2701,7 +2701,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; @@ -2941,7 +2941,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 7d4ad099e6f..be803a74c7b 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 # check that CSV engine was compiled in, as the result of the test 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/sp.test b/mysql-test/t/sp.test index bb18c0e5858..8f4763c636a 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -11,6 +11,7 @@ # Tests that uses 'goto' to into sp-goto.test (currently disabled) # Tests that destroys system tables (e.g. mysql.proc) for error testing # go to sp-destruct. +# Tests that require --with-geometry go into sp_gis.test use test; @@ -2584,6 +2585,9 @@ begin end if; end| +# so that from_unixtime() has a deterministic result +set time_zone='+03:00'; + call bug3426(1000, @i)| select @i, from_unixtime(@stamped_time, '%d-%m-%Y %h:%i:%s') as time| call bug3426(NULL, @i)| @@ -6585,6 +6589,122 @@ drop procedure proc_21462_b| --echo End of 5.0 tests +--echo Begin of 5.1 tests + +# +# BUG#18239: Possible to overload internal functions with stored functions +# + +delimiter ;| + +--disable_warnings +drop function if exists pi; +--enable_warnings + +create function pi() returns varchar(50) +return "pie, my favorite desert."; + +SET @save_sql_mode=@@sql_mode; + +SET SQL_MODE='IGNORE_SPACE'; + +select pi(), pi (); + +# Non deterministic warnings from db_load_routine +--disable_warnings +select test.pi(), test.pi (); +--enable_warnings + +SET SQL_MODE=''; + +select pi(), pi (); + +# Non deterministic warnings from db_load_routine +--disable_warnings +select test.pi(), test.pi (); +--enable_warnings + +SET @@sql_mode=@save_sql_mode; + +drop function pi; +# End of BUG#18239 + +# +# BUG#22619: Spaces considered harmful +# + +--disable_warnings +drop function if exists test.database; +drop function if exists test.current_user; +drop function if exists test.md5; +--enable_warnings + +create database nowhere; +use nowhere; +drop database nowhere; + +SET @save_sql_mode=@@sql_mode; + +SET SQL_MODE='IGNORE_SPACE'; + +select database(), database (); +select current_user(), current_user (); +select md5("aaa"), md5 ("aaa"); + +SET SQL_MODE=''; + +select database(), database (); +select current_user(), current_user (); +select md5("aaa"), md5 ("aaa"); + +use test; + +create function `database`() returns varchar(50) +return "Stored function database"; + +create function `current_user`() returns varchar(50) +return "Stored function current_user"; + +create function md5(x varchar(50)) returns varchar(50) +return "Stored function md5"; + +SET SQL_MODE='IGNORE_SPACE'; + +select database(), database (); +select current_user(), current_user (); +select md5("aaa"), md5 ("aaa"); + +# Non deterministic warnings from db_load_routine +--disable_warnings +select test.database(), test.database (); +select test.current_user(), test.current_user (); +select test.md5("aaa"), test.md5 ("aaa"); +--enable_warnings + +SET SQL_MODE=''; + +select database(), database (); +select current_user(), current_user (); +select md5("aaa"), md5 ("aaa"); + +# Non deterministic warnings from db_load_routine +--disable_warnings +select test.database(), test.database (); +select test.current_user(), test.current_user (); +select test.md5("aaa"), test.md5 ("aaa"); +--enable_warnings + +SET @@sql_mode=@save_sql_mode; + +drop function test.database; +drop function test.current_user; +drop function md5; + +use test; +delimiter |; +# End of BUG#22619 + +--echo End of 5.1 tests # # BUG#NNNN: New bug synopsis diff --git a/mysql-test/t/sp_gis.test b/mysql-test/t/sp_gis.test new file mode 100644 index 00000000000..51ed78b27d5 --- /dev/null +++ b/mysql-test/t/sp_gis.test @@ -0,0 +1,39 @@ +-- source include/have_geometry.inc + +use test; + +# +# BUG#21025: misleading error message when creating functions named 'x', or 'y' +# + +--disable_warnings +drop function if exists a; +drop function if exists x; +drop function if exists y; +--enable_warnings + +create function a() returns int +return 1; + +create function x() returns int +return 2; + +create function y() returns int +return 3; + +select a(); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select x(); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select y(); +select x(PointFromText("POINT(10 20)")), y(PointFromText("POINT(10 20)")); + +# Non deterministic warnings from db_load_routine +--disable_warnings +select test.a(), test.x(), test.y(); +--enable_warnings + +drop function a; +drop function x; +drop function y; + diff --git a/mysql-test/t/status.test b/mysql-test/t/status.test index 2afcd49962c..099c2e062bb 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 ae5e4365af3..2f35bbf22f2 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/synchronization.test b/mysql-test/t/synchronization.test index c7696195ee0..71e13a65ec3 100644 --- a/mysql-test/t/synchronization.test +++ b/mysql-test/t/synchronization.test @@ -4,7 +4,7 @@ # --disable_warnings -drop table if exists t1; +drop table if exists t1,t2; --enable_warnings connect (con1,localhost,root,,); diff --git a/mysql-test/t/system_mysql_db_fix.test b/mysql-test/t/system_mysql_db_fix.test index 3956e26e9cc..53bb366c642 100644 --- a/mysql-test/t/system_mysql_db_fix.test +++ b/mysql-test/t/system_mysql_db_fix.test @@ -96,7 +96,7 @@ INSERT INTO user VALUES ('localhost','', '','N','N','N','N','N','N','N','N',' DROP TABLE db, host, user, func, plugin, tables_priv, columns_priv, procs_priv, help_category, help_keyword, help_relation, help_topic, proc, time_zone, time_zone_leap_second, time_zone_name, time_zone_transition, -time_zone_transition_type, general_log, slow_log, event; +time_zone_transition_type, general_log, slow_log, event, binlog_index; -- enable_query_log diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test index 8242c614d0a..12262894e5b 100644 --- a/mysql-test/t/trigger.test +++ b/mysql-test/t/trigger.test @@ -1499,4 +1499,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_datetime.test b/mysql-test/t/type_datetime.test index 09576d415e5..3aa162b4700 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 1b80a15e4ff..f16e5dec40c 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'; # @@ -1120,6 +1120,12 @@ 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#16172 DECIMAL data type processed incorrectly # @@ -1130,3 +1136,8 @@ select cast(-3.4 as decimal(2,1)); select cast(99.6 as decimal(2,0)); select cast(-13.4 as decimal(2,1)); select cast(98.6 as decimal(2,0)); + +# Bug #8663 (cant use bigint as input to CAST) +# +select cast(19999999999999999999 as unsigned); + diff --git a/mysql-test/t/udf.test b/mysql-test/t/udf.test index 96e559f5c05..01aac24ded4 100644 --- a/mysql-test/t/udf.test +++ b/mysql-test/t/udf.test @@ -127,9 +127,89 @@ 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. # +# BUG#18239: Possible to overload internal functions with stored functions +# + +--disable_warnings +drop function if exists pi; +--enable_warnings + +--error ER_NATIVE_FCT_NAME_COLLISION +CREATE FUNCTION pi RETURNS STRING SONAME "should_not_parse.so"; + +# Verify that Stored Functions and UDF are mutually exclusive +DROP FUNCTION IF EXISTS metaphon; + +CREATE FUNCTION metaphon(a int) RETURNS int +return 0; + +--replace_result $UDF_EXAMPLE_LIB UDF_EXAMPLE_LIB +--error ER_UDF_EXISTS +eval CREATE FUNCTION metaphon RETURNS STRING SONAME "$UDF_EXAMPLE_LIB"; + +DROP FUNCTION metaphon; + +--replace_result $UDF_EXAMPLE_LIB UDF_EXAMPLE_LIB +eval CREATE FUNCTION metaphon RETURNS STRING SONAME "$UDF_EXAMPLE_LIB"; + +--error ER_UDF_EXISTS +CREATE FUNCTION metaphon(a int) RETURNS int +return 0; + +--error ER_UDF_EXISTS +CREATE FUNCTION test.metaphon(a int) RETURNS int +return 0; + +# End of Bug#18239 + +# # Drop the example functions from udf_example # diff --git a/mysql-test/t/upgrade.test b/mysql-test/t/upgrade.test index 5c5046cf7e9..f517c7787f8 100644 --- a/mysql-test/t/upgrade.test +++ b/mysql-test/t/upgrade.test @@ -47,3 +47,12 @@ select * from `txu@0023p@0023p1`; select * from `txu#p#p1`; drop table `txu@0023p@0023p1`; drop table `txu#p#p1`; + +# +# Check if old tables work +# + +system cp $MYSQL_TEST_DIR/std_data/old_table-323.frm $MYSQLTEST_VARDIR/master-data/test/t1.frm; +truncate t1; +drop table t1; + 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/view.test b/mysql-test/t/view.test index fa3ddd28489..7175db1db4e 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -2959,3 +2959,22 @@ DROP TABLE t1; --echo End of 5.0 tests. + +# +# Bug#21370 View renaming lacks tablename_to_filename encoding +# +--disable_warnings +DROP DATABASE IF EXISTS `d-1`; +--enable_warnings +CREATE DATABASE `d-1`; +USE `d-1`; +CREATE TABLE `t-1` (c1 INT); +CREATE VIEW `v-1` AS SELECT c1 FROM `t-1`; +SHOW TABLES; +RENAME TABLE `t-1` TO `t-2`; +RENAME TABLE `v-1` TO `v-2`; +SHOW TABLES; +DROP TABLE `t-2`; +DROP VIEW `v-2`; +DROP DATABASE `d-1`; +USE test; diff --git a/mysql-test/t/view_grant.test b/mysql-test/t/view_grant.test index daba7dfaa3c..39444a97984 100644 --- a/mysql-test/t/view_grant.test +++ b/mysql-test/t/view_grant.test @@ -806,7 +806,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; 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/warnings-master.opt b/mysql-test/t/warnings-master.opt index e924a22e2ce..e69de29bb2d 100644 --- a/mysql-test/t/warnings-master.opt +++ b/mysql-test/t/warnings-master.opt @@ -1 +0,0 @@ ---skip-isam --skip-merge diff --git a/mysql-test/t/warnings.test b/mysql-test/t/warnings.test index a8b8e5f5103..eb5a24a8604 100644 --- a/mysql-test/t/warnings.test +++ b/mysql-test/t/warnings.test @@ -113,11 +113,8 @@ show variables like 'max_error_count'; # Test for handler type # drop table t1; -#create table t1 (id int) engine=isam; -#alter table t1 engine=isam; -#drop table t1; -create table t1 (id int) engine=merge; -alter table t1 engine=merge; +create table t1 (id int) engine=NDB; +alter table t1 engine=NDB; drop table t1; # diff --git a/mysql-test/t/windows.test b/mysql-test/t/windows.test index d6bcfeb8cb3..4dab646df2c 100644 --- a/mysql-test/t/windows.test +++ b/mysql-test/t/windows.test @@ -18,3 +18,25 @@ create table nu (a int); drop table nu; # End of 4.1 tests + +# +# Bug #20665: All commands supported in Stored Procedures should work in +# Prepared Statements +# + +create procedure proc_1() install plugin my_plug soname '\\root\\some_plugin.dll'; +--error ER_UDF_NO_PATHS +call proc_1(); +--error ER_UDF_NO_PATHS +call proc_1(); +--error ER_UDF_NO_PATHS +call proc_1(); +drop procedure proc_1; + +prepare abc from "install plugin my_plug soname '\\\\root\\\\some_plugin.dll'"; +--error ER_UDF_NO_PATHS +execute abc; +--error ER_UDF_NO_PATHS +execute abc; +deallocate prepare abc; + diff --git a/mysql-test/t/xml.test b/mysql-test/t/xml.test index 3347573b4b7..ef94c7508c4 100644 --- a/mysql-test/t/xml.test +++ b/mysql-test/t/xml.test @@ -376,3 +376,33 @@ select extractValue('<:>test</:>','//*'); select extractValue('<_>test</_>','//*'); # dot, dash, underscore and semicolon are good identifier middle characters select extractValue('<x.-_:>test</x.-_:>','//*'); + +# +# Bug#22823 gt and lt operators appear to be +# reversed in ExtractValue() command +# +set @xml= "<entry><id>pt10</id><pt>10</pt></entry><entry><id>pt50</id><pt>50</pt></entry>"; +select ExtractValue(@xml, "/entry[(pt=10)]/id"); +select ExtractValue(@xml, "/entry[(pt!=10)]/id"); +select ExtractValue(@xml, "/entry[(pt<10)]/id"); +select ExtractValue(@xml, "/entry[(pt<=10)]/id"); +select ExtractValue(@xml, "/entry[(pt>10)]/id"); +select ExtractValue(@xml, "/entry[(pt>=10)]/id"); +select ExtractValue(@xml, "/entry[(pt=50)]/id"); +select ExtractValue(@xml, "/entry[(pt!=50)]/id"); +select ExtractValue(@xml, "/entry[(pt<50)]/id"); +select ExtractValue(@xml, "/entry[(pt<=50)]/id"); +select ExtractValue(@xml, "/entry[(pt>50)]/id"); +select ExtractValue(@xml, "/entry[(pt>=50)]/id"); +select ExtractValue(@xml, "/entry[(10=pt)]/id"); +select ExtractValue(@xml, "/entry[(10!=pt)]/id"); +select ExtractValue(@xml, "/entry[(10>pt)]/id"); +select ExtractValue(@xml, "/entry[(10>=pt)]/id"); +select ExtractValue(@xml, "/entry[(10<pt)]/id"); +select ExtractValue(@xml, "/entry[(10<=pt)]/id"); +select ExtractValue(@xml, "/entry[(50=pt)]/id"); +select ExtractValue(@xml, "/entry[(50!=pt)]/id"); +select ExtractValue(@xml, "/entry[(50>pt)]/id"); +select ExtractValue(@xml, "/entry[(50>=pt)]/id"); +select ExtractValue(@xml, "/entry[(50<pt)]/id"); +select ExtractValue(@xml, "/entry[(50<=pt)]/id"); diff --git a/mysys/Makefile.am b/mysys/Makefile.am index 79d79d41c34..e115739b421 100644 --- a/mysys/Makefile.am +++ b/mysys/Makefile.am @@ -20,7 +20,7 @@ MYSQLBASEdir= $(prefix) INCLUDES = @ZLIB_INCLUDES@ -I$(top_builddir)/include \ -I$(top_srcdir)/include -I$(srcdir) pkglib_LIBRARIES = libmysys.a -LDADD = libmysys.a $(top_builddir)/strings/libmystrings.a +LDADD = libmysys.a $(top_builddir)/strings/libmystrings.a $(top_builddir)/dbug/libdbug.a 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 \ diff --git a/mysys/default.c b/mysys/default.c index 863ebc37dbc..b3c6b8ed72a 100644 --- a/mysys/default.c +++ b/mysys/default.c @@ -488,7 +488,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, @@ -676,7 +676,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; @@ -869,7 +869,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; diff --git a/mysys/hash.c b/mysys/hash.c index 165745986dc..1e7f96ac8d5 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%lx", hash)); + DBUG_PRINT("enter",("hash: 0x%lx", (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 e6f4348968f..5327116f131 100644 --- a/mysys/mf_keycache.c +++ b/mysys/mf_keycache.c @@ -404,9 +404,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, @@ -621,7 +621,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; @@ -640,7 +640,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, @@ -1073,7 +1073,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); @@ -1092,7 +1092,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)); } } @@ -1345,11 +1345,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);); @@ -1641,8 +1641,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) @@ -2341,7 +2341,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) @@ -2546,7 +2546,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 9f3676618eb..883f350798f 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_compress.c b/mysys/my_compress.c index 2643d4d16ac..713489e7c2f 100644 --- a/mysys/my_compress.c +++ b/mysys/my_compress.c @@ -138,14 +138,14 @@ int packfrm(const void *data, uint len, uint blob_len; struct 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; @@ -165,7 +165,8 @@ 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); @@ -194,13 +195,13 @@ 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); @@ -220,7 +221,7 @@ 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); } #endif /* HAVE_COMPRESS */ diff --git a/mysys/my_dup.c b/mysys/my_dup.c index 1fdb4db7276..8f891beb390 100644 --- a/mysys/my_dup.c +++ b/mysys/my_dup.c @@ -29,7 +29,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_error.c b/mysys/my_error.c index e60c4eb21d7..cc7c28b6207 100644 --- a/mysys/my_error.c +++ b/mysys/my_error.c @@ -252,3 +252,15 @@ const char **my_error_unregister(int first, int last) return errmsgs; } + + +void my_error_unregister_all(void) +{ + struct my_err_head *list, *next; + for (list= my_errmsgs_globerrs.meh_next; list; list= next) + { + next= list->meh_next; + my_free((gptr) list, MYF(0)); + } + my_errmsgs_list= &my_errmsgs_globerrs; +} 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 4de2984d9b9..13524ce4e13 100644 --- a/mysys/my_getopt.c +++ b/mysys/my_getopt.c @@ -936,8 +936,8 @@ void my_print_variables(const struct my_option *options) (*getopt_get_addr)("", 0, optp) : optp->value); if (value) { - printf("%s", optp->name); - length= (uint) strlen(optp->name); + printf("%s ", optp->name); + length= (uint) strlen(optp->name)+1; for (; length < name_space; length++) putchar(' '); switch ((optp->var_type & GET_TYPE_MASK)) { diff --git a/mysys/my_getwd.c b/mysys/my_getwd.c index de8ad108ba4..be880680dfa 100644 --- a/mysys/my_getwd.c +++ b/mysys/my_getwd.c @@ -37,7 +37,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 (curr_dir[0]) /* Current pos is saved here */ VOID(strmake(buf,&curr_dir[0],size-1)); diff --git a/mysys/my_init.c b/mysys/my_init.c index dca68637161..149ccac531e 100644 --- a/mysys/my_init.c +++ b/mysys/my_init.c @@ -154,6 +154,7 @@ void my_end(int infoflag) } } free_charsets(); + my_error_unregister_all(); my_once_free(); if ((infoflag & MY_GIVE_INFO) || print_info) @@ -208,7 +209,8 @@ Voluntary context switches %ld, Involuntary context switches %ld\n", Check on destroying of mutexes. A few may be left that will get cleaned up by C++ destructors */ - safe_mutex_end(infoflag & MY_GIVE_INFO ? stderr : (FILE *) 0); + safe_mutex_end((infoflag & (MY_GIVE_INFO | MY_CHECK_ERROR)) ? stderr : + (FILE *) 0); #endif /* defined(SAFE_MUTEX) */ #endif /* THREAD */ diff --git a/mysys/my_lib.c b/mysys/my_lib.c index 76c31a8fbae..5d04359c7c0 100644 --- a/mysys/my_lib.c +++ b/mysys/my_lib.c @@ -529,7 +529,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_malloc.c b/mysys/my_malloc.c index 9dd5530bd28..dac9a5357fd 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_pread.c b/mysys/my_pread.c index 45a4a363c0a..9824d9bbab4 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= 0; 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 (;;) { @@ -72,8 +72,8 @@ uint my_pread(File Filedes, byte *Buffer, uint Count, my_off_t offset, #endif if (error || readbytes != Count) { - 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) { @@ -110,7 +110,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 269d1a65b31..e6f66041ccc 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_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/mysys_priv.h b/mysys/mysys_priv.h index 89a6d8aa2a7..1d9c2812eb6 100644 --- a/mysys/mysys_priv.h +++ b/mysys/mysys_priv.h @@ -41,3 +41,5 @@ extern pthread_mutex_t THR_LOCK_charset; #ifndef EDQUOT #define EDQUOT (-1) #endif + +void my_error_unregister_all(void); diff --git a/mysys/safemalloc.c b/mysys/safemalloc.c index 518a6a5fdd0..1983139c762 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_alarm.c b/mysys/thr_alarm.c index c55cc32b47d..dbadc45ae9f 100644 --- a/mysys/thr_alarm.c +++ b/mysys/thr_alarm.c @@ -276,7 +276,7 @@ sig_handler process_alarm(int sig __attribute__((unused))) if (!pthread_equal(pthread_self(),alarm_thread)) { #if defined(MAIN) && !defined(__bsdi__) - printf("thread_alarm\n"); fflush(stdout); + printf("thread_alarm in process_alarm\n"); fflush(stdout); #endif #ifdef DONT_REMEMBER_SIGNAL my_sigset(THR_CLIENT_ALARM,process_alarm); /* int. thread system calls */ @@ -848,8 +848,9 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) MY_INIT(argv[0]); if (argc > 1 && argv[1][0] == '-' && argv[1][1] == '#') + { DBUG_PUSH(argv[1]+2); - + } pthread_mutex_init(&LOCK_thread_count,MY_MUTEX_INIT_FAST); pthread_cond_init(&COND_thread_count,NULL); @@ -917,8 +918,8 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) } } pthread_mutex_unlock(&LOCK_thread_count); - end_thr_alarm(1); thr_alarm_info(&alarm_info); + end_thr_alarm(1); printf("Main_thread: Alarms: %u max_alarms: %u next_alarm_time: %lu\n", alarm_info.active_alarms, alarm_info.max_used_alarms, alarm_info.next_alarm_time); diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c index a2c42ee326c..f1b2cceb67a 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: 0x%lx 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: 0x%lx, type: %ld", + DBUG_PRINT("lock",("write locked by thread: 0x%lx, 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: 0x%lx 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..abbc99b2445 100644 --- a/mysys/tree.c +++ b/mysys/tree.c @@ -89,7 +89,7 @@ void init_tree(TREE *tree, uint default_alloc_size, uint memory_limit, 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; @@ -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 90a093b0b32..d329b687668 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/netware/BUILD/nwbootstrap b/netware/BUILD/nwbootstrap index 563d316ea56..2f291cde9f2 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,20 +151,19 @@ 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 - -PWD=`pwd` -# This line will catch the default value only, let's hope it is correct -SRC_DIR=`grep "^ *export MYDEV=" $mwenv | cut -d'=' -f2 | \ - sed -e 's;";;g' -e "s;^;echo ;g" -e "s;$;/\`basename $PWD\`;g" | /bin/sh` - +#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 +#obsolete +#obsolete PWD=`pwd` +#obsolete # This line will catch the default value only, let's hope it is correct +#obsolete SRC_DIR=`grep "^ *export MYDEV=" $mwenv | cut -d'=' -f2 | \ +#obsolete sed -e 's;";;g' -e "s;^;echo ;g" -e "s;$;/\`basename $PWD\`;g" | /bin/sh` # edit the def file versions echo "updating *.def file versions..." diff --git a/plugin/daemon_example/AUTHORS b/plugin/daemon_example/AUTHORS new file mode 100644 index 00000000000..fe992df1360 --- /dev/null +++ b/plugin/daemon_example/AUTHORS @@ -0,0 +1 @@ +Brian Aker <brian@mysql.com> diff --git a/plugin/daemon_example/ChangeLog b/plugin/daemon_example/ChangeLog new file mode 100644 index 00000000000..c4b09806f83 --- /dev/null +++ b/plugin/daemon_example/ChangeLog @@ -0,0 +1,2 @@ +0.1 + - Added diff --git a/plugin/daemon_example/Makefile.am b/plugin/daemon_example/Makefile.am new file mode 100644 index 00000000000..ccbada1be90 --- /dev/null +++ b/plugin/daemon_example/Makefile.am @@ -0,0 +1,21 @@ +#Makefile.am example for a daemon +MYSQLDATAdir = $(localstatedir) +MYSQLSHAREdir = $(pkgdatadir) +MYSQLBASEdir= $(prefix) +MYSQLLIBdir= $(pkglibdir) +INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include \ + -I$(srcdir) + +EXTRA_LTLIBRARIES = libdaemon_example.la +pkglib_LTLIBRARIES = @plugin_daemon_example_shared_target@ +libdaemon_example_la_LDFLAGS = -module -rpath $(MYSQLLIBdir) +libdaemon_example_la_CXXFLAGS= $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN +libdaemon_example_la_CFLAGS = $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN +libdaemon_example_la_SOURCES = daemon_example.c + + +EXTRA_LIBRARIES = libdaemon_example.a +noinst_LIBRARIES = @plugin_daemon_example_static_target@ +libdaemon_example_a_CXXFLAGS = $(AM_CFLAGS) +libdaemon_example_a_CFLAGS = $(AM_CFLAGS) +libdaemon_example_a_SOURCES= daemon_example.c diff --git a/plugin/daemon_example/NEWS b/plugin/daemon_example/NEWS new file mode 100644 index 00000000000..ddae9fc3297 --- /dev/null +++ b/plugin/daemon_example/NEWS @@ -0,0 +1,2 @@ +0.1 - Tue Nov 7 12:08:03 PST 2006 + * Added Example to test interface diff --git a/plugin/daemon_example/README b/plugin/daemon_example/README new file mode 100644 index 00000000000..d3c67be6f52 --- /dev/null +++ b/plugin/daemon_example/README @@ -0,0 +1,8 @@ +Hi! + +This is an example of a daemon plugin. These are generic plugins that +only hook ino the startup and shutdown of the database. + +Cheers, + -Brian + Seattle, WA diff --git a/plugin/daemon_example/configure.in b/plugin/daemon_example/configure.in new file mode 100644 index 00000000000..8924b7f5bc4 --- /dev/null +++ b/plugin/daemon_example/configure.in @@ -0,0 +1,9 @@ +# configure.in example for a daemon + +AC_INIT(daemon_example, 0.1) +AM_INIT_AUTOMAKE +AC_DISABLE_STATIC +AC_PROG_LIBTOOL +AC_CONFIG_FILES([Makefile]) +AC_OUTPUT + diff --git a/plugin/daemon_example/daemon_example.c b/plugin/daemon_example/daemon_example.c new file mode 100644 index 00000000000..d302aec6515 --- /dev/null +++ b/plugin/daemon_example/daemon_example.c @@ -0,0 +1,89 @@ +/* + 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 <stdlib.h> +#include <ctype.h> +#include <mysql_version.h> +#include <mysql/plugin.h> + +/* +#if !defined(__attribute__) && (defined(__cplusplus) || !defined(__GNUC__) || __GNUC__ == 2 && __GNUC_MINOR__ < 8) +#define __attribute__(A) +#endif +*/ + + + +/* + Initialize the daemon example at server start or plugin installation. + + SYNOPSIS + daemon_example_plugin_init() + + DESCRIPTION + Does nothing. + + RETURN VALUE + 0 success + 1 failure (cannot happen) +*/ + +static int daemon_example_plugin_init(void *p) +{ + return(0); +} + + +/* + Terminate the daemon example at server shutdown or plugin deinstallation. + + SYNOPSIS + daemon_example_plugin_deinit() + Does nothing. + + RETURN VALUE + 0 success + 1 failure (cannot happen) + +*/ + +static int daemon_example_plugin_deinit(void *p) +{ + return(0); +} + +struct st_mysql_daemon daemon_example_plugin= +{ MYSQL_DAEMON_INTERFACE_VERSION }; + +/* + Plugin library descriptor +*/ + +mysql_declare_plugin(daemon_example) +{ + MYSQL_DAEMON_PLUGIN, + &daemon_example_plugin, + "daemon_example", + "Brian Aker", + "Daemon example that tests init and deinit of a plugin", + PLUGIN_LICENSE_GPL, + daemon_example_plugin_init, /* Plugin Init */ + daemon_example_plugin_deinit, /* Plugin Deinit */ + 0x0100 /* 1.0 */, + NULL, /* status variables */ + NULL, /* system variables */ + NULL /* config options */ +} +mysql_declare_plugin_end; diff --git a/plugin/daemon_example/plug.in b/plugin/daemon_example/plug.in new file mode 100644 index 00000000000..72e87a70f59 --- /dev/null +++ b/plugin/daemon_example/plug.in @@ -0,0 +1,3 @@ +MYSQL_PLUGIN(daemon_example,[Daemon Example Plugin], + [This is an example plugin daemon.]) +MYSQL_PLUGIN_DYNAMIC(daemon_example, [libdaemon_example.la]) diff --git a/plugin/fulltext/Makefile.am b/plugin/fulltext/Makefile.am index 7b4ae22cbd2..6ce503f3331 100644 --- a/plugin/fulltext/Makefile.am +++ b/plugin/fulltext/Makefile.am @@ -2,8 +2,8 @@ pkglibdir=$(libdir)/mysql INCLUDES= -I$(top_builddir)/include -I$(top_srcdir)/include -noinst_LTLIBRARIES= mypluglib.la -#pkglib_LTLIBRARIES= mypluglib.la +#noinst_LTLIBRARIES= mypluglib.la +pkglib_LTLIBRARIES= mypluglib.la mypluglib_la_SOURCES= plugin_example.c mypluglib_la_LDFLAGS= -module -rpath $(pkglibdir) mypluglib_la_CFLAGS= -DMYSQL_DYNAMIC_PLUGIN diff --git a/plugin/fulltext/plug.in b/plugin/fulltext/plug.in new file mode 100644 index 00000000000..5bfc401f805 --- /dev/null +++ b/plugin/fulltext/plug.in @@ -0,0 +1,3 @@ +MYSQL_PLUGIN(ftexample, [Simple Parser], + [Simple full-text parser plugin]) +MYSQL_PLUGIN_DYNAMIC(ftexample, [mypluglib.la]) diff --git a/plugin/fulltext/plugin_example.c b/plugin/fulltext/plugin_example.c index f09462f2d1a..4194f1df689 100644 --- a/plugin/fulltext/plugin_example.c +++ b/plugin/fulltext/plugin_example.c @@ -62,7 +62,7 @@ static long number_of_calls= 0; /* for SHOW STATUS, see below */ 1 failure (cannot happen) */ -static int simple_parser_plugin_init(void) +static int simple_parser_plugin_init(void *arg __attribute__((unused))) { return(0); } @@ -81,7 +81,7 @@ static int simple_parser_plugin_init(void) */ -static int simple_parser_plugin_deinit(void) +static int simple_parser_plugin_deinit(void *arg __attribute__((unused))) { return(0); } 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 68798e92725..ddcea343609 100644 --- a/scripts/make_binary_distribution.sh +++ b/scripts/make_binary_distribution.sh @@ -243,6 +243,7 @@ $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 \ diff --git a/scripts/mysql_create_system_tables.sh b/scripts/mysql_create_system_tables.sh index 69ea8e3d004..a8e4fed5d27 100644 --- a/scripts/mysql_create_system_tables.sh +++ b/scripts/mysql_create_system_tables.sh @@ -874,8 +874,7 @@ $c_pp $c_gl $c_sl $c_ev -CREATE DATABASE IF NOT EXISTS cluster; -CREATE TABLE IF NOT EXISTS cluster.binlog_index (Position BIGINT UNSIGNED NOT NULL, File VARCHAR(255) NOT NULL, epoch BIGINT UNSIGNED NOT NULL, inserts BIGINT UNSIGNED NOT NULL, updates BIGINT UNSIGNED NOT NULL, deletes BIGINT UNSIGNED NOT NULL, schemaops BIGINT UNSIGNED NOT NULL, PRIMARY KEY(epoch)) ENGINE=MYISAM; +CREATE TABLE IF NOT EXISTS mysql.binlog_index (Position BIGINT UNSIGNED NOT NULL, File VARCHAR(255) NOT NULL, epoch BIGINT UNSIGNED NOT NULL, inserts BIGINT UNSIGNED NOT NULL, updates BIGINT UNSIGNED NOT NULL, deletes BIGINT UNSIGNED NOT NULL, schemaops BIGINT UNSIGNED NOT NULL, PRIMARY KEY(epoch)) ENGINE=MYISAM; END_OF_DATA diff --git a/scripts/mysql_fix_privilege_tables.sql b/scripts/mysql_fix_privilege_tables.sql index f3c0c7f13be..15ebef7d9c0 100644 --- a/scripts/mysql_fix_privilege_tables.sql +++ b/scripts/mysql_fix_privilege_tables.sql @@ -1,13 +1,13 @@ --- This script converts any old privilege tables to privilege tables suitable --- for this version of MySQL +# This script converts any old privilege tables to privilege tables suitable +# for this version of MySQL --- You can safely ignore all 'Duplicate column' and 'Unknown column' errors" --- because these just mean that your tables are already up to date. --- This script is safe to run even if your tables are already up to date! +# You can safely ignore all 'Duplicate column' and 'Unknown column' errors" +# because these just mean that your tables are already up to date. +# This script is safe to run even if your tables are already up to date! --- On unix, you should use the mysql_fix_privilege_tables script to execute --- this sql script. --- On windows you should do 'mysql --force mysql < mysql_fix_privilege_tables.sql' +# On unix, you should use the mysql_fix_privilege_tables script to execute +# this sql script. +# On windows you should do 'mysql --force mysql < mysql_fix_privilege_tables.sql' set storage_engine=MyISAM; @@ -27,7 +27,7 @@ CREATE TABLE IF NOT EXISTS plugin ( ALTER TABLE user add File_priv enum('N','Y') COLLATE utf8_general_ci NOT NULL; --- Detect whether or not we had the Grant_priv column +# Detect whether or not we had the Grant_priv column SET @hadGrantPriv:=0; SELECT @hadGrantPriv:=1 FROM user WHERE Grant_priv LIKE '%'; @@ -35,14 +35,14 @@ ALTER TABLE user add Grant_priv enum('N','Y') COLLATE utf8_general_ci NOT NULL,a ALTER TABLE host add Grant_priv enum('N','Y') NOT NULL,add References_priv enum('N','Y') COLLATE utf8_general_ci NOT NULL,add Index_priv enum('N','Y') COLLATE utf8_general_ci NOT NULL,add Alter_priv enum('N','Y') COLLATE utf8_general_ci NOT NULL; ALTER TABLE db add Grant_priv enum('N','Y') COLLATE utf8_general_ci NOT NULL,add References_priv enum('N','Y') COLLATE utf8_general_ci NOT NULL,add Index_priv enum('N','Y') COLLATE utf8_general_ci NOT NULL,add Alter_priv enum('N','Y') COLLATE utf8_general_ci NOT NULL; --- Fix privileges for old tables +# Fix privileges for old tables UPDATE user SET Grant_priv=File_priv,References_priv=Create_priv,Index_priv=Create_priv,Alter_priv=Create_priv WHERE @hadGrantPriv = 0; UPDATE db SET References_priv=Create_priv,Index_priv=Create_priv,Alter_priv=Create_priv WHERE @hadGrantPriv = 0; UPDATE host SET References_priv=Create_priv,Index_priv=Create_priv,Alter_priv=Create_priv WHERE @hadGrantPriv = 0; --- --- The second alter changes ssl_type to new 4.0.2 format --- Adding columns needed by GRANT .. REQUIRE (openssl)" +# +# The second alter changes ssl_type to new 4.0.2 format +# Adding columns needed by GRANT .. REQUIRE (openssl)" ALTER TABLE user ADD ssl_type enum('','ANY','X509', 'SPECIFIED') COLLATE utf8_general_ci NOT NULL, @@ -51,9 +51,9 @@ ADD x509_issuer BLOB NOT NULL, 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 --- +# +# Create tables_priv and columns_priv if they don't exists +# CREATE TABLE IF NOT EXISTS tables_priv ( Host char(60) binary DEFAULT '' NOT NULL, @@ -66,7 +66,7 @@ CREATE TABLE IF NOT EXISTS tables_priv ( 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 +# 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; @@ -88,26 +88,26 @@ 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 +# 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 --- +# +# 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; --- --- Add the new 'type' column to the func table. --- +# +# Add the new 'type' column to the func table. +# 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 MySQL 4.0 format +# # Detect whether we had Show_db_priv SET @hadShowDbPriv:=0; @@ -122,22 +122,22 @@ ADD Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTE ADD Repl_slave_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Execute_priv, ADD Repl_client_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Repl_slave_priv; --- Convert privileges so that users have similar privileges as before +# Convert privileges so that users have similar privileges as before UPDATE user SET Show_db_priv= Select_priv, Super_priv=Process_priv, Execute_priv=Process_priv, Create_tmp_table_priv='Y', Lock_tables_priv='Y', Repl_slave_priv=file_priv, Repl_client_priv=File_priv where user<>"" AND @hadShowDbPriv = 0; --- Add fields that can be used to limit number of questions and connections --- for some users. +# Add fields that can be used to limit number of questions and connections +# for some users. ALTER TABLE user ADD max_questions int(11) NOT NULL DEFAULT 0 AFTER x509_subject, ADD max_updates int(11) unsigned NOT NULL DEFAULT 0 AFTER max_questions, ADD max_connections int(11) unsigned NOT NULL DEFAULT 0 AFTER max_updates; --- --- Add Create_tmp_table_priv and Lock_tables_priv to db and host --- +# +# Add Create_tmp_table_priv and Lock_tables_priv to db and host +# ALTER TABLE db ADD Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, @@ -156,8 +156,8 @@ 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 +# Convert all tables to UTF-8 with binary collation +# and reset all char columns to correct width ALTER TABLE user MODIFY Host char(60) NOT NULL default '', MODIFY User char(16) NOT NULL default '', @@ -385,7 +385,7 @@ Time_zone_id int unsigned NOT NULL auto_increment, Use_leap_seconds enum('Y','N') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY TzId (Time_zone_id) ) CHARACTER SET utf8 comment='Time zones'; --- Make enum field case-insensitive +# Make enum field case-insensitive ALTER TABLE time_zone MODIFY Use_leap_seconds enum('Y','N') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL; @@ -527,9 +527,9 @@ ALTER TABLE proc MODIFY db MODIFY comment char(64) collate utf8_bin DEFAULT '' NOT NULL; --- --- Create missing log tables (5.1) --- +# +# Create missing log tables (5.1) +# delimiter // CREATE PROCEDURE create_log_tables() @@ -673,9 +673,9 @@ ALTER TABLE event ADD sql_mode UPDATE user SET Event_priv=Super_priv WHERE @hadEventPriv = 0; ALTER TABLE event MODIFY name char(64) CHARACTER SET utf8 NOT NULL default ''; --- --- TRIGGER privilege --- +# +# TRIGGER privilege +# SET @hadTriggerPriv := 0; SELECT @hadTriggerPriv :=1 FROM user WHERE Trigger_priv LIKE '%'; @@ -687,6 +687,8 @@ ALTER TABLE tables_priv MODIFY Table_priv set('Select','Insert','Update','Delete UPDATE user SET Trigger_priv=Super_priv WHERE @hadTriggerPriv = 0; +CREATE TABLE IF NOT EXISTS binlog_index (Position BIGINT UNSIGNED NOT NULL, File VARCHAR(255) NOT NULL, epoch BIGINT UNSIGNED NOT NULL, inserts BIGINT UNSIGNED NOT NULL, updates BIGINT UNSIGNED NOT NULL, deletes BIGINT UNSIGNED NOT NULL, schemaops BIGINT UNSIGNED NOT NULL, PRIMARY KEY(epoch)) ENGINE=MYISAM; + # Activate the new, possible modified privilege tables # This should not be needed, but gives us some extra testing that the above # changes was correct diff --git a/server-tools/instance-manager/IMService.cpp b/server-tools/instance-manager/IMService.cpp index f9ea7ee471d..c8968fe9c16 100644 --- a/server-tools/instance-manager/IMService.cpp +++ b/server-tools/instance-manager/IMService.cpp @@ -21,22 +21,22 @@ void IMService::Stop() { ReportStatus(SERVICE_STOP_PENDING); - // stop the IM work + /* stop the IM work */ raise(SIGTERM); } void IMService::Run(DWORD argc, LPTSTR *argv) { - // report to the SCM that we're about to start + /* report to the SCM that we're about to start */ ReportStatus((DWORD)SERVICE_START_PENDING); Options::load(argc, argv); - // init goes here + /* init goes here */ ReportStatus((DWORD)SERVICE_RUNNING); - // wait for main loop to terminate - manager(); + /* wait for main loop to terminate */ + (void) Manager::main(); Options::cleanup(); } @@ -54,24 +54,24 @@ int HandleServiceOptions() if (Options::Service::install_as_service) { if (winService.IsInstalled()) - log_info("Service is already installed"); + log_info("Service is already installed."); else if (winService.Install()) - log_info("Service installed successfully"); + log_info("Service installed successfully."); else { - log_info("Service failed to install"); + log_error("Service failed to install."); ret_val= 1; } } else if (Options::Service::remove_service) { if (! winService.IsInstalled()) - log_info("Service is not installed"); + log_info("Service is not installed."); else if (winService.Remove()) - log_info("Service removed successfully"); + log_info("Service removed successfully."); else { - log_info("Service failed to remove"); + log_error("Service failed to remove."); ret_val= 1; } } @@ -81,7 +81,7 @@ int HandleServiceOptions() if (!winService.Init()) { - log_info("Service failed to initialize."); + log_error("Service failed to initialize."); fprintf(stderr, "The service should be started by Windows Service Manager.\n" "The MySQL Manager should be started with '--standalone'\n" diff --git a/server-tools/instance-manager/IMService.h b/server-tools/instance-manager/IMService.h index 94d59c2af31..aacc957e195 100644 --- a/server-tools/instance-manager/IMService.h +++ b/server-tools/instance-manager/IMService.h @@ -19,7 +19,7 @@ #pragma once #include "windowsservice.h" -class IMService : public WindowsService +class IMService: public WindowsService { public: IMService(void); diff --git a/server-tools/instance-manager/Makefile.am b/server-tools/instance-manager/Makefile.am index 4719828081a..2d2365caa44 100644 --- a/server-tools/instance-manager/Makefile.am +++ b/server-tools/instance-manager/Makefile.am @@ -61,6 +61,8 @@ client_settings.h: libexec_PROGRAMS= mysqlmanager +mysqlmanager_CXXFLAGS= -Wall -W + mysqlmanager_SOURCES= command.cc command.h mysqlmanager.cc \ manager.h manager.cc log.h log.cc \ thread_registry.h thread_registry.cc \ diff --git a/server-tools/instance-manager/buffer.cc b/server-tools/instance-manager/buffer.cc index 8039ab24481..e1a57a53087 100644 --- a/server-tools/instance-manager/buffer.cc +++ b/server-tools/instance-manager/buffer.cc @@ -27,7 +27,7 @@ const uint Buffer::MAX_BUFFER_SIZE= 16777216; /* Puts the given string to the buffer. - SYNOPSYS + SYNOPSIS append() position start position in the buffer string string to be put in the buffer @@ -59,7 +59,7 @@ int Buffer::append(uint position, const char *string, uint len_arg) Checks whether the current buffer size is ok to put a string of the length "len_arg" starting from "position" and reallocs it if no. - SYNOPSYS + SYNOPSIS reserve() position the number starting byte on the buffer to store a buffer len_arg the length of the string. diff --git a/server-tools/instance-manager/command.cc b/server-tools/instance-manager/command.cc index f76366d5661..0ada11e8865 100644 --- a/server-tools/instance-manager/command.cc +++ b/server-tools/instance-manager/command.cc @@ -19,10 +19,12 @@ #endif #include "command.h" +#include "manager.h" -Command::Command(Instance_map *instance_map_arg) - :instance_map(instance_map_arg) +Command::Command() + :guardian(Manager::get_guardian()), + instance_map(Manager::get_instance_map()) {} Command::~Command() diff --git a/server-tools/instance-manager/command.h b/server-tools/instance-manager/command.h index f31ea404867..e5f7d6e97e6 100644 --- a/server-tools/instance-manager/command.h +++ b/server-tools/instance-manager/command.h @@ -24,6 +24,7 @@ /* Class responsible for allocation of IM commands. */ +class Guardian; class Instance_map; struct st_net; @@ -36,13 +37,13 @@ struct st_net; class Command { public: - Command(Instance_map *instance_map_arg= 0); + Command(); virtual ~Command(); /* This operation incapsulates behaviour of the command. - SYNOPSYS + SYNOPSIS net The network connection to the client. connection_id Client connection ID @@ -53,6 +54,7 @@ public: virtual int execute(st_net *net, ulong connection_id) = 0; protected: + Guardian *guardian; Instance_map *instance_map; }; diff --git a/server-tools/instance-manager/commands.cc b/server-tools/instance-manager/commands.cc index 66140b8b049..15738f8ebb3 100644 --- a/server-tools/instance-manager/commands.cc +++ b/server-tools/instance-manager/commands.cc @@ -29,7 +29,6 @@ #include "guardian.h" #include "instance_map.h" #include "log.h" -#include "manager.h" #include "messages.h" #include "mysqld_error.h" #include "mysql_manager_error.h" @@ -50,7 +49,7 @@ static const int modify_defaults_to_im_error[]= { 0, ER_OUT_OF_RESOURCES, /* Add a string to a buffer. - SYNOPSYS + SYNOPSIS put_to_buff() buff buffer to add the string str string to add @@ -130,7 +129,7 @@ Instance_name::Instance_name(const LEX_STRING *name) ER_OUT_OF_RESOURCES Not enough resources to complete the operation */ -int Show_instances::execute(st_net *net, ulong connection_id) +int Show_instances::execute(st_net *net, ulong /* connection_id */) { int err_code; @@ -242,10 +241,8 @@ int Flush_instances::execute(st_net *net, ulong connection_id) Implementation of Abstract_instance_cmd. **************************************************************************/ -Abstract_instance_cmd::Abstract_instance_cmd( - Instance_map *instance_map_arg, const LEX_STRING *instance_name_arg) - :Command(instance_map_arg), - instance_name(instance_name_arg) +Abstract_instance_cmd::Abstract_instance_cmd(const LEX_STRING *instance_name_arg) + :instance_name(instance_name_arg) { /* MT-NOTE: we can not make a search for Instance object here, @@ -285,9 +282,8 @@ int Abstract_instance_cmd::execute(st_net *net, ulong connection_id) Implementation of Show_instance_status. **************************************************************************/ -Show_instance_status::Show_instance_status(Instance_map *instance_map_arg, - const LEX_STRING *instance_name_arg) - :Abstract_instance_cmd(instance_map_arg, instance_name_arg) +Show_instance_status::Show_instance_status(const LEX_STRING *instance_name_arg) + :Abstract_instance_cmd(instance_name_arg) { } @@ -312,7 +308,8 @@ int Show_instance_status::execute_impl(st_net *net, Instance *instance) } -int Show_instance_status::send_ok_response(st_net *net, ulong connection_id) +int Show_instance_status::send_ok_response(st_net *net, + ulong /* connection_id */) { if (send_eof(net) || net_flush(net)) return ER_OUT_OF_RESOURCES; @@ -406,8 +403,8 @@ int Show_instance_status::write_data(st_net *net, Instance *instance) **************************************************************************/ Show_instance_options::Show_instance_options( - Instance_map *instance_map_arg, const LEX_STRING *instance_name_arg) - :Abstract_instance_cmd(instance_map_arg, instance_name_arg) + const LEX_STRING *instance_name_arg) + :Abstract_instance_cmd(instance_name_arg) { } @@ -432,7 +429,8 @@ int Show_instance_options::execute_impl(st_net *net, Instance *instance) } -int Show_instance_options::send_ok_response(st_net *net, ulong connection_id) +int Show_instance_options::send_ok_response(st_net *net, + ulong /* connection_id */) { if (send_eof(net) || net_flush(net)) return ER_OUT_OF_RESOURCES; @@ -501,9 +499,8 @@ int Show_instance_options::write_data(st_net *net, Instance *instance) Implementation of Start_instance. **************************************************************************/ -Start_instance::Start_instance(Instance_map *instance_map_arg, - const LEX_STRING *instance_name_arg) - :Abstract_instance_cmd(instance_map_arg, instance_name_arg) +Start_instance::Start_instance(const LEX_STRING *instance_name_arg) + :Abstract_instance_cmd(instance_name_arg) { } @@ -516,7 +513,7 @@ Start_instance::Start_instance(Instance_map *instance_map_arg, ER_OUT_OF_RESOURCES Not enough resources to complete the operation */ -int Start_instance::execute_impl(st_net *net, Instance *instance) +int Start_instance::execute_impl(st_net * /* net */, Instance *instance) { int err_code; @@ -543,9 +540,8 @@ int Start_instance::send_ok_response(st_net *net, ulong connection_id) Implementation of Stop_instance. **************************************************************************/ -Stop_instance::Stop_instance(Instance_map *instance_map_arg, - const LEX_STRING *instance_name_arg) - :Abstract_instance_cmd(instance_map_arg, instance_name_arg) +Stop_instance::Stop_instance(const LEX_STRING *instance_name_arg) + :Abstract_instance_cmd(instance_name_arg) { } @@ -558,7 +554,7 @@ Stop_instance::Stop_instance(Instance_map *instance_map_arg, ER_OUT_OF_RESOURCES Not enough resources to complete the operation */ -int Stop_instance::execute_impl(st_net *net, Instance *instance) +int Stop_instance::execute_impl(st_net * /* net */, Instance *instance) { int err_code; @@ -585,10 +581,8 @@ int Stop_instance::send_ok_response(st_net *net, ulong connection_id) Implementation for Create_instance. **************************************************************************/ -Create_instance::Create_instance(Instance_map *instance_map_arg, - const LEX_STRING *instance_name_arg) - :Command(instance_map_arg), - instance_name(instance_name_arg) +Create_instance::Create_instance(const LEX_STRING *instance_name_arg) + :instance_name(instance_name_arg) { } @@ -596,7 +590,7 @@ Create_instance::Create_instance(Instance_map *instance_map_arg, /* This operation initializes Create_instance object. - SYNOPSYS + SYNOPSIS text [IN/OUT] a pointer to the text containing instance options. RETURN @@ -613,7 +607,7 @@ bool Create_instance::init(const char **text) /* This operation parses CREATE INSTANCE options. - SYNOPSYS + SYNOPSIS text [IN/OUT] a pointer to the text containing instance options. RETURN @@ -795,9 +789,8 @@ int Create_instance::execute(st_net *net, ulong connection_id) Implementation for Drop_instance. **************************************************************************/ -Drop_instance::Drop_instance(Instance_map *instance_map_arg, - const LEX_STRING *instance_name_arg) - :Abstract_instance_cmd(instance_map_arg, instance_name_arg) +Drop_instance::Drop_instance(const LEX_STRING *instance_name_arg) + :Abstract_instance_cmd(instance_name_arg) { } @@ -811,7 +804,7 @@ Drop_instance::Drop_instance(Instance_map *instance_map_arg, ER_OUT_OF_RESOURCES Not enough resources to complete the operation */ -int Drop_instance::execute_impl(st_net *net, Instance *instance) +int Drop_instance::execute_impl(st_net * /* net */, Instance *instance) { int err_code; @@ -863,11 +856,10 @@ int Drop_instance::send_ok_response(st_net *net, ulong connection_id) Implementation for Show_instance_log. **************************************************************************/ -Show_instance_log::Show_instance_log(Instance_map *instance_map_arg, - const LEX_STRING *instance_name_arg, +Show_instance_log::Show_instance_log(const LEX_STRING *instance_name_arg, Log_type log_type_arg, uint size_arg, uint offset_arg) - :Abstract_instance_cmd(instance_map_arg, instance_name_arg), + :Abstract_instance_cmd(instance_name_arg), log_type(log_type_arg), size(size_arg), offset(offset_arg) @@ -908,7 +900,8 @@ int Show_instance_log::execute_impl(st_net *net, Instance *instance) } -int Show_instance_log::send_ok_response(st_net *net, ulong connection_id) +int Show_instance_log::send_ok_response(st_net *net, + ulong /* connection_id */) { if (send_eof(net) || net_flush(net)) return ER_OUT_OF_RESOURCES; @@ -1013,9 +1006,8 @@ int Show_instance_log::write_data(st_net *net, Instance *instance) **************************************************************************/ Show_instance_log_files::Show_instance_log_files - (Instance_map *instance_map_arg, - const LEX_STRING *instance_name_arg) - :Abstract_instance_cmd(instance_map_arg, instance_name_arg) + (const LEX_STRING *instance_name_arg) + :Abstract_instance_cmd(instance_name_arg) { } @@ -1040,7 +1032,8 @@ int Show_instance_log_files::execute_impl(st_net *net, Instance *instance) } -int Show_instance_log_files::send_ok_response(st_net *net, ulong connection_id) +int Show_instance_log_files::send_ok_response(st_net *net, + ulong /* connection_id */) { if (send_eof(net) || net_flush(net)) return ER_OUT_OF_RESOURCES; @@ -1214,9 +1207,8 @@ C_MODE_END /**************************************************************************/ -Abstract_option_cmd::Abstract_option_cmd(Instance_map *instance_map_arg) - :Command(instance_map_arg), - initialized(FALSE) +Abstract_option_cmd::Abstract_option_cmd() + :initialized(FALSE) { } @@ -1263,7 +1255,7 @@ bool Abstract_option_cmd::init(const char **text) Correct the option file. The "skip" option is used to remove the found option. - SYNOPSYS + SYNOPSIS Abstract_option_cmd::correct_file() skip Skip the option, being searched while writing the result file. That is, to delete it. @@ -1400,16 +1392,10 @@ int Abstract_option_cmd::execute_impl(st_net *net, ulong connection_id) Implementation of Set_option. **************************************************************************/ -Set_option::Set_option(Instance_map *instance_map_arg) - :Abstract_option_cmd(instance_map_arg) -{ -} - - /* This operation parses SET options. - SYNOPSYS + SYNOPSIS text [IN/OUT] a pointer to the text containing options. RETURN @@ -1553,7 +1539,7 @@ int Set_option::process_option(Instance *instance, Named_value *option) if (instance->is_mysqld_compatible() && Instance_options::is_option_im_specific(option->get_name())) { - log_error("Error: IM-option (%s) can not be used " + log_error("IM-option (%s) can not be used " "in the configuration of mysqld-compatible instance (%s).", (const char *) option->get_name(), (const char *) instance->get_name()->str); @@ -1580,16 +1566,10 @@ int Set_option::process_option(Instance *instance, Named_value *option) Implementation of Unset_option. **************************************************************************/ -Unset_option::Unset_option(Instance_map *instance_map_arg) - :Abstract_option_cmd(instance_map_arg) -{ -} - - /* This operation parses UNSET options. - SYNOPSYS + SYNOPSIS text [IN/OUT] a pointer to the text containing options. RETURN @@ -1712,7 +1692,7 @@ int Unset_option::process_option(Instance *instance, Named_value *option) Implementation of Syntax_error. **************************************************************************/ -int Syntax_error::execute(st_net *net, ulong connection_id) +int Syntax_error::execute(st_net * /* net */, ulong /* connection_id */) { return ER_SYNTAX_ERROR; } diff --git a/server-tools/instance-manager/commands.h b/server-tools/instance-manager/commands.h index 9a9911f2358..8768aaab121 100644 --- a/server-tools/instance-manager/commands.h +++ b/server-tools/instance-manager/commands.h @@ -32,15 +32,16 @@ /* Print all instances of this instance manager. - Grammar: SHOW ISTANCES + Grammar: SHOW INSTANCES */ -class Show_instances : public Command +class Show_instances: public Command { public: - Show_instances(Instance_map *instance_map_arg): Command(instance_map_arg) - {} + Show_instances() + { } +public: int execute(st_net *net, ulong connection_id); private: @@ -54,12 +55,13 @@ private: Grammar: FLUSH INSTANCES */ -class Flush_instances : public Command +class Flush_instances: public Command { public: - Flush_instances(Instance_map *instance_map_arg): Command(instance_map_arg) - {} + Flush_instances() + { } +public: int execute(st_net *net, ulong connection_id); }; @@ -68,11 +70,10 @@ public: Abstract class for Instance-specific commands. */ -class Abstract_instance_cmd : public Command +class Abstract_instance_cmd: public Command { public: - Abstract_instance_cmd(Instance_map *instance_map_arg, - const LEX_STRING *instance_name_arg); + Abstract_instance_cmd(const LEX_STRING *instance_name_arg); public: virtual int execute(st_net *net, ulong connection_id); @@ -102,14 +103,13 @@ private: /* Print status of an instance. - Grammar: SHOW ISTANCE STATUS <instance_name> + Grammar: SHOW INSTANCE STATUS <instance_name> */ -class Show_instance_status : public Abstract_instance_cmd +class Show_instance_status: public Abstract_instance_cmd { public: - Show_instance_status(Instance_map *instance_map_arg, - const LEX_STRING *instance_name_arg); + Show_instance_status(const LEX_STRING *instance_name_arg); protected: virtual int execute_impl(st_net *net, Instance *instance); @@ -126,11 +126,10 @@ private: Grammar: SHOW INSTANCE OPTIONS <instance_name> */ -class Show_instance_options : public Abstract_instance_cmd +class Show_instance_options: public Abstract_instance_cmd { public: - Show_instance_options(Instance_map *instance_map_arg, - const LEX_STRING *instance_name_arg); + Show_instance_options(const LEX_STRING *instance_name_arg); protected: virtual int execute_impl(st_net *net, Instance *instance); @@ -147,11 +146,10 @@ private: Grammar: START INSTANCE <instance_name> */ -class Start_instance : public Abstract_instance_cmd +class Start_instance: public Abstract_instance_cmd { public: - Start_instance(Instance_map *instance_map_arg, - const LEX_STRING *instance_name_arg); + Start_instance(const LEX_STRING *instance_name_arg); protected: virtual int execute_impl(st_net *net, Instance *instance); @@ -164,11 +162,10 @@ protected: Grammar: STOP INSTANCE <instance_name> */ -class Stop_instance : public Abstract_instance_cmd +class Stop_instance: public Abstract_instance_cmd { public: - Stop_instance(Instance_map *instance_map_arg, - const LEX_STRING *instance_name_arg); + Stop_instance(const LEX_STRING *instance_name_arg); protected: virtual int execute_impl(st_net *net, Instance *instance); @@ -181,11 +178,10 @@ protected: Grammar: CREATE INSTANCE <instance_name> [<options>] */ -class Create_instance : public Command +class Create_instance: public Command { public: - Create_instance(Instance_map *instance_map_arg, - const LEX_STRING *instance_name_arg); + Create_instance(const LEX_STRING *instance_name_arg); public: bool init(const char **text); @@ -217,11 +213,10 @@ private: is removed from the instance map. */ -class Drop_instance : public Abstract_instance_cmd +class Drop_instance: public Abstract_instance_cmd { public: - Drop_instance(Instance_map *instance_map_arg, - const LEX_STRING *instance_name_arg); + Drop_instance(const LEX_STRING *instance_name_arg); protected: virtual int execute_impl(st_net *net, Instance *instance); @@ -235,11 +230,10 @@ protected: SHOW <instance_name> LOG {ERROR | SLOW | GENERAL} size[, offset_from_end] */ -class Show_instance_log : public Abstract_instance_cmd +class Show_instance_log: public Abstract_instance_cmd { public: - Show_instance_log(Instance_map *instance_map_arg, - const LEX_STRING *instance_name_arg, + Show_instance_log(const LEX_STRING *instance_name_arg, Log_type log_type_arg, uint size_arg, uint offset_arg); protected: @@ -263,11 +257,10 @@ private: Grammar: SHOW <instance_name> LOG FILES */ -class Show_instance_log_files : public Abstract_instance_cmd +class Show_instance_log_files: public Abstract_instance_cmd { public: - Show_instance_log_files(Instance_map *instance_map_arg, - const LEX_STRING *instance_name_arg); + Show_instance_log_files(const LEX_STRING *instance_name_arg); protected: virtual int execute_impl(st_net *net, Instance *instance); @@ -285,7 +278,7 @@ private: class Instance_options_list; -class Abstract_option_cmd : public Command +class Abstract_option_cmd: public Command { public: ~Abstract_option_cmd(); @@ -299,7 +292,7 @@ public: virtual int execute(st_net *net, ulong connection_id); protected: - Abstract_option_cmd(Instance_map *instance_map_arg); + Abstract_option_cmd(); int correct_file(Instance *instance, Named_value *option, bool skip); @@ -324,10 +317,11 @@ private: Grammar: SET instance_name.option[=option_value][, ...] */ -class Set_option : public Abstract_option_cmd +class Set_option: public Abstract_option_cmd { public: - Set_option(Instance_map *instance_map_arg); + Set_option() + { } protected: virtual bool parse_args(const char **text); @@ -343,7 +337,8 @@ protected: class Unset_option: public Abstract_option_cmd { public: - Unset_option(Instance_map *instance_map_arg); + Unset_option() + { } protected: virtual bool parse_args(const char **text); @@ -360,12 +355,11 @@ protected: just returns NULL. */ -class Syntax_error : public Command +class Syntax_error: public Command { public: - /* This is just to avoid compiler warning. */ - Syntax_error() :Command(NULL) - {} + Syntax_error() + { } public: int execute(st_net *net, ulong connection_id); diff --git a/server-tools/instance-manager/guardian.cc b/server-tools/instance-manager/guardian.cc index 03bfadd8571..e601ce0111c 100644 --- a/server-tools/instance-manager/guardian.cc +++ b/server-tools/instance-manager/guardian.cc @@ -20,7 +20,6 @@ #endif #include "guardian.h" - #include <string.h> #include <sys/types.h> #include <signal.h> @@ -30,17 +29,8 @@ #include "log.h" #include "mysql_manager_error.h" - -pthread_handler_t guardian(void *arg) -{ - Guardian_thread *guardian_thread= (Guardian_thread *) arg; - guardian_thread->run(); - return 0; -} - - const char * -Guardian_thread::get_instance_state_name(enum_instance_state state) +Guardian::get_instance_state_name(enum_instance_state state) { switch (state) { case NOT_STARTED: @@ -68,23 +58,24 @@ Guardian_thread::get_instance_state_name(enum_instance_state state) return NULL; /* just to ignore compiler warning. */ } +/* {{{ Constructor & destructor. */ -Guardian_thread::Guardian_thread(Thread_registry &thread_registry_arg, - Instance_map *instance_map_arg, - uint monitoring_interval_arg) : - Guardian_thread_args(thread_registry_arg, instance_map_arg, - monitoring_interval_arg), - thread_info(pthread_self(), TRUE), guarded_instances(0) +Guardian::Guardian(Thread_registry *thread_registry_arg, + Instance_map *instance_map_arg, + uint monitoring_interval_arg) + :stopped(FALSE), + monitoring_interval(monitoring_interval_arg), + thread_registry(thread_registry_arg), + instance_map(instance_map_arg), + shutdown_requested(FALSE) { pthread_mutex_init(&LOCK_guardian, 0); pthread_cond_init(&COND_guardian, 0); - shutdown_requested= FALSE; - stopped= FALSE; init_alloc_root(&alloc, MEM_ROOT_BLOCK_SIZE, 0); } -Guardian_thread::~Guardian_thread() +Guardian::~Guardian() { /* delay guardian destruction to the moment when no one needs it */ pthread_mutex_lock(&LOCK_guardian); @@ -94,21 +85,23 @@ Guardian_thread::~Guardian_thread() pthread_cond_destroy(&COND_guardian); } +/* }}} */ -void Guardian_thread::request_shutdown() + +void Guardian::request_shutdown() { pthread_mutex_lock(&LOCK_guardian); - /* stop instances or just clean up Guardian repository */ + /* STOP Instances or just clean up Guardian repository */ stop_instances(); shutdown_requested= TRUE; pthread_mutex_unlock(&LOCK_guardian); } -void Guardian_thread::process_instance(Instance *instance, - GUARD_NODE *current_node, - LIST **guarded_instances, - LIST *node) +void Guardian::process_instance(Instance *instance, + GUARD_NODE *current_node, + LIST **guarded_instances, + LIST *node) { uint waitchild= (uint) Instance::DEFAULT_SHUTDOWN_DELAY; /* The amount of times, Guardian attempts to restart an instance */ @@ -117,23 +110,14 @@ void Guardian_thread::process_instance(Instance *instance, if (current_node->state == STOPPING) { - /* this brach is executed during shutdown */ - if (instance->options.shutdown_delay) - { - /* - NOTE: it is important to check shutdown_delay here, but use - shutdown_delay_val. The idea is that if the option is unset, - shutdown_delay will be NULL, but shutdown_delay_val will not be reset. - */ - waitchild= instance->options.shutdown_delay_val; - } + waitchild= instance->options.get_shutdown_delay(); /* this returns TRUE if and only if an instance was stopped for sure */ if (instance->is_crashed()) *guarded_instances= list_delete(*guarded_instances, node); else if ( (uint) (current_time - current_node->last_checked) > waitchild) { - instance->kill_instance(SIGKILL); + instance->kill_mysqld(SIGKILL); /* Later we do node= node->next. This is ok, as we are only removing the node from the list. The pointer to the next one is still valid. @@ -144,20 +128,20 @@ void Guardian_thread::process_instance(Instance *instance, return; } - if (instance->is_running()) + if (instance->is_mysqld_running()) { /* The instance can be contacted on it's port */ /* If STARTING also check that pidfile has been created */ if (current_node->state == STARTING && - current_node->instance->options.get_pid() == 0) + current_node->instance->options.load_pid() == 0) { /* Pid file not created yet, don't go to STARTED state yet */ } else if (current_node->state != STARTED) { /* clear status fields */ - log_info("guardian: instance '%s' is running, set state to STARTED.", + log_info("Guardian: '%s' is running, set state to STARTED.", (const char *) instance->options.instance_name.str); current_node->restart_counter= 0; current_node->crash_moment= 0; @@ -168,7 +152,7 @@ void Guardian_thread::process_instance(Instance *instance, { switch (current_node->state) { case NOT_STARTED: - log_info("guardian: starting instance '%s'...", + log_info("Guardian: starting '%s'...", (const char *) instance->options.instance_name.str); /* NOTE, set state to STARTING _before_ start() is called */ @@ -193,7 +177,7 @@ void Guardian_thread::process_instance(Instance *instance, if (instance->is_crashed()) { instance->start(); - log_info("guardian: starting instance '%s'...", + log_info("Guardian: starting '%s'...", (const char *) instance->options.instance_name.str); } } @@ -211,14 +195,15 @@ void Guardian_thread::process_instance(Instance *instance, instance->start(); current_node->last_checked= current_time; current_node->restart_counter++; - log_info("guardian: restarting instance '%s'...", + log_info("Guardian: restarting '%s'...", (const char *) instance->options.instance_name.str); } } else { - log_info("guardian: cannot start instance %s. Abandoning attempts " - "to (re)start it", instance->options.instance_name.str); + log_info("Guardian: can not start '%s'. " + "Abandoning attempts to (re)start it", + (const char *) instance->options.instance_name.str); current_node->state= CRASHED_AND_ABANDONED; } } @@ -233,18 +218,17 @@ void Guardian_thread::process_instance(Instance *instance, /* - Run guardian thread + Main function of Guardian thread. - SYNOPSYS + SYNOPSIS run() DESCRIPTION - Check for all guarded instances and restart them if needed. If everything is fine go and sleep for some time. */ -void Guardian_thread::run() +void Guardian::run() { Instance *instance; LIST *node; @@ -252,9 +236,8 @@ void Guardian_thread::run() log_info("Guardian: started."); - thread_registry.register_thread(&thread_info); + thread_registry->register_thread(&thread_info); - my_thread_init(); pthread_mutex_lock(&LOCK_guardian); /* loop, until all instances were shut down at the end */ @@ -275,8 +258,8 @@ void Guardian_thread::run() /* check the loop predicate before sleeping */ if (!(shutdown_requested && (!(guarded_instances)))) - thread_registry.cond_timedwait(&thread_info, &COND_guardian, - &LOCK_guardian, &timeout); + thread_registry->cond_timedwait(&thread_info, &COND_guardian, + &LOCK_guardian, &timeout); } log_info("Guardian: stopped."); @@ -284,15 +267,14 @@ void Guardian_thread::run() stopped= TRUE; pthread_mutex_unlock(&LOCK_guardian); /* now, when the Guardian is stopped we can stop the IM */ - thread_registry.unregister_thread(&thread_info); - thread_registry.request_shutdown(); - my_thread_end(); + thread_registry->unregister_thread(&thread_info); + thread_registry->request_shutdown(); log_info("Guardian: finished."); } -int Guardian_thread::is_stopped() +int Guardian::is_stopped() { int var; pthread_mutex_lock(&LOCK_guardian); @@ -306,19 +288,19 @@ int Guardian_thread::is_stopped() Initialize the list of guarded instances: loop through the Instance_map and add all of the instances, which don't have 'nonguarded' option specified. - SYNOPSYS - Guardian_thread::init() + SYNOPSIS + Guardian::init() NOTE: The operation should be invoked with the following locks acquired: - - Guardian_thread; + - Guardian; - Instance_map; RETURN 0 - ok - 1 - error occured + 1 - error occurred */ -int Guardian_thread::init() +int Guardian::init() { Instance *instance; Instance_map::Iterator iterator(instance_map); @@ -344,7 +326,7 @@ int Guardian_thread::init() /* Add instance to the Guardian list - SYNOPSYS + SYNOPSIS guard() instance the instance to be guarded nolock whether we prefer do not lock Guardian here, @@ -357,10 +339,10 @@ int Guardian_thread::init() RETURN 0 - ok - 1 - error occured + 1 - error occurred */ -int Guardian_thread::guard(Instance *instance, bool nolock) +int Guardian::guard(Instance *instance, bool nolock) { LIST *node; GUARD_NODE *content; @@ -397,7 +379,7 @@ int Guardian_thread::guard(Instance *instance, bool nolock) a piece of the MEM_ROOT). */ -int Guardian_thread::stop_guard(Instance *instance) +int Guardian::stop_guard(Instance *instance) { LIST *node; @@ -418,7 +400,7 @@ int Guardian_thread::stop_guard(Instance *instance) An internal method which is called at shutdown to unregister instances and attempt to stop them if requested. - SYNOPSYS + SYNOPSIS stop_instances() DESCRIPTION @@ -431,10 +413,10 @@ int Guardian_thread::stop_guard(Instance *instance) RETURN 0 - ok - 1 - error occured + 1 - error occurred */ -int Guardian_thread::stop_instances() +int Guardian::stop_instances() { LIST *node; node= guarded_instances; @@ -445,7 +427,7 @@ int Guardian_thread::stop_instances() If instance is running or was running (and now probably hanging), request stop. */ - if (current_node->instance->is_running() || + if (current_node->instance->is_mysqld_running() || (current_node->state == STARTED)) { current_node->state= STOPPING; @@ -455,26 +437,26 @@ int Guardian_thread::stop_instances() /* otherwise remove it from the list */ guarded_instances= list_delete(guarded_instances, node); /* But try to kill it anyway. Just in case */ - current_node->instance->kill_instance(SIGTERM); + current_node->instance->kill_mysqld(SIGTERM); node= node->next; } return 0; } -void Guardian_thread::lock() +void Guardian::lock() { pthread_mutex_lock(&LOCK_guardian); } -void Guardian_thread::unlock() +void Guardian::unlock() { pthread_mutex_unlock(&LOCK_guardian); } -LIST *Guardian_thread::find_instance_node(Instance *instance) +LIST *Guardian::find_instance_node(Instance *instance) { LIST *node= guarded_instances; @@ -494,7 +476,7 @@ LIST *Guardian_thread::find_instance_node(Instance *instance) } -bool Guardian_thread::is_active(Instance *instance) +bool Guardian::is_active(Instance *instance) { bool guarded; @@ -508,5 +490,5 @@ bool Guardian_thread::is_active(Instance *instance) if (guarded) return true; - return instance->is_running(); + return instance->is_mysqld_running(); } diff --git a/server-tools/instance-manager/guardian.h b/server-tools/instance-manager/guardian.h index 27ca155fd67..0eee1dc631d 100644 --- a/server-tools/instance-manager/guardian.h +++ b/server-tools/instance-manager/guardian.h @@ -16,11 +16,10 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <my_global.h> -#include <my_sys.h> -#include <my_list.h> #include "thread_registry.h" +#include <my_sys.h> +#include <my_list.h> #if defined(__GNUC__) && defined(USE_PRAGMA_INTERFACE) #pragma interface @@ -31,30 +30,12 @@ class Instance_map; class Thread_registry; struct GUARD_NODE; -pthread_handler_t guardian(void *arg); - -struct Guardian_thread_args -{ - Thread_registry &thread_registry; - Instance_map *instance_map; - int monitoring_interval; - - Guardian_thread_args(Thread_registry &thread_registry_arg, - Instance_map *instance_map_arg, - uint monitoring_interval_arg) : - thread_registry(thread_registry_arg), - instance_map(instance_map_arg), - monitoring_interval(monitoring_interval_arg) - {} -}; - - -/* +/** The guardian thread is responsible for monitoring and restarting of guarded instances. */ -class Guardian_thread: public Guardian_thread_args +class Guardian: public Thread { public: /* states of an instance */ @@ -82,12 +63,10 @@ public: /* Return client state name. */ static const char *get_instance_state_name(enum_instance_state state); - Guardian_thread(Thread_registry &thread_registry_arg, - Instance_map *instance_map_arg, - uint monitoring_interval_arg); - ~Guardian_thread(); - /* Main funtion of the thread */ - void run(); + Guardian(Thread_registry *thread_registry_arg, + Instance_map *instance_map_arg, + uint monitoring_interval_arg); + virtual ~Guardian(); /* Initialize or refresh the list of guarded instances */ int init(); /* Request guardian shutdown. Stop instances if needed */ @@ -117,6 +96,9 @@ public: a valid list node. */ inline enum_instance_state get_instance_state(LIST *instance_node); +protected: + /* Main funtion of the thread */ + virtual void run(); public: pthread_cond_t COND_guardian; @@ -133,6 +115,9 @@ private: private: pthread_mutex_t LOCK_guardian; Thread_info thread_info; + int monitoring_interval; + Thread_registry *thread_registry; + Instance_map *instance_map; LIST *guarded_instances; MEM_ROOT alloc; /* this variable is set to TRUE when we want to stop Guardian thread */ @@ -140,8 +125,8 @@ private: }; -inline Guardian_thread::enum_instance_state -Guardian_thread::get_instance_state(LIST *instance_node) +inline Guardian::enum_instance_state +Guardian::get_instance_state(LIST *instance_node) { return ((GUARD_NODE *) instance_node->data)->state; } diff --git a/server-tools/instance-manager/instance.cc b/server-tools/instance-manager/instance.cc index 3927363a3e5..6b4289c5b29 100644 --- a/server-tools/instance-manager/instance.cc +++ b/server-tools/instance-manager/instance.cc @@ -20,7 +20,6 @@ #include "instance.h" -#include <my_global.h> #include <mysql.h> #include <signal.h> @@ -29,24 +28,15 @@ #endif #include "guardian.h" -#include "instance_map.h" +#include "manager.h" #include "log.h" #include "mysql_manager_error.h" #include "portability.h" #include "priv.h" #include "thread_registry.h" +#include "instance_map.h" - -const LEX_STRING -Instance::DFLT_INSTANCE_NAME= { C_STRING_WITH_LEN("mysqld") }; - -static const char * const INSTANCE_NAME_PREFIX= Instance::DFLT_INSTANCE_NAME.str; -static const int INSTANCE_NAME_PREFIX_LEN= Instance::DFLT_INSTANCE_NAME.length; - - -static void start_and_monitor_instance(Instance_options *old_instance_options, - Instance_map *instance_map, - Thread_registry *thread_registry); +/* {{{ Platform-specific functions. */ #ifndef __WIN__ typedef pid_t My_process_info; @@ -61,19 +51,31 @@ typedef PROCESS_INFORMATION My_process_info; to do it in a portable way. */ -pthread_handler_t proxy(void *arg) +class Instance_monitor: public Thread +{ +public: + Instance_monitor(Instance *instance_arg) :instance(instance_arg) {} +protected: + virtual void run(); + void start_and_monitor_instance(Instance_options *old_instance_options, + Instance_map *instance_map, + Thread_registry *thread_registry); +private: + Instance *instance; +}; + +void Instance_monitor::run() { - Instance *instance= (Instance *) arg; start_and_monitor_instance(&instance->options, - instance->get_map(), - &instance->thread_registry); - return 0; + Manager::get_instance_map(), + Manager::get_thread_registry()); + delete this; } /* Wait for an instance - SYNOPSYS + SYNOPSIS wait_process() pi Pointer to the process information structure (platform-dependent). @@ -103,7 +105,7 @@ static int wait_process(My_process_info *pi) couldn't use wait(), because it could return in any wait() in the program. */ - if (linuxthreads) + if (Manager::is_linux_threads()) wait(NULL); /* LinuxThreads were detected */ else waitpid(*pi, NULL, 0); @@ -131,11 +133,10 @@ static int wait_process(My_process_info *pi) } #endif - /* Launch an instance - SYNOPSYS + SYNOPSIS start_process() instance_options Pointer to the options of the instance to be launched. @@ -143,13 +144,13 @@ static int wait_process(My_process_info *pi) (platform-dependent). RETURN - 0 - Success - 1 - Cannot create an instance + FALSE - Success + TRUE - Cannot create an instance */ #ifndef __WIN__ -static int start_process(Instance_options *instance_options, - My_process_info *pi) +static bool start_process(Instance_options *instance_options, + My_process_info *pi) { #ifndef __QNX__ *pi= fork(); @@ -169,15 +170,16 @@ static int start_process(Instance_options *instance_options, /* exec never returns */ exit(1); case -1: - log_info("cannot create a new process to start instance '%s'.", - (const char *) instance_options->instance_name.str); - return 1; + log_error("Instance '%s': can not start mysqld: fork() failed.", + (const char *) instance_options->instance_name.str); + return TRUE; } - return 0; + + return FALSE; } #else -static int start_process(Instance_options *instance_options, - My_process_info *pi) +static bool start_process(Instance_options *instance_options, + My_process_info *pi) { STARTUPINFO si; @@ -192,7 +194,7 @@ static int start_process(Instance_options *instance_options, char *cmdline= new char[cmdlen]; if (cmdline == NULL) - return 1; + return TRUE; cmdline[0]= 0; for (int i= 0; instance_options->argv[i] != 0; i++) @@ -216,14 +218,87 @@ static int start_process(Instance_options *instance_options, pi); /* Pointer to PROCESS_INFORMATION structure */ delete cmdline; - return (!result); + return !result; } #endif +#ifdef __WIN__ + +BOOL SafeTerminateProcess(HANDLE hProcess, UINT uExitCode) +{ + DWORD dwTID, dwCode, dwErr= 0; + HANDLE hProcessDup= INVALID_HANDLE_VALUE; + HANDLE hRT= NULL; + HINSTANCE hKernel= GetModuleHandle("Kernel32"); + BOOL bSuccess= FALSE; + + BOOL bDup= DuplicateHandle(GetCurrentProcess(), + hProcess, GetCurrentProcess(), &hProcessDup, + PROCESS_ALL_ACCESS, FALSE, 0); + + // Detect the special case where the process is + // already dead... + if (GetExitCodeProcess((bDup) ? hProcessDup : hProcess, &dwCode) && + (dwCode == STILL_ACTIVE)) + { + FARPROC pfnExitProc; + + pfnExitProc= GetProcAddress(hKernel, "ExitProcess"); + + hRT= CreateRemoteThread((bDup) ? hProcessDup : hProcess, NULL, 0, + (LPTHREAD_START_ROUTINE)pfnExitProc, + (PVOID)uExitCode, 0, &dwTID); + + if (hRT == NULL) + dwErr= GetLastError(); + } + else + dwErr= ERROR_PROCESS_ABORTED; + + if (hRT) + { + // Must wait process to terminate to + // guarantee that it has exited... + WaitForSingleObject((bDup) ? hProcessDup : hProcess, INFINITE); + + CloseHandle(hRT); + bSuccess= TRUE; + } + + if (bDup) + CloseHandle(hProcessDup); + + if (!bSuccess) + SetLastError(dwErr); + + return bSuccess; +} + +int kill(pid_t pid, int signum) +{ + HANDLE processhandle= ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); + if (signum == SIGTERM) + ::SafeTerminateProcess(processhandle, 0); + else + ::TerminateProcess(processhandle, -1); + return 0; +} +#endif + +/* }}} */ + +/* {{{ Static constants. */ + +const LEX_STRING +Instance::DFLT_INSTANCE_NAME= { C_STRING_WITH_LEN("mysqld") }; + +/* }}} */ + + /* Fork child, exec an instance and monitor it. - SYNOPSYS + SYNOPSIS start_and_monitor_instance() old_instance_options Pointer to the options of the instance to be launched. This info is likely to become obsolete @@ -238,32 +313,39 @@ static int start_process(Instance_options *instance_options, set appropriate flags and wake all threads waiting for instance to stop. + NOTE + A separate thread for starting/monitoring instance is a simple way + to avoid all pitfalls of the threads implementation in the OS (e.g. + LinuxThreads). For one, with such a thread we don't have to process + SIGCHLD, which is a tricky business if we want to do it in a + portable way. + RETURN Function returns no value */ -static void start_and_monitor_instance(Instance_options *old_instance_options, - Instance_map *instance_map, - Thread_registry *thread_registry) +void +Instance_monitor:: +start_and_monitor_instance(Instance_options *old_instance_options, + Instance_map *instance_map, + Thread_registry *thread_registry) { Instance_name instance_name(&old_instance_options->instance_name); Instance *current_instance; My_process_info process_info; - Thread_info thread_info(pthread_self(), FALSE); + Thread_info thread_info; - log_info("Monitoring thread (instance: '%s'): started.", - (const char *) instance_name.get_c_str()); + log_info("Instance '%s': Monitor: started.", + (const char *) instance->get_name()->str); if (!old_instance_options->nonguarded) { /* Register thread in Thread_registry to wait for it to stop on shutdown - only if instance is nuarded. If instance is guarded, the thread will not + only if instance is guarded. If instance is guarded, the thread will not finish, because nonguarded instances are not stopped on shutdown. */ - - thread_registry->register_thread(&thread_info); - my_thread_init(); + thread_registry->register_thread(&thread_info, FALSE); } /* @@ -277,8 +359,8 @@ static void start_and_monitor_instance(Instance_options *old_instance_options, are using is destroyed. (E.g. by "FLUSH INSTANCES") */ - log_info("starting instance %s...", - (const char *) instance_name.get_c_str()); + log_info("Instance '%s': Monitor: starting mysqld...", + (const char *) instance->get_name()->str); if (start_process(old_instance_options, &process_info)) { @@ -289,8 +371,10 @@ static void start_and_monitor_instance(Instance_options *old_instance_options, /* allow users to delete instances */ instance_map->unlock(); - /* don't check for return value */ - wait_process(&process_info); + log_info("Instance '%s': Monitor: waiting for mysqld to stop...", + (const char *) instance->get_name()->str); + + wait_process(&process_info); /* Don't check for return value. */ instance_map->lock(); @@ -302,21 +386,19 @@ static void start_and_monitor_instance(Instance_options *old_instance_options, instance_map->unlock(); if (!old_instance_options->nonguarded) - { thread_registry->unregister_thread(&thread_info); - my_thread_end(); - } - log_info("Monitoring thread (instance: '%s'): finished.", - (const char *) instance_name.get_c_str()); + log_info("Instance '%s': Monitor: finished.", + (const char *) instance->get_name()->str); } bool Instance::is_name_valid(const LEX_STRING *name) { - const char *name_suffix= name->str + INSTANCE_NAME_PREFIX_LEN; + const char *name_suffix= name->str + DFLT_INSTANCE_NAME.length; - if (strncmp(name->str, INSTANCE_NAME_PREFIX, INSTANCE_NAME_PREFIX_LEN) != 0) + if (strncmp(name->str, Instance::DFLT_INSTANCE_NAME.str, + Instance::DFLT_INSTANCE_NAME.length) != 0) return FALSE; return *name_suffix == 0 || my_isdigit(default_charset_info, *name_suffix); @@ -325,31 +407,139 @@ bool Instance::is_name_valid(const LEX_STRING *name) bool Instance::is_mysqld_compatible_name(const LEX_STRING *name) { - return strcmp(name->str, INSTANCE_NAME_PREFIX) == 0; + return strcmp(name->str, DFLT_INSTANCE_NAME.str) == 0; } -Instance_map *Instance::get_map() + +/* {{{ Constructor & destructor */ + +Instance::Instance() + :crashed(FALSE), + configured(FALSE) { - return instance_map; + pthread_mutex_init(&LOCK_instance, 0); + pthread_cond_init(&COND_instance_stopped, 0); } -void Instance::remove_pid() +Instance::~Instance() +{ + log_info("Instance '%s': destroying...", (const char *) get_name()->str); + + pthread_cond_destroy(&COND_instance_stopped); + pthread_mutex_destroy(&LOCK_instance); +} + +/* }}} */ + +/* + Initialize instance options. + + SYNOPSIS + init() + name_arg name of the instance + + RETURN: + FALSE - ok + TRUE - error +*/ + +bool Instance::init(const LEX_STRING *name_arg) { - int pid; - if ((pid= options.get_pid()) != 0) /* check the pidfile */ - if (options.unlink_pidfile()) /* remove stalled pidfile */ - log_error("cannot remove pidfile for instance '%s', this might be " - "since IM lacks permmissions or hasn't found the pidifle", - (const char *) options.instance_name.str); + mysqld_compatible= is_mysqld_compatible_name(name_arg); + + return options.init(name_arg); } /* + Complete instance options initialization. + + SYNOPSIS + complete_initialization() + + RETURN + FALSE - ok + TRUE - error +*/ + +bool Instance::complete_initialization() +{ + configured= ! options.complete_initialization(); + return FALSE; + /* + TODO: return actual status (from + Instance_options::complete_initialization()) here. + */ +} + +/* + Determine if mysqld is accepting connections. + + SYNOPSIS + is_mysqld_running() + + DESCRIPTION + Try to connect to mysqld with fake login/password to check whether it is + accepting connections or not. + + MT-NOTE: this operation must be called under acquired LOCK_instance. + + RETURN + TRUE - mysqld is alive and accept connections + FALSE - otherwise. +*/ + +bool Instance::is_mysqld_running() +{ + MYSQL mysql; + uint port= options.get_mysqld_port(); /* 0 if not specified. */ + const char *socket= NULL; + static const char *password= "check_connection"; + static const char *username= "MySQL_Instance_Manager"; + static const char *access_denied_message= "Access denied for user"; + bool return_val; + + if (options.mysqld_socket) + socket= options.mysqld_socket; + + /* no port was specified => instance falled back to default value */ + if (!port && !options.mysqld_socket) + port= SERVER_DEFAULT_PORT; + + pthread_mutex_lock(&LOCK_instance); + + mysql_init(&mysql); + /* try to connect to a server with a fake username/password pair */ + if (mysql_real_connect(&mysql, LOCAL_HOST, username, + password, + NullS, port, + socket, 0)) + { + /* + We have successfully connected to the server using fake + username/password. Write a warning to the logfile. + */ + log_error("Instance '%s': was able to log into mysqld.", + (const char *) get_name()->str); + pthread_mutex_unlock(&LOCK_instance); + return_val= TRUE; /* server is alive */ + } + else + return_val= test(!strncmp(access_denied_message, mysql_error(&mysql), + sizeof(access_denied_message) - 1)); + + mysql_close(&mysql); + pthread_mutex_unlock(&LOCK_instance); + + return return_val; +} + +/* The method starts an instance. - SYNOPSYS + SYNOPSIS start() RETURN @@ -367,24 +557,21 @@ int Instance::start() pthread_mutex_unlock(&LOCK_instance); - if (configured && !is_running()) + if (configured && !is_mysqld_running()) { + Instance_monitor *instance_monitor; remove_pid(); - pthread_t proxy_thd_id; - pthread_attr_t proxy_thd_attr; - int rc; + instance_monitor= new Instance_monitor(this); - pthread_attr_init(&proxy_thd_attr); - pthread_attr_setdetachstate(&proxy_thd_attr, PTHREAD_CREATE_DETACHED); - rc= pthread_create(&proxy_thd_id, &proxy_thd_attr, proxy, - this); - pthread_attr_destroy(&proxy_thd_attr); - if (rc) + if (instance_monitor == NULL || instance_monitor->start(Thread::DETACHED)) { - log_error("Instance::start(): pthread_create(proxy) failed"); + delete instance_monitor; + log_error("Instance::start(): failed to create the monitoring thread" + " to start an instance"); return ER_CANNOT_START_INSTANCE; } + /* The monitoring thread will delete itself when it's finished. */ return 0; } @@ -397,7 +584,7 @@ int Instance::start() The method sets the crash flag and wakes all waiters on COND_instance_stopped and COND_guardian - SYNOPSYS + SYNOPSIS set_crash_flag_n_wake_all() DESCRIPTION @@ -423,97 +610,14 @@ void Instance::set_crash_flag_n_wake_all() */ pthread_cond_signal(&COND_instance_stopped); /* wake guardian */ - pthread_cond_signal(&instance_map->guardian->COND_guardian); -} - - - -Instance::Instance(Thread_registry &thread_registry_arg): - crashed(FALSE), configured(FALSE), thread_registry(thread_registry_arg) -{ - pthread_mutex_init(&LOCK_instance, 0); - pthread_cond_init(&COND_instance_stopped, 0); -} - - -Instance::~Instance() -{ - pthread_cond_destroy(&COND_instance_stopped); - pthread_mutex_destroy(&LOCK_instance); -} - - -bool Instance::is_crashed() -{ - bool val; - pthread_mutex_lock(&LOCK_instance); - val= crashed; - pthread_mutex_unlock(&LOCK_instance); - return val; -} - - -bool Instance::is_running() -{ - MYSQL mysql; - uint port= 0; - const char *socket= NULL; - static const char *password= "check_connection"; - static const char *username= "MySQL_Instance_Manager"; - static const char *access_denied_message= "Access denied for user"; - bool return_val; - - if (options.mysqld_port) - { - /* - NOTE: it is important to check mysqld_port here, but use - mysqld_port_val. The idea is that if the option is unset, mysqld_port - will be NULL, but mysqld_port_val will not be reset. - */ - port= options.mysqld_port_val; - } - - if (options.mysqld_socket) - socket= options.mysqld_socket; - - /* no port was specified => instance falled back to default value */ - if (!options.mysqld_port && !options.mysqld_socket) - port= SERVER_DEFAULT_PORT; - - pthread_mutex_lock(&LOCK_instance); - - mysql_init(&mysql); - /* try to connect to a server with a fake username/password pair */ - if (mysql_real_connect(&mysql, LOCAL_HOST, username, - password, - NullS, port, - socket, 0)) - { - /* - We have successfully connected to the server using fake - username/password. Write a warning to the logfile. - */ - log_info("The Instance Manager was able to log into you server " - "with faked compiled-in password while checking server status. " - "Looks like something is wrong."); - pthread_mutex_unlock(&LOCK_instance); - return_val= TRUE; /* server is alive */ - } - else - return_val= test(!strncmp(access_denied_message, mysql_error(&mysql), - sizeof(access_denied_message) - 1)); - - mysql_close(&mysql); - pthread_mutex_unlock(&LOCK_instance); - - return return_val; + pthread_cond_signal(&Manager::get_guardian()->COND_guardian); } /* Stop an instance. - SYNOPSYS + SYNOPSIS stop() RETURN: @@ -527,19 +631,11 @@ int Instance::stop() struct timespec timeout; uint waitchild= (uint) DEFAULT_SHUTDOWN_DELAY; - if (is_running()) + if (is_mysqld_running()) { - if (options.shutdown_delay) - { - /* - NOTE: it is important to check shutdown_delay here, but use - shutdown_delay_val. The idea is that if the option is unset, - shutdown_delay will be NULL, but shutdown_delay_val will not be reset. - */ - waitchild= options.shutdown_delay_val; - } + waitchild= options.get_shutdown_delay(); - kill_instance(SIGTERM); + kill_mysqld(SIGTERM); /* sleep on condition to wait for SIGCHLD */ timeout.tv_sec= time(NULL) + waitchild; @@ -547,7 +643,7 @@ int Instance::stop() if (pthread_mutex_lock(&LOCK_instance)) return ER_STOP_INSTANCE; - while (options.get_pid() != 0) /* while server isn't stopped */ + while (options.load_pid() != 0) /* while server isn't stopped */ { int status; @@ -560,7 +656,7 @@ int Instance::stop() pthread_mutex_unlock(&LOCK_instance); - kill_instance(SIGKILL); + kill_mysqld(SIGKILL); return 0; } @@ -568,120 +664,83 @@ int Instance::stop() return ER_INSTANCE_IS_NOT_STARTED; } -#ifdef __WIN__ -BOOL SafeTerminateProcess(HANDLE hProcess, UINT uExitCode) -{ - DWORD dwTID, dwCode, dwErr= 0; - HANDLE hProcessDup= INVALID_HANDLE_VALUE; - HANDLE hRT= NULL; - HINSTANCE hKernel= GetModuleHandle("Kernel32"); - BOOL bSuccess= FALSE; +/* + Send signal to mysqld. - BOOL bDup= DuplicateHandle(GetCurrentProcess(), - hProcess, GetCurrentProcess(), &hProcessDup, - PROCESS_ALL_ACCESS, FALSE, 0); + SYNOPSIS + kill_mysqld() +*/ - // Detect the special case where the process is - // already dead... - if (GetExitCodeProcess((bDup) ? hProcessDup : hProcess, &dwCode) && - (dwCode == STILL_ACTIVE)) +void Instance::kill_mysqld(int signum) +{ + pid_t mysqld_pid= options.load_pid(); + + if (mysqld_pid == 0) { - FARPROC pfnExitProc; + log_info("Instance '%s': no pid file to send a signal (%d).", + (const char *) get_name()->str, + (int) signum); + return; + } - pfnExitProc= GetProcAddress(hKernel, "ExitProcess"); + log_info("Instance '%s': sending %d to %d...", + (const char *) get_name()->str, + (int) signum, + (int) mysqld_pid); - hRT= CreateRemoteThread((bDup) ? hProcessDup : hProcess, NULL, 0, - (LPTHREAD_START_ROUTINE)pfnExitProc, - (PVOID)uExitCode, 0, &dwTID); - - if (hRT == NULL) - dwErr= GetLastError(); + if (kill(mysqld_pid, signum)) + { + log_info("Instance '%s': kill() failed.", + (const char *) get_name()->str); + return; } - else - dwErr= ERROR_PROCESS_ABORTED; - if (hRT) + /* Kill suceeded */ + if (signum == SIGKILL) /* really killed instance with SIGKILL */ { - // Must wait process to terminate to - // guarantee that it has exited... - WaitForSingleObject((bDup) ? hProcessDup : hProcess, INFINITE); + log_error("Instance '%s': killed.", + (const char *) options.instance_name.str); - CloseHandle(hRT); - bSuccess= TRUE; + /* After sucessful hard kill the pidfile need to be removed */ + options.unlink_pidfile(); } +} - if (bDup) - CloseHandle(hProcessDup); - - if (!bSuccess) - SetLastError(dwErr); +/* + Return crashed flag. - return bSuccess; -} + SYNOPSIS + is_crashed() -int kill(pid_t pid, int signum) -{ - HANDLE processhandle= ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); - if (signum == SIGTERM) - ::SafeTerminateProcess(processhandle, 0); - else - ::TerminateProcess(processhandle, -1); - return 0; -} -#endif + RETURN + TRUE - mysqld crashed + FALSE - mysqld hasn't crashed yet +*/ -void Instance::kill_instance(int signum) +bool Instance::is_crashed() { - pid_t pid; - /* if there are no pid, everything seems to be fine */ - if ((pid= options.get_pid()) != 0) /* get pid from pidfile */ - { - if (kill(pid, signum) == 0) - { - /* Kill suceeded */ - if (signum == SIGKILL) /* really killed instance with SIGKILL */ - { - log_error("The instance '%s' is being stopped forcibly. Normally" - "it should not happen. Probably the instance has been" - "hanging. You should also check your IM setup", - (const char *) options.instance_name.str); - /* After sucessful hard kill the pidfile need to be removed */ - options.unlink_pidfile(); - } - } - } - return; + bool val; + pthread_mutex_lock(&LOCK_instance); + val= crashed; + pthread_mutex_unlock(&LOCK_instance); + return val; } /* - Initialize instance parameters. - - SYNOPSYS - Instance::init() - name_arg name of the instance - - RETURN: - 0 ok - !0 error + Remove pid file. */ -int Instance::init(const LEX_STRING *name_arg) +void Instance::remove_pid() { - mysqld_compatible= is_mysqld_compatible_name(name_arg); - - return options.init(name_arg); -} + int mysqld_pid= options.load_pid(); + if (mysqld_pid == 0) + return; -int Instance::complete_initialization(Instance_map *instance_map_arg, - const char *mysqld_path) -{ - instance_map= instance_map_arg; - configured= !options.complete_initialization(mysqld_path); - return 0; - /* - TODO: return actual status (from - Instance_options::complete_initialization()) here. - */ + if (options.unlink_pidfile()) + { + log_error("Instance '%s': can not unlink pid file.", + (const char *) options.instance_name.str); + } } diff --git a/server-tools/instance-manager/instance.h b/server-tools/instance-manager/instance.h index 329eaa68b1a..412d01acc46 100644 --- a/server-tools/instance-manager/instance.h +++ b/server-tools/instance-manager/instance.h @@ -88,21 +88,19 @@ public: static bool is_mysqld_compatible_name(const LEX_STRING *name); public: - Instance(Thread_registry &thread_registry_arg); + Instance(); ~Instance(); - int init(const LEX_STRING *name_arg); - int complete_initialization(Instance_map *instance_map_arg, - const char *mysqld_path); + bool init(const LEX_STRING *name_arg); + bool complete_initialization(); - bool is_running(); + bool is_mysqld_running(); int start(); int stop(); /* send a signal to the instance */ - void kill_instance(int signo); + void kill_mysqld(int signo); bool is_crashed(); void set_crash_flag_n_wake_all(); - Instance_map *get_map(); /* The operation is intended to check if the instance is mysqld-compatible @@ -121,7 +119,6 @@ public: public: enum { DEFAULT_SHUTDOWN_DELAY= 35 }; Instance_options options; - Thread_registry &thread_registry; private: /* This attributes is a flag, specifies if the instance has been crashed. */ @@ -155,7 +152,6 @@ private: stop in Instance::stop() */ pthread_cond_t COND_instance_stopped; - Instance_map *instance_map; void remove_pid(); }; diff --git a/server-tools/instance-manager/instance_map.cc b/server-tools/instance-manager/instance_map.cc index 2f830e616c4..a356e308e44 100644 --- a/server-tools/instance-manager/instance_map.cc +++ b/server-tools/instance-manager/instance_map.cc @@ -63,7 +63,7 @@ static void delete_instance(void *u) /* The option handler to pass to the process_default_option_files finction. - SYNOPSYS + SYNOPSIS process_option() ctx Handler context. Here it is an instance_map structure. group_name The name of the group the option belongs to. @@ -169,7 +169,7 @@ int Instance_map::process_one_option(const LEX_STRING *group, if (!(instance= (Instance *) hash_search(&hash, (byte *) group->str, group->length))) { - if (!(instance= new Instance(thread_registry))) + if (!(instance= new Instance())) return 1; if (instance->init(group) || add_instance(instance)) @@ -213,16 +213,13 @@ int Instance_map::process_one_option(const LEX_STRING *group, } -Instance_map::Instance_map(const char *default_mysqld_path_arg, - Thread_registry &thread_registry_arg): - mysqld_path(default_mysqld_path_arg), - thread_registry(thread_registry_arg) +Instance_map::Instance_map() { pthread_mutex_init(&LOCK_instance_map, 0); } -int Instance_map::init() +bool Instance_map::init() { return hash_init(&hash, default_charset_info, START_HASH_SIZE, 0, 0, get_instance_key, delete_instance, 0); @@ -276,7 +273,7 @@ void Instance_map::unlock() FLUSH INSTANCES without prior stop of all running instances. NOTE: The operation should be invoked with the following locks acquired: - - Guardian_thread; + - Guardian; - Instance_map; */ @@ -310,7 +307,7 @@ bool Instance_map::is_there_active_instance() while ((instance= iterator.next())) { if (guardian->find_instance_node(instance) != NULL || - instance->is_running()) + instance->is_mysqld_running()) { return TRUE; } @@ -335,18 +332,18 @@ int Instance_map::remove_instance(Instance *instance) int Instance_map::create_instance(const LEX_STRING *instance_name, const Named_value_arr *options) { - Instance *instance= new Instance(thread_registry); + Instance *instance= new Instance(); if (!instance) { - log_error("Error: can not initialize (name: '%s').", + log_error("Can not allocate instance (name: '%s').", (const char *) instance_name->str); return ER_OUT_OF_RESOURCES; } if (instance->init(instance_name)) { - log_error("Error: can not initialize (name: '%s').", + log_error("Can not initialize instance (name: '%s').", (const char *) instance_name->str); delete instance; return ER_OUT_OF_RESOURCES; @@ -359,7 +356,7 @@ int Instance_map::create_instance(const LEX_STRING *instance_name, if (instance->is_mysqld_compatible() && Instance_options::is_option_im_specific(option.get_name())) { - log_error("Error: IM-option (%s) can not be used " + log_error("IM-option (%s) can not be used " "in configuration of mysqld-compatible instance (%s).", (const char *) option.get_name(), (const char *) instance_name->str); @@ -374,9 +371,9 @@ int Instance_map::create_instance(const LEX_STRING *instance_name, log_info("Warning: instance name '%s' is mysqld-compatible.", (const char *) instance_name->str); - if (instance->complete_initialization(this, mysqld_path)) + if (instance->complete_initialization()) { - log_error("Error: can not complete initialization of instance (name: '%s').", + log_error("Can not complete initialization of instance (name: '%s').", (const char *) instance_name->str); delete instance; return ER_OUT_OF_RESOURCES; @@ -385,7 +382,7 @@ int Instance_map::create_instance(const LEX_STRING *instance_name, if (add_instance(instance)) { - log_error("Error: can not register instance (name: '%s').", + log_error("Can not register instance (name: '%s').", (const char *) instance_name->str); delete instance; return ER_OUT_OF_RESOURCES; @@ -411,7 +408,7 @@ bool Instance_map::complete_initialization() { Instance *instance= (Instance *) hash_element(&hash, i); - if (instance->complete_initialization(this, mysqld_path)) + if (instance->complete_initialization()) return TRUE; } @@ -429,7 +426,7 @@ bool Instance_map::complete_initialization() if (create_instance(&Instance::DFLT_INSTANCE_NAME, NULL)) { - log_error("Error: could not create default instance."); + log_error("Can not create default instance."); return TRUE; } @@ -444,7 +441,7 @@ bool Instance_map::complete_initialization() break; default: - log_error("Error: could not add default instance to the config file."); + log_error("Can not add default instance to the config file."); Instance *instance= find(&Instance::DFLT_INSTANCE_NAME); @@ -502,7 +499,7 @@ int Instance_map::load() if (my_search_option_files(Options::Main::config_file, &argc, (char ***) &argv, &args_used, process_option, (void*) this)) - log_info("Falling back to compiled-in defaults"); + log_info("Falling back to compiled-in defaults."); return complete_initialization(); } @@ -537,20 +534,20 @@ const char *Instance_map::get_instance_state_name(Instance *instance) { /* The instance is managed by Guardian: we can report precise state. */ - return Guardian_thread::get_instance_state_name( + return Guardian::get_instance_state_name( guardian->get_instance_state(instance_node)); } /* The instance is not managed by Guardian: we can report status only. */ - return instance->is_running() ? "online" : "offline"; + return instance->is_mysqld_running() ? "online" : "offline"; } /* Create a new configuration section for mysqld-instance in the config file. - SYNOPSYS + SYNOPSIS create_instance_in_file() instance_name mysqld-instance name options options for the new mysqld-instance @@ -569,7 +566,7 @@ int create_instance_in_file(const LEX_STRING *instance_name, if (my_access(Options::Main::config_file, W_OK)) { - log_error("Error: configuration file (%s) does not exist.", + log_error("Configuration file (%s) does not exist.", (const char *) Options::Main::config_file); return ER_CONF_FILE_DOES_NOT_EXIST; } @@ -578,7 +575,7 @@ int create_instance_in_file(const LEX_STRING *instance_name, if (cnf_file <= 0) { - log_error("Error: can not open configuration file (%s): %s.", + log_error("Can not open configuration file (%s): %s.", (const char *) Options::Main::config_file, (const char *) strerror(errno)); return ER_ACCESS_OPTION_FILE; @@ -591,7 +588,7 @@ int create_instance_in_file(const LEX_STRING *instance_name, my_write(cnf_file, (byte*)"]", 1, MYF(MY_NABP)) || my_write(cnf_file, (byte*)NEWLINE, NEWLINE_LEN, MYF(MY_NABP))) { - log_error("Error: can not write to configuration file (%s): %s.", + log_error("Can not write to configuration file (%s): %s.", (const char *) Options::Main::config_file, (const char *) strerror(errno)); my_close(cnf_file, MYF(0)); @@ -615,7 +612,7 @@ int create_instance_in_file(const LEX_STRING *instance_name, if (my_write(cnf_file, (byte*)option_str, option_str_len, MYF(MY_NABP)) || my_write(cnf_file, (byte*)NEWLINE, NEWLINE_LEN, MYF(MY_NABP))) { - log_error("Error: can not write to configuration file (%s): %s.", + log_error("Can not write to configuration file (%s): %s.", (const char *) Options::Main::config_file, (const char *) strerror(errno)); my_close(cnf_file, MYF(0)); diff --git a/server-tools/instance-manager/instance_map.h b/server-tools/instance-manager/instance_map.h index 9de40e35e0f..69d225c89f7 100644 --- a/server-tools/instance-manager/instance_map.h +++ b/server-tools/instance-manager/instance_map.h @@ -25,7 +25,7 @@ #pragma interface #endif -class Guardian_thread; +class Guardian; class Instance; class Named_value_arr; class Thread_registry; @@ -75,7 +75,7 @@ public: void lock(); void unlock(); - int init(); + bool init(); /* Process a given option and assign it to appropricate instance. This is @@ -105,8 +105,7 @@ public: int create_instance(const LEX_STRING *instance_name, const Named_value_arr *options); - Instance_map(const char *default_mysqld_path_arg, - Thread_registry &thread_registry_arg); + Instance_map(); ~Instance_map(); /* @@ -115,13 +114,13 @@ public: MT-NOTE: the options must be called under acquired locks of the following objects: - Instance_map; - - Guardian_thread; + - Guardian; */ const char *get_instance_state_name(Instance *instance); public: const char *mysqld_path; - Guardian_thread *guardian; + Guardian *guardian; private: /* loads options from config files */ @@ -132,8 +131,6 @@ private: enum { START_HASH_SIZE = 16 }; pthread_mutex_t LOCK_instance_map; HASH hash; - - Thread_registry &thread_registry; }; #endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_INSTANCE_MAP_H */ diff --git a/server-tools/instance-manager/instance_options.cc b/server-tools/instance-manager/instance_options.cc index 00da6660703..58e7b630fe9 100644 --- a/server-tools/instance-manager/instance_options.cc +++ b/server-tools/instance-manager/instance_options.cc @@ -29,13 +29,14 @@ #include "buffer.h" #include "instance.h" #include "log.h" +#include "options.h" #include "parse_output.h" #include "priv.h" /* Create "mysqld ..." command in the buffer */ -static inline int create_mysqld_command(Buffer *buf, +static inline bool create_mysqld_command(Buffer *buf, const LEX_STRING *mysqld_path, const LEX_STRING *option) { @@ -54,12 +55,35 @@ static inline int create_mysqld_command(Buffer *buf, /* here the '\0' character is copied from the option string */ buf->append(position, option->str, option->length + 1); - return buf->is_error(); + return buf->is_error() ? TRUE : FALSE; } - return 1; + return TRUE; +} + +static inline bool is_path_separator(char ch) +{ +#if defined(__WIN__) || defined(__NETWARE__) + /* On windows and netware more delimiters are possible */ + return ch == FN_LIBCHAR || ch == FN_DEVCHAR || ch == '/'; +#else + return ch == FN_LIBCHAR; /* Unixes */ +#endif } +static char *find_last_path_separator(char *path, uint length) +{ + while (length) + { + if (is_path_separator(path[length])) + return path + length; + length--; + } + return NULL; /* No path separator found */ +} + + + bool Instance_options::is_option_im_specific(const char *option_name) { static const char *IM_SPECIFIC_OPTIONS[] = @@ -82,8 +106,12 @@ bool Instance_options::is_option_im_specific(const char *option_name) Instance_options::Instance_options() :mysqld_version(NULL), mysqld_socket(NULL), mysqld_datadir(NULL), - mysqld_pid_file(NULL), mysqld_port(NULL), mysqld_port_val(0), - nonguarded(NULL), shutdown_delay(NULL), shutdown_delay_val(0), + mysqld_pid_file(NULL), + nonguarded(NULL), + mysqld_port(NULL), + mysqld_port_val(0), + shutdown_delay(NULL), + shutdown_delay_val(0), filled_default_options(0) { mysqld_path.str= NULL; @@ -99,7 +127,7 @@ Instance_options::Instance_options() /* Get compiled-in value of default_option - SYNOPSYS + SYNOPSIS get_default_option() result buffer to put found value result_len buffer size @@ -139,7 +167,7 @@ err: /* Fill mysqld_version option (used at initialization stage) - SYNOPSYS + SYNOPSIS fill_instance_version() DESCRIPTION @@ -147,27 +175,36 @@ err: Get mysqld version string from "mysqld --version" output. RETURN - 0 - ok - 1 - error occured + FALSE - ok + TRUE - error occured */ -int Instance_options::fill_instance_version() +bool Instance_options::fill_instance_version() { char result[MAX_VERSION_LENGTH]; LEX_STRING version_option= { C_STRING_WITH_LEN(" --no-defaults --version") }; - int rc= 1; Buffer cmd(mysqld_path.length + version_option.length + 1); if (create_mysqld_command(&cmd, &mysqld_path, &version_option)) - goto err; + { + log_error("Failed to get version of '%s': out of memory.", + (const char *) mysqld_path.str); + return TRUE; + } bzero(result, MAX_VERSION_LENGTH); - rc= parse_output_and_get_value(cmd.buffer, "Ver", result, - MAX_VERSION_LENGTH, GET_LINE); + if (parse_output_and_get_value(cmd.buffer, "Ver", result, + MAX_VERSION_LENGTH, GET_LINE)) + { + log_error("Failed to get version of '%s': unexpected output.", + (const char *) mysqld_path.str); + return TRUE; + } + + DBUG_ASSERT(*result != '\0'); - if (*result != '\0') { char *start; /* chop the newline from the end of the version string */ @@ -179,18 +216,15 @@ int Instance_options::fill_instance_version() mysqld_version= strdup_root(&alloc, start); } -err: - if (rc) - log_error("fill_instance_version: Failed to get version of '%s'", - mysqld_path.str); - return rc; + + return FALSE; } /* Fill mysqld_real_path - SYNOPSYS + SYNOPSIS fill_mysqld_real_path() DESCRIPTION @@ -202,28 +236,37 @@ err: script(for example libtool) or a symlink. RETURN - 0 - ok - 1 - error occured + FALSE - ok + TRUE - error occured */ -int Instance_options::fill_mysqld_real_path() +bool Instance_options::fill_mysqld_real_path() { char result[FN_REFLEN]; LEX_STRING help_option= { C_STRING_WITH_LEN(" --no-defaults --help") }; - int rc= 1; Buffer cmd(mysqld_path.length + help_option.length); if (create_mysqld_command(&cmd, &mysqld_path, &help_option)) - goto err; + { + log_error("Failed to get real path of '%s': out of memory.", + (const char *) mysqld_path.str); + return TRUE; + } bzero(result, FN_REFLEN); - rc= parse_output_and_get_value(cmd.buffer, "Usage: ", + if (parse_output_and_get_value(cmd.buffer, "Usage: ", result, FN_REFLEN, - GET_LINE); + GET_LINE)) + { + log_error("Failed to get real path of '%s': unexpected output.", + (const char *) mysqld_path.str); + return TRUE; + } + + DBUG_ASSERT(*result != '\0'); - if (*result != '\0') { char* options_str; /* chop the path of at [OPTIONS] */ @@ -232,17 +275,15 @@ int Instance_options::fill_mysqld_real_path() mysqld_real_path.str= strdup_root(&alloc, result); mysqld_real_path.length= strlen(mysqld_real_path.str); } -err: - if (rc) - log_error("fill_mysqld_real_path: Failed to get real path of mysqld"); - return rc; + + return FALSE; } /* Fill various log options - SYNOPSYS + SYNOPSIS fill_log_options() DESCRIPTION @@ -252,11 +293,11 @@ err: file name and placement. RETURN - 0 - ok - 1 - error occured + FALSE - ok + TRUE - error occured */ -int Instance_options::fill_log_options() +bool Instance_options::fill_log_options() { Buffer buff; enum { MAX_LOG_OPTION_LENGTH= 256 }; @@ -282,7 +323,7 @@ int Instance_options::fill_log_options() if (mysqld_datadir == NULL) { if (get_default_option(datadir, MAX_LOG_OPTION_LENGTH, "--datadir")) - goto err; + return TRUE; } else { @@ -320,7 +361,7 @@ int Instance_options::fill_log_options() if ((MAX_LOG_OPTION_LENGTH - strlen(full_name)) <= strlen(log_files->default_suffix)) - goto err; + return TRUE; strmov(full_name + strlen(full_name), log_files->default_suffix); @@ -340,22 +381,20 @@ int Instance_options::fill_log_options() datadir, "", MY_UNPACK_FILENAME | MY_SAFE_PATH); if (!(*(log_files->value)= strdup_root(&alloc, full_name))) - goto err; + return TRUE; } } } } - return 0; -err: - return 1; + return FALSE; } /* Get the full pid file name with path - SYNOPSYS + SYNOPSIS get_pid_filaname() result buffer to sotre the pidfile value @@ -396,7 +435,7 @@ int Instance_options::unlink_pidfile() } -pid_t Instance_options::get_pid() +pid_t Instance_options::load_pid() { FILE *pid_file_stream; @@ -415,26 +454,56 @@ pid_t Instance_options::get_pid() } -int Instance_options::complete_initialization(const char *default_path) +bool Instance_options::complete_initialization() { int arg_idx; const char *tmp; char *end; + char bin_name_firstchar; if (!mysqld_path.str) { - // Need one extra byte, as convert_dirname() adds a slash at the end. - if (!(mysqld_path.str= alloc_root(&alloc, strlen(default_path) + 2))) - goto err; - strcpy(mysqld_path.str, default_path); - } + /* + Need to copy the path to allocated memory, as convert_dirname() might + need to change it + */ + mysqld_path.str= + alloc_root(&alloc, strlen(Options::Main::default_mysqld_path) + 1); + + if (!mysqld_path.str) + return TRUE; - // it's safe to cast this to char* since this is a buffer we are allocating - end= convert_dirname((char*)mysqld_path.str, mysqld_path.str, NullS); - end[-1]= 0; + strcpy(mysqld_path.str, Options::Main::default_mysqld_path); + } mysqld_path.length= strlen(mysqld_path.str); + /* + If we found path with no slashes (end == NULL), we should not call + convert_dirname() at all. As we have got relative path to the binary. + That is, user supposes that mysqld resides in the same dir as + mysqlmanager. + */ + if ((end= find_last_path_separator(mysqld_path.str, mysqld_path.length))) + { + bin_name_firstchar= end[1]; + + /* + Below we will conver the path to mysqld in the case, it was given + in a format of another OS (e.g. uses '/' instead of '\' etc). + Here we strip the path to get rid of the binary name ("mysqld"), + we do it by removing first letter of the binary name (e.g. 'm' + in "mysqld"). Later we put it back. + */ + end[1]= 0; + + /* convert dirname to the format of current OS */ + convert_dirname((char*)mysqld_path.str, mysqld_path.str, NullS); + + /* put back the first character of the binary name*/ + end[1]= bin_name_firstchar; + } + if (mysqld_port) mysqld_port_val= atoi(mysqld_port); @@ -442,7 +511,7 @@ int Instance_options::complete_initialization(const char *default_path) shutdown_delay_val= atoi(shutdown_delay); if (!(tmp= strdup_root(&alloc, "--no-defaults"))) - goto err; + return TRUE; if (!mysqld_pid_file) { @@ -477,21 +546,21 @@ int Instance_options::complete_initialization(const char *default_path) } if (get_pid_filename(pid_file_with_path)) - goto err; + return TRUE; /* we need to reserve space for the final zero + possible default options */ if (!(argv= (char**) alloc_root(&alloc, (get_num_options() + 1 + MAX_NUMBER_OF_DEFAULT_OPTIONS) * sizeof(char*)))) - goto err; + return TRUE; filled_default_options= 0; /* the path must be first in the argv */ if (add_to_argv(mysqld_path.str)) - goto err; + return TRUE; if (add_to_argv(tmp)) - goto err; + return TRUE; arg_idx= filled_default_options; for (int opt_idx= 0; opt_idx < get_num_options(); ++opt_idx) @@ -514,12 +583,9 @@ int Instance_options::complete_initialization(const char *default_path) argv[arg_idx]= 0; if (fill_log_options() || fill_mysqld_real_path() || fill_instance_version()) - goto err; - - return 0; + return TRUE; -err: - return 1; + return FALSE; } @@ -636,26 +702,26 @@ void Instance_options::print_argv() /* We execute this function to initialize some options. - Return value: 0 - ok. 1 - unable to allocate memory. + + RETURN + FALSE - ok + TRUE - memory allocation error */ -int Instance_options::init(const LEX_STRING *instance_name_arg) +bool Instance_options::init(const LEX_STRING *instance_name_arg) { instance_name.length= instance_name_arg->length; init_alloc_root(&alloc, MEM_ROOT_BLOCK_SIZE, 0); if (options.init()) - goto err; + return TRUE; if (!(instance_name.str= strmake_root(&alloc, instance_name_arg->str, instance_name_arg->length))) - goto err; - - return 0; + return TRUE; -err: - return 1; + return FALSE; } @@ -663,3 +729,29 @@ Instance_options::~Instance_options() { free_root(&alloc, MYF(0)); } + + +uint Instance_options::get_shutdown_delay() const +{ + static const uint DEFAULT_SHUTDOWN_DELAY= 35; + + /* + NOTE: it is important to check shutdown_delay here, but use + shutdown_delay_val. The idea is that if the option is unset, + shutdown_delay will be NULL, but shutdown_delay_val will not be reset. + */ + + return shutdown_delay ? shutdown_delay_val : DEFAULT_SHUTDOWN_DELAY; +} + +int Instance_options::get_mysqld_port() const +{ + /* + NOTE: it is important to check mysqld_port here, but use mysqld_port_val. + The idea is that if the option is unset, mysqld_port will be NULL, but + mysqld_port_val will not be reset. + */ + + return mysqld_port ? mysqld_port_val : 0; +} + diff --git a/server-tools/instance-manager/instance_options.h b/server-tools/instance-manager/instance_options.h index c3b0a16a40d..7c1e1a8dcf3 100644 --- a/server-tools/instance-manager/instance_options.h +++ b/server-tools/instance-manager/instance_options.h @@ -45,8 +45,9 @@ public: public: Instance_options(); ~Instance_options(); + /* fills in argv */ - int complete_initialization(const char *default_path); + bool complete_initialization(); bool set_option(Named_value *option); void unset_option(const char *option_name); @@ -55,12 +56,15 @@ public: inline Named_value get_option(int idx) const; public: - int init(const LEX_STRING *instance_name_arg); - pid_t get_pid(); + bool init(const LEX_STRING *instance_name_arg); + pid_t load_pid(); int get_pid_filename(char *result); int unlink_pidfile(); void print_argv(); + uint get_shutdown_delay() const; + int get_mysqld_port() const; + public: /* We need this value to be greater or equal then FN_REFLEN found in @@ -79,21 +83,17 @@ public: const char *mysqld_socket; const char *mysqld_datadir; const char *mysqld_pid_file; - const char *mysqld_port; - uint mysqld_port_val; LEX_STRING instance_name; LEX_STRING mysqld_path; LEX_STRING mysqld_real_path; const char *nonguarded; - const char *shutdown_delay; - uint shutdown_delay_val; /* log enums are defined in parse.h */ char *logs[3]; private: - int fill_log_options(); - int fill_instance_version(); - int fill_mysqld_real_path(); + bool fill_log_options(); + bool fill_instance_version(); + bool fill_mysqld_real_path(); int add_to_argv(const char *option); int get_default_option(char *result, size_t result_len, const char *option_name); @@ -102,6 +102,11 @@ private: int find_option(const char *option_name); private: + const char *mysqld_port; + uint mysqld_port_val; + const char *shutdown_delay; + uint shutdown_delay_val; + uint filled_default_options; MEM_ROOT alloc; diff --git a/server-tools/instance-manager/listener.cc b/server-tools/instance-manager/listener.cc index 62962c00957..f18a594985c 100644 --- a/server-tools/instance-manager/listener.cc +++ b/server-tools/instance-manager/listener.cc @@ -29,7 +29,6 @@ #include <sys/un.h> #endif -#include "instance_map.h" #include "log.h" #include "mysql_connection.h" #include "options.h" @@ -59,47 +58,18 @@ static void set_no_inherit(int socket) } -/* - Listener_thread - incapsulates listening functionality -*/ - -class Listener_thread: public Listener_thread_args -{ -public: - Listener_thread(const Listener_thread_args &args); - ~Listener_thread(); - void run(); -private: - static const int LISTEN_BACK_LOG_SIZE= 5; /* standard backlog size */ - ulong total_connection_count; - Thread_info thread_info; - - int sockets[2]; - int num_sockets; - fd_set read_fds; -private: - void handle_new_mysql_connection(Vio *vio); - int create_tcp_socket(); - int create_unix_socket(struct sockaddr_un &unix_socket_address); -}; - - -Listener_thread::Listener_thread(const Listener_thread_args &args) : - Listener_thread_args(args.thread_registry, args.user_map, args.instance_map) - ,total_connection_count(0) - ,thread_info(pthread_self(), TRUE) - ,num_sockets(0) -{ -} - - -Listener_thread::~Listener_thread() +Listener::Listener(Thread_registry *thread_registry_arg, + User_map *user_map_arg) + :thread_registry(thread_registry_arg), + user_map(user_map_arg), + total_connection_count(0), + num_sockets(0) { } /* - Listener_thread::run() - listen all supported sockets and spawn a thread + Listener::run() - listen all supported sockets and spawn a thread to handle incoming connection. Using 'die' in case of syscall failure is OK now - we don't hold any resources and 'die' kills the signal thread automatically. To be rewritten @@ -108,26 +78,17 @@ Listener_thread::~Listener_thread() architecture. */ -void Listener_thread::run() +void Listener::run() { int i, n= 0; - log_info("Listener_thread: started."); - #ifndef __WIN__ - /* we use this var to check whether we are running on LinuxThreads */ - pid_t thread_pid; - - thread_pid= getpid(); - struct sockaddr_un unix_socket_address; - /* set global variable */ - linuxthreads= (thread_pid != manager_pid); #endif - thread_registry.register_thread(&thread_info); + log_info("Listener: started."); - my_thread_init(); + thread_registry->register_thread(&thread_info); FD_ZERO(&read_fds); @@ -146,7 +107,7 @@ void Listener_thread::run() n++; timeval tv; - while (!thread_registry.is_shutdown()) + while (!thread_registry->is_shutdown()) { fd_set read_fds_arg= read_fds; /* @@ -166,8 +127,8 @@ void Listener_thread::run() if (rc == 0 || rc == -1) { if (rc == -1 && errno != EINTR) - log_error("Listener_thread: select() failed, %s", - strerror(errno)); + log_error("Listener: select() failed: %s.", + (const char *) strerror(errno)); continue; } @@ -183,10 +144,12 @@ void Listener_thread::run() { set_no_inherit(client_fd); - Vio *vio= vio_new(client_fd, socket_index == 0 ? - VIO_TYPE_SOCKET : VIO_TYPE_TCPIP, - socket_index == 0 ? 1 : 0); - if (vio != 0) + struct st_vio *vio= + vio_new(client_fd, + socket_index == 0 ? VIO_TYPE_SOCKET : VIO_TYPE_TCPIP, + socket_index == 0 ? 1 : 0); + + if (vio != NULL) handle_new_mysql_connection(vio); else { @@ -200,7 +163,7 @@ void Listener_thread::run() /* III. Release all resources and exit */ - log_info("Listener_thread: shutdown requested, exiting..."); + log_info("Listener: shutdown requested, exiting..."); for (i= 0; i < num_sockets; i++) close(sockets[i]); @@ -209,10 +172,9 @@ void Listener_thread::run() unlink(unix_socket_address.sun_path); #endif - thread_registry.unregister_thread(&thread_info); - my_thread_end(); + thread_registry->unregister_thread(&thread_info); - log_info("Listener_thread: finished."); + log_info("Listener: finished."); return; err: @@ -220,13 +182,12 @@ err: for (i= 0; i < num_sockets; i++) close(sockets[i]); - thread_registry.unregister_thread(&thread_info); - thread_registry.request_shutdown(); - my_thread_end(); + thread_registry->unregister_thread(&thread_info); + thread_registry->request_shutdown(); return; } -int Listener_thread::create_tcp_socket() +int Listener::create_tcp_socket() { /* value to be set by setsockopt */ int arg= 1; @@ -234,8 +195,8 @@ int Listener_thread::create_tcp_socket() int ip_socket= socket(AF_INET, SOCK_STREAM, 0); if (ip_socket == INVALID_SOCKET) { - log_error("Listener_thead: socket(AF_INET) failed, %s", - strerror(errno)); + log_error("Listener: socket(AF_INET) failed: %s.", + (const char *) strerror(errno)); return -1; } @@ -247,7 +208,7 @@ int Listener_thread::create_tcp_socket() { im_bind_addr= (ulong) inet_addr(Options::Main::bind_address); - if (im_bind_addr == INADDR_NONE) + if (im_bind_addr == (ulong) INADDR_NONE) im_bind_addr= htonl(INADDR_ANY); } else @@ -265,16 +226,16 @@ int Listener_thread::create_tcp_socket() if (bind(ip_socket, (struct sockaddr *) &ip_socket_address, sizeof(ip_socket_address))) { - log_error("Listener_thread: bind(ip socket) failed, '%s'", - strerror(errno)); + log_error("Listener: bind(ip socket) failed: %s.", + (const char *) strerror(errno)); close(ip_socket); return -1; } if (listen(ip_socket, LISTEN_BACK_LOG_SIZE)) { - log_error("Listener_thread: listen(ip socket) failed, %s", - strerror(errno)); + log_error("Listener: listen(ip socket) failed: %s.", + (const char *) strerror(errno)); close(ip_socket); return -1; } @@ -287,19 +248,20 @@ int Listener_thread::create_tcp_socket() FD_SET(ip_socket, &read_fds); sockets[num_sockets++]= ip_socket; - log_info("accepting connections on ip socket (port: %d)", (int) im_port); + log_info("Listener: accepting connections on ip socket (port: %d)...", + (int) im_port); return 0; } #ifndef __WIN__ -int Listener_thread:: +int Listener:: create_unix_socket(struct sockaddr_un &unix_socket_address) { int unix_socket= socket(AF_UNIX, SOCK_STREAM, 0); if (unix_socket == INVALID_SOCKET) { - log_error("Listener_thead: socket(AF_UNIX) failed, %s", - strerror(errno)); + log_error("Listener: socket(AF_UNIX) failed: %s.", + (const char *) strerror(errno)); return -1; } @@ -318,9 +280,9 @@ create_unix_socket(struct sockaddr_un &unix_socket_address) if (bind(unix_socket, (struct sockaddr *) &unix_socket_address, sizeof(unix_socket_address))) { - log_error("Listener_thread: bind(unix socket) failed, " - "socket file name is '%s', error '%s'", - unix_socket_address.sun_path, strerror(errno)); + log_error("Listener: bind(unix socket) failed for '%s': %s.", + (const char *) unix_socket_address.sun_path, + (const char *) strerror(errno)); close(unix_socket); return -1; } @@ -329,8 +291,8 @@ create_unix_socket(struct sockaddr_un &unix_socket_address) if (listen(unix_socket, LISTEN_BACK_LOG_SIZE)) { - log_error("Listener_thread: listen(unix socket) failed, %s", - strerror(errno)); + log_error("Listener: listen(unix socket) failed: %s.", + (const char *) strerror(errno)); close(unix_socket); return -1; } @@ -341,8 +303,8 @@ create_unix_socket(struct sockaddr_un &unix_socket_address) /* make sure that instances won't be listening our sockets */ set_no_inherit(unix_socket); - log_info("accepting connections on unix socket '%s'", - unix_socket_address.sun_path); + log_info("Listener: accepting connections on unix socket '%s'...", + (const char *) unix_socket_address.sun_path); sockets[num_sockets++]= unix_socket; FD_SET(unix_socket, &read_fds); return 0; @@ -352,51 +314,21 @@ create_unix_socket(struct sockaddr_un &unix_socket_address) /* Create new mysql connection. Created thread is responsible for deletion of - the Mysql_connection_thread_args and Vio instances passed to it. - SYNOPSYS + the Mysql_connection and Vio instances passed to it. + SYNOPSIS handle_new_mysql_connection() */ -void Listener_thread::handle_new_mysql_connection(Vio *vio) +void Listener::handle_new_mysql_connection(struct st_vio *vio) { - if (Mysql_connection_thread_args *mysql_thread_args= - new Mysql_connection_thread_args(vio, thread_registry, user_map, - ++total_connection_count, - instance_map) - ) + Mysql_connection *mysql_connection= + new Mysql_connection(thread_registry, user_map, + vio, ++total_connection_count); + if (mysql_connection == NULL || mysql_connection->start(Thread::DETACHED)) { - /* - Initialize thread attributes to create detached thread; it seems - easier to do it ad-hoc than have a global variable for attributes. - */ - pthread_t mysql_thd_id; - pthread_attr_t mysql_thd_attr; - pthread_attr_init(&mysql_thd_attr); - pthread_attr_setdetachstate(&mysql_thd_attr, PTHREAD_CREATE_DETACHED); - if (set_stacksize_n_create_thread(&mysql_thd_id, &mysql_thd_attr, - mysql_connection, mysql_thread_args)) - { - delete mysql_thread_args; - vio_delete(vio); - log_error("handle_one_mysql_connection():" - "set_stacksize_n_create_thread(mysql) failed"); - } - pthread_attr_destroy(&mysql_thd_attr); - } - else + log_error("Listener: can not start connection handler."); + delete mysql_connection; vio_delete(vio); + } + /* The connection will delete itself when the thread is finished */ } - - -pthread_handler_t listener(void *arg) -{ - Listener_thread_args *args= (Listener_thread_args *) arg; - Listener_thread listener(*args); - listener.run(); - /* - args is a stack variable because listener thread lives as long as the - manager process itself - */ - return 0; -} - diff --git a/server-tools/instance-manager/listener.h b/server-tools/instance-manager/listener.h index c28ab0649d7..811744f8ea6 100644 --- a/server-tools/instance-manager/listener.h +++ b/server-tools/instance-manager/listener.h @@ -16,33 +16,46 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <my_global.h> -#include <my_pthread.h> +#include "thread_registry.h" #if defined(__GNUC__) && defined(USE_PRAGMA_INTERFACE) #pragma interface #endif - -pthread_handler_t listener(void *arg); - class Thread_registry; class User_map; -class Instance_map; -struct Listener_thread_args +/** + Listener - a thread listening on sockets and spawning + connection threads. +*/ + +class Listener: public Thread { - Thread_registry &thread_registry; - const User_map &user_map; - Instance_map &instance_map; - - Listener_thread_args(Thread_registry &thread_registry_arg, - const User_map &user_map_arg, - Instance_map &instance_map_arg) : - thread_registry(thread_registry_arg) - ,user_map(user_map_arg) - ,instance_map(instance_map_arg) - {} +public: + Listener(Thread_registry *thread_registry_arg, User_map *user_map_arg); + +protected: + virtual void run(); + +private: + static const int LISTEN_BACK_LOG_SIZE= 5; /* standard backlog size */ + +private: + Thread_info thread_info; + Thread_registry *thread_registry; + User_map *user_map; + + ulong total_connection_count; + + int sockets[2]; + int num_sockets; + fd_set read_fds; + +private: + void handle_new_mysql_connection(struct st_vio *vio); + int create_tcp_socket(); + int create_unix_socket(struct sockaddr_un &unix_socket_address); }; #endif // INCLUDES_MYSQL_INSTANCE_MANAGER_LISTENER_H diff --git a/server-tools/instance-manager/log.cc b/server-tools/instance-manager/log.cc index 7214cde7193..7ff45a15432 100644 --- a/server-tools/instance-manager/log.cc +++ b/server-tools/instance-manager/log.cc @@ -33,11 +33,12 @@ /* Format log entry and write it to the given stream. - SYNOPSYS + SYNOPSIS log() */ -static inline void log(FILE *file, const char *format, va_list args) +static void log(FILE *file,const char *level_tag, const char *format, + va_list args) { /* log() should be thread-safe; it implies that we either call fprintf() @@ -53,15 +54,16 @@ static inline void log(FILE *file, const char *format, va_list args) localtime_r(&now, &bd_time); char buff_date[128]; - sprintf(buff_date, "[%d/%lu] [%02d/%02d/%02d %02d:%02d:%02d] ", + sprintf(buff_date, "[%d/%lu] [%02d/%02d/%02d %02d:%02d:%02d] [%s] ", (int) getpid(), (unsigned long) pthread_self(), - bd_time.tm_year % 100, - bd_time.tm_mon + 1, - bd_time.tm_mday, - bd_time.tm_hour, - bd_time.tm_min, - bd_time.tm_sec); + (int) bd_time.tm_year % 100, + (int) bd_time.tm_mon + 1, + (int) bd_time.tm_mday, + (int) bd_time.tm_hour, + (int) bd_time.tm_min, + (int) bd_time.tm_sec, + (const char *) level_tag); /* Format the message */ char buff_stack[256]; @@ -109,57 +111,73 @@ static inline void log(FILE *file, const char *format, va_list args) /* don't fflush() the file: buffering strategy is set in log_init() */ } +/************************************************************************** + Logging: implementation of public interface. +**************************************************************************/ -void log_error(const char *format, ...) -{ - va_list args; - va_start(args, format); - log(stderr, format, args); - va_end(args); -} +/* + The function initializes logging sub-system. + SYNOPSIS + log_init() +*/ -void log_info(const char *format, ...) +void log_init() { - va_list args; - va_start(args, format); - log(stdout, format, args); - va_end(args); + /* + stderr is unbuffered by default; there is no good of line buffering, + as all logging is performed linewise - so remove buffering from stdout + also + */ + setbuf(stdout, 0); } -/* TODO: rewrite with buffering print */ -void print_info(const char *format, ...) + +/* + The function is intended to log error messages. It precedes a message + with date, time and [ERROR] tag and print it to the stderr. + + SYNOPSIS + log_error() + format [IN] format string + ... [IN] arguments to format +*/ + +void log_error(const char *format, ...) { va_list args; va_start(args, format); - vfprintf(stdout, format, args); + log(stderr, "ERROR", format, args); va_end(args); } -void print_error(const char *format, ...) + +/* + The function is intended to log information messages. It precedes + a message with date, time and [INFO] tag and print it to the stdout. + + SYNOPSIS + log_error() + format [IN] format string + ... [IN] arguments to format +*/ + +void log_info(const char *format, ...) { va_list args; va_start(args, format); - vfprintf(stderr, format, args); + log(stdout, "INFO", format, args); va_end(args); } /* - log_init() - RETURN VALUE - 0 ok - !0 error -*/ + The function prints information to the error log and eixt(1). -void log_init() -{ - /* - stderr is unbuffered by default; there is no good of line buffering, - as all logging is performed linewise - so remove buffering from stdout - also - */ - setbuf(stdout, 0); -} + SYNOPSIS + die() + format [IN] format string + ... [IN] arguments to format +*/ void die(const char *format, ...) { diff --git a/server-tools/instance-manager/log.h b/server-tools/instance-manager/log.h index 825d7515513..9c47dbe04f5 100644 --- a/server-tools/instance-manager/log.h +++ b/server-tools/instance-manager/log.h @@ -19,20 +19,23 @@ /* Logging facilities. - Two logging streams are supported: error log and info log. Additionally - libdbug may be used for debug information output. + Two logging streams are supported: error log and info log. + Additionally libdbug may be used for debug information output. + ANSI C buffered I/O is used to perform logging. + Logging is performed via stdout/stder, so one can reopen them to point to - ordinary files. To initialize loggin environment log_init() must be called. + ordinary files. To initialize logging environment log_init() must be called. Rationale: - no MYSQL_LOG as it has BIN mode, and not easy to fetch from sql_class.h - no constructors/desctructors to make logging available all the time - Function names are subject to change. */ -/* Precede error message with date and time and print it to the stdout */ +void log_init(); + + void log_info(const char *format, ...) #ifdef __GNUC__ __attribute__ ((format(printf, 1, 2))) @@ -40,7 +43,6 @@ void log_info(const char *format, ...) ; -/* Precede error message with date and time and print it to the stderr */ void log_error(const char *format, ...) #ifdef __GNUC__ __attribute__ ((format (printf, 1, 2))) @@ -48,30 +50,6 @@ void log_error(const char *format, ...) ; -/* - Now this is simple catchouts for printf (no date/time is logged), to be - able to replace underlying streams in future. -*/ - -void print_info(const char *format, ...) -#ifdef __GNUC__ - __attribute__ ((format (printf, 1, 2))) -#endif - ; - - -void print_error(const char *format, ...) -#ifdef __GNUC__ - __attribute__ ((format (printf, 1, 2))) -#endif - ; - -/* initialize logs */ -void log_init(); - - -/* print information to the error log and eixt(1) */ - void die(const char *format, ...) #ifdef __GNUC__ __attribute__ ((format (printf, 1, 2))) diff --git a/server-tools/instance-manager/manager.cc b/server-tools/instance-manager/manager.cc index 4bd298eedec..a002902bd56 100644 --- a/server-tools/instance-manager/manager.cc +++ b/server-tools/instance-manager/manager.cc @@ -37,33 +37,6 @@ #include "user_map.h" -int create_pid_file(const char *pid_file_name, int pid) -{ - FILE *pid_file; - - if (!(pid_file= my_fopen(pid_file_name, O_WRONLY | O_CREAT | O_BINARY, - MYF(0)))) - { - log_error("Error: can not create pid file '%s': %s (errno: %d)", - (const char *) pid_file_name, - (const char *) strerror(errno), - (int) errno); - return 1; - } - - if (fprintf(pid_file, "%d\n", (int) pid) <= 0) - { - log_error("Error: can not write to pid file '%s': %s (errno: %d)", - (const char *) pid_file_name, - (const char *) strerror(errno), - (int) errno); - return 1; - } - - my_fclose(pid_file, MYF(0)); - - return 0; -} #ifndef __WIN__ void set_signals(sigset_t *mask) @@ -120,19 +93,79 @@ int my_sigwait(const sigset_t *set, int *sig) #endif -void stop_all(Guardian_thread *guardian, Thread_registry *registry) +/********************************************************************** + Implementation of checking the actual thread model. +***********************************************************************/ + +namespace { /* no-indent */ + +class ThreadModelChecker: public Thread +{ +public: + ThreadModelChecker() + :main_pid(getpid()) + { } + +public: + inline bool is_linux_threads() const + { + return linux_threads; + } + +protected: + virtual void run() + { + linux_threads= main_pid != getpid(); + } + +private: + pid_t main_pid; + bool linux_threads; +}; + +bool check_if_linux_threads(bool *linux_threads) +{ + ThreadModelChecker checker; + + if (checker.start() || checker.join()) + return TRUE; + + *linux_threads= checker.is_linux_threads(); + + return FALSE; +} + +} + + +/********************************************************************** + Manager implementation +***********************************************************************/ + +Guardian *Manager::p_guardian; +Instance_map *Manager::p_instance_map; +Thread_registry *Manager::p_thread_registry; +User_map *Manager::p_user_map; + +#ifndef __WIN__ +bool Manager::linux_threads; +#endif // __WIN__ + + +void Manager::stop_all_threads() { /* Let guardian thread know that it should break it's processing cycle, once it wakes up. */ - guardian->request_shutdown(); + p_guardian->request_shutdown(); /* wake guardian */ - pthread_cond_signal(&guardian->COND_guardian); + pthread_cond_signal(&p_guardian->COND_guardian); /* stop all threads */ - registry->deliver_shutdown(); + p_thread_registry->deliver_shutdown(); } + /* manager - entry point to the main instance manager process: start listener thread, write pid file and enter into signal handling. @@ -142,11 +175,24 @@ void stop_all(Guardian_thread *guardian, Thread_registry *registry) TODO: how about returning error status. */ -void manager() +int Manager::main() { int err_code; + int rc= 1; const char *err_msg; bool shutdown_complete= FALSE; + pid_t manager_pid= getpid(); + +#ifndef __WIN__ + if (check_if_linux_threads(&linux_threads)) + { + log_error("Can not determine thread model."); + return 1; + } + + log_info("Detected threads model: %s.", + (const char *) (linux_threads ? "LINUX threads" : "POSIX threads")); +#endif // __WIN__ Thread_registry thread_registry; /* @@ -156,31 +202,31 @@ void manager() */ User_map user_map; - Instance_map instance_map(Options::Main::default_mysqld_path, - thread_registry); - Guardian_thread guardian_thread(thread_registry, - &instance_map, - Options::Main::monitoring_interval); + Instance_map instance_map; + Guardian guardian(&thread_registry, &instance_map, + Options::Main::monitoring_interval); - Listener_thread_args listener_args(thread_registry, user_map, instance_map); + Listener listener(&thread_registry, &user_map); - manager_pid= getpid(); - instance_map.guardian= &guardian_thread; + p_instance_map= &instance_map; + p_guardian= instance_map.guardian= &guardian; + p_thread_registry= &thread_registry; + p_user_map= &user_map; /* Initialize instance map. */ if (instance_map.init()) { - log_error("Error: can not initialize instance list: out of memory."); - return; + log_error("Can not initialize instance list: out of memory."); + return 1; } /* Initialize user map and load password file. */ if (user_map.init()) { - log_error("Error: can not initialize user list: out of memory."); - return; + log_error("Can not initialize user list: out of memory."); + return 1; } if ((err_code= user_map.load(Options::Main::password_file_name, &err_msg))) @@ -193,13 +239,13 @@ void manager() mysqld_safe-compatible mode. Continue, but complain in log. */ - log_error("Warning: password file does not exist, " - "nobody will be able to connect to Instance Manager."); + log_info("Warning: password file does not exist, " + "nobody will be able to connect to Instance Manager."); } else { - log_error("Error: %s.", (const char *) err_msg); - return; + log_error("%s.", (const char *) err_msg); + return 1; } } @@ -210,7 +256,7 @@ void manager() (int) manager_pid); if (create_pid_file(Options::Main::pid_file_name, manager_pid)) - return; /* necessary logging has been already done. */ + return 1; /* necessary logging has been already done. */ /* Initialize signals and alarm-infrastructure. @@ -218,49 +264,36 @@ void manager() NOTE: To work nicely with LinuxThreads, the signal thread is the first thread in the process. - NOTE: - After init_thr_alarm() call it's possible to call thr_alarm() (from - different threads), that results in sending ALARM signal to the alarm - thread (which can be the main thread). That signal can interrupt - blocking calls. - - In other words, a blocking call can be interrupted in the main thread - after init_thr_alarm(). + NOTE: After init_thr_alarm() call it's possible to call thr_alarm() + (from different threads), that results in sending ALARM signal to the + alarm thread (which can be the main thread). That signal can interrupt + blocking calls. In other words, a blocking call can be interrupted in + the main thread after init_thr_alarm(). */ sigset_t mask; set_signals(&mask); - /* create guardian thread */ + /* + Create the guardian thread. The newly started thread will block until + we actually load instances. + + NOTE: Guardian should be shutdown first. Only then all other threads + can be stopped. This should be done in this order because the guardian + is responsible for shutting down all the guarded instances, and this + is a long operation. + + NOTE: Guardian uses thr_alarm() when detects the current state of an + instance (is_running()), but this does not interfere with + flush_instances() call later in the code, because until + flush_instances() completes in the main thread, Guardian thread is not + permitted to process instances. And before flush_instances() has + completed, there are no instances to guard. + */ + if (guardian.start(Thread::DETACHED)) { - pthread_t guardian_thd_id; - pthread_attr_t guardian_thd_attr; - int rc; - - /* - NOTE: Guardian should be shutdown first. Only then all other threads - need to be stopped. This should be done, as guardian is responsible - for shutting down the instances, and this is a long operation. - - NOTE: Guardian uses thr_alarm() when detects current state of - instances (is_running()), but it is not interfere with - flush_instances() later in the code, because until flush_instances() - complete in the main thread, Guardian thread is not permitted to - process instances. And before flush_instances() there is no instances - to proceed. - */ - - pthread_attr_init(&guardian_thd_attr); - pthread_attr_setdetachstate(&guardian_thd_attr, PTHREAD_CREATE_DETACHED); - rc= set_stacksize_n_create_thread(&guardian_thd_id, &guardian_thd_attr, - guardian, &guardian_thread); - pthread_attr_destroy(&guardian_thd_attr); - if (rc) - { - log_error("manager(): set_stacksize_n_create_thread(guardian) failed"); - goto err; - } - + log_error("Can not start Guardian thread."); + goto err; } /* Load instances. */ @@ -276,40 +309,30 @@ void manager() if (flush_instances_status) { - log_error("Cannot init instances repository. This might be caused by " - "the wrong config file options. For instance, missing mysqld " - "binary. Aborting."); - stop_all(&guardian_thread, &thread_registry); + log_error("Can not init instances repository."); + stop_all_threads(); goto err; } } - /* create the listener */ + /* Initialize the Listener. */ + + if (listener.start(Thread::DETACHED)) { - pthread_t listener_thd_id; - pthread_attr_t listener_thd_attr; - int rc; - - pthread_attr_init(&listener_thd_attr); - pthread_attr_setdetachstate(&listener_thd_attr, PTHREAD_CREATE_DETACHED); - rc= set_stacksize_n_create_thread(&listener_thd_id, &listener_thd_attr, - listener, &listener_args); - pthread_attr_destroy(&listener_thd_attr); - if (rc) - { - log_error("manager(): set_stacksize_n_create_thread(listener) failed"); - stop_all(&guardian_thread, &thread_registry); - goto err; - } + log_error("Can not start Listener thread."); + stop_all_threads(); + goto err; } /* After the list of guarded instances have been initialized, Guardian should start them. */ - pthread_cond_signal(&guardian_thread.COND_guardian); + pthread_cond_signal(&guardian.COND_guardian); - log_info("Main loop: started."); + /* Main loop. */ + + log_info("Manager: started."); while (!shutdown_complete) { @@ -319,7 +342,7 @@ void manager() if ((status= my_sigwait(&mask, &signo)) != 0) { log_error("sigwait() failed"); - stop_all(&guardian_thread, &thread_registry); + stop_all_threads(); goto err; } @@ -328,8 +351,8 @@ void manager() - we are waiting for SIGINT, SIGTERM -- signals that mean we should shutdown; - as shutdown signal is caught, we stop Guardian thread (by calling - Guardian_thread::request_shutdown()); - - as Guardian_thread is stopped, it sends SIGTERM to this thread + Guardian::request_shutdown()); + - as Guardian is stopped, it sends SIGTERM to this thread (by calling Thread_registry::request_shutdown()), so that the my_sigwait() above returns; - as we catch the second SIGTERM, we send signals to all threads @@ -345,7 +368,7 @@ void manager() Bug #14164 IM tests fail on MacOS X (powermacg5) */ #ifdef IGNORE_SIGHUP_SIGQUIT - if ( SIGHUP == signo ) + if (SIGHUP == signo) continue; #endif if (THR_SERVER_ALARM == signo) @@ -353,12 +376,12 @@ void manager() else #endif { - log_info("Main loop: got shutdown signal."); + log_info("Manager: got shutdown signal."); - if (!guardian_thread.is_stopped()) + if (!guardian.is_stopped()) { - guardian_thread.request_shutdown(); - pthread_cond_signal(&guardian_thread.COND_guardian); + guardian.request_shutdown(); + pthread_cond_signal(&guardian.COND_guardian); } else { @@ -368,7 +391,9 @@ void manager() } } - log_info("Main loop: finished."); + log_info("Manager: finished."); + + rc= 0; err: /* delete the pid file */ @@ -379,4 +404,5 @@ err: end_thr_alarm(1); /* don't pthread_exit to kill all threads who did not shut down in time */ #endif + return rc; } diff --git a/server-tools/instance-manager/manager.h b/server-tools/instance-manager/manager.h index 7aa4b3e1a96..a77809cca6d 100644 --- a/server-tools/instance-manager/manager.h +++ b/server-tools/instance-manager/manager.h @@ -16,8 +16,49 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -void manager(); +#if defined(__GNUC__) && defined(USE_PRAGMA_INTERFACE) +#pragma interface +#endif +#include <my_global.h> -int create_pid_file(const char *pid_file_name, int pid); +class Guardian; +class Instance_map; +class Thread_registry; +class User_map; + +class Manager +{ +public: + static int main(); + /** + These methods return a non-zero value only for the duration + of main(). + */ + static Instance_map *get_instance_map() { return p_instance_map; } + static Guardian *get_guardian() { return p_guardian; } + static Thread_registry *get_thread_registry() { return p_thread_registry; } + static User_map *get_user_map() { return p_user_map; } + +#ifndef __WIN__ + static bool is_linux_threads() { return linux_threads; } +#endif // __WIN__ + +private: + static void stop_all_threads(); + +private: + static Guardian *p_guardian; + static Instance_map *p_instance_map; + static Thread_registry *p_thread_registry; + static User_map *p_user_map; + +#ifndef __WIN__ + /* + This flag is set if Instance Manager is running on the system using + LinuxThreads. + */ + static bool linux_threads; +#endif // __WIN__ +}; #endif // INCLUDES_MYSQL_INSTANCE_MANAGER_MANAGER_H diff --git a/server-tools/instance-manager/mysql_connection.cc b/server-tools/instance-manager/mysql_connection.cc index 82b24491903..952bdcd0e73 100644 --- a/server-tools/instance-manager/mysql_connection.cc +++ b/server-tools/instance-manager/mysql_connection.cc @@ -23,7 +23,6 @@ #include <m_string.h> #include <m_string.h> #include <my_global.h> -#include <mysql_com.h> #include <mysql.h> #include <my_sys.h> #include <violite.h> @@ -40,66 +39,15 @@ #include "user_map.h" -Mysql_connection_thread_args::Mysql_connection_thread_args( - struct st_vio *vio_arg, - Thread_registry &thread_registry_arg, - const User_map &user_map_arg, - ulong connection_id_arg, - Instance_map &instance_map_arg) : - vio(vio_arg) - ,thread_registry(thread_registry_arg) - ,user_map(user_map_arg) - ,connection_id(connection_id_arg) - ,instance_map(instance_map_arg) - {} - -/* - MySQL connection - handle one connection with mysql command line client - See also comments in mysqlmanager.cc to picture general Instance Manager - architecture. - We use conventional technique to work with classes without exceptions: - class acquires all vital resource in init(); Thus if init() succeed, - a user must call cleanup(). All other methods are valid only between - init() and cleanup(). -*/ - -class Mysql_connection_thread: public Mysql_connection_thread_args -{ -public: - Mysql_connection_thread(const Mysql_connection_thread_args &args); - - int init(); - void cleanup(); - - void run(); - - ~Mysql_connection_thread(); -private: - Thread_info thread_info; - NET net; - struct rand_struct rand_st; - char scramble[SCRAMBLE_LENGTH + 1]; - uint status; - ulong client_capabilities; -private: - /* Names are conventionally the same as in mysqld */ - int check_connection(); - int do_command(); - int dispatch_command(enum enum_server_command command, - const char *text, uint len); -}; - - -Mysql_connection_thread::Mysql_connection_thread( - const Mysql_connection_thread_args &args) : - Mysql_connection_thread_args(args.vio, - args.thread_registry, - args.user_map, - args.connection_id, - args.instance_map) - ,thread_info(pthread_self(), TRUE) +Mysql_connection::Mysql_connection(Thread_registry *thread_registry_arg, + User_map *user_map_arg, + struct st_vio *vio_arg, ulong + connection_id_arg) + :vio(vio_arg), + connection_id(connection_id_arg), + thread_registry(thread_registry_arg), + user_map(user_map_arg) { - thread_registry.register_thread(&thread_info); } @@ -129,68 +77,73 @@ C_MODE_END This function is complementary to cleanup(). */ -int Mysql_connection_thread::init() +bool Mysql_connection::init() { /* Allocate buffers for network I/O */ if (my_net_init(&net, vio)) - return 1; + return TRUE; + net.return_status= &status; + /* Initialize random number generator */ { ulong seed1= (ulong) &rand_st + rand(); ulong seed2= (ulong) rand() + time(0); randominit(&rand_st, seed1, seed2); } + /* Fill scramble - server's random message used for handshake */ create_random_string(scramble, SCRAMBLE_LENGTH, &rand_st); + /* We don't support transactions, every query is atomic */ status= SERVER_STATUS_AUTOCOMMIT; - return 0; + + thread_registry->register_thread(&thread_info); + + return FALSE; } -void Mysql_connection_thread::cleanup() +void Mysql_connection::cleanup() { net_end(&net); + thread_registry->unregister_thread(&thread_info); } -Mysql_connection_thread::~Mysql_connection_thread() +Mysql_connection::~Mysql_connection() { /* vio_delete closes the socket if necessary */ vio_delete(vio); - thread_registry.unregister_thread(&thread_info); } -void Mysql_connection_thread::run() +void Mysql_connection::main() { - log_info("accepted mysql connection %lu", (unsigned long) connection_id); - - my_thread_init(); + log_info("Connection %lu: accepted.", (unsigned long) connection_id); if (check_connection()) { - my_thread_end(); + log_info("Connection %lu: failed to authorize the user.", + (unsigned long) connection_id); + return; } - log_info("connection %lu is checked successfully", + log_info("Connection %lu: the user was authorized successfully.", (unsigned long) connection_id); vio_keepalive(vio, TRUE); - while (!net.error && net.vio && !thread_registry.is_shutdown()) + while (!net.error && net.vio && !thread_registry->is_shutdown()) { if (do_command()) break; } - - my_thread_end(); } -int Mysql_connection_thread::check_connection() +int Mysql_connection::check_connection() { ulong pkt_len=0; // to hold client reply length @@ -279,7 +232,7 @@ int Mysql_connection_thread::check_connection() net_send_error(&net, ER_ACCESS_DENIED_ERROR); return 1; } - if (user_map.authenticate(&user_name, password, scramble)) + if (user_map->authenticate(&user_name, password, scramble)) { net_send_error(&net, ER_ACCESS_DENIED_ERROR); return 1; @@ -289,7 +242,7 @@ int Mysql_connection_thread::check_connection() } -int Mysql_connection_thread::do_command() +int Mysql_connection::do_command() { char *packet; ulong packet_length; @@ -302,7 +255,7 @@ int Mysql_connection_thread::do_command() /* Check if we can continue without closing the connection */ if (net.error != 3) // what is 3 - find out return 1; - if (thread_registry.is_shutdown()) + if (thread_registry->is_shutdown()) return 1; net_send_error(&net, net.last_errno); net.error= 0; @@ -310,83 +263,101 @@ int Mysql_connection_thread::do_command() } else { - if (thread_registry.is_shutdown()) + if (thread_registry->is_shutdown()) return 1; packet= (char*) net.read_pos; enum enum_server_command command= (enum enum_server_command) (uchar) *packet; - log_info("connection %lu: packet_length=%lu, command=%d", - (int) connection_id, (int) packet_length, (int) command); - return dispatch_command(command, packet + 1, packet_length - 1); + log_info("Connection %lu: received packet (length: %lu; command: %d).", + (unsigned long) connection_id, + (unsigned long) packet_length, + (int) command); + + return dispatch_command(command, packet + 1); } } -int Mysql_connection_thread::dispatch_command(enum enum_server_command command, - const char *packet, uint len) +int Mysql_connection::dispatch_command(enum enum_server_command command, + const char *packet) { switch (command) { case COM_QUIT: // client exit - log_info("query for connection %lu received quit command", + log_info("Connection %lu: received QUIT command.", (unsigned long) connection_id); return 1; + case COM_PING: - log_info("query for connection %lu received ping command", + log_info("Connection %lu: received PING command.", (unsigned long) connection_id); net_send_ok(&net, connection_id, NULL); - break; + return 0; + case COM_QUERY: { - log_info("query for connection %lu : ----\n%s\n-------------------------", - (int) connection_id, + log_info("Connection %lu: received QUERY command: '%s'.", + (unsigned long) connection_id, (const char *) packet); - if (Command *command= parse_command(&instance_map, packet)) + + if (Command *command= parse_command(packet)) { int res= 0; - log_info("query for connection %lu successfully parsed", + + log_info("Connection %lu: query parsed successfully.", (unsigned long) connection_id); + res= command->execute(&net, connection_id); delete command; + if (!res) - log_info("query for connection %lu executed ok", + { + log_info("Connection %lu: query executed successfully", (unsigned long) connection_id); + } else { - log_info("query for connection %lu executed err=%d", - (unsigned long) connection_id, (int) res); + log_info("Connection %lu: can not execute query (error: %d).", + (unsigned long) connection_id, + (int) res); + net_send_error(&net, res); - return 0; } } else { + log_error("Connection %lu: can not parse query: out ot resources.", + (unsigned long) connection_id); + net_send_error(&net,ER_OUT_OF_RESOURCES); - return 0; } - break; + + return 0; } + default: - log_info("query for connection %lu received unknown command", - (unsigned long) connection_id); + log_info("Connection %lu: received unsupported command (%d).", + (unsigned long) connection_id, + (int) command); + net_send_error(&net, ER_UNKNOWN_COM_ERROR); - break; + return 0; } - return 0; + + return 0; /* Just to make compiler happy. */ } -pthread_handler_t mysql_connection(void *arg) +void Mysql_connection::run() { - Mysql_connection_thread_args *args= (Mysql_connection_thread_args *) arg; - Mysql_connection_thread mysql_connection_thread(*args); - delete args; - if (mysql_connection_thread.init()) - log_info("mysql_connection(): error initializing thread"); + if (init()) + log_error("Connection %lu: can not init handler.", + (unsigned long) connection_id); else { - mysql_connection_thread.run(); - mysql_connection_thread.cleanup(); + main(); + cleanup(); } - return 0; + + delete this; } /* diff --git a/server-tools/instance-manager/mysql_connection.h b/server-tools/instance-manager/mysql_connection.h index 3496cc05815..ef58d921637 100644 --- a/server-tools/instance-manager/mysql_connection.h +++ b/server-tools/instance-manager/mysql_connection.h @@ -16,33 +16,59 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <my_global.h> -#include <my_pthread.h> +#include "thread_registry.h" +#include <mysql_com.h> #if defined(__GNUC__) && defined(USE_PRAGMA_INTERFACE) #pragma interface #endif -pthread_handler_t mysql_connection(void *arg); - -class Thread_registry; -class User_map; -class Instance_map; struct st_vio; +class User_map; -struct Mysql_connection_thread_args +/* + MySQL connection - handle one connection with mysql command line client + See also comments in mysqlmanager.cc to picture general Instance Manager + architecture. + We use conventional technique to work with classes without exceptions: + class acquires all vital resource in init(); Thus if init() succeed, + a user must call cleanup(). All other methods are valid only between + init() and cleanup(). +*/ + +class Mysql_connection: public Thread { +public: + Mysql_connection(Thread_registry *thread_registry_arg, + User_map *user_map_arg, + struct st_vio *vio_arg, + ulong connection_id_arg); + virtual ~Mysql_connection(); + +protected: + virtual void run(); + +private: struct st_vio *vio; - Thread_registry &thread_registry; - const User_map &user_map; ulong connection_id; - Instance_map &instance_map; + Thread_info thread_info; + Thread_registry *thread_registry; + User_map *user_map; + NET net; + struct rand_struct rand_st; + char scramble[SCRAMBLE_LENGTH + 1]; + uint status; + ulong client_capabilities; +private: + /* The main loop implementation triad */ + bool init(); + void main(); + void cleanup(); - Mysql_connection_thread_args(struct st_vio *vio_arg, - Thread_registry &thread_registry_arg, - const User_map &user_map_arg, - ulong connection_id_arg, - Instance_map &instance_map_arg); + /* Names are conventionally the same as in mysqld */ + int check_connection(); + int do_command(); + int dispatch_command(enum enum_server_command command, const char *text); }; #endif // INCLUDES_MYSQL_INSTANCE_MANAGER_MYSQL_CONNECTION_H diff --git a/server-tools/instance-manager/mysqlmanager.cc b/server-tools/instance-manager/mysqlmanager.cc index 177b761b419..8ee8321fffc 100644 --- a/server-tools/instance-manager/mysqlmanager.cc +++ b/server-tools/instance-manager/mysqlmanager.cc @@ -31,6 +31,7 @@ #include "log.h" #include "manager.h" #include "options.h" +#include "priv.h" #include "user_management_commands.h" #ifdef __WIN__ @@ -117,7 +118,7 @@ int main(int argc, char *argv[]) angel(); } - manager(); + (void) Manager::main(); /* ignore the return value for now */ #else @@ -131,7 +132,7 @@ int main(int argc, char *argv[]) } else { - manager(); + (void) Manager::main(); /* ignore the return value for now */ } #endif @@ -190,7 +191,8 @@ static struct passwd *check_user(const char *user) return user_info; err: - log_error("Fatal error: Can't change to run as user '%s' ; Please check that the user exists!\n", user); + log_error("Can not start under user '%s'.", + (const char *) user); return NULL; } @@ -231,7 +233,7 @@ static void init_environment(char *progname) #ifndef __WIN__ /* Become a UNIX service - SYNOPSYS + SYNOPSIS daemonize() */ @@ -384,11 +386,10 @@ spawn: } /* mysqlmanager successfully exited, let's silently evaporate - If we return to main we fall into the manager() function, so let's - simply exit(). + If we return to main we will fall into the manager functionality, + so let's simply exit(). */ exit(0); } } - #endif diff --git a/server-tools/instance-manager/parse.cc b/server-tools/instance-manager/parse.cc index 048f7983b32..e81320584ea 100644 --- a/server-tools/instance-manager/parse.cc +++ b/server-tools/instance-manager/parse.cc @@ -269,12 +269,11 @@ void skip_spaces(const char **text) } -Command *parse_command(Instance_map *map, const char *text) +Command *parse_command(const char *text) { uint word_len; LEX_STRING instance_name; Command *command= 0; - const char *saved_text= text; Token tok1= shift_token(&text, &word_len); @@ -294,7 +293,7 @@ Command *parse_command(Instance_map *map, const char *text) if (tok1 == TOK_CREATE) { - Create_instance *cmd= new Create_instance(map, &instance_name); + Create_instance *cmd= new Create_instance(&instance_name); if (!cmd) return NULL; /* Report ER_OUT_OF_RESOURCES. */ @@ -317,16 +316,16 @@ Command *parse_command(Instance_map *map, const char *text) switch (tok1) { case TOK_START: - command= new Start_instance(map, &instance_name); + command= new Start_instance(&instance_name); break; case TOK_STOP: - command= new Stop_instance(map, &instance_name); + command= new Stop_instance(&instance_name); break; case TOK_CREATE: ; /* command already initialized. */ break; case TOK_DROP: - command= new Drop_instance(map, &instance_name); + command= new Drop_instance(&instance_name); break; default: /* this is impossible, but nevertheless... */ DBUG_ASSERT(0); @@ -340,7 +339,7 @@ Command *parse_command(Instance_map *map, const char *text) if (word_len) goto syntax_error; - command= new Flush_instances(map); + command= new Flush_instances(); break; case TOK_UNSET: case TOK_SET: @@ -348,9 +347,9 @@ Command *parse_command(Instance_map *map, const char *text) Abstract_option_cmd *cmd; if (tok1 == TOK_SET) - cmd= new Set_option(map); + cmd= new Set_option(); else - cmd= new Unset_option(map); + cmd= new Unset_option(); if (!cmd) return NULL; /* Report ER_OUT_OF_RESOURCES. */ @@ -371,7 +370,7 @@ Command *parse_command(Instance_map *map, const char *text) get_word(&text, &word_len, NONSPACE); if (word_len) goto syntax_error; - command= new Show_instances(map); + command= new Show_instances(); break; case TOK_INSTANCE: switch (Token tok2= shift_token(&text, &word_len)) { @@ -385,9 +384,9 @@ Command *parse_command(Instance_map *map, const char *text) if (word_len) goto syntax_error; if (tok2 == TOK_STATUS) - command= new Show_instance_status(map, &instance_name); + command= new Show_instance_status(&instance_name); else - command= new Show_instance_options(map, &instance_name); + command= new Show_instance_options(&instance_name); break; default: goto syntax_error; @@ -414,7 +413,7 @@ Command *parse_command(Instance_map *map, const char *text) /* check that this is the end of the command */ if (word_len) goto syntax_error; - command= new Show_instance_log_files(map, &instance_name); + command= new Show_instance_log_files(&instance_name); break; case TOK_ERROR: case TOK_GENERAL: @@ -484,7 +483,7 @@ Command *parse_command(Instance_map *map, const char *text) goto syntax_error; } - command= new Show_instance_log(map, &instance_name, + command= new Show_instance_log(&instance_name, log_type, log_size, log_offset); break; default: @@ -504,5 +503,8 @@ Command *parse_command(Instance_map *map, const char *text) syntax_error: command= new Syntax_error(); } + + DBUG_ASSERT(command); + return command; } diff --git a/server-tools/instance-manager/parse.h b/server-tools/instance-manager/parse.h index fd970f54d29..7e954b4918f 100644 --- a/server-tools/instance-manager/parse.h +++ b/server-tools/instance-manager/parse.h @@ -21,7 +21,6 @@ #include <m_string.h> class Command; -class Instance_map; enum Log_type { @@ -30,7 +29,7 @@ enum Log_type IM_LOG_SLOW }; -Command *parse_command(Instance_map *map, const char *text); +Command *parse_command(const char *text); bool parse_option_value(const char *text, uint *text_len, char **value); diff --git a/server-tools/instance-manager/parse_output.cc b/server-tools/instance-manager/parse_output.cc index 643a50625a1..9213de82e1d 100644 --- a/server-tools/instance-manager/parse_output.cc +++ b/server-tools/instance-manager/parse_output.cc @@ -43,7 +43,7 @@ void trim_space(const char **text, uint *word_len) /* Parse output of the given command - SYNOPSYS + SYNOPSIS parse_output_and_get_value() command the command to execue with popen. diff --git a/server-tools/instance-manager/priv.cc b/server-tools/instance-manager/priv.cc index 3dae900d84b..7695b585169 100644 --- a/server-tools/instance-manager/priv.cc +++ b/server-tools/instance-manager/priv.cc @@ -18,26 +18,9 @@ #include <my_global.h> #include <mysql_com.h> +#include <my_sys.h> -#if defined(__ia64__) || defined(__ia64) -/* - We can live with 32K, but reserve 64K. Just to be safe. - On ia64 we need to reserve double of the size. -*/ -#define IM_THREAD_STACK_SIZE (128*1024L) -#else -#define IM_THREAD_STACK_SIZE (64*1024) -#endif - - -/* the pid of the manager process (of the signal thread on the LinuxThreads) */ -pid_t manager_pid; - -/* - This flag is set if mysqlmanager has detected that it is running on the - system using LinuxThreads -*/ -bool linuxthreads; +#include "log.h" /* The following string must be less then 80 characters, as @@ -63,30 +46,32 @@ unsigned long bytes_sent = 0L, bytes_received = 0L; unsigned long mysqld_net_retry_count = 10L; unsigned long open_files_limit; -/* - Change the stack size and start a thread. Return an error if either - pthread_attr_setstacksize or pthread_create fails. - Arguments are the same as for pthread_create(). -*/ -int set_stacksize_n_create_thread(pthread_t *thread, pthread_attr_t *attr, - void *(*start_routine)(void *), void *arg) + +int create_pid_file(const char *pid_file_name, int pid) { - int rc= 0; - -#ifndef __WIN__ -#ifndef PTHREAD_STACK_MIN -#define PTHREAD_STACK_MIN 32768 -#endif - /* - Set stack size to be safe on the platforms with too small - default thread stack. - */ - rc= pthread_attr_setstacksize(attr, - (size_t) (PTHREAD_STACK_MIN + - IM_THREAD_STACK_SIZE)); -#endif - if (!rc) - rc= pthread_create(thread, attr, start_routine, arg); - return rc; + FILE *pid_file; + + if (!(pid_file= my_fopen(pid_file_name, O_WRONLY | O_CREAT | O_BINARY, + MYF(0)))) + { + log_error("Can not create pid file '%s': %s (errno: %d)", + (const char *) pid_file_name, + (const char *) strerror(errno), + (int) errno); + return 1; + } + + if (fprintf(pid_file, "%d\n", (int) pid) <= 0) + { + log_error("Can not write to pid file '%s': %s (errno: %d)", + (const char *) pid_file_name, + (const char *) strerror(errno), + (int) errno); + return 1; + } + + my_fclose(pid_file, MYF(0)); + + return 0; } diff --git a/server-tools/instance-manager/priv.h b/server-tools/instance-manager/priv.h index 0b393c17ac2..4d434213781 100644 --- a/server-tools/instance-manager/priv.h +++ b/server-tools/instance-manager/priv.h @@ -50,17 +50,6 @@ const int MAX_VERSION_LENGTH= 160; const int MAX_INSTANCE_NAME_SIZE= FN_REFLEN; -/* the pid of the manager process (of the signal thread on the LinuxThreads) */ -extern pid_t manager_pid; - -#ifndef __WIN__ -/* - This flag is set if mysqlmanager has detected that it is running on the - system using LinuxThreads -*/ -extern bool linuxthreads; -#endif - extern const LEX_STRING mysqlmanager_version; /* MySQL client-server protocol version: substituted from configure */ @@ -105,8 +94,6 @@ extern unsigned long bytes_sent, bytes_received; extern unsigned long mysqld_net_retry_count; extern unsigned long open_files_limit; - -int set_stacksize_n_create_thread(pthread_t *thread, pthread_attr_t *attr, - void *(*start_routine)(void *), void *arg); +int create_pid_file(const char *pid_file_name, int pid); #endif // INCLUDES_MYSQL_INSTANCE_MANAGER_PRIV_H diff --git a/server-tools/instance-manager/thread_registry.cc b/server-tools/instance-manager/thread_registry.cc index 10370e0981e..5cbf1eb044e 100644 --- a/server-tools/instance-manager/thread_registry.cc +++ b/server-tools/instance-manager/thread_registry.cc @@ -25,8 +25,6 @@ #include <signal.h> -#include "log.h" - #ifndef __WIN__ /* Kick-off signal handler */ @@ -38,15 +36,13 @@ static void handle_signal(int __attribute__((unused)) sig_no) } #endif -/* - Thread_info initializer methods -*/ +/* Thread_info initializer methods */ -Thread_info::Thread_info() {} -Thread_info::Thread_info(pthread_t thread_id_arg, - bool send_signal_on_shutdown_arg) : - thread_id(thread_id_arg), - send_signal_on_shutdown(send_signal_on_shutdown_arg) {} +void Thread_info::init(bool send_signal_on_shutdown_arg) +{ + thread_id= pthread_self(); + send_signal_on_shutdown= send_signal_on_shutdown_arg; +} /* TODO: think about moving signal information (now it's shutdown_in_progress) @@ -86,10 +82,13 @@ Thread_registry::~Thread_registry() points to the last node. */ -void Thread_registry::register_thread(Thread_info *info) +void Thread_registry::register_thread(Thread_info *info, + bool send_signal_on_shutdown) { - log_info("Thread_registry: registering thread %d...", - (int) info->thread_id); + info->init(send_signal_on_shutdown); + + DBUG_PRINT("info", ("Thread_registry: registering thread %lu...", + (unsigned long) info->thread_id)); #ifndef __WIN__ struct sigaction sa; @@ -117,8 +116,8 @@ void Thread_registry::register_thread(Thread_info *info) void Thread_registry::unregister_thread(Thread_info *info) { - log_info("Thread_registry: unregistering thread %d...", - (int) info->thread_id); + DBUG_PRINT("info", ("Thread_registry: unregistering thread %lu...", + (unsigned long) info->thread_id)); pthread_mutex_lock(&LOCK_thread_registry); info->prev->next= info->next; @@ -126,7 +125,7 @@ void Thread_registry::unregister_thread(Thread_info *info) if (head.next == &head) { - log_info("Thread_registry: thread registry is empty!"); + DBUG_PRINT("info", ("Thread_registry: thread registry is empty!")); pthread_cond_signal(&COND_thread_registry_is_empty); } @@ -230,6 +229,7 @@ void Thread_registry::deliver_shutdown() wait_for_threads_to_unregister(); +#ifndef DBUG_OFF /* Print out threads, that didn't stopped. Thread_registry destructor will probably abort the program if there is still any alive thread. @@ -237,15 +237,16 @@ void Thread_registry::deliver_shutdown() if (head.next != &head) { - log_info("Thread_registry: non-stopped threads:"); + DBUG_PRINT("info", ("Thread_registry: non-stopped threads:")); for (Thread_info *info= head.next; info != &head; info= info->next) - log_info(" - %ld", (long int) info->thread_id); + DBUG_PRINT("info", (" - %lu", (unsigned long) info->thread_id)); } else { - log_info("Thread_registry: all threads stopped."); + DBUG_PRINT("info", ("Thread_registry: all threads stopped.")); } +#endif // DBUG_OFF pthread_mutex_unlock(&LOCK_thread_registry); } @@ -277,13 +278,13 @@ void Thread_registry::wait_for_threads_to_unregister() set_timespec(shutdown_time, 1); - log_info("Thread_registry: joining threads..."); + DBUG_PRINT("info", ("Thread_registry: joining threads...")); while (true) { if (head.next == &head) { - log_info("Thread_registry: emptied."); + DBUG_PRINT("info", ("Thread_registry: emptied.")); return; } @@ -293,8 +294,101 @@ void Thread_registry::wait_for_threads_to_unregister() if (error == ETIMEDOUT || error == ETIME) { - log_info("Thread_registry: threads shutdown timed out."); + DBUG_PRINT("info", ("Thread_registry: threads shutdown timed out.")); return; } } } + + +/********************************************************************* + class Thread +*********************************************************************/ + +#if defined(__ia64__) || defined(__ia64) +/* + We can live with 32K, but reserve 64K. Just to be safe. + On ia64 we need to reserve double of the size. +*/ +#define IM_THREAD_STACK_SIZE (128*1024L) +#else +#define IM_THREAD_STACK_SIZE (64*1024) +#endif + +/* + Change the stack size and start a thread. Return an error if either + pthread_attr_setstacksize or pthread_create fails. + Arguments are the same as for pthread_create(). +*/ + +static +int set_stacksize_and_create_thread(pthread_t *thread, pthread_attr_t *attr, + void *(*start_routine)(void *), void *arg) +{ + int rc= 0; + +#ifndef __WIN__ +#ifndef PTHREAD_STACK_MIN +#define PTHREAD_STACK_MIN 32768 +#endif + /* + Set stack size to be safe on the platforms with too small + default thread stack. + */ + rc= pthread_attr_setstacksize(attr, + (size_t) (PTHREAD_STACK_MIN + + IM_THREAD_STACK_SIZE)); +#endif + if (!rc) + rc= pthread_create(thread, attr, start_routine, arg); + return rc; +} + + +Thread::~Thread() +{ +} + + +void *Thread::thread_func(void *arg) +{ + Thread *thread= (Thread *) arg; + my_thread_init(); + + thread->run(); + + my_thread_end(); + return NULL; +} + + +bool Thread::start(enum_thread_type thread_type) +{ + pthread_attr_t attr; + int rc; + + pthread_attr_init(&attr); + + if (thread_type == DETACHED) + { + detached = TRUE; + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + } + else + { + detached = FALSE; + } + + rc= set_stacksize_and_create_thread(&id, &attr, Thread::thread_func, this); + pthread_attr_destroy(&attr); + + return rc != 0; +} + + +bool Thread::join() +{ + DBUG_ASSERT(!detached); + + return pthread_join(id, NULL) != 0; +} diff --git a/server-tools/instance-manager/thread_registry.h b/server-tools/instance-manager/thread_registry.h index 503d24e5fb0..b9ece271c21 100644 --- a/server-tools/instance-manager/thread_registry.h +++ b/server-tools/instance-manager/thread_registry.h @@ -57,7 +57,7 @@ #pragma interface #endif -/* +/** Thread_info - repository entry for each worker thread All entries comprise double-linked list like: 0 -- entry -- entry -- entry - 0 @@ -67,12 +67,10 @@ class Thread_info { public: - Thread_info(pthread_t thread_id_arg, bool send_signal_on_shutdown_arg); + Thread_info() {} friend class Thread_registry; - private: - Thread_info(); - + void init(bool send_signal_on_shutdown); private: pthread_cond_t *current_cond; Thread_info *prev, *next; @@ -81,7 +79,51 @@ private: }; -/* +/** + A base class for a detached thread. +*/ + +class Thread +{ +public: + enum enum_thread_type + { + DETACHED, + JOINABLE + }; +public: + Thread() + { } + +public: + inline bool is_detached() const; + + bool start(enum_thread_type thread_type = JOINABLE); + bool join(); + +protected: + virtual void run()= 0; + virtual ~Thread(); + +private: + pthread_t id; + bool detached; + +private: + static void *thread_func(void *arg); + +private: + Thread(const Thread & /* rhs */); /* not implemented */ + Thread &operator=(const Thread & /* rhs */); /* not implemented */ +}; + +inline bool Thread::is_detached() const +{ + return detached; +} + + +/** Thread_registry - contains handles for each worker thread to deliver signal information to workers. */ @@ -92,7 +134,7 @@ public: Thread_registry(); ~Thread_registry(); - void register_thread(Thread_info *info); + void register_thread(Thread_info *info, bool send_signal_on_shutdown= TRUE); void unregister_thread(Thread_info *info); void deliver_shutdown(); void request_shutdown(); @@ -101,6 +143,7 @@ public: pthread_mutex_t *mutex); int cond_timedwait(Thread_info *info, pthread_cond_t *cond, pthread_mutex_t *mutex, struct timespec *wait_time); + private: void interrupt_threads(); void wait_for_threads_to_unregister(); @@ -111,6 +154,10 @@ private: pthread_mutex_t LOCK_thread_registry; pthread_cond_t COND_thread_registry_is_empty; pthread_t sigwait_thread_pid; + +private: + Thread_registry(const Thread_registry &); + Thread_registry &operator =(const Thread_registry &); }; diff --git a/server-tools/instance-manager/user_management_commands.cc b/server-tools/instance-manager/user_management_commands.cc index 20ebeb0d6bf..a32a4e94415 100644 --- a/server-tools/instance-manager/user_management_commands.cc +++ b/server-tools/instance-manager/user_management_commands.cc @@ -20,7 +20,7 @@ This function must not be used in user-management command implementations. Use get_user_name() instead. - SYNOPSYS + SYNOPSIS get_user_name_impl() RETURN @@ -58,7 +58,7 @@ static char *get_user_name_impl() (not empty, not exceeds USERNAME_LENGTH). Report to stderr if something is wrong. - SYNOPSYS + SYNOPSIS get_user_name() user_name [OUT] on success contains user name @@ -102,7 +102,7 @@ static bool get_user_name(LEX_STRING *user_name) The password is retrieved from command-line options (if specified) or from console. - SYNOPSYS + SYNOPSIS get_password() RETURN @@ -131,7 +131,7 @@ static const char *get_password() /* Load password file into user map. - SYNOPSYS + SYNOPSIS load_password_file() user_map target user map @@ -160,7 +160,7 @@ static int load_password_file(User_map *user_map) /* Save user map into password file. - SYNOPSYS + SYNOPSIS save_password_file() user_map user map diff --git a/server-tools/instance-manager/user_management_commands.h b/server-tools/instance-manager/user_management_commands.h index 8d820be5ec7..17c11ccfef0 100644 --- a/server-tools/instance-manager/user_management_commands.h +++ b/server-tools/instance-manager/user_management_commands.h @@ -49,7 +49,7 @@ public: /* Executes user-management command. - SYNOPSYS + SYNOPSIS execute() RETURN @@ -65,7 +65,7 @@ public: option. *************************************************************************/ -class Print_password_line_cmd : public User_management_cmd +class Print_password_line_cmd: public User_management_cmd { public: Print_password_line_cmd() @@ -80,7 +80,7 @@ public: Add_user_cmd: support for --add-user command-line option. *************************************************************************/ -class Add_user_cmd : public User_management_cmd +class Add_user_cmd: public User_management_cmd { public: Add_user_cmd() @@ -95,7 +95,7 @@ public: Drop_user_cmd: support for --drop-user command-line option. *************************************************************************/ -class Drop_user_cmd : public User_management_cmd +class Drop_user_cmd: public User_management_cmd { public: Drop_user_cmd() @@ -110,7 +110,7 @@ public: Edit_user_cmd: support for --edit-user command-line option. *************************************************************************/ -class Edit_user_cmd : public User_management_cmd +class Edit_user_cmd: public User_management_cmd { public: Edit_user_cmd() @@ -125,7 +125,7 @@ public: Clean_db_cmd: support for --clean-db command-line option. *************************************************************************/ -class Clean_db_cmd : public User_management_cmd +class Clean_db_cmd: public User_management_cmd { public: Clean_db_cmd() @@ -140,7 +140,7 @@ public: Check_db_cmd: support for --check-db command-line option. *************************************************************************/ -class Check_db_cmd : public User_management_cmd +class Check_db_cmd: public User_management_cmd { public: Check_db_cmd() @@ -155,7 +155,7 @@ public: List_users_cmd: support for --list-users command-line option. *************************************************************************/ -class List_users_cmd : public User_management_cmd +class List_users_cmd: public User_management_cmd { public: List_users_cmd() diff --git a/server-tools/instance-manager/user_map.cc b/server-tools/instance-manager/user_map.cc index c1439e983d8..f3a6e3cd76c 100644 --- a/server-tools/instance-manager/user_map.cc +++ b/server-tools/instance-manager/user_map.cc @@ -41,8 +41,8 @@ int User::init(const char *line) name_end= strchr(name_begin, line[0]); if (name_end == 0 || name_end[1] != ':') { - log_info("Error: invalid format (unmatched quote) of user line (%s).", - (const char *) line); + log_error("Invalid format (unmatched quote) of user line (%s).", + (const char *) line); return 1; } password= name_end + 2; @@ -53,8 +53,8 @@ int User::init(const char *line) name_end= strchr(name_begin, ':'); if (name_end == 0) { - log_info("Error: invalid format (no delimiter) of user line (%s).", - (const char *) line); + log_error("Invalid format (no delimiter) of user line (%s).", + (const char *) line); return 1; } password= name_end + 1; @@ -63,18 +63,19 @@ int User::init(const char *line) user_length= name_end - name_begin; if (user_length > USERNAME_LENGTH) { - log_info("Error: user name is too long (%d). Max length: %d. " - "User line: '%s'.", - (int) user_length, - (int) USERNAME_LENGTH, - (const char *) line); + log_error("User name is too long (%d). Max length: %d. " + "User line: '%s'.", + (int) user_length, + (int) USERNAME_LENGTH, + (const char *) line); return 1; } password_length= strlen(password); if (password_length > SCRAMBLED_PASSWORD_CHAR_LENGTH) { - log_info("Error: password is too long (%d). Max length: %d. User line: '%s'.", + log_error("Password is too long (%d). Max length: %d." + "User line: '%s'.", (int) password_length, (int) SCRAMBLED_PASSWORD_CHAR_LENGTH, line); @@ -89,7 +90,7 @@ int User::init(const char *line) get_salt_from_password(salt, password); - log_info("loaded user '%s'.", user); + log_info("Loaded user '%s'.", (const char *) user); return 0; } @@ -158,7 +159,7 @@ User_map::~User_map() /* Load password database. - SYNOPSYS + SYNOPSIS load() password_file_name [IN] password file path err_msg [OUT] error message @@ -185,7 +186,6 @@ int User_map::load(const char *password_file_name, const char **err_msg) 2 + /* for newline */ 1]; /* for trailing zero */ User *user; - int rc= 1; if (my_access(password_file_name, F_OK) != 0) { @@ -214,7 +214,7 @@ int User_map::load(const char *password_file_name, const char **err_msg) return ERR_IO_ERROR; } - log_info("loading the password database..."); + log_info("Loading the password database..."); while (fgets(line, sizeof(line), file)) { @@ -292,7 +292,7 @@ int User_map::load(const char *password_file_name, const char **err_msg) } } - log_info("the password database loaded successfully."); + log_info("The password database loaded successfully."); my_fclose(file, MYF(0)); diff --git a/server-tools/instance-manager/user_map.h b/server-tools/instance-manager/user_map.h index de207c11e65..5325af12058 100644 --- a/server-tools/instance-manager/user_map.h +++ b/server-tools/instance-manager/user_map.h @@ -60,7 +60,7 @@ public: { public: Iterator(User_map *user_map_arg) : - cur_idx(0), user_map(user_map_arg) + user_map(user_map_arg), cur_idx(0) { } public: diff --git a/sql-common/client.c b/sql-common/client.c index b6947028e74..7d6f7024727 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -593,7 +593,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)) @@ -748,6 +748,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 */ @@ -845,6 +868,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) { @@ -857,6 +881,7 @@ void end_server(MYSQL *mysql) } net_end(&mysql->net); free_old_query(mysql); + errno= save_errno; DBUG_VOID_RETURN; } @@ -865,7 +890,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; @@ -1186,6 +1211,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 ((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]); @@ -1361,7 +1388,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); } @@ -2026,7 +2053,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; } @@ -2035,8 +2065,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]; @@ -2170,7 +2206,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; } @@ -2249,7 +2288,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; } @@ -2259,7 +2301,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) @@ -2271,12 +2320,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 */ @@ -2287,8 +2346,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) { @@ -2319,7 +2385,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); @@ -2692,7 +2758,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 ab9a2c6d7c8..f836da2147e 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) { @@ -780,7 +780,7 @@ long calc_daynr(uint year,uint month,uint day) */ my_time_t my_system_gmt_sec(const MYSQL_TIME *t_src, long *my_timezone, - bool *in_dst_time_gap) + my_bool *in_dst_time_gap) { uint loop; time_t tmp= 0; @@ -963,7 +963,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/CMakeLists.txt b/sql/CMakeLists.txt index 1c2944de530..4cdc4c01c4e 100644 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -54,6 +54,7 @@ ADD_EXECUTABLE(mysqld ../sql-common/client.c derror.cc des_key_file.cc event_queue.cc event_db_repository.cc sql_tablespace.cc events.cc ../sql-common/my_user.c partition_info.cc rpl_utility.cc rpl_injector.cc sql_locale.cc + rpl_rli.cc rpl_mi.cc ${PROJECT_SOURCE_DIR}/sql/sql_yacc.cc ${PROJECT_SOURCE_DIR}/sql/sql_yacc.h ${PROJECT_SOURCE_DIR}/include/mysqld_error.h diff --git a/sql/Makefile.am b/sql/Makefile.am index 9a0303a433f..91fe875c73d 100644 --- a/sql/Makefile.am +++ b/sql/Makefile.am @@ -54,7 +54,7 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \ ha_ndbcluster.h ha_ndbcluster_binlog.h \ ha_ndbcluster_tables.h \ opt_range.h protocol.h rpl_tblmap.h rpl_utility.h \ - log.h sql_show.h rpl_rli.h \ + log.h sql_show.h rpl_rli.h rpl_mi.h \ sql_select.h structs.h table.h sql_udf.h hash_filo.h \ lex.h lex_symbol.h sql_acl.h sql_crypt.h \ log_event.h sql_repl.h slave.h rpl_filter.h \ @@ -94,7 +94,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \ sql_load.cc mf_iocache.cc field_conv.cc sql_show.cc \ sql_udf.cc sql_analyse.cc sql_analyse.h sql_cache.cc \ slave.cc sql_repl.cc rpl_filter.cc rpl_tblmap.cc \ - rpl_utility.cc rpl_injector.cc \ + rpl_utility.cc rpl_injector.cc rpl_rli.cc rpl_mi.cc \ sql_union.cc sql_derived.cc \ client.c sql_client.cc mini_client_errors.c pack.c\ stacktrace.c repl_failsafe.h repl_failsafe.cc \ @@ -155,12 +155,15 @@ 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 > sql_yacc.cc-new + @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 # FIXME seems like now "lex_hash.h" differs depending on configure # flags, so can't pregenerate and include in source TAR. Revert to diff --git a/sql/event_data_objects.cc b/sql/event_data_objects.cc index afd10350bb5..0de90e4145b 100644 --- a/sql/event_data_objects.cc +++ b/sql/event_data_objects.cc @@ -124,8 +124,8 @@ void Event_parse_data::init_body(THD *thd) { DBUG_ENTER("Event_parse_data::init_body"); - DBUG_PRINT("info", ("body=[%s] body_begin=0x%lx end=0x%lx", body_begin, - body_begin, thd->lex->ptr)); + DBUG_PRINT("info", ("body: '%s' body_begin: 0x%lx end: 0x%lx", body_begin, + (long) body_begin, (long) thd->lex->ptr)); body.length= thd->lex->ptr - body_begin; const uchar *body_end= body_begin + body.length - 1; @@ -399,8 +399,9 @@ Event_parse_data::init_starts(THD *thd) thd->variables.time_zone->gmt_sec_to_TIME(&time_tmp, (my_time_t) thd->query_start()); - DBUG_PRINT("info",("now =%lld", TIME_to_ulonglong_datetime(&time_tmp))); - DBUG_PRINT("info",("starts=%lld", TIME_to_ulonglong_datetime(<ime))); + DBUG_PRINT("info",("now: %ld starts: %ld", + (long) TIME_to_ulonglong_datetime(&time_tmp), + (long) TIME_to_ulonglong_datetime(<ime))); if (TIME_to_ulonglong_datetime(<ime) < TIME_to_ulonglong_datetime(&time_tmp)) goto wrong_value; @@ -536,8 +537,9 @@ Event_parse_data::check_parse_data(THD *thd) { bool ret; DBUG_ENTER("Event_parse_data::check_parse_data"); - DBUG_PRINT("info", ("execute_at=0x%lx expr=0x%lx starts=0x%lx ends=0x%lx", - item_execute_at, item_expression, item_starts, item_ends)); + DBUG_PRINT("info", ("execute_at: 0x%lx expr=0x%lx starts=0x%lx ends=0x%lx", + (long) item_execute_at, (long) item_expression, + (long) item_starts, (long) item_ends)); init_name(thd, identifier); @@ -564,9 +566,9 @@ Event_parse_data::init_definer(THD *thd) int definer_host_len; DBUG_ENTER("Event_parse_data::init_definer"); - DBUG_PRINT("info",("init definer_user thd->mem_root=0x%lx " - "thd->sec_ctx->priv_user=0x%lx", thd->mem_root, - thd->security_ctx->priv_user)); + DBUG_PRINT("info",("init definer_user thd->mem_root: 0x%lx " + "thd->sec_ctx->priv_user: 0x%lx", (long) thd->mem_root, + (long) thd->security_ctx->priv_user)); definer_user_len= strlen(thd->security_ctx->priv_user); definer_host_len= strlen(thd->security_ctx->priv_host); @@ -1032,8 +1034,9 @@ bool get_next_time(TIME *next, TIME *start, TIME *time_now, TIME *last_exec, TIME tmp; longlong months=0, seconds=0; DBUG_ENTER("get_next_time"); - DBUG_PRINT("enter", ("start=%llu now=%llu", TIME_to_ulonglong_datetime(start), - TIME_to_ulonglong_datetime(time_now))); + DBUG_PRINT("enter", ("start: %lu now: %lu", + (long) TIME_to_ulonglong_datetime(start), + (long) TIME_to_ulonglong_datetime(time_now))); bzero(&interval, sizeof(interval)); @@ -1081,7 +1084,7 @@ bool get_next_time(TIME *next, TIME *start, TIME *time_now, TIME *last_exec, case INTERVAL_LAST: DBUG_ASSERT(0); } - DBUG_PRINT("info", ("seconds=%ld months=%ld", seconds, months)); + DBUG_PRINT("info", ("seconds: %ld months: %ld", (long) seconds, (long) months)); if (seconds) { longlong seconds_diff; @@ -1099,14 +1102,14 @@ bool get_next_time(TIME *next, TIME *start, TIME *time_now, TIME *last_exec, event two times for the same time get the next exec if the modulus is not */ - DBUG_PRINT("info", ("multiplier=%d", multiplier)); + DBUG_PRINT("info", ("multiplier: %d", multiplier)); if (seconds_diff % seconds || (!seconds_diff && last_exec->year) || TIME_to_ulonglong_datetime(time_now) == TIME_to_ulonglong_datetime(last_exec)) ++multiplier; interval.second= seconds * multiplier; - DBUG_PRINT("info", ("multiplier=%u interval.second=%u", multiplier, - interval.second)); + DBUG_PRINT("info", ("multiplier: %lu interval.second: %lu", (ulong) multiplier, + (ulong) interval.second)); tmp= *start; if (!(ret= date_add_interval(&tmp, INTERVAL_SECOND, interval))) *next= tmp; @@ -1158,7 +1161,7 @@ bool get_next_time(TIME *next, TIME *start, TIME *time_now, TIME *last_exec, } done: - DBUG_PRINT("info", ("next=%llu", TIME_to_ulonglong_datetime(next))); + DBUG_PRINT("info", ("next: %lu", (long) TIME_to_ulonglong_datetime(next))); DBUG_RETURN(ret); } @@ -1183,17 +1186,17 @@ Event_queue_element::compute_next_execution_time() { TIME time_now; int tmp; - DBUG_ENTER("Event_queue_element::compute_next_execution_time"); - DBUG_PRINT("enter", ("starts=%llu ends=%llu last_executed=%llu this=0x%lx", - TIME_to_ulonglong_datetime(&starts), - TIME_to_ulonglong_datetime(&ends), - TIME_to_ulonglong_datetime(&last_executed), this)); + DBUG_PRINT("enter", ("starts: %lu ends: %lu last_executed: %lu this: 0x%lx", + (long) TIME_to_ulonglong_datetime(&starts), + (long) TIME_to_ulonglong_datetime(&ends), + (long) TIME_to_ulonglong_datetime(&last_executed), + (long) this)); if (status == Event_queue_element::DISABLED) { DBUG_PRINT("compute_next_execution_time", - ("Event %s is DISABLED", name.str)); + ("Event %s is DISABLED", name.str)); goto ret; } /* If one-time, no need to do computation */ @@ -1203,9 +1206,9 @@ Event_queue_element::compute_next_execution_time() if (last_executed.year) { DBUG_PRINT("info",("One-time event %s.%s of was already executed", - dbname.str, name.str, definer.str)); + dbname.str, name.str)); dropped= (on_completion == Event_queue_element::ON_COMPLETION_DROP); - DBUG_PRINT("info",("One-time event will be dropped=%d.", dropped)); + DBUG_PRINT("info",("One-time event will be dropped: %d.", dropped)); status= Event_queue_element::DISABLED; status_changed= TRUE; @@ -1215,7 +1218,8 @@ Event_queue_element::compute_next_execution_time() my_tz_UTC->gmt_sec_to_TIME(&time_now, current_thd->query_start()); - DBUG_PRINT("info",("NOW=[%llu]", TIME_to_ulonglong_datetime(&time_now))); + DBUG_PRINT("info",("NOW: [%lu]", + (ulong) TIME_to_ulonglong_datetime(&time_now))); /* if time_now is after ends don't execute anymore */ if (!ends_null && (tmp= my_time_compare(&ends, &time_now)) == -1) @@ -1226,7 +1230,7 @@ Event_queue_element::compute_next_execution_time() execute_at_null= TRUE; if (on_completion == Event_queue_element::ON_COMPLETION_DROP) dropped= TRUE; - DBUG_PRINT("info", ("Dropped=%d", dropped)); + DBUG_PRINT("info", ("Dropped: %d", dropped)); status= Event_queue_element::DISABLED; status_changed= TRUE; @@ -1297,7 +1301,8 @@ Event_queue_element::compute_next_execution_time() } else { - DBUG_PRINT("info",("Next[%llu]",TIME_to_ulonglong_datetime(&next_exec))); + DBUG_PRINT("info",("Next[%lu]", + (ulong) TIME_to_ulonglong_datetime(&next_exec))); execute_at= next_exec; execute_at_null= FALSE; } @@ -1319,7 +1324,8 @@ Event_queue_element::compute_next_execution_time() expression, interval)) goto err; execute_at= next_exec; - DBUG_PRINT("info",("Next[%llu]",TIME_to_ulonglong_datetime(&next_exec))); + DBUG_PRINT("info",("Next[%lu]", + (ulong) TIME_to_ulonglong_datetime(&next_exec))); } else { @@ -1353,7 +1359,8 @@ Event_queue_element::compute_next_execution_time() expression, interval)) goto err; execute_at= next_exec; - DBUG_PRINT("info",("Next[%llu]",TIME_to_ulonglong_datetime(&next_exec))); + DBUG_PRINT("info",("Next[%lu]", + (ulong) TIME_to_ulonglong_datetime(&next_exec))); } execute_at_null= FALSE; } @@ -1390,8 +1397,8 @@ Event_queue_element::compute_next_execution_time() } else { - DBUG_PRINT("info", ("Next[%llu]", - TIME_to_ulonglong_datetime(&next_exec))); + DBUG_PRINT("info", ("Next[%lu]", + (ulong) TIME_to_ulonglong_datetime(&next_exec))); execute_at= next_exec; execute_at_null= FALSE; } @@ -1400,8 +1407,8 @@ Event_queue_element::compute_next_execution_time() goto ret; } ret: - DBUG_PRINT("info", ("ret=0 execute_at=%llu", - TIME_to_ulonglong_datetime(&execute_at))); + DBUG_PRINT("info", ("ret: 0 execute_at: %lu", + (long) TIME_to_ulonglong_datetime(&execute_at))); DBUG_RETURN(FALSE); err: DBUG_PRINT("info", ("ret=1")); @@ -1688,7 +1695,7 @@ done: thd->end_statement(); thd->cleanup_after_query(); - DBUG_PRINT("info", ("EXECUTED %s.%s ret=%d", dbname.str, name.str, ret)); + DBUG_PRINT("info", ("EXECUTED %s.%s ret: %d", dbname.str, name.str, ret)); DBUG_RETURN(ret); } @@ -1752,7 +1759,7 @@ Event_job_data::compile(THD *thd, MEM_ROOT *mem_root) thd->update_charset(); - DBUG_PRINT("info",("old_sql_mode=%d new_sql_mode=%d",old_sql_mode, sql_mode)); + DBUG_PRINT("info",("old_sql_mode: %lu new_sql_mode: %lu",old_sql_mode, sql_mode)); thd->variables.sql_mode= this->sql_mode; /* Change the memory root for the execution time */ if (mem_root) @@ -1769,7 +1776,7 @@ Event_job_data::compile(THD *thd, MEM_ROOT *mem_root) thd->query= show_create.c_ptr_safe(); thd->query_length= show_create.length(); - DBUG_PRINT("info", ("query:%s",thd->query)); + DBUG_PRINT("info", ("query: %s",thd->query)); event_change_security_context(thd, definer_user, definer_host, dbname, &save_ctx); @@ -1777,14 +1784,14 @@ Event_job_data::compile(THD *thd, MEM_ROOT *mem_root) mysql_init_query(thd, (uchar*) thd->query, thd->query_length); if (MYSQLparse((void *)thd) || thd->is_fatal_error) { - DBUG_PRINT("error", ("error during compile or thd->is_fatal_error=%d", + DBUG_PRINT("error", ("error during compile or thd->is_fatal_error: %d", thd->is_fatal_error)); /* Free lex associated resources QQ: Do we really need all this stuff here? */ sql_print_error("SCHEDULER: Error during compilation of %s.%s or " - "thd->is_fatal_error=%d", + "thd->is_fatal_error: %d", dbname.str, name.str, thd->is_fatal_error); lex.unit.cleanup(); diff --git a/sql/event_data_objects.h b/sql/event_data_objects.h index e7e96d299fb..2da39c2158b 100644 --- a/sql/event_data_objects.h +++ b/sql/event_data_objects.h @@ -111,14 +111,14 @@ public: void *p; DBUG_ENTER("Event_queue_element::new(size)"); p= my_malloc(size, MYF(0)); - DBUG_PRINT("info", ("alloc_ptr=0x%lx", p)); + DBUG_PRINT("info", ("alloc_ptr: 0x%lx", (long) p)); DBUG_RETURN(p); } static void operator delete(void *ptr, size_t size) { DBUG_ENTER("Event_queue_element::delete(ptr,size)"); - DBUG_PRINT("enter", ("free_ptr=0x%lx", ptr)); + DBUG_PRINT("enter", ("free_ptr: 0x%lx", (long) ptr)); TRASH(ptr, size); my_free((gptr) ptr, MYF(0)); DBUG_VOID_RETURN; diff --git a/sql/event_db_repository.cc b/sql/event_db_repository.cc index 3d30aff669b..367c5bae579 100644 --- a/sql/event_db_repository.cc +++ b/sql/event_db_repository.cc @@ -958,7 +958,7 @@ Event_db_repository::load_named_event(THD *thd, LEX_STRING dbname, Open_tables_state backup; DBUG_ENTER("Event_db_repository::load_named_event"); - DBUG_PRINT("enter",("thd=0x%lx name:%*s",thd, name.length, name.str)); + DBUG_PRINT("enter",("thd: 0x%lx name: %*s", (long) thd, name.length, name.str)); thd->reset_n_backup_open_tables_state(&backup); diff --git a/sql/event_queue.cc b/sql/event_queue.cc index 527a59018a8..7ec665fcd5f 100644 --- a/sql/event_queue.cc +++ b/sql/event_queue.cc @@ -143,7 +143,7 @@ Event_queue::init_queue(THD *thd, Event_db_repository *db_repo) struct event_queue_param *event_queue_param_value= NULL; DBUG_ENTER("Event_queue::init_queue"); - DBUG_PRINT("enter", ("this=0x%lx", this)); + DBUG_PRINT("enter", ("this: 0x%lx", (long) this)); LOCK_QUEUE_DATA(); db_repository= db_repo; @@ -218,7 +218,7 @@ Event_queue::create_event(THD *thd, LEX_STRING dbname, LEX_STRING name) int res; Event_queue_element *new_element; DBUG_ENTER("Event_queue::create_event"); - DBUG_PRINT("enter", ("thd=0x%lx et=%s.%s",thd, dbname.str, name.str)); + DBUG_PRINT("enter", ("thd: 0x%lx et=%s.%s", (long) thd, dbname.str, name.str)); new_element= new Event_queue_element(); res= db_repository->load_named_event(thd, dbname, name, new_element); @@ -229,7 +229,7 @@ Event_queue::create_event(THD *thd, LEX_STRING dbname, LEX_STRING name) new_element->compute_next_execution_time(); LOCK_QUEUE_DATA(); - DBUG_PRINT("info", ("new event in the queue 0x%lx", new_element)); + DBUG_PRINT("info", ("new event in the queue: 0x%lx", (long) new_element)); queue_insert_safe(&queue, (byte *) new_element); dbug_dump_queue(thd->query_start()); pthread_cond_broadcast(&COND_queue_state); @@ -264,7 +264,7 @@ Event_queue::update_event(THD *thd, LEX_STRING dbname, LEX_STRING name, Event_queue_element *new_element; DBUG_ENTER("Event_queue::update_event"); - DBUG_PRINT("enter", ("thd=0x%lx et=[%s.%s]", thd, dbname.str, name.str)); + DBUG_PRINT("enter", ("thd: 0x%lx et=[%s.%s]", (long) thd, dbname.str, name.str)); new_element= new Event_queue_element(); @@ -294,7 +294,7 @@ Event_queue::update_event(THD *thd, LEX_STRING dbname, LEX_STRING name, /* If not disabled event */ if (new_element) { - DBUG_PRINT("info", ("new event in the Q 0x%lx", new_element)); + DBUG_PRINT("info", ("new event in the queue: 0x%lx", (long) new_element)); queue_insert_safe(&queue, (byte *) new_element); pthread_cond_broadcast(&COND_queue_state); } @@ -322,7 +322,8 @@ void Event_queue::drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name) { DBUG_ENTER("Event_queue::drop_event"); - DBUG_PRINT("enter", ("thd=0x%lx db=%s name=%s", thd, dbname.str, name.str)); + DBUG_PRINT("enter", ("thd: 0x%lx db :%s name: %s", (long) thd, + dbname.str, name.str)); LOCK_QUEUE_DATA(); find_n_remove_event(dbname, name); @@ -484,7 +485,7 @@ Event_queue::load_events_from_db(THD *thd) bool clean_the_queue= TRUE; DBUG_ENTER("Event_queue::load_events_from_db"); - DBUG_PRINT("enter", ("thd=0x%lx", thd)); + DBUG_PRINT("enter", ("thd: 0x%lx", (long) thd)); if ((ret= db_repository->open_event_table(thd, TL_READ, &table))) { @@ -555,7 +556,6 @@ Event_queue::load_events_from_db(THD *thd) goto end; } - DBUG_PRINT("load_events_from_db", ("Adding 0x%lx to the exec list.")); queue_insert_safe(&queue, (byte *) et); count++; } @@ -663,16 +663,20 @@ Event_queue::dbug_dump_queue(time_t now) for (i = 0; i < queue.elements; i++) { et= ((Event_queue_element*)queue_element(&queue, i)); - DBUG_PRINT("info",("et=0x%lx db=%s name=%s",et, et->dbname.str, et->name.str)); - DBUG_PRINT("info", ("exec_at=%llu starts=%llu ends=%llu execs_so_far=%u" - " expr=%lld et.exec_at=%d now=%d (et.exec_at - now)=%d if=%d", - TIME_to_ulonglong_datetime(&et->execute_at), - TIME_to_ulonglong_datetime(&et->starts), - TIME_to_ulonglong_datetime(&et->ends), - et->execution_count, - et->expression, sec_since_epoch_TIME(&et->execute_at), now, - (int)(sec_since_epoch_TIME(&et->execute_at) - now), - sec_since_epoch_TIME(&et->execute_at) <= now)); + DBUG_PRINT("info", ("et: 0x%lx name: %s.%s", (long) et, + et->dbname.str, et->name.str)); + DBUG_PRINT("info", ("exec_at: %lu starts: %lu ends: %lu execs_so_far: %u " + "expr: %ld et.exec_at: %ld now: %ld " + "(et.exec_at - now): %d if: %d", + (long) TIME_to_ulonglong_datetime(&et->execute_at), + (long) TIME_to_ulonglong_datetime(&et->starts), + (long) TIME_to_ulonglong_datetime(&et->ends), + et->execution_count, + (long) et->expression, + (long) (sec_since_epoch_TIME(&et->execute_at)), + (long) now, + (int) (sec_since_epoch_TIME(&et->execute_at) - now), + sec_since_epoch_TIME(&et->execute_at) <= now)); } DBUG_VOID_RETURN; #endif @@ -812,11 +816,11 @@ end: if (to_free) delete top; - DBUG_PRINT("info", ("returning %d. et_new=0x%lx abstime.tv_sec=%d ", - ret, *job_data, abstime? abstime->tv_sec:0)); + DBUG_PRINT("info", ("returning %d et_new: 0x%lx abstime.tv_sec: %ld ", + ret, (long) *job_data, abstime ? abstime->tv_sec : 0)); if (*job_data) - DBUG_PRINT("info", ("db=%s name=%s definer=%s", (*job_data)->dbname.str, + DBUG_PRINT("info", ("db: %s name: %s definer=%s", (*job_data)->dbname.str, (*job_data)->name.str, (*job_data)->definer.str)); DBUG_RETURN(ret); diff --git a/sql/event_scheduler.cc b/sql/event_scheduler.cc index 6f9f6887c12..9be2f2d1125 100644 --- a/sql/event_scheduler.cc +++ b/sql/event_scheduler.cc @@ -264,8 +264,9 @@ event_worker_thread(void *arg) if (!post_init_event_thread(thd)) { - DBUG_PRINT("info", ("Baikonur, time is %d, BURAN reporting and operational." - "THD=0x%lx", time(NULL), thd)); + DBUG_PRINT("info", ("Baikonur, time is %ld, BURAN reporting and operational." + "THD: 0x%lx", + (long) time(NULL), (long) thd)); sql_print_information("SCHEDULER: [%s.%s of %s] executing in thread %lu. " "Execution %u", @@ -378,7 +379,7 @@ Event_scheduler::start() DBUG_ENTER("Event_scheduler::start"); LOCK_DATA(); - DBUG_PRINT("info", ("state before action %s", scheduler_states_names[state])); + DBUG_PRINT("info", ("state before action %s", scheduler_states_names[state].str)); if (state > INITIALIZED) goto end; @@ -400,7 +401,7 @@ Event_scheduler::start() scheduler_thd= new_thd; DBUG_PRINT("info", ("Setting state go RUNNING")); state= RUNNING; - DBUG_PRINT("info", ("Forking new thread for scheduduler. THD=0x%lx", new_thd)); + DBUG_PRINT("info", ("Forking new thread for scheduduler. THD: 0x%lx", (long) new_thd)); if (pthread_create(&th, &connection_attrib, event_scheduler_thread, (void*)scheduler_param_value)) { @@ -463,7 +464,7 @@ Event_scheduler::run(THD *thd) break; } - DBUG_PRINT("info", ("get_top returned job_data=0x%lx", job_data)); + DBUG_PRINT("info", ("get_top returned job_data: 0x%lx", (long) job_data)); if (job_data) { if ((res= execute_top(thd, job_data))) @@ -522,11 +523,11 @@ Event_scheduler::execute_top(THD *thd, Event_job_data *job_data) ++started_events; - DBUG_PRINT("info", ("Launch succeeded. BURAN is in THD=0x%lx", new_thd)); + DBUG_PRINT("info", ("Launch succeeded. BURAN is in THD: 0x%lx", (long) new_thd)); DBUG_RETURN(FALSE); error: - DBUG_PRINT("error", ("Baikonur, we have a problem! res=%d", res)); + DBUG_PRINT("error", ("Baikonur, we have a problem! res: %d", res)); if (new_thd) { new_thd->proc_info= "Clearing"; @@ -581,10 +582,10 @@ Event_scheduler::stop() { THD *thd= current_thd; DBUG_ENTER("Event_scheduler::stop"); - DBUG_PRINT("enter", ("thd=0x%lx", current_thd)); + DBUG_PRINT("enter", ("thd: 0x%lx", (long) thd)); LOCK_DATA(); - DBUG_PRINT("info", ("state before action %s", scheduler_states_names[state])); + DBUG_PRINT("info", ("state before action %s", scheduler_states_names[state].str)); if (state != RUNNING) goto end; @@ -605,7 +606,7 @@ Event_scheduler::stop() */ state= STOPPING; - DBUG_PRINT("info", ("Manager thread has id %d", scheduler_thd->thread_id)); + DBUG_PRINT("info", ("Manager thread has id %lu", scheduler_thd->thread_id)); /* Lock from delete */ pthread_mutex_lock(&scheduler_thd->LOCK_delete); /* This will wake up the thread if it waits on Queue's conditional */ @@ -775,7 +776,7 @@ Event_scheduler::dump_internal_status() mutex_last_unlocked_at_line); printf("WOC : %s\n", waiting_on_cond? "YES":"NO"); printf("Workers : %u\n", workers_count()); - printf("Executed : %llu\n", started_events); + printf("Executed : %lu\n", (ulong) started_events); printf("Data locked: %s\n", mutex_scheduler_data_locked ? "YES":"NO"); DBUG_VOID_RETURN; diff --git a/sql/events.cc b/sql/events.cc index 10a8be948ef..3dbc6fd27e1 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -858,7 +858,7 @@ Events::check_system_tables(THD *thd) bool ret= FALSE; DBUG_ENTER("Events::check_system_tables"); - DBUG_PRINT("enter", ("thd=0x%lx", thd)); + DBUG_PRINT("enter", ("thd: 0x%lx", (long) thd)); thd->reset_n_backup_open_tables_state(&backup); diff --git a/sql/field.cc b/sql/field.cc index 122a44305f2..c55eebe356b 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -1237,12 +1237,6 @@ Field::Field(char *ptr_arg,uint32 length_arg,uchar *null_ptr_arg, } -uint Field::offset() -{ - return (uint) (ptr - (char*) table->record[0]); -} - - void Field::hash(ulong *nr, ulong *nr2) { if (is_null()) @@ -1427,6 +1421,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; } @@ -2477,6 +2472,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) { ASSERT_COLUMN_MARKED_FOR_READ; @@ -4918,7 +4920,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, TRUE); + return Field_time::store((longlong) tmp, FALSE); } @@ -5529,7 +5531,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 ((my_bool)check_date(ltime, tmp, + (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; @@ -5744,8 +5760,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 ((my_bool)check_date(ltime, tmp, + (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; @@ -5921,38 +5951,149 @@ 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) { ASSERT_COLUMN_MARKED_FOR_WRITE; - 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) @@ -5960,32 +6101,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; } @@ -6343,58 +6475,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) { ASSERT_COLUMN_MARKED_FOR_WRITE; - 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 ((from_end_pos < from + length) && table->in_use->count_cuted_fields) { - 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 (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; @@ -6578,9 +6687,9 @@ void Field_varstring::sql_type(String &res) const } -uint32 Field_varstring::data_length(const char *from) +uint32 Field_varstring::data_length() { - return length_bytes == 1 ? (uint) (uchar) *ptr : uint2korr(ptr); + return length_bytes == 1 ? (uint32) (uchar) *ptr : uint2korr(ptr); } /* @@ -7012,68 +7121,70 @@ void Field_blob::put_length(char *pos, uint32 length) int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs) { ASSERT_COLUMN_MARKED_FOR_WRITE; - 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; } @@ -8104,8 +8215,8 @@ Field_bit::do_last_null_byte() const bits. On systems with CHAR_BIT > 8 (not very common), the storage will lose the extra bits. */ - DBUG_PRINT("debug", ("bit_ofs=%d, bit_len=%d, bit_ptr=%p", - bit_ofs, bit_len, bit_ptr)); + DBUG_PRINT("test", ("bit_ofs: %d, bit_len: %d bit_ptr: 0x%lx", + bit_ofs, bit_len, (long) bit_ptr)); uchar *result; if (bit_len == 0) result= null_ptr; diff --git a/sql/field.h b/sql/field.h index 9b81931d416..6ff6882ed87 100644 --- a/sql/field.h +++ b/sql/field.h @@ -153,7 +153,7 @@ public: /* data_length() return the "real size" of the data in memory. */ - virtual uint32 data_length(const char *from) { return pack_length(); } + virtual uint32 data_length() { return pack_length(); } virtual uint32 sort_length() const { return pack_length(); } virtual void reset(void) { bzero(ptr,pack_length()); } virtual void reset_fields() {} @@ -239,7 +239,7 @@ public: */ my_size_t last_null_byte() const { my_size_t bytes= do_last_null_byte(); - DBUG_PRINT("debug", ("last_null_byte() ==> %d", bytes)); + DBUG_PRINT("debug", ("last_null_byte() ==> %ld", (long) bytes)); DBUG_ASSERT(bytes <= table->s->null_bytes); return bytes; } @@ -342,7 +342,10 @@ public: virtual int pack_cmp(const char *b, uint key_length_arg, my_bool insert_or_update) { return cmp(ptr,b); } - uint offset(); // Should be inline ... + uint offset(byte *record) + { + return (uint) (ptr - (char*) record); + } void copy_from_tmp(int offset); uint fill_cache_field(struct st_cache_field *copy); virtual bool get_date(TIME *ltime,uint fuzzydate); @@ -351,6 +354,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, @@ -446,6 +452,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, @@ -459,6 +466,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; @@ -555,6 +565,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); @@ -1167,7 +1178,7 @@ public: int key_cmp(const byte *str, uint length); uint packed_col_length(const char *to, uint length); uint max_packed_col_length(uint max_length); - uint32 data_length(const char *from); + uint32 data_length(); uint size_of() const { return sizeof(*this); } enum_field_types real_type() const { return MYSQL_TYPE_VARCHAR; } bool has_charset(void) const diff --git a/sql/field_conv.cc b/sql/field_conv.cc index 7bc6c432d1c..01b5306f5a4 100644 --- a/sql/field_conv.cc +++ b/sql/field_conv.cc @@ -119,12 +119,12 @@ set_field_to_null(Field *field) return 0; } field->reset(); - if (current_thd->count_cuted_fields == CHECK_FIELD_WARN) + if (field->table->in_use->count_cuted_fields == CHECK_FIELD_WARN) { field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1); return 0; } - if (!current_thd->no_errors) + if (!field->table->in_use->no_errors) my_error(ER_BAD_NULL_ERROR, MYF(0), field->field_name); return -1; } @@ -176,12 +176,12 @@ set_field_to_null_with_conversions(Field *field, bool no_conversions) field->table->auto_increment_field_not_null= FALSE; return 0; // field is set in handler.cc } - if (current_thd->count_cuted_fields == CHECK_FIELD_WARN) + if (field->table->in_use->count_cuted_fields == CHECK_FIELD_WARN) { field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_BAD_NULL_ERROR, 1); return 0; } - if (!current_thd->no_errors) + if (!field->table->in_use->no_errors) my_error(ER_BAD_NULL_ERROR, MYF(0), field->field_name); return -1; } @@ -403,7 +403,7 @@ static void do_varstring1(Copy_field *copy) if (length > copy->to_length- 1) { length=copy->to_length - 1; - if (current_thd->count_cuted_fields) + if (copy->from_field->table->in_use->count_cuted_fields) copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1); } @@ -418,7 +418,7 @@ static void do_varstring2(Copy_field *copy) if (length > copy->to_length- HA_KEY_BLOB_LENGTH) { length=copy->to_length-HA_KEY_BLOB_LENGTH; - if (current_thd->count_cuted_fields) + if (copy->from_field->table->in_use->count_cuted_fields) copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1); } diff --git a/sql/filesort.cc b/sql/filesort.cc index 01f3bb97557..5f8153e64e7 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -115,6 +115,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 @@ -127,7 +129,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); @@ -208,13 +209,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), @@ -241,8 +244,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) && @@ -275,8 +282,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)) @@ -302,18 +315,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)); @@ -1023,7 +1050,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/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index dfb33ce1f2c..48c7c195e10 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -413,7 +413,8 @@ Thd_ndb::get_open_table(THD *thd, const void *key) thd_ndb_share->stat.no_uncommitted_rows_count= 0; thd_ndb_share->stat.records= ~(ha_rows)0; } - DBUG_PRINT("exit", ("thd_ndb_share: 0x%x key: 0x%x", thd_ndb_share, key)); + DBUG_PRINT("exit", ("thd_ndb_share: 0x%lx key: 0x%lx", + (long) thd_ndb_share, (long) key)); DBUG_RETURN(thd_ndb_share); } @@ -761,8 +762,8 @@ int ha_ndbcluster::set_ndb_value(NdbOperation *ndb_op, Field *field, blob_ptr= (char*)""; } - DBUG_PRINT("value", ("set blob ptr=%p len=%u", - blob_ptr, blob_len)); + DBUG_PRINT("value", ("set blob ptr: 0x%lx len: %u", + (long) blob_ptr, blob_len)); DBUG_DUMP("value", (char*)blob_ptr, min(blob_len, 26)); if (set_blob_value) @@ -847,8 +848,8 @@ int get_ndb_blobs_value(TABLE* table, NdbValue* value_array, uint32 len= 0xffffffff; // Max uint32 if (ndb_blob->readData(buf, len) != 0) ERR_RETURN(ndb_blob->getNdbError()); - DBUG_PRINT("info", ("[%u] offset=%u buf=%p len=%u [ptrdiff=%d]", - i, offset, buf, len, (int)ptrdiff)); + DBUG_PRINT("info", ("[%u] offset: %u buf: 0x%lx len=%u [ptrdiff=%d]", + i, offset, (long) buf, len, (int)ptrdiff)); DBUG_ASSERT(len == len64); // Ugly hack assumes only ptr needs to be changed field_blob->ptr+= ptrdiff; @@ -1170,8 +1171,8 @@ int ha_ndbcluster::add_index_handle(THD *thd, NDBDICT *dict, KEY *key_info, index= dict->getIndexGlobal(index_name, *m_table); if (!index) ERR_RETURN(dict->getNdbError()); - DBUG_PRINT("info", ("index: 0x%x id: %d version: %d.%d status: %d", - index, + DBUG_PRINT("info", ("index: 0x%lx id: %d version: %d.%d status: %d", + (long) index, index->getObjectId(), index->getObjectVersion() & 0xFFFFFF, index->getObjectVersion() >> 24, @@ -1214,8 +1215,8 @@ int ha_ndbcluster::add_index_handle(THD *thd, NDBDICT *dict, KEY *key_info, index= dict->getIndexGlobal(unique_index_name, *m_table); if (!index) ERR_RETURN(dict->getNdbError()); - DBUG_PRINT("info", ("index: 0x%x id: %d version: %d.%d status: %d", - index, + DBUG_PRINT("info", ("index: 0x%lx id: %d version: %d.%d status: %d", + (long) index, index->getObjectId(), index->getObjectVersion() & 0xFFFFFF, index->getObjectVersion() >> 24, @@ -2076,7 +2077,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) @@ -2309,7 +2310,7 @@ int ha_ndbcluster::set_bounds(NdbIndexScanOperation *op, // Set bound if not done with this key if (p.key != NULL) { - DBUG_PRINT("info", ("key %d:%d offset=%d length=%d last=%d bound=%d", + DBUG_PRINT("info", ("key %d:%d offset: %d length: %d last: %d bound: %d", j, i, tot_len, part_len, p.part_last, p.bound_type)); DBUG_DUMP("info", (const char*)p.part_ptr, part_store_len); @@ -2538,7 +2539,7 @@ int ha_ndbcluster::full_table_scan(byte *buf) part_spec.start_part= 0; part_spec.end_part= m_part_info->get_tot_partitions() - 1; prune_partition_set(table, &part_spec); - DBUG_PRINT("info", ("part_spec.start_part = %u, part_spec.end_part = %u", + DBUG_PRINT("info", ("part_spec.start_part: %u part_spec.end_part: %u", part_spec.start_part, part_spec.end_part)); /* If partition pruning has found no partition in set @@ -2734,7 +2735,7 @@ int ha_ndbcluster::write_row(byte *record) { // Send rows to NDB DBUG_PRINT("info", ("Sending inserts to NDB, "\ - "rows_inserted:%d, bulk_insert_rows: %d", + "rows_inserted: %d bulk_insert_rows: %d", (int)m_rows_inserted, (int)m_bulk_insert_rows)); m_bulk_insert_not_flushed= FALSE; @@ -2833,6 +2834,21 @@ int ha_ndbcluster::update_row(const byte *old_data, byte *new_data) DBUG_ENTER("update_row"); m_write_op= TRUE; + /* + * If IGNORE the ignore constraint violations on primary and unique keys + */ + if (m_ignore_dup_key) + { + int peek_res= peek_indexed_rows(new_data); + + 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) { @@ -3184,7 +3200,8 @@ void ndb_unpack_record(TABLE *table, NdbValue *value, char* ptr; field_blob->get_ptr(&ptr, row_offset); uint32 len= field_blob->get_length(row_offset); - DBUG_PRINT("info",("[%u] SET ptr=%p len=%u", col_no, ptr, len)); + DBUG_PRINT("info",("[%u] SET ptr: 0x%lx len: %u", + col_no, (long) ptr, len)); #endif } } @@ -3426,7 +3443,7 @@ int ha_ndbcluster::read_range_first_to_buf(const key_range *start_key, if (m_use_partition_function) { get_partition_set(table, buf, active_index, start_key, &part_spec); - DBUG_PRINT("info", ("part_spec.start_part = %u, part_spec.end_part = %u", + DBUG_PRINT("info", ("part_spec.start_part: %u part_spec.end_part: %u", part_spec.start_part, part_spec.end_part)); /* If partition pruning has found no partition in set @@ -3561,7 +3578,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)); @@ -3969,7 +3986,7 @@ int ha_ndbcluster::end_bulk_insert() NdbTransaction *trans= m_active_trans; // Send rows to NDB DBUG_PRINT("info", ("Sending inserts to NDB, "\ - "rows_inserted:%d, bulk_insert_rows: %d", + "rows_inserted: %d bulk_insert_rows: %d", (int) m_rows_inserted, (int) m_bulk_insert_rows)); m_bulk_insert_not_flushed= FALSE; if (m_transaction_on) @@ -4379,8 +4396,8 @@ static int ndbcluster_commit(handlerton *hton, 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->key, 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); @@ -4783,8 +4800,7 @@ int ha_ndbcluster::create(const char *name, my_free((char*)data, MYF(0)); DBUG_RETURN(2); } - - DBUG_PRINT("info", ("setFrm data=%lx 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)); @@ -5200,13 +5216,12 @@ void ha_ndbcluster::prepare_for_alter() int ha_ndbcluster::add_index(TABLE *table_arg, KEY *key_info, uint num_of_keys) { - DBUG_ENTER("ha_ndbcluster::add_index"); - DBUG_PRINT("info", ("ha_ndbcluster::add_index to table %s", - table_arg->s->table_name)); int error= 0; uint idx; - + DBUG_ENTER("ha_ndbcluster::add_index"); + DBUG_PRINT("enter", ("table %s", table_arg->s->table_name.str)); DBUG_ASSERT(m_share->state == NSS_ALTERED); + for (idx= 0; idx < num_of_keys; idx++) { KEY *key= key_info + idx; @@ -6761,7 +6776,7 @@ static int ndbcluster_end(handlerton *hton, ha_panic_function type) void ha_ndbcluster::print_error(int error, myf errflag) { DBUG_ENTER("ha_ndbcluster::print_error"); - DBUG_PRINT("enter", ("error = %d", error)); + DBUG_PRINT("enter", ("error: %d", error)); if (error == HA_ERR_NO_PARTITION_FOUND) m_part_info->print_no_partition_found(table); @@ -7267,16 +7282,16 @@ static void dbug_print_open_tables() for (uint i= 0; i < ndbcluster_open_tables.records; i++) { NDB_SHARE *share= (NDB_SHARE*) hash_element(&ndbcluster_open_tables, i); - DBUG_PRINT("share", - ("[%d] 0x%lx key: %s key_length: %d", - i, share, share->key, share->key_length)); - DBUG_PRINT("share", - ("db.tablename: %s.%s use_count: %d commit_count: %d", + DBUG_PRINT("loop", + ("[%d] 0x%lx key: %s key_length: %d", + i, (long) share, share->key, share->key_length)); + DBUG_PRINT("loop", + ("db.tablename: %s.%s use_count: %d commit_count: %lu", share->db, share->table_name, - share->use_count, share->commit_count)); + share->use_count, (ulong) share->commit_count)); #ifdef HAVE_NDB_BINLOG if (share->table) - DBUG_PRINT("share", + DBUG_PRINT("loop", ("table->s->db.table_name: %s.%s", share->table->s->db.str, share->table->s->table_name.str)); #endif @@ -7429,13 +7444,13 @@ static int rename_share(NDB_SHARE *share, const char *new_key) share->table_name= share->db + strlen(share->db) + 1; ha_ndbcluster::set_tabname(new_key, share->table_name); - DBUG_PRINT("rename_share", - ("0x%lx key: %s key_length: %d", - share, share->key, share->key_length)); - DBUG_PRINT("rename_share", - ("db.tablename: %s.%s use_count: %d commit_count: %d", + DBUG_PRINT("info", + ("share: 0x%lx key: %s key_length: %d", + (long) share, share->key, share->key_length)); + DBUG_PRINT("info", + ("db.tablename: %s.%s use_count: %d commit_count: %lu", share->db, share->table_name, - share->use_count, share->commit_count)); + share->use_count, (ulong) share->commit_count)); if (share->table) { DBUG_PRINT("rename_share", @@ -7470,13 +7485,13 @@ NDB_SHARE *ndbcluster_get_share(NDB_SHARE *share) dbug_print_open_tables(); - DBUG_PRINT("get_share", - ("0x%lx key: %s key_length: %d", - share, share->key, share->key_length)); - DBUG_PRINT("get_share", - ("db.tablename: %s.%s use_count: %d commit_count: %d", + DBUG_PRINT("info", + ("share: 0x%lx key: %s key_length: %d", + (long) share, share->key, share->key_length)); + DBUG_PRINT("info", + ("db.tablename: %s.%s use_count: %d commit_count: %lu", share->db, share->table_name, - share->use_count, share->commit_count)); + share->use_count, (ulong) share->commit_count)); pthread_mutex_unlock(&ndbcluster_mutex); return share; } @@ -7570,11 +7585,11 @@ NDB_SHARE *ndbcluster_get_share(const char *key, TABLE *table, DBUG_PRINT("info", ("0x%lx key: %s key_length: %d key: %s", - share, share->key, share->key_length, key)); + (long) share, share->key, share->key_length, key)); DBUG_PRINT("info", - ("db.tablename: %s.%s use_count: %d commit_count: %d", + ("db.tablename: %s.%s use_count: %d commit_count: %lu", share->db, share->table_name, - share->use_count, share->commit_count)); + share->use_count, (ulong) share->commit_count)); if (!have_lock) pthread_mutex_unlock(&ndbcluster_mutex); DBUG_RETURN(share); @@ -7584,13 +7599,12 @@ NDB_SHARE *ndbcluster_get_share(const char *key, TABLE *table, void ndbcluster_real_free_share(NDB_SHARE **share) { DBUG_ENTER("ndbcluster_real_free_share"); - DBUG_PRINT("real_free_share", - ("0x%lx key: %s key_length: %d", - (*share), (*share)->key, (*share)->key_length)); - DBUG_PRINT("real_free_share", - ("db.tablename: %s.%s use_count: %d commit_count: %d", + DBUG_PRINT("enter", + ("share: 0x%lx key: %s key_length: %d " + "db.tablename: %s.%s use_count: %d commit_count: %lu", + (long) (*share), (*share)->key, (*share)->key_length, (*share)->db, (*share)->table_name, - (*share)->use_count, (*share)->commit_count)); + (*share)->use_count, (ulong) (*share)->commit_count)); hash_delete(&ndbcluster_open_tables, (byte*) *share); thr_lock_delete(&(*share)->lock); @@ -7638,13 +7652,13 @@ void ndbcluster_free_share(NDB_SHARE **share, bool have_lock) else { dbug_print_open_tables(); - DBUG_PRINT("free_share", - ("0x%lx key: %s key_length: %d", - *share, (*share)->key, (*share)->key_length)); - DBUG_PRINT("free_share", - ("db.tablename: %s.%s use_count: %d commit_count: %d", + DBUG_PRINT("info", + ("share: 0x%lx key: %s key_length: %d", + (long) *share, (*share)->key, (*share)->key_length)); + DBUG_PRINT("info", + ("db.tablename: %s.%s use_count: %d commit_count: %lu", (*share)->db, (*share)->table_name, - (*share)->use_count, (*share)->commit_count)); + (*share)->use_count, (ulong) (*share)->commit_count)); } if (!have_lock) pthread_mutex_unlock(&ndbcluster_mutex); @@ -7941,7 +7955,7 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p, get_partition_set(table, curr, active_index, &multi_range_curr->start_key, &part_spec); - DBUG_PRINT("info", ("part_spec.start_part = %u, part_spec.end_part = %u", + DBUG_PRINT("info", ("part_spec.start_part: %u part_spec.end_part: %u", part_spec.start_part, part_spec.end_part)); /* If partition pruning has found no partition in set @@ -8307,7 +8321,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); @@ -8395,7 +8409,7 @@ pthread_handler_t ndb_util_thread_func(void *arg __attribute__((unused))) &abstime); pthread_mutex_unlock(&LOCK_ndb_util_thread); #ifdef NDB_EXTRA_DEBUG_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)); #endif if (abort_loop) @@ -8473,8 +8487,8 @@ pthread_handler_t ndb_util_thread_func(void *arg __attribute__((unused))) ndb_get_table_statistics(NULL, false, ndb, ndbtab_g.get_table(), &stat) == 0) { char buff[22], buff2[22]; - DBUG_PRINT("ndb_util_thread", - ("Table: %s, commit_count: %llu, rows: %llu", + DBUG_PRINT("info", + ("Table: %s commit_count: %s rows: %s", share->key, llstr(stat.commit_count, buff), llstr(stat.row_count, buff2))); @@ -9316,7 +9330,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); @@ -9339,7 +9353,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; @@ -9387,7 +9401,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; diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc index 8eae4a676d1..92bc82f3114 100644 --- a/sql/ha_ndbcluster_binlog.cc +++ b/sql/ha_ndbcluster_binlog.cc @@ -162,16 +162,16 @@ static void dbug_print_table(const char *info, TABLE *table) } DBUG_PRINT("info", ("%s: %s.%s s->fields: %d " - "reclength: %d rec_buff_length: %d record[0]: %lx " - "record[1]: %lx", + "reclength: %lu rec_buff_length: %u record[0]: 0x%lx " + "record[1]: 0x%lx", info, table->s->db.str, table->s->table_name.str, table->s->fields, table->s->reclength, table->s->rec_buff_length, - table->record[0], - table->record[1])); + (long) table->record[0], + (long) table->record[1])); for (unsigned int i= 0; i < table->s->fields; i++) { @@ -181,7 +181,7 @@ static void dbug_print_table(const char *info, TABLE *table) "ptr: 0x%lx[+%d] null_bit: %u null_ptr: 0x%lx[+%d]", i, f->field_name, - f->flags, + (long) f->flags, (f->flags & PRI_KEY_FLAG) ? "pri" : "attr", (f->flags & NOT_NULL_FLAG) ? "" : ",nullable", (f->flags & UNSIGNED_FLAG) ? ",unsigned" : ",signed", @@ -190,16 +190,18 @@ static void dbug_print_table(const char *info, TABLE *table) (f->flags & BINARY_FLAG) ? ",binary" : "", f->real_type(), f->pack_length(), - f->ptr, f->ptr - table->record[0], + (long) f->ptr, (int) (f->ptr - table->record[0]), f->null_bit, - f->null_ptr, (byte*) f->null_ptr - table->record[0])); + (long) f->null_ptr, + (int) ((byte*) f->null_ptr - table->record[0]))); if (f->type() == MYSQL_TYPE_BIT) { Field_bit *g= (Field_bit*) f; DBUG_PRINT("MYSQL_TYPE_BIT",("field_length: %d bit_ptr: 0x%lx[+%d] " - "bit_ofs: %u bit_len: %u", - g->field_length, g->bit_ptr, - (byte*) g->bit_ptr-table->record[0], + "bit_ofs: %d bit_len: %u", + g->field_length, (long) g->bit_ptr, + (int) ((byte*) g->bit_ptr - + table->record[0]), g->bit_ofs, g->bit_len)); } } @@ -606,11 +608,11 @@ static int ndbcluster_binlog_end(THD *thd) { DBUG_PRINT("share", ("[%d] 0x%lx key: %s key_length: %d", - i, share, share->key, share->key_length)); + i, (long) share, share->key, share->key_length)); DBUG_PRINT("share", - ("db.tablename: %s.%s use_count: %d commit_count: %d", + ("db.tablename: %s.%s use_count: %d commit_count: %lu", share->db, share->table_name, - share->use_count, share->commit_count)); + share->use_count, (long) share->commit_count)); } } pthread_mutex_unlock(&ndbcluster_mutex); @@ -686,8 +688,8 @@ static NDB_SHARE *ndbcluster_check_apply_status_share() void *share= hash_search(&ndbcluster_open_tables, NDB_APPLY_TABLE_FILE, sizeof(NDB_APPLY_TABLE_FILE) - 1); - DBUG_PRINT("info",("ndbcluster_check_apply_status_share %s %p", - NDB_APPLY_TABLE_FILE, share)); + DBUG_PRINT("info",("ndbcluster_check_apply_status_share %s 0x%lx", + NDB_APPLY_TABLE_FILE, (long) share)); pthread_mutex_unlock(&ndbcluster_mutex); return (NDB_SHARE*) share; } @@ -704,8 +706,8 @@ static NDB_SHARE *ndbcluster_check_schema_share() void *share= hash_search(&ndbcluster_open_tables, NDB_SCHEMA_TABLE_FILE, sizeof(NDB_SCHEMA_TABLE_FILE) - 1); - DBUG_PRINT("info",("ndbcluster_check_schema_share %s %p", - NDB_SCHEMA_TABLE_FILE, share)); + DBUG_PRINT("info",("ndbcluster_check_schema_share %s 0x%lx", + NDB_SCHEMA_TABLE_FILE, (long) share)); pthread_mutex_unlock(&ndbcluster_mutex); return (NDB_SHARE*) share; } @@ -2761,10 +2763,9 @@ ndbcluster_create_event_ops(NDB_SHARE *share, const NDBTAB *ndbtab, if (share->flags & NSF_BLOB_FLAG) op->mergeEvents(TRUE); // currently not inherited from event - DBUG_PRINT("info", ("share->ndb_value[0]: 0x%x", - share->ndb_value[0])); - DBUG_PRINT("info", ("share->ndb_value[1]: 0x%x", - share->ndb_value[1])); + DBUG_PRINT("info", ("share->ndb_value[0]: 0x%lx share->ndb_value[1]: 0x%lx", + (long) share->ndb_value[0], + (long) share->ndb_value[1])); int n_columns= ndbtab->getNoOfColumns(); int n_fields= table ? table->s->fields : 0; // XXX ??? for (int j= 0; j < n_columns; j++) @@ -2818,12 +2819,14 @@ ndbcluster_create_event_ops(NDB_SHARE *share, const NDBTAB *ndbtab, } share->ndb_value[0][j].ptr= attr0.ptr; share->ndb_value[1][j].ptr= attr1.ptr; - DBUG_PRINT("info", ("&share->ndb_value[0][%d]: 0x%x " - "share->ndb_value[0][%d]: 0x%x", - j, &share->ndb_value[0][j], j, attr0.ptr)); - DBUG_PRINT("info", ("&share->ndb_value[1][%d]: 0x%x " - "share->ndb_value[1][%d]: 0x%x", - j, &share->ndb_value[0][j], j, attr1.ptr)); + DBUG_PRINT("info", ("&share->ndb_value[0][%d]: 0x%lx " + "share->ndb_value[0][%d]: 0x%lx", + j, (long) &share->ndb_value[0][j], + j, (long) attr0.ptr)); + DBUG_PRINT("info", ("&share->ndb_value[1][%d]: 0x%lx " + "share->ndb_value[1][%d]: 0x%lx", + j, (long) &share->ndb_value[0][j], + j, (long) attr1.ptr)); } op->setCustomData((void *) share); // set before execute share->op= op; // assign op in NDB_SHARE @@ -2866,8 +2869,8 @@ ndbcluster_create_event_ops(NDB_SHARE *share, const NDBTAB *ndbtab, (void) pthread_cond_signal(&injector_cond); } - DBUG_PRINT("info",("%s share->op: 0x%lx, share->use_count: %u", - share->key, share->op, share->use_count)); + DBUG_PRINT("info",("%s share->op: 0x%lx share->use_count: %u", + share->key, (long) share->op, share->use_count)); if (ndb_extra_logging) sql_print_information("NDB Binlog: logging %s", share->key); @@ -3052,10 +3055,11 @@ ndb_binlog_thread_handle_non_data_event(THD *thd, Ndb *ndb, free_share(&apply_status_share); apply_status_share= 0; } - DBUG_PRINT("info", ("CLUSTER FAILURE EVENT: " - "%s received share: 0x%lx op: %lx share op: %lx " - "op_old: %lx", - share->key, share, pOp, share->op, share->op_old)); + DBUG_PRINT("error", ("CLUSTER FAILURE EVENT: " + "%s received share: 0x%lx op: 0x%lx share op: 0x%lx " + "op_old: 0x%lx", + share->key, (long) share, (long) pOp, + (long) share->op, (long) share->op_old)); break; case NDBEVENT::TE_DROP: if (apply_status_share == share) @@ -3073,10 +3077,11 @@ ndb_binlog_thread_handle_non_data_event(THD *thd, Ndb *ndb, // fall through case NDBEVENT::TE_ALTER: row.n_schemaops++; - DBUG_PRINT("info", ("TABLE %s EVENT: %s received share: 0x%lx op: %lx " - "share op: %lx op_old: %lx", - type == NDBEVENT::TE_DROP ? "DROP" : "ALTER", - share->key, share, pOp, share->op, share->op_old)); + DBUG_PRINT("info", ("TABLE %s EVENT: %s received share: 0x%lx op: 0x%lx " + "share op: 0x%lx op_old: 0x%lx", + type == NDBEVENT::TE_DROP ? "DROP" : "ALTER", + share->key, (long) share, (long) pOp, + (long) share->op, (long) share->op_old)); break; case NDBEVENT::TE_NODE_FAILURE: /* fall through */ @@ -3476,7 +3481,6 @@ pthread_handler_t ndb_binlog_thread_func(void *arg) global_system_variables.binlog_format == BINLOG_FORMAT_MIXED) { ndb_binlog_running= TRUE; - thd->current_stmt_binlog_row_based= TRUE; // If in mixed mode } else { @@ -3554,7 +3558,8 @@ restart: } } // now check that we have epochs consistant with what we had before the restart - DBUG_PRINT("info", ("schema_res: %d schema_gci: %d", schema_res, schema_gci)); + DBUG_PRINT("info", ("schema_res: %d schema_gci: %lu", schema_res, + (long) schema_gci)); { i_ndb->flushIncompleteEvents(schema_gci); s_ndb->flushIncompleteEvents(schema_gci); @@ -3598,9 +3603,11 @@ restart: if (do_ndbcluster_binlog_close_connection) { DBUG_PRINT("info", ("do_ndbcluster_binlog_close_connection: %d, " - "ndb_latest_handled_binlog_epoch: %llu, " - "*p_latest_trans_gci: %llu", do_ndbcluster_binlog_close_connection, - ndb_latest_handled_binlog_epoch, *p_latest_trans_gci)); + "ndb_latest_handled_binlog_epoch: %lu, " + "*p_latest_trans_gci: %lu", + do_ndbcluster_binlog_close_connection, + (ulong) ndb_latest_handled_binlog_epoch, + (ulong) *p_latest_trans_gci)); } #endif #ifdef RUN_NDB_BINLOG_TIMER @@ -3688,9 +3695,10 @@ restart: do_ndbcluster_binlog_close_connection= BCCC_restart; if (ndb_latest_received_binlog_epoch < *p_latest_trans_gci && ndb_binlog_running) { - sql_print_error("NDB Binlog: latest transaction in epoch %lld not in binlog " - "as latest received epoch is %lld", - *p_latest_trans_gci, ndb_latest_received_binlog_epoch); + sql_print_error("NDB Binlog: latest transaction in epoch %lu not in binlog " + "as latest received epoch is %lu", + (ulong) *p_latest_trans_gci, + (ulong) ndb_latest_received_binlog_epoch); } } } @@ -3738,8 +3746,8 @@ restart: != NULL) { NDB_SHARE *share= (NDB_SHARE*)gci_op->getCustomData(); - DBUG_PRINT("info", ("per gci_op: %p share: %p event_types: 0x%x", - gci_op, share, event_types)); + DBUG_PRINT("info", ("per gci_op: 0x%lx share: 0x%lx event_types: 0x%x", + (long) gci_op, (long) share, event_types)); // workaround for interface returning TE_STOP events // which are normally filtered out below in the nextEvent loop if ((event_types & ~NdbDictionary::Event::TE_STOP) == 0) @@ -3825,11 +3833,13 @@ restart: { NDB_SHARE *share= (NDB_SHARE*) pOp->getCustomData(); DBUG_PRINT("info", - ("EVENT TYPE: %d GCI: %lld last applied: %lld " - "share: 0x%lx (%s.%s)", pOp->getEventType(), gci, - ndb_latest_applied_binlog_epoch, share, - share ? share->db : "share == NULL", - share ? share->table_name : "")); + ("EVENT TYPE: %d GCI: %ld last applied: %ld " + "share: 0x%lx (%s.%s)", pOp->getEventType(), + (long) gci, + (long) ndb_latest_applied_binlog_epoch, + (long) share, + share ? share->db : "'NULL'", + share ? share->table_name : "'NULL'")); DBUG_ASSERT(share != 0); } // assert that there is consistancy between gci op list @@ -3874,9 +3884,10 @@ restart: do_ndbcluster_binlog_close_connection= BCCC_restart; if (ndb_latest_received_binlog_epoch < *p_latest_trans_gci && ndb_binlog_running) { - sql_print_error("NDB Binlog: latest transaction in epoch %lld not in binlog " - "as latest received epoch is %lld", - *p_latest_trans_gci, ndb_latest_received_binlog_epoch); + sql_print_error("NDB Binlog: latest transaction in epoch %lu not in binlog " + "as latest received epoch is %lu", + (ulong) *p_latest_trans_gci, + (ulong) ndb_latest_received_binlog_epoch); } } } @@ -3908,7 +3919,7 @@ restart: row.master_log_file= start.file_name(); row.master_log_pos= start.file_pos(); - DBUG_PRINT("info", ("COMMIT gci: %lld", gci)); + DBUG_PRINT("info", ("COMMIT gci: %lu", (ulong) gci)); if (ndb_update_binlog_index) ndb_add_binlog_index(thd, &row); ndb_latest_applied_binlog_epoch= gci; diff --git a/sql/ha_ndbcluster_tables.h b/sql/ha_ndbcluster_tables.h index 12124cd8820..9d7fda33102 100644 --- a/sql/ha_ndbcluster_tables.h +++ b/sql/ha_ndbcluster_tables.h @@ -15,7 +15,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#define NDB_REP_DB "cluster" +#define NDB_REP_DB "mysql" #define NDB_REP_TABLE "binlog_index" #define NDB_APPLY_TABLE "apply_status" #define NDB_SCHEMA_TABLE "schema" diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 3edd3923779..7cd33dd5726 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -2027,7 +2027,7 @@ bool ha_partition::create_handlers(MEM_ROOT *mem_root) if (!(m_file[i]= get_new_handler(table_share, mem_root, m_engine_array[i]))) DBUG_RETURN(TRUE); - DBUG_PRINT("info", ("engine_type: %u", m_engine_array[i])); + DBUG_PRINT("info", ("engine_type: %u", m_engine_array[i]->db_type)); } /* For the moment we only support partition over the same table engine */ if (m_engine_array[0] == myisam_hton) @@ -2427,7 +2427,7 @@ repeat: do { DBUG_PRINT("info", ("external_lock(thd, %d) iteration %d", - lock_type, (file - m_file))); + lock_type, (int) (file - m_file))); if ((error= (*file)->external_lock(thd, lock_type))) { if (F_UNLCK != lock_type) @@ -2508,7 +2508,7 @@ THR_LOCK_DATA **ha_partition::store_lock(THD *thd, file= m_file; do { - DBUG_PRINT("info", ("store lock %d iteration", (file - m_file))); + DBUG_PRINT("info", ("store lock %d iteration", (int) (file - m_file))); to= (*file)->store_lock(thd, to, lock_type); } while (*(++file)); DBUG_RETURN(to); @@ -2939,8 +2939,8 @@ int ha_partition::rnd_init(bool scan) include_partition_fields_in_used_fields(); /* Now we see what the index of our first important partition is */ - DBUG_PRINT("info", ("m_part_info->used_partitions 0x%x", - m_part_info->used_partitions.bitmap)); + DBUG_PRINT("info", ("m_part_info->used_partitions: 0x%lx", + (long) m_part_info->used_partitions.bitmap)); part_id= bitmap_get_first_set(&(m_part_info->used_partitions)); DBUG_PRINT("info", ("m_part_spec.start_part %d", part_id)); diff --git a/sql/handler.cc b/sql/handler.cc index 451f974a066..85345c70e36 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1513,7 +1513,7 @@ int handler::ha_open(TABLE *table_arg, const char *name, int mode, DBUG_ENTER("handler::ha_open"); DBUG_PRINT("enter", ("name: %s db_type: %d db_stat: %d mode: %d lock_test: %d", - name, table_share->db_type, table_arg->db_stat, mode, + name, ht->db_type, table_arg->db_stat, mode, test_if_locked)); table= table_arg; @@ -1654,7 +1654,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) @@ -1927,8 +1927,8 @@ int handler::update_auto_increment() void handler::column_bitmaps_signal() { DBUG_ENTER("column_bitmaps_signal"); - DBUG_PRINT("info", ("read_set: 0x%lx write_set: 0x%lx", table->read_set, - table->write_set)); + DBUG_PRINT("info", ("read_set: 0x%lx write_set: 0x%lx", (long) table->read_set, + (long) table->write_set)); DBUG_VOID_RETURN; } @@ -2119,8 +2119,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; @@ -3460,38 +3460,15 @@ bool ha_show_status(THD *thd, handlerton *db_type, enum ha_stat_type stat) declared static, but it works by putting it into an anonymous namespace. */ namespace { - struct st_table_data { - char const *db; - char const *name; - }; - - static int table_name_compare(void const *a, void const *b) - { - st_table_data const *x = (st_table_data const*) a; - st_table_data const *y = (st_table_data const*) b; - - /* Doing lexical compare in order (db,name) */ - int const res= strcmp(x->db, y->db); - return res != 0 ? res : strcmp(x->name, y->name); - } - bool check_table_binlog_row_based(THD *thd, TABLE *table) { - static st_table_data const ignore[] = { - { "mysql", "event" }, - { "mysql", "general_log" }, - { "mysql", "slow_log" } - }; - - my_size_t const ignore_size = sizeof(ignore)/sizeof(*ignore); - st_table_data const item = { table->s->db.str, table->s->table_name.str }; - if (table->s->cached_row_logging_check == -1) - table->s->cached_row_logging_check= - (table->s->tmp_table == NO_TMP_TABLE) && - binlog_filter->db_ok(table->s->db.str) && - bsearch(&item, ignore, ignore_size, - sizeof(st_table_data), table_name_compare) == NULL; + { + int const check(table->s->tmp_table == NO_TMP_TABLE && + binlog_filter->db_ok(table->s->db.str) && + strcmp("mysql", table->s->db.str) != 0); + table->s->cached_row_logging_check= check; + } DBUG_ASSERT(table->s->cached_row_logging_check == 0 || table->s->cached_row_logging_check == 1); @@ -3530,8 +3507,10 @@ namespace int write_locked_table_maps(THD *thd) { DBUG_ENTER("write_locked_table_maps"); - DBUG_PRINT("enter", ("thd=%p, thd->lock=%p, thd->locked_tables=%p, thd->extra_lock", - thd, thd->lock, thd->locked_tables, thd->extra_lock)); + DBUG_PRINT("enter", ("thd: 0x%lx thd->lock: 0x%lx thd->locked_tables: 0x%lx " + "thd->extra_lock: 0x%lx", + (long) thd, (long) thd->lock, + (long) thd->locked_tables, (long) thd->extra_lock)); if (thd->get_binlog_table_maps() == 0) { @@ -3551,7 +3530,7 @@ namespace ++table_ptr) { TABLE *const table= *table_ptr; - DBUG_PRINT("info", ("Checking table %s", table->s->table_name)); + DBUG_PRINT("info", ("Checking table %s", table->s->table_name.str)); if (table->current_lock == F_WRLCK && check_table_binlog_row_based(thd, table)) { diff --git a/sql/handler.h b/sql/handler.h index 888f837d427..f27912f4d1e 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -684,6 +684,7 @@ struct handlerton int (*table_exists_in_engine)(handlerton *hton, THD* thd, const char *db, const char *name); uint32 license; /* Flag for Engine License */ + void *data; /* Location for engines to keep personal structures */ }; diff --git a/sql/item.cc b/sql/item.cc index f8a8b4a6272..e15672e4d45 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -269,6 +269,34 @@ 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; + longlong date; + 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; + longlong date; + 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 */ @@ -292,6 +320,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), @@ -1176,6 +1223,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 @@ -1228,8 +1297,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); @@ -1655,7 +1724,7 @@ void Item_field::set_field(Field *field_par) db_name= field_par->table->s->db.str; 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; } @@ -3672,11 +3741,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) @@ -4193,6 +4288,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; } diff --git a/sql/item.h b/sql/item.h index 8799fa07eb7..126e106330d 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 @@ -658,9 +646,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; } @@ -2061,6 +2054,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 691715c3bff..b1b73a523be 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -833,9 +833,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(); @@ -2229,7 +2261,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++) @@ -2519,7 +2551,6 @@ void Item_func_in::fix_length_and_dec() } } } - maybe_null= args[0]->maybe_null; max_length= 1; } @@ -3061,7 +3092,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 c2d93fdd5ef..51cf5667c95 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>"; } @@ -258,9 +277,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 @@ -278,6 +299,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 @@ -1095,6 +1120,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_create.cc b/sql/item_create.cc index 7722ce28d4a..da8954910c8 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -2612,15 +2612,8 @@ Create_func_benchmark Create_func_benchmark::s_singleton; Item* Create_func_benchmark::create(THD *thd, Item *arg1, Item *arg2) { - /* TODO: Known limitation, see Bug#22684 */ - if ((arg1->type() != Item::INT_ITEM) || ! arg1->basic_const_item()) - { - my_error(ER_WRONG_PARAMETERS_TO_NATIVE_FCT, MYF(0), "BENCHMARK"); - return NULL; - } - thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); - return new (thd->mem_root) Item_func_benchmark(arg1->val_int(), arg2); + return new (thd->mem_root) Item_func_benchmark(arg1, arg2); } @@ -2887,17 +2880,7 @@ Create_func_decode Create_func_decode::s_singleton; Item* Create_func_decode::create(THD *thd, Item *arg1, Item *arg2) { - /* TODO: Known limitation, see Bug#22684 */ - if ((arg2->type() != Item::STRING_ITEM) || ! arg2->basic_const_item()) - { - my_error(ER_WRONG_PARAMETERS_TO_NATIVE_FCT, MYF(0), "DECODE"); - return NULL; - } - - String dummy; - String *val = arg2->val_str(& dummy); - DBUG_ASSERT(val); - return new (thd->mem_root) Item_func_decode(arg1, val->c_ptr()); + return new (thd->mem_root) Item_func_decode(arg1, arg2); } @@ -3033,17 +3016,7 @@ Create_func_encode Create_func_encode::s_singleton; Item* Create_func_encode::create(THD *thd, Item *arg1, Item *arg2) { - /* TODO: Known limitation, see Bug#22684 */ - if ((arg2->type() != Item::STRING_ITEM) || ! arg2->basic_const_item()) - { - my_error(ER_WRONG_PARAMETERS_TO_NATIVE_FCT, MYF(0), "ENCODE"); - return NULL; - } - - String dummy; - String *val = arg2->val_str(& dummy); - DBUG_ASSERT(val); - return new (thd->mem_root) Item_func_encode(arg1, val->c_ptr()); + return new (thd->mem_root) Item_func_encode(arg1, arg2); } @@ -3235,14 +3208,7 @@ Create_func_format Create_func_format::s_singleton; Item* Create_func_format::create(THD *thd, Item *arg1, Item *arg2) { - /* TODO: Known limitation, see Bug#22684 */ - if ((arg2->type() != Item::INT_ITEM) || ! arg2->basic_const_item()) - { - my_error(ER_WRONG_PARAMETERS_TO_NATIVE_FCT, MYF(0), "FORMAT"); - return NULL; - } - - return new (thd->mem_root) Item_func_format(arg1, arg2->val_int()); + return new (thd->mem_root) Item_func_format(arg1, arg2); } diff --git a/sql/item_func.cc b/sql/item_func.cc index fa17dee9605..e658a70d7cb 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -961,7 +961,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,21 +2337,27 @@ longlong Item_func_locate::val_int() return 0; /* purecov: inspected */ } null_value=0; - uint start=0; - uint start0=0; + /* must be longlong to avoid truncation */ + longlong start= 0; + longlong start0= 0; my_match_t match; if (arg_count == 3) { - start0= start =(uint) args[2]->val_int()-1; - start=a->charpos(start); - - if (start > a->length() || start+b->length() > a->length()) + start0= start= args[2]->val_int() - 1; + + if ((start < 0) || (start > a->length())) + return 0; + + /* start is now sufficiently valid to pass to charpos function */ + start= a->charpos(start); + + if (start + b->length() > a->length()) return 0; } if (!b->length()) // Found empty string at start - return (longlong) (start+1); + return start + 1; if (!cmp_collation.collation->coll->instr(cmp_collation.collation, a->ptr()+start, a->length()-start, @@ -2893,6 +2906,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); @@ -3397,18 +3424,28 @@ longlong Item_func_benchmark::val_int() char buff[MAX_FIELD_WIDTH]; String tmp(buff,sizeof(buff), &my_charset_bin); THD *thd=current_thd; + ulong loop_count; + + loop_count= args[0]->val_int(); + if (args[0]->null_value) + { + null_value= 1; + return 0; + } + + null_value=0; for (ulong loop=0 ; loop < loop_count && !thd->killed; loop++) { - switch (args[0]->result_type()) { + switch (args[1]->result_type()) { case REAL_RESULT: - (void) args[0]->val_real(); + (void) args[1]->val_real(); break; case INT_RESULT: - (void) args[0]->val_int(); + (void) args[1]->val_int(); break; case STRING_RESULT: - (void) args[0]->val_str(&tmp); + (void) args[1]->val_str(&tmp); break; case ROW_RESULT: default: @@ -3424,13 +3461,9 @@ longlong Item_func_benchmark::val_int() void Item_func_benchmark::print(String *str) { str->append(STRING_WITH_LEN("benchmark(")); - char buffer[20]; - // my_charset_bin is good enough for numbers - String st(buffer, sizeof(buffer), &my_charset_bin); - st.set((ulonglong)loop_count, &my_charset_bin); - str->append(st); - str->append(','); args[0]->print(str); + str->append(','); + args[1]->print(str); str->append(')'); } @@ -4846,6 +4879,7 @@ Item_func_sp::cleanup() result_field= NULL; } m_sp= NULL; + dummy_table->alias= NULL; Item_func::cleanup(); } @@ -5038,7 +5072,7 @@ Item_func_sp::result_type() const { Field *field; DBUG_ENTER("Item_func_sp::result_type"); - DBUG_PRINT("info", ("m_sp = %p", m_sp)); + DBUG_PRINT("info", ("m_sp: 0x%lx", (long) m_sp)); if (result_field) DBUG_RETURN(result_field->result_type()); diff --git a/sql/item_func.h b/sql/item_func.h index dc4371ac967..5dca1705f9a 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -925,10 +925,9 @@ public: class Item_func_benchmark :public Item_int_func { - ulong loop_count; public: - Item_func_benchmark(ulong loop_count_arg,Item *expr) - :Item_int_func(expr), loop_count(loop_count_arg) + Item_func_benchmark(Item *count_expr, Item *expr) + :Item_int_func(count_expr, expr) {} longlong val_int(); const char *func_name() const { return "benchmark"; } @@ -980,6 +979,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); }; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index bf837f6720b..32b283fca57 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); @@ -951,24 +965,35 @@ String *Item_func_insert::val_str(String *str) { DBUG_ASSERT(fixed == 1); String *res,*res2; - uint start,length; + longlong start, length; /* must be longlong to avoid truncation */ null_value=0; res=args[0]->val_str(str); res2=args[3]->val_str(&tmp_value); - start=(uint) args[1]->val_int()-1; - length=(uint) args[2]->val_int(); + start= args[1]->val_int() - 1; + length= args[2]->val_int(); + if (args[0]->null_value || args[1]->null_value || args[2]->null_value || args[3]->null_value) goto null; /* purecov: inspected */ - start=res->charpos(start); - length=res->charpos(length,start); - if (start > res->length()+1) - return res; // Wrong param; skip insert - if (length > res->length()-start) - length=res->length()-start; - if (res->length() - length + res2->length() > - current_thd->variables.max_allowed_packet) + + if ((start < 0) || (start > res->length() + 1)) + return res; // Wrong param; skip insert + if ((length < 0) || (length > res->length() + 1)) + 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); + + /* Re-testing with corrected params */ + if (start > res->length() + 1) + return res; // Wrong param; skip insert + if (length > res->length() - start) + length= res->length() - start; + + 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, @@ -1039,16 +1064,21 @@ String *Item_str_conv::val_str(String *str) String *Item_func_left::val_str(String *str) { DBUG_ASSERT(fixed == 1); - String *res =args[0]->val_str(str); - long length =(long) args[1]->val_int(); + String *res= args[0]->val_str(str); + + /* must be longlong to avoid truncation */ + longlong length= args[1]->val_int(); uint char_pos; if ((null_value=(args[0]->null_value || args[1]->null_value))) return 0; - if (length <= 0) + + /* if "unsigned_flag" is set, we have a *huge* positive number. */ + if ((length <= 0) && (!args[1]->unsigned_flag)) return &my_empty_string; - if (res->length() <= (uint) length || - res->length() <= (char_pos= res->charpos(length))) + + if ((res->length() <= (ulonglong) length) || + (res->length() <= (char_pos= res->charpos(length)))) return res; tmp_value.set(*res, 0, char_pos); @@ -1080,14 +1110,18 @@ void Item_func_left::fix_length_and_dec() String *Item_func_right::val_str(String *str) { DBUG_ASSERT(fixed == 1); - String *res =args[0]->val_str(str); - long length =(long) args[1]->val_int(); + String *res= args[0]->val_str(str); + /* must be longlong to avoid truncation */ + longlong length= args[1]->val_int(); if ((null_value=(args[0]->null_value || args[1]->null_value))) return 0; /* purecov: inspected */ - if (length <= 0) + + /* if "unsigned_flag" is set, we have a *huge* positive number. */ + if ((length <= 0) && (!args[1]->unsigned_flag)) return &my_empty_string; /* purecov: inspected */ - if (res->length() <= (uint) length) + + if (res->length() <= (ulonglong) length) return res; /* purecov: inspected */ uint start=res->numchars(); @@ -1110,25 +1144,43 @@ String *Item_func_substr::val_str(String *str) { DBUG_ASSERT(fixed == 1); String *res = args[0]->val_str(str); - int32 start = (int32) args[1]->val_int(); - int32 length = arg_count == 3 ? (int32) args[2]->val_int() : INT_MAX32; - int32 tmp_length; + /* must be longlong to avoid truncation */ + longlong start= args[1]->val_int(); + /* Assumes that the maximum length of a String is < INT_MAX32. */ + /* Limit so that code sees out-of-bound value properly. */ + longlong length= arg_count == 3 ? args[2]->val_int() : INT_MAX32; + longlong tmp_length; if ((null_value=(args[0]->null_value || args[1]->null_value || (arg_count == 3 && args[2]->null_value)))) return 0; /* purecov: inspected */ - start= (int32)((start < 0) ? res->numchars() + start : start -1); - start=res->charpos(start); - length=res->charpos(length,start); - if (start < 0 || (uint) start+1 > res->length() || length <= 0) + + /* Negative length, will return empty string. */ + if ((arg_count == 3) && (length <= 0) && !args[2]->unsigned_flag) + return &my_empty_string; + + /* Assumes that the maximum length of a String is < INT_MAX32. */ + /* Set here so that rest of code sees out-of-bound value as such. */ + if ((length <= 0) || (length > INT_MAX32)) + length= INT_MAX32; + + /* if "unsigned_flag" is set, we have a *huge* positive number. */ + /* Assumes that the maximum length of a String is < INT_MAX32. */ + if ((args[1]->unsigned_flag) || (start < INT_MIN32) || (start > INT_MAX32)) + return &my_empty_string; + + start= ((start < 0) ? res->numchars() + start : start - 1); + start= res->charpos(start); + if ((start < 0) || ((uint) start + 1 > res->length())) return &my_empty_string; - tmp_length=(int32) res->length()-start; - length=min(length,tmp_length); + length= res->charpos(length, start); + tmp_length= res->length() - start; + length= min(length, tmp_length); - if (!start && res->length() == (uint) length) + if (!start && res->length() == (ulonglong) length) return res; - tmp_value.set(*res,(uint) start,(uint) length); + tmp_value.set(*res, (ulonglong) start, (ulonglong) length); return &tmp_value; } @@ -1621,21 +1673,33 @@ String *Item_func_encrypt::val_str(String *str) void Item_func_encode::fix_length_and_dec() { max_length=args[0]->max_length; - maybe_null=args[0]->maybe_null; + maybe_null=args[0]->maybe_null || args[1]->maybe_null; collation.set(&my_charset_bin); } String *Item_func_encode::val_str(String *str) { - DBUG_ASSERT(fixed == 1); String *res; + char pw_buff[80]; + String tmp_pw_value(pw_buff, sizeof(pw_buff), system_charset_info); + String *password; + DBUG_ASSERT(fixed == 1); + if (!(res=args[0]->val_str(str))) { null_value=1; /* purecov: inspected */ return 0; /* purecov: inspected */ } + + if (!(password=args[1]->val_str(& tmp_pw_value))) + { + null_value=1; + return 0; + } + null_value=0; res=copy_if_not_alloced(str,res,res->length()); + SQL_CRYPT sql_crypt(password->ptr()); sql_crypt.init(); sql_crypt.encode((char*) res->ptr(),res->length()); res->set_charset(&my_charset_bin); @@ -1644,15 +1708,27 @@ String *Item_func_encode::val_str(String *str) String *Item_func_decode::val_str(String *str) { - DBUG_ASSERT(fixed == 1); String *res; + char pw_buff[80]; + String tmp_pw_value(pw_buff, sizeof(pw_buff), system_charset_info); + String *password; + DBUG_ASSERT(fixed == 1); + if (!(res=args[0]->val_str(str))) { null_value=1; /* purecov: inspected */ return 0; /* purecov: inspected */ } + + if (!(password=args[1]->val_str(& tmp_pw_value))) + { + null_value=1; + return 0; + } + null_value=0; res=copy_if_not_alloced(str,res,res->length()); + SQL_CRYPT sql_crypt(password->ptr()); sql_crypt.init(); sql_crypt.decode((char*) res->ptr(),res->length()); return res; @@ -1822,9 +1898,19 @@ String *Item_func_soundex::val_str(String *str) ** This should be 'internationalized' sometimes. */ -Item_func_format::Item_func_format(Item *org,int dec) :Item_str_func(org) +const int FORMAT_MAX_DECIMALS= 30; + +Item_func_format::Item_func_format(Item *org, Item *dec) +: Item_str_func(org, dec) { - decimals=(uint) set_zone(dec,0,30); +} + +void Item_func_format::fix_length_and_dec() +{ + collation.set(default_charset()); + uint char_length= args[0]->max_length/args[0]->collation.collation->mbmaxlen; + max_length= ((char_length + (char_length-args[0]->decimals)/3) * + collation.collation->mbmaxlen); } @@ -1835,10 +1921,25 @@ Item_func_format::Item_func_format(Item *org,int dec) :Item_str_func(org) String *Item_func_format::val_str(String *str) { - uint32 length, str_length ,dec; + uint32 length; + uint32 str_length; + /* Number of decimal digits */ + int dec; + /* Number of characters used to represent the decimals, including '.' */ + uint32 dec_length; int diff; DBUG_ASSERT(fixed == 1); - dec= decimals ? decimals+1 : 0; + + dec= args[1]->val_int(); + if (args[1]->null_value) + { + null_value=1; + return NULL; + } + + dec= set_zone(dec, 0, FORMAT_MAX_DECIMALS); + dec_length= dec ? dec+1 : 0; + null_value=0; if (args[0]->result_type() == DECIMAL_RESULT || args[0]->result_type() == INT_RESULT) @@ -1847,7 +1948,7 @@ String *Item_func_format::val_str(String *str) res= args[0]->val_decimal(&dec_val); if ((null_value=args[0]->null_value)) return 0; /* purecov: inspected */ - my_decimal_round(E_DEC_FATAL_ERROR, res, decimals, false, &rnd_dec); + my_decimal_round(E_DEC_FATAL_ERROR, res, dec, false, &rnd_dec); my_decimal2string(E_DEC_FATAL_ERROR, &rnd_dec, 0, 0, 0, str); str_length= str->length(); if (rnd_dec.sign()) @@ -1858,9 +1959,9 @@ String *Item_func_format::val_str(String *str) double nr= args[0]->val_real(); if ((null_value=args[0]->null_value)) return 0; /* purecov: inspected */ - nr= my_double_round(nr, decimals, FALSE); + nr= my_double_round(nr, dec, FALSE); /* Here default_charset() is right as this is not an automatic conversion */ - str->set_real(nr,decimals, default_charset()); + str->set_real(nr, dec, default_charset()); if (isnan(nr)) return str; str_length=str->length(); @@ -1868,13 +1969,13 @@ String *Item_func_format::val_str(String *str) str_length--; // Don't count sign } /* We need this test to handle 'nan' values */ - if (str_length >= dec+4) + if (str_length >= dec_length+4) { char *tmp,*pos; - length= str->length()+(diff=((int)(str_length- dec-1))/3); + length= str->length()+(diff=((int)(str_length- dec_length-1))/3); str= copy_if_not_alloced(&tmp_str,str,length); str->length(length); - tmp= (char*) str->ptr()+length - dec-1; + tmp= (char*) str->ptr()+length - dec_length-1; for (pos= (char*) str->ptr()+length-1; pos != tmp; pos--) pos[0]= pos[-diff]; while (diff) @@ -1898,12 +1999,8 @@ void Item_func_format::print(String *str) { str->append(STRING_WITH_LEN("format(")); args[0]->print(str); - str->append(','); - // my_charset_bin is good enough for numbers - char buffer[20]; - String st(buffer, sizeof(buffer), &my_charset_bin); - st.set((ulonglong)decimals, &my_charset_bin); - str->append(st); + str->append(','); + args[1]->print(str); str->append(')'); } @@ -2141,8 +2238,15 @@ void Item_func_repeat::fix_length_and_dec() collation.set(args[0]->collation); if (args[1]->const_item()) { - ulonglong max_result_length= ((ulonglong) args[0]->max_length * - args[1]->val_int()); + /* must be longlong to avoid truncation */ + longlong count= args[1]->val_int(); + + /* Assumes that the maximum length of a String is < INT_MAX32. */ + /* Set here so that rest of code sees out-of-bound value as such. */ + if (count > INT_MAX32) + count= INT_MAX32; + + ulonglong max_result_length= (ulonglong) args[0]->max_length * count; if (max_result_length >= MAX_BLOB_WIDTH) { max_result_length= MAX_BLOB_WIDTH; @@ -2167,13 +2271,20 @@ String *Item_func_repeat::val_str(String *str) DBUG_ASSERT(fixed == 1); uint length,tot_length; char *to; - long count= (long) args[1]->val_int(); - String *res =args[0]->val_str(str); + /* must be longlong to avoid truncation */ + longlong tmp_count= args[1]->val_int(); + long count= tmp_count; + String *res= args[0]->val_str(str); + + /* Assumes that the maximum length of a String is < INT_MAX32. */ + /* Bounds check on count: If this is triggered, we will error. */ + if ((tmp_count > INT_MAX32) || args[1]->unsigned_flag) + count= INT_MAX32; if (args[0]->null_value || args[1]->null_value) goto err; // string and/or delim are null - null_value=0; - if (count <= 0) // For nicer SQL code + null_value= 0; + if ((tmp_count <= 0) && !args[1]->unsigned_flag) // For nicer SQL code return &my_empty_string; if (count == 1) // To avoid reallocs return res; @@ -2212,8 +2323,20 @@ void Item_func_rpad::fix_length_and_dec() return; if (args[1]->const_item()) { - ulonglong length= ((ulonglong) args[1]->val_int() * - collation.collation->mbmaxlen); + ulonglong length= 0; + + if (collation.collation->mbmaxlen > 0) + { + ulonglong temp= (ulonglong) args[1]->val_int(); + + /* Assumes that the maximum length of a String is < INT_MAX32. */ + /* Set here so that rest of code sees out-of-bound value as such. */ + if (temp > INT_MAX32) + temp = INT_MAX32; + + length= temp * collation.collation->mbmaxlen; + } + if (length >= MAX_BLOB_WIDTH) { length= MAX_BLOB_WIDTH; @@ -2235,21 +2358,30 @@ String *Item_func_rpad::val_str(String *str) uint32 res_byte_length,res_char_length,pad_char_length,pad_byte_length; char *to; const char *ptr_pad; - int32 count= (int32) args[1]->val_int(); - int32 byte_count= count * collation.collation->mbmaxlen; - String *res =args[0]->val_str(str); - String *rpad = args[2]->val_str(&rpad_str); + /* must be longlong to avoid truncation */ + longlong count= args[1]->val_int(); + longlong byte_count; + String *res= args[0]->val_str(str); + String *rpad= args[2]->val_str(&rpad_str); + + /* Assumes that the maximum length of a String is < INT_MAX32. */ + /* Set here so that rest of code sees out-of-bound value as such. */ + if ((count > INT_MAX32) || args[1]->unsigned_flag) + count= INT_MAX32; if (!res || args[1]->null_value || !rpad || count < 0) goto err; null_value=0; - if (count <= (int32) (res_char_length=res->numchars())) + + if (count <= (res_char_length= res->numchars())) { // String to pad is big enough res->length(res->charpos(count)); // Shorten result if longer return (res); } pad_char_length= rpad->numchars(); - if ((ulong) byte_count > current_thd->variables.max_allowed_packet) + + byte_count= count * collation.collation->mbmaxlen; + 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, @@ -2295,8 +2427,20 @@ void Item_func_lpad::fix_length_and_dec() if (args[1]->const_item()) { - ulonglong length= ((ulonglong) args[1]->val_int() * - collation.collation->mbmaxlen); + ulonglong length= 0; + + if (collation.collation->mbmaxlen > 0) + { + ulonglong temp= (ulonglong) args[1]->val_int(); + + /* Assumes that the maximum length of a String is < INT_MAX32. */ + /* Set here so that rest of code sees out-of-bound value as such. */ + if (temp > INT_MAX32) + temp= INT_MAX32; + + length= temp * collation.collation->mbmaxlen; + } + if (length >= MAX_BLOB_WIDTH) { length= MAX_BLOB_WIDTH; @@ -2316,13 +2460,19 @@ String *Item_func_lpad::val_str(String *str) { DBUG_ASSERT(fixed == 1); uint32 res_char_length,pad_char_length; - ulong count= (long) args[1]->val_int(), byte_count; + /* must be longlong to avoid truncation */ + longlong count= args[1]->val_int(); + longlong byte_count; String *res= args[0]->val_str(&tmp_value); String *pad= args[2]->val_str(&lpad_str); - if (!res || args[1]->null_value || !pad) - goto err; + /* Assumes that the maximum length of a String is < INT_MAX32. */ + /* Set here so that rest of code sees out-of-bound value as such. */ + if ((count > INT_MAX32) || args[1]->unsigned_flag) + count= INT_MAX32; + if (!res || args[1]->null_value || !pad || count < 0) + goto err; null_value=0; res_char_length= res->numchars(); @@ -2335,7 +2485,7 @@ String *Item_func_lpad::val_str(String *str) 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, diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 2adccd212b3..3b171b5d50f 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 @@ -360,11 +361,9 @@ public: class Item_func_encode :public Item_str_func { - protected: - SQL_CRYPT sql_crypt; public: - Item_func_encode(Item *a, char *seed): - Item_str_func(a),sql_crypt(seed) {} + Item_func_encode(Item *a, Item *seed): + Item_str_func(a, seed) {} String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "encode"; } @@ -374,7 +373,7 @@ public: class Item_func_decode :public Item_func_encode { public: - Item_func_decode(Item *a, char *seed): Item_func_encode(a,seed) {} + Item_func_decode(Item *a, Item *seed): Item_func_encode(a, seed) {} String *val_str(String *); const char *func_name() const { return "decode"; } }; @@ -507,15 +506,9 @@ class Item_func_format :public Item_str_func { String tmp_str; public: - Item_func_format(Item *org,int dec); + Item_func_format(Item *org, Item *dec); String *val_str(String *); - void fix_length_and_dec() - { - collation.set(default_charset()); - uint char_length= args[0]->max_length/args[0]->collation.collation->mbmaxlen; - max_length= ((char_length + (char_length-args[0]->decimals)/3) * - collation.collation->mbmaxlen); - } + void fix_length_and_dec(); const char *func_name() const { return "format"; } void print(String *); }; @@ -530,9 +523,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 4e6c67cba60..da491b91143 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) @@ -235,16 +235,16 @@ bool Item_subselect::walk(Item_processor processor, bool walk_subquery, } -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); } @@ -434,6 +434,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) @@ -484,13 +493,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(); @@ -505,7 +514,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(); @@ -519,7 +528,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); @@ -534,7 +543,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); @@ -549,7 +558,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(); @@ -600,7 +609,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; @@ -645,7 +655,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; @@ -656,7 +666,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; @@ -667,7 +677,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; @@ -680,7 +690,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; @@ -693,7 +703,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; @@ -710,7 +720,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; @@ -730,7 +741,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; @@ -750,7 +762,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; @@ -769,7 +782,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; @@ -787,8 +801,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; @@ -801,7 +816,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, @@ -934,8 +997,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. */ @@ -950,10 +1017,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 @@ -982,19 +1054,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 @@ -1005,12 +1077,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; /* @@ -1037,13 +1112,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; /* @@ -1248,6 +1324,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 @@ -1261,6 +1339,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(); /* @@ -1477,6 +1557,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"); @@ -1542,32 +1643,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; @@ -1579,13 +1706,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; } } @@ -1595,7 +1723,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; @@ -1633,7 +1765,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; @@ -1644,29 +1812,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, 0); error= table->file->index_read(table->record[0], @@ -1695,14 +1993,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) { @@ -1711,14 +2063,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, 1); diff --git a/sql/item_subselect.h b/sql/item_subselect.h index a72c6e85739..77199365710 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}; @@ -92,7 +95,7 @@ public: 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 @@ -156,6 +160,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(); @@ -216,7 +221,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 { @@ -232,12 +250,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; } @@ -257,6 +277,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); @@ -292,6 +313,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: @@ -301,6 +323,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 @@ -314,10 +337,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; @@ -326,6 +371,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); }; @@ -343,7 +393,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(); @@ -352,6 +402,7 @@ public: bool change_result(Item_subselect *si, select_subselect *result); bool no_tables(); bool is_executed() const { return executed; } + bool no_rows(); }; @@ -365,7 +416,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(); @@ -374,6 +425,7 @@ public: bool change_result(Item_subselect *si, select_subselect *result); bool no_tables(); bool is_executed() const; + bool no_rows(); }; @@ -383,6 +435,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 @@ -396,7 +454,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(); @@ -404,11 +462,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: @@ -419,7 +481,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); }; @@ -429,3 +491,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 b2ff62028c1..cfa4b2ce16c 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; } @@ -903,6 +907,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); } @@ -910,6 +915,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); @@ -939,6 +945,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; } @@ -948,6 +955,7 @@ void Item_sum_distinct::cleanup() delete tree; tree= 0; table= 0; + is_evaluated= FALSE; } Item_sum_distinct::~Item_sum_distinct() @@ -959,16 +967,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; } } @@ -1024,9 +1036,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; + } } @@ -2497,6 +2513,7 @@ void Item_sum_count_distinct::cleanup() */ delete tree; tree= 0; + is_evaluated= FALSE; if (table) { free_tmp_table(table->in_use, table); @@ -2518,6 +2535,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; } @@ -2637,6 +2655,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; } @@ -2653,8 +2672,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); @@ -2675,6 +2697,7 @@ bool Item_sum_count_distinct::add() if ((*field)->is_real_null(0)) return 0; // Don't count NULL + is_evaluated= FALSE; if (tree) { /* @@ -2700,12 +2723,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; } @@ -2929,13 +2954,14 @@ int group_concat_key_cmp_with_distinct(void* arg, byte* key1, */ Field *field= (*field_item)->get_tmp_table_field(); /* - If field_item is a const item then either get_tp_table_field returns 0 + If field_item is a const item then either get_tmp_table_field returns 0 or it is an item over a const table. */ if (field && !(*field_item)->const_item()) { int res; - uint offset= field->offset() - table->s->null_bytes; + uint offset= (field->offset(field->table->record[0]) - + table->s->null_bytes); if ((res= field->cmp((char *) key1 + offset, (char *) key2 + offset))) return res; } @@ -2973,7 +2999,8 @@ int group_concat_key_cmp_with_order(void* arg, byte* key1, byte* key2) if (field && !item->const_item()) { int res; - uint offset= field->offset() - table->s->null_bytes; + uint offset= (field->offset(field->table->record[0]) - + table->s->null_bytes); if ((res= field->cmp((char *) key1 + offset, (char *) key2 + offset))) return (*order_item)->asc ? res : -res; } @@ -3019,6 +3046,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; @@ -3040,7 +3068,8 @@ int dump_leaf_key(byte* key, element_count count __attribute__((unused)), because it contains both order and arg list fields. */ Field *field= (*arg)->get_tmp_table_field(); - uint offset= field->offset() - table->s->null_bytes; + uint offset= (field->offset(field->table->record[0]) - + table->s->null_bytes); DBUG_ASSERT(offset < table->s->reclength); res= field->val_str(&tmp, (char *) key + offset); } @@ -3053,8 +3082,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; } @@ -3244,8 +3287,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); @@ -3314,7 +3356,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++) diff --git a/sql/item_sum.h b/sql/item_sum.h index eb4c21bbe06..a4cd078b98b 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(); diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 3d49305cfd3..6771b44ccd3 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -1368,11 +1368,9 @@ bool get_interval_value(Item *args,interval_type int_type, interval->second= array[0]; interval->second_part= array[1]; break; - /* purecov: begin deadcode */ - case INTERVAL_LAST: - DBUG_ASSERT(0); - break; - /* purecov: end */ + case INTERVAL_LAST: /* purecov: begin deadcode */ + DBUG_ASSERT(0); + break; /* purecov: end */ } return 0; } @@ -1394,17 +1392,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); @@ -2199,7 +2186,7 @@ void Item_extract::fix_length_and_dec() case INTERVAL_HOUR_MICROSECOND: max_length=13; date_value=0; break; case INTERVAL_MINUTE_MICROSECOND: max_length=11; date_value=0; break; case INTERVAL_SECOND_MICROSECOND: max_length=9; date_value=0; break; - case INTERVAL_LAST: DBUG_ASSERT(0); break; /* purecov: deadcode */ + case INTERVAL_LAST: DBUG_ASSERT(0); break; /* purecov: deadcode */ } } @@ -2269,8 +2256,7 @@ longlong Item_extract::val_int() ltime.second_part)*neg; case INTERVAL_SECOND_MICROSECOND: return ((longlong)ltime.second*1000000L+ ltime.second_part)*neg; - case INTERVAL_LAST: DBUG_ASSERT(0); return(0); /* purecov: deadcode */ - /* purecov: end */ + case INTERVAL_LAST: DBUG_ASSERT(0); break; /* purecov: deadcode */ } return 0; // Impossible } @@ -2385,7 +2371,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", (ulong) length); + cast_cs == &my_charset_bin ? "BINARY" : "CHAR", + (ulong) length); if (!res->alloced_length()) { // Don't change const str diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index 2a6ddd1bc65..360307a677f 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -360,12 +360,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 *table) { return tmp_table_field_from_field_type(table, 0); } 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); + } }; @@ -382,29 +390,61 @@ public: return tmp_table_field_from_field_type(table, 0); } 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 *table) + { + return tmp_table_field_from_field_type(table, 0); + } + 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); void fix_length_and_dec(); - Field *tmp_table_field(TABLE *table) - { - return tmp_table_field_from_field_type(table, 0); - } /* Abstract method that defines which time zone is used for conversion. Converts time current time in my_time_t representation to broken-down @@ -626,10 +666,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); @@ -639,17 +679,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 *table) - { - return tmp_table_field_from_field_type(table, 0); - } bool result_as_longlong() { return TRUE; } bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -774,6 +809,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); + } }; @@ -792,6 +836,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); + } }; @@ -809,12 +862,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; } @@ -823,11 +885,6 @@ public: decimals=0; max_length=MAX_DATE_WIDTH*MY_CHARSET_BIN_MB_MAXLEN; } - Field *tmp_table_field(TABLE *table) - { - return tmp_table_field_from_field_type(table, 0); - } - bool result_as_longlong() { return TRUE; } longlong val_int(); bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; @@ -853,45 +910,46 @@ public: void print(String *str); const char *func_name() const { return "add_time"; } bool check_partition_func_processor(byte *int_arg) {return FALSE;} + 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 *table) - { - return tmp_table_field_from_field_type(table, 0); - } }; -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 *table) - { - return tmp_table_field_from_field_type(table, 0); - } bool check_partition_func_processor(byte *int_arg) {return FALSE;} }; diff --git a/sql/item_xmlfunc.cc b/sql/item_xmlfunc.cc index 44a2b690bac..21239a13735 100644 --- a/sql/item_xmlfunc.cc +++ b/sql/item_xmlfunc.cc @@ -532,7 +532,7 @@ public: longlong val_int() { Item_func *comp= (Item_func*)args[1]; - Item_string *fake= (Item_string*)(comp->arguments()[1]); + Item_string *fake= (Item_string*)(comp->arguments()[0]); String *res= args[0]->val_nodeset(&tmp_nodeset); MY_XPATH_FLT *fltbeg= (MY_XPATH_FLT*) res->ptr(); MY_XPATH_FLT *fltend= (MY_XPATH_FLT*) (res->ptr() + res->length()); @@ -884,7 +884,7 @@ static Item *eq_func(int oper, Item *a, Item *b) Create a comparator function for scalar arguments, for the given arguments and reverse operation, e.g. - A >= B is converted into A < B + A > B is converted into B < A RETURN The newly created item. @@ -895,10 +895,10 @@ static Item *eq_func_reverse(int oper, Item *a, Item *b) { case '=': return new Item_func_eq(a, b); case '!': return new Item_func_ne(a, b); - case MY_XPATH_LEX_GE: return new Item_func_lt(a, b); - case MY_XPATH_LEX_LE: return new Item_func_gt(a, b); - case MY_XPATH_LEX_GREATER: return new Item_func_le(a, b); - case MY_XPATH_LEX_LESS: return new Item_func_ge(a, b); + case MY_XPATH_LEX_GE: return new Item_func_le(a, b); + case MY_XPATH_LEX_LE: return new Item_func_ge(a, b); + case MY_XPATH_LEX_GREATER: return new Item_func_lt(a, b); + case MY_XPATH_LEX_LESS: return new Item_func_gt(a, b); } return 0; } @@ -951,13 +951,13 @@ static Item *create_comparator(MY_XPATH *xpath, { nodeset= (Item_nodeset_func*) a; scalar= b; - comp= eq_func(oper, scalar, fake); + comp= eq_func(oper, fake, scalar); } else { nodeset= (Item_nodeset_func*) b; scalar= a; - comp= eq_func_reverse(oper, scalar, fake); + comp= eq_func_reverse(oper, fake, scalar); } return new Item_nodeset_to_const_comparator(nodeset, comp, xpath->pxml); } diff --git a/sql/key.cc b/sql/key.cc index be21bf11c3c..dceeab1c011 100644 --- a/sql/key.cc +++ b/sql/key.cc @@ -19,37 +19,54 @@ #include "mysql_priv.h" - /* - ** Search after with key field is. If no key starts with field test - ** if field is part of some key. - ** - ** returns number of key. keylength is set to length of key before - ** (not including) field - ** Used when calculating key for NEXT_NUMBER - */ - -int find_ref_key(KEY *key, uint key_count, Field *field, uint *key_length) +/* + Search after a key that starts with 'field' + + SYNOPSIS + find_ref_key() + key First key to check + key_count How many keys to check + record Start of record + field Field to search after + key_length On partial match, contains length of fields before + field + + NOTES + Used when calculating key for NEXT_NUMBER + + IMPLEMENTATION + If no key starts with field test if field is part of some key. If we find + one, then return first key and set key_length to the number of bytes + preceding 'field'. + + RETURN + -1 field is not part of the key + # Key part for key matching key. + key_length is set to length of key before (not including) field +*/ + +int find_ref_key(KEY *key, uint key_count, byte *record, Field *field, + uint *key_length) { reg2 int i; reg3 KEY *key_info; uint fieldpos; - fieldpos= field->offset(); - - /* Test if some key starts as fieldpos */ + fieldpos= field->offset(record); + /* Test if some key starts as fieldpos */ for (i= 0, key_info= key ; i < (int) key_count ; i++, key_info++) { if (key_info->key_part[0].offset == fieldpos) - { /* Found key. Calc keylength */ + { /* Found key. Calc keylength */ *key_length=0; - return(i); /* Use this key */ + return(i); /* Use this key */ } } - /* Test if some key contains fieldpos */ + /* Test if some key contains fieldpos */ for (i= 0, key_info= key; i < (int) key_count ; i++, key_info++) @@ -62,7 +79,7 @@ int find_ref_key(KEY *key, uint key_count, Field *field, uint *key_length) j++, key_part++) { if (key_part->offset == fieldpos) - return(i); /* Use this key */ + return(i); /* Use this key */ *key_length+=key_part->store_length; } } diff --git a/sql/log.cc b/sql/log.cc index 83e190a5c01..b12eca9bb07 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -424,6 +424,18 @@ bool Log_to_csv_event_handler:: { TABLE *table= general_log.table; + /* + "INSERT INTO general_log" can generate warning sometimes. + Let's reset warnings from previous queries, + otherwise warning list can grow too much, + so thd->query gets spoiled as some point in time, + and mysql_parse() receives a broken query. + QQ: this problem needs to be studied in more details. + Probably it's better to suppress warnings in logging INSERTs at all. + Comment this line and run "cast.test" to see what's happening: + */ + mysql_reset_errors(table->in_use, 1); + /* below should never happen */ if (unlikely(!logger.is_log_tables_initialized)) return FALSE; @@ -1332,7 +1344,7 @@ binlog_trans_log_savepos(THD *thd, my_off_t *pos) (binlog_trx_data*) thd->ha_data[binlog_hton->slot]; DBUG_ASSERT(mysql_bin_log.is_open()); *pos= trx_data->position(); - DBUG_PRINT("return", ("*pos=%u", *pos)); + DBUG_PRINT("return", ("*pos: %lu", (ulong) *pos)); DBUG_VOID_RETURN; } @@ -1356,7 +1368,7 @@ static void binlog_trans_log_truncate(THD *thd, my_off_t pos) { DBUG_ENTER("binlog_trans_log_truncate"); - DBUG_PRINT("enter", ("pos=%u", pos)); + DBUG_PRINT("enter", ("pos: %lu", (ulong) pos)); DBUG_ASSERT(thd->ha_data[binlog_hton->slot] != NULL); /* Only true if binlog_trans_log_savepos() wasn't called before */ @@ -1432,8 +1444,8 @@ binlog_end_trans(THD *thd, binlog_trx_data *trx_data, DBUG_ENTER("binlog_end_trans"); int error=0; IO_CACHE *trans_log= &trx_data->trans_log; - DBUG_PRINT("enter", ("transaction: %s, end_ev=%p", - all ? "all" : "stmt", end_ev)); + DBUG_PRINT("enter", ("transaction: %s end_ev: 0x%lx", + all ? "all" : "stmt", (long) end_ev)); DBUG_PRINT("info", ("thd->options={ %s%s}", FLAGSTR(thd->options, OPTION_NOT_AUTOCOMMIT), FLAGSTR(thd->options, OPTION_BEGIN))); @@ -3405,12 +3417,13 @@ int THD::binlog_setup_trx_data() void THD::binlog_start_trans_and_stmt() { - DBUG_ENTER("binlog_start_trans_and_stmt"); binlog_trx_data *trx_data= (binlog_trx_data*) ha_data[binlog_hton->slot]; - DBUG_PRINT("enter", ("trx_data=0x%lu", trx_data)); - if (trx_data) - DBUG_PRINT("enter", ("trx_data->before_stmt_pos=%u", - trx_data->before_stmt_pos)); + DBUG_ENTER("binlog_start_trans_and_stmt"); + DBUG_PRINT("enter", ("trx_data: 0x%lx trx_data->before_stmt_pos: %lu", + (long) trx_data, + (trx_data ? (ulong) trx_data->before_stmt_pos : + (ulong) 0))); + if (trx_data == NULL || trx_data->before_stmt_pos == MY_OFF_T_UNDEF) { @@ -3441,8 +3454,8 @@ int THD::binlog_write_table_map(TABLE *table, bool is_trans) { int error; DBUG_ENTER("THD::binlog_write_table_map"); - DBUG_PRINT("enter", ("table: %0xlx (%s: #%u)", - (long) table, table->s->table_name, + DBUG_PRINT("enter", ("table: 0x%lx (%s: #%lu)", + (long) table, table->s->table_name.str, table->s->table_map_id)); /* Pre-conditions */ @@ -3505,7 +3518,7 @@ MYSQL_BIN_LOG::flush_and_set_pending_rows_event(THD *thd, { DBUG_ENTER("MYSQL_BIN_LOG::flush_and_set_pending_rows_event(event)"); DBUG_ASSERT(mysql_bin_log.is_open()); - DBUG_PRINT("enter", ("event=%p", event)); + DBUG_PRINT("enter", ("event: 0x%lx", (long) event)); int error= 0; @@ -3514,7 +3527,7 @@ MYSQL_BIN_LOG::flush_and_set_pending_rows_event(THD *thd, DBUG_ASSERT(trx_data); - DBUG_PRINT("info", ("trx_data->pending()=%p", trx_data->pending())); + DBUG_PRINT("info", ("trx_data->pending(): 0x%lx", (long) trx_data->pending())); if (Rows_log_event* pending= trx_data->pending()) { @@ -3669,9 +3682,9 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info) my_off_t trans_log_pos= my_b_tell(trans_log); if (event_info->get_cache_stmt() || trans_log_pos != 0) { - DBUG_PRINT("info", ("Using trans_log: cache=%d, trans_log_pos=%u", + DBUG_PRINT("info", ("Using trans_log: cache: %d, trans_log_pos: %lu", event_info->get_cache_stmt(), - trans_log_pos)); + (ulong) trans_log_pos)); if (trans_log_pos == 0) thd->binlog_start_trans_and_stmt(); file= trans_log; @@ -3713,15 +3726,17 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info) } if (thd->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements() > 0) { - DBUG_PRINT("info",("number of auto_inc intervals: %lu", - thd->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements())); + DBUG_PRINT("info",("number of auto_inc intervals: %u", + thd->auto_inc_intervals_in_cur_stmt_for_binlog. + nb_elements())); /* If the auto_increment was second in a table's index (possible with MyISAM or BDB) (table->next_number_key_offset != 0), such event is in fact not necessary. We could avoid logging it. */ - Intvar_log_event e(thd,(uchar) INSERT_ID_EVENT, - thd->auto_inc_intervals_in_cur_stmt_for_binlog.minimum()); + Intvar_log_event e(thd, (uchar) INSERT_ID_EVENT, + thd->auto_inc_intervals_in_cur_stmt_for_binlog. + minimum()); if (e.write(file)) goto err; } diff --git a/sql/log_event.cc b/sql/log_event.cc index d99fb9da8f8..112f4aee135 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -140,6 +140,21 @@ static void pretty_print_str(IO_CACHE* cache, char* str, int len) } #endif /* MYSQL_CLIENT */ +#ifdef HAVE_purify +static void +valgrind_check_mem(void *ptr, size_t len) +{ + static volatile uchar dummy; + for (volatile uchar *p= (uchar*) ptr ; p != (uchar*) ptr + len ; ++p) + { + int const c = *p; + if (c < 128) + dummy= c + 1; + else + dummy = c - 1; + } +} +#endif #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) @@ -831,7 +846,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*) \ @@ -1398,6 +1413,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); /* @@ -1483,7 +1499,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 */ @@ -1531,7 +1548,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)); /* @@ -1579,7 +1596,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: @@ -3354,8 +3371,8 @@ Rotate_log_event::Rotate_log_event(const char* new_log_ident_arg, #ifndef DBUG_OFF char buff[22]; DBUG_ENTER("Rotate_log_event::Rotate_log_event(...,flags)"); - 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_strndup(new_log_ident_arg, ident_len, MYF(MY_WME)); @@ -4136,7 +4153,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 @@ -5328,8 +5345,8 @@ Rows_log_event::Rows_log_event(const char *buf, uint event_len, uint8 const common_header_len= description_event->common_header_len; uint8 const post_header_len= description_event->post_header_len[event_type-1]; - DBUG_PRINT("enter",("event_len=%ld, common_header_len=%d, " - "post_header_len=%d", + DBUG_PRINT("enter",("event_len: %u common_header_len: %d " + "post_header_len: %d", event_len, common_header_len, post_header_len)); @@ -5359,7 +5376,7 @@ Rows_log_event::Rows_log_event(const char *buf, uint event_len, const byte* const ptr_rows_data= var_start + byte_count + 1; my_size_t const data_size= event_len - (ptr_rows_data - (const byte *) buf); - DBUG_PRINT("info",("m_table_id=%lu, m_flags=%d, m_width=%u, data_size=%lu", + DBUG_PRINT("info",("m_table_id: %lu m_flags: %d m_width: %lu data_size: %lu", m_table_id, m_flags, m_width, data_size)); m_rows_buf= (byte*)my_malloc(data_size, MYF(MY_WME)); @@ -5400,8 +5417,14 @@ int Rows_log_event::do_add_row_data(byte *const row_data, */ DBUG_ENTER("Rows_log_event::do_add_row_data"); DBUG_PRINT("enter", ("row_data: 0x%lx length: %lu", (ulong) row_data, - length)); + (ulong) length)); + /* + Don't print debug messages when running valgrind since they can + trigger false warnings. + */ +#ifndef HAVE_purify DBUG_DUMP("row_data", (const char*)row_data, min(length, 32)); +#endif DBUG_ASSERT(m_rows_buf <= m_rows_cur); DBUG_ASSERT(!m_rows_buf || m_rows_end && m_rows_buf < m_rows_end); @@ -5445,14 +5468,13 @@ int Rows_log_event::do_add_row_data(byte *const row_data, #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) /* - Unpack a row into a record. + Unpack a row into table->record[0]. SYNOPSIS unpack_row() rli Relay log info table Table to unpack into colcnt Number of columns to read from record - record Record where the data should be unpacked row Packed row data cols Pointer to columns data to fill in row_end Pointer to variable that will hold the value of the @@ -5465,6 +5487,11 @@ int Rows_log_event::do_add_row_data(byte *const row_data, DESCRIPTION + The function will always unpack into the table->record[0] + record. This is because there are too many dependencies on + where the various member functions of Field and subclasses + expect to write. + The row is assumed to only consist of the fields for which the bitset represented by 'arr' and 'bits'; the other parts of the record are left alone. @@ -5483,13 +5510,15 @@ int Rows_log_event::do_add_row_data(byte *const row_data, */ static int unpack_row(RELAY_LOG_INFO *rli, - TABLE *table, uint const colcnt, byte *record, + TABLE *table, uint const colcnt, char const *row, MY_BITMAP const *cols, char const **row_end, ulong *master_reclength, MY_BITMAP* const rw_set, Log_event_type const event_type) { + byte *const record= table->record[0]; + DBUG_ENTER("unpack_row"); DBUG_ASSERT(record && row); - my_ptrdiff_t const offset= record - (byte*) table->record[0]; + DBUG_PRINT("enter", ("row: 0x%lx table->record[0]: 0x%lx", (long) row, (long) record)); my_size_t master_null_bytes= table->s->null_bytes; if (colcnt != table->s->fields) @@ -5529,9 +5558,13 @@ unpack_row(RELAY_LOG_INFO *rli, if (bitmap_is_set(cols, field_ptr - begin_ptr)) { - f->move_field_offset(offset); + DBUG_ASSERT(table->record[0] <= f->ptr); + DBUG_ASSERT(f->ptr < (table->record[0] + table->s->reclength + + (f->pack_length_in_rec() == 0))); + + DBUG_PRINT("info", ("unpacking column '%s' to 0x%lx", f->field_name, + (long) f->ptr)); ptr= f->unpack(f->ptr, ptr); - f->move_field_offset(-offset); /* Field...::unpack() cannot return 0 */ DBUG_ASSERT(ptr != NULL); } @@ -5562,13 +5595,11 @@ unpack_row(RELAY_LOG_INFO *rli, for ( ; *field_ptr ; ++field_ptr) { uint32 const mask= NOT_NULL_FLAG | NO_DEFAULT_VALUE_FLAG; + Field *const f= *field_ptr; - DBUG_PRINT("debug", ("flags = 0x%x, mask = 0x%x, flags & mask = 0x%x", - (*field_ptr)->flags, mask, - (*field_ptr)->flags & mask)); - - if (event_type == WRITE_ROWS_EVENT && - ((*field_ptr)->flags & mask) == mask) + DBUG_PRINT("info", ("processing column '%s' @ 0x%lx", f->field_name, + (long) f->ptr)); + if (event_type == WRITE_ROWS_EVENT && (f->flags & mask) == mask) { slave_print_msg(ERROR_LEVEL, rli, ER_NO_DEFAULT_FOR_FIELD, "Field `%s` of table `%s`.`%s` " @@ -5578,10 +5609,10 @@ unpack_row(RELAY_LOG_INFO *rli, error = ER_NO_DEFAULT_FOR_FIELD; } else - (*field_ptr)->set_default(); + f->set_default(); } - return error; + DBUG_RETURN(error); } int Rows_log_event::exec_event(st_relay_log_info *rli) @@ -5689,12 +5720,10 @@ int Rows_log_event::exec_event(st_relay_log_info *rli) We also invalidate the query cache for all the tables, since they will now be changed. */ - TABLE_LIST *ptr; for (ptr= rli->tables_to_lock ; ptr ; ptr= ptr->next_global) { rli->m_table_map.set_table(ptr->table_id, ptr->table); - rli->touching_table(ptr->db, ptr->table_name, ptr->table_id); } #ifdef HAVE_QUERY_CACHE query_cache.invalidate_locked_for_write(rli->tables_to_lock); @@ -5747,7 +5776,7 @@ int Rows_log_event::exec_event(st_relay_log_info *rli) if ((error= do_prepare_row(thd, rli, table, row_start, &row_end))) break; // We should perform the after-row operation even in // the case of error - + DBUG_ASSERT(row_end != NULL); // cannot happen DBUG_ASSERT(row_end <= (const char*)m_rows_end); @@ -5803,9 +5832,10 @@ int Rows_log_event::exec_event(st_relay_log_info *rli) STMT_END_F. For now we code, knowing that error is not skippable and so slave SQL thread is certainly going to stop. + rollback at the caller along with sbr. */ thd->reset_current_stmt_binlog_row_based(); - rli->cleanup_context(thd, 1); + rli->cleanup_context(thd, 0); /* rollback at caller in step with sbr */ thd->query_error= 1; DBUG_RETURN(error); } @@ -6044,10 +6074,16 @@ Table_map_log_event::Table_map_log_event(const char *buf, uint event_len, uint8 common_header_len= description_event->common_header_len; uint8 post_header_len= description_event->post_header_len[TABLE_MAP_EVENT-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)); + /* + Don't print debug messages when running valgrind since they can + trigger false warnings. + */ +#ifndef HAVE_purify DBUG_DUMP("event buffer", buf, event_len); +#endif /* Read the post-header */ const char *post_start= buf + common_header_len; @@ -6086,10 +6122,10 @@ Table_map_log_event::Table_map_log_event(const char *buf, uint event_len, uchar *ptr_after_colcnt= (uchar*) ptr_colcnt; m_colcnt= net_field_length(&ptr_after_colcnt); - DBUG_PRINT("info",("m_dblen=%d off=%d m_tbllen=%d off=%d m_colcnt=%d off=%d", - m_dblen, ptr_dblen-(const byte*)vpart, - m_tbllen, ptr_tbllen-(const byte*)vpart, - m_colcnt, ptr_colcnt-(const byte*)vpart)); + DBUG_PRINT("info",("m_dblen: %lu off: %ld m_tbllen: %lu off: %ld m_colcnt: %lu off: %ld", + m_dblen, (long) (ptr_dblen-(const byte*)vpart), + m_tbllen, (long) (ptr_tbllen-(const byte*)vpart), + m_colcnt, (long) (ptr_colcnt-(const byte*)vpart))); /* Allocate mem for all fields in one go. If fails, catched in is_valid() */ m_memory= my_multi_malloc(MYF(MY_WME), @@ -6230,8 +6266,7 @@ int Table_map_log_event::exec_event(st_relay_log_info *rli) /* We record in the slave's information that the table should be - locked by linking the table into the list of tables to lock, and - tell the RLI that we are touching a table. + locked by linking the table into the list of tables to lock. */ table_list->next_global= table_list->next_local= rli->tables_to_lock; rli->tables_to_lock= table_list; @@ -6423,17 +6458,15 @@ int Write_rows_log_event::do_after_row_operations(TABLE *table, int error) int Write_rows_log_event::do_prepare_row(THD *thd, RELAY_LOG_INFO *rli, TABLE *table, - char const *row_start, - char const **row_end) + char const *const row_start, + char const **const row_end) { DBUG_ASSERT(table != NULL); DBUG_ASSERT(row_start && row_end); int error; - error= unpack_row(rli, - table, m_width, table->record[0], - row_start, &m_cols, row_end, &m_master_reclength, - table->write_set, WRITE_ROWS_EVENT); + error= unpack_row(rli, table, m_width, row_start, &m_cols, row_end, + &m_master_reclength, table->write_set, WRITE_ROWS_EVENT); bitmap_copy(table->read_set, table->write_set); return error; } @@ -6494,11 +6527,11 @@ copy_extra_record_fields(TABLE *table, my_size_t master_reclength, my_ptrdiff_t master_fields) { - DBUG_PRINT("info", ("Copying to %p " - "from field %d at offset %u " - "to field %d at offset %u", - table->record[0], - master_fields, master_reclength, + DBUG_PRINT("info", ("Copying to 0x%lx " + "from field %lu at offset %lu " + "to field %d at offset %lu", + (long) table->record[0], + (ulong) master_fields, (ulong) master_reclength, table->s->fields, table->s->reclength)); /* Copying the extra fields of the slave that does not exist on @@ -6595,6 +6628,11 @@ replace_record(THD *thd, TABLE *table, while ((error= table->file->ha_write_row(table->record[0]))) { + if (error == HA_ERR_LOCK_DEADLOCK || error == HA_ERR_LOCK_WAIT_TIMEOUT) + { + table->file->print_error(error, MYF(0)); /* to check at exec_relay_log_event */ + DBUG_RETURN(error); + } if ((keynum= table->file->get_dup_key(error)) < 0) { /* We failed to retrieve the duplicate key */ @@ -6649,7 +6687,7 @@ replace_record(THD *thd, TABLE *table, present on the master from table->record[1], if there are any. */ copy_extra_record_fields(table, master_reclength, master_fields); - + /* REPLACE is defined as either INSERT or DELETE + INSERT. If possible, we can replace it with an UPDATE, but that will not @@ -6728,8 +6766,26 @@ static bool record_compare(TABLE *table) /* Find the row given by 'key', if the table has keys, or else use a table scan - to find (and fetch) the row. If the engine allows random access of the - records, a combination of position() and rnd_pos() will be used. + to find (and fetch) the row. + + If the engine allows random access of the records, a combination of + position() and rnd_pos() will be used. + + @param table Pointer to table to search + @param key Pointer to key to use for search, if table has key + + @pre <code>table->record[0]</code> shall contain the row to locate + and <code>key</code> shall contain a key to use for searching, if + the engine has a key. + + @post If the return value is zero, <code>table->record[1]</code> + will contain the fetched row and the internal "cursor" will refer to + the row. If the return value is non-zero, + <code>table->record[1]</code> is undefined. In either case, + <code>table->record[0]</code> is undefined. + + @return Zero if the row was successfully fetched into + <code>table->record[1]</code>, error code otherwise. */ static int find_and_fetch_row(TABLE *table, byte *key) @@ -6749,13 +6805,28 @@ static int find_and_fetch_row(TABLE *table, byte *key) row reference using the position() member function (it will be stored in table->file->ref) and the use rnd_pos() to position the "cursor" (i.e., record[0] in this case) at the correct row. + + TODO: Add a check that the correct record has been fetched by + comparing with the original record. Take into account that the + record on the master and slave can be of different + length. Something along these lines should work: + + ADD>>> store_record(table,record[1]); + int error= table->file->rnd_pos(table->record[0], table->file->ref); + ADD>>> DBUG_ASSERT(memcmp(table->record[1], table->record[0], + table->s->reclength) == 0); + */ table->file->position(table->record[0]); - DBUG_RETURN(table->file->rnd_pos(table->record[0], table->file->ref)); + int error= table->file->rnd_pos(table->record[0], table->file->ref); + /* + rnd_pos() returns the record in table->record[0], so we have to + move it to table->record[1]. + */ + bmove_align(table->record[1], table->record[0], table->s->reclength); + DBUG_RETURN(error); } - DBUG_ASSERT(table->record[1]); - /* We need to retrieve all fields */ /* TODO: Move this out from this function to main loop */ table->use_all_columns(); @@ -6765,7 +6836,16 @@ static int find_and_fetch_row(TABLE *table, byte *key) int error; /* We have a key: search the table using the index */ if (!table->file->inited && (error= table->file->ha_index_init(0, FALSE))) - return error; + DBUG_RETURN(error); + + /* + Don't print debug messages when running valgrind since they can + trigger false warnings. + */ +#ifndef HAVE_purify + DBUG_DUMP("table->record[0]", table->record[0], table->s->reclength); + DBUG_DUMP("table->record[1]", table->record[1], table->s->reclength); +#endif /* We need to set the null bytes to ensure that the filler bit are @@ -6785,6 +6865,14 @@ static int find_and_fetch_row(TABLE *table, byte *key) DBUG_RETURN(error); } + /* + Don't print debug messages when running valgrind since they can + trigger false warnings. + */ +#ifndef HAVE_purify + DBUG_DUMP("table->record[0]", table->record[0], table->s->reclength); + DBUG_DUMP("table->record[1]", table->record[1], table->s->reclength); +#endif /* Below is a minor "optimization". If the key (i.e., key number 0) has the HA_NOSAME flag set, we know that we have found the @@ -6969,8 +7057,8 @@ int Delete_rows_log_event::do_after_row_operations(TABLE *table, int error) int Delete_rows_log_event::do_prepare_row(THD *thd, RELAY_LOG_INFO *rli, TABLE *table, - char const *row_start, - char const **row_end) + char const *const row_start, + char const **const row_end) { int error; DBUG_ASSERT(row_start && row_end); @@ -6980,10 +7068,8 @@ int Delete_rows_log_event::do_prepare_row(THD *thd, RELAY_LOG_INFO *rli, */ DBUG_ASSERT(table->s->fields >= m_width); - error= unpack_row(rli, - table, m_width, table->record[0], - row_start, &m_cols, row_end, &m_master_reclength, - table->read_set, DELETE_ROWS_EVENT); + error= unpack_row(rli, table, m_width, row_start, &m_cols, row_end, + &m_master_reclength, table->read_set, DELETE_ROWS_EVENT); /* If we will access rows using the random access method, m_key will be set to NULL, so we do not need to make a key copy in that case. @@ -7106,8 +7192,8 @@ int Update_rows_log_event::do_after_row_operations(TABLE *table, int error) int Update_rows_log_event::do_prepare_row(THD *thd, RELAY_LOG_INFO *rli, TABLE *table, - char const *row_start, - char const **row_end) + char const *const row_start, + char const **const row_end) { int error; DBUG_ASSERT(row_start && row_end); @@ -7117,21 +7203,31 @@ int Update_rows_log_event::do_prepare_row(THD *thd, RELAY_LOG_INFO *rli, */ DBUG_ASSERT(table->s->fields >= m_width); + /* + We need to perform some juggling below since unpack_row() always + unpacks into table->record[0]. For more information, see the + comments for unpack_row(). + */ + /* record[0] is the before image for the update */ - error= unpack_row(rli, - table, m_width, table->record[0], - row_start, &m_cols, row_end, &m_master_reclength, - table->read_set, UPDATE_ROWS_EVENT); - row_start = *row_end; + error= unpack_row(rli, table, m_width, row_start, &m_cols, row_end, + &m_master_reclength, table->read_set, UPDATE_ROWS_EVENT); + store_record(table, record[1]); + char const *next_start = *row_end; /* m_after_image is the after image for the update */ - error= unpack_row(rli, - table, m_width, m_after_image, - row_start, &m_cols, row_end, &m_master_reclength, - table->write_set, UPDATE_ROWS_EVENT); + error= unpack_row(rli, table, m_width, next_start, &m_cols, row_end, + &m_master_reclength, table->write_set, UPDATE_ROWS_EVENT); + bmove_align(m_after_image, table->record[0], table->s->reclength); + restore_record(table, record[1]); + /* + Don't print debug messages when running valgrind since they can + trigger false warnings. + */ +#ifndef HAVE_purify DBUG_DUMP("record[0]", (const char *)table->record[0], table->s->reclength); DBUG_DUMP("m_after_image", (const char *)m_after_image, table->s->reclength); - +#endif /* If we will access rows using the random access method, m_key will diff --git a/sql/log_event.h b/sql/log_event.h index 81ce2f18b4d..c3f015e723c 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 89607129026..30a271df064 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 3ce8cfee75d..9e2dea26700 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 b0947249439..915e4200fd1 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -105,6 +105,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; @@ -1423,7 +1434,8 @@ void print_plan(JOIN* join,uint idx, double record_count, double read_time, #endif void mysql_print_status(); /* key.cc */ -int find_ref_key(KEY *key, uint key_count, Field *field, uint *key_length); +int find_ref_key(KEY *key, uint key_count, byte *record, Field *field, + uint *key_length); void key_copy(byte *to_key, byte *from_record, KEY *key_info, uint key_length); void key_restore(byte *to_record, byte *from_key, KEY *key_info, uint key_length); @@ -1640,14 +1652,9 @@ extern TYPELIB log_output_typelib; /* optional things, have_* variables */ extern SHOW_COMP_OPTION have_innodb; -extern SHOW_COMP_OPTION have_example_db; -extern SHOW_COMP_OPTION have_archive_db; extern SHOW_COMP_OPTION have_csv_db; -extern SHOW_COMP_OPTION have_federated_db; -extern SHOW_COMP_OPTION have_blackhole_db; extern SHOW_COMP_OPTION have_ndbcluster; extern SHOW_COMP_OPTION have_partition_db; -extern SHOW_COMP_OPTION have_merge_db; extern handlerton *partition_hton; extern handlerton *myisam_hton; @@ -1792,7 +1799,7 @@ ha_rows filesort(THD *thd, TABLE *form,struct st_sort_field *sortorder, uint s_length, SQL_SELECT *select, ha_rows max_rows, bool sort_positions, 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); @@ -1812,7 +1819,7 @@ int create_frm(THD *thd, const char *name, const char *db, const char *table, HA_CREATE_INFO *create_info, uint keys); void update_create_info_from_table(HA_CREATE_INFO *info, TABLE *form); int rename_file_ext(const char * from,const char * to,const char * ext); -bool check_db_name(char *db); +bool check_db_name(LEX_STRING *db); bool check_column_name(const char *name); bool check_table_name(const char *name, uint length); char *get_field(MEM_ROOT *mem, Field *field); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index bcc2d4c49dd..77679a9795e 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -310,7 +310,7 @@ static bool lower_case_table_names_used= 0; static bool volatile select_thread_in_use, signal_thread_in_use; static bool volatile ready_to_exit; static my_bool opt_debugging= 0, opt_external_locking= 0, opt_console= 0; -static my_bool opt_isam, opt_ndbcluster, opt_merge; +static my_bool opt_ndbcluster; static my_bool opt_short_log_format= 0; static uint kill_cached_threads, wake_thread; static ulong killed_threads, thread_created; @@ -1610,7 +1610,7 @@ 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 (> %u): %s", - sizeof(UNIXaddr.sun_path) - 1, mysqld_unix_port); + (uint) sizeof(UNIXaddr.sun_path) - 1, mysqld_unix_port); unireg_abort(1); } if ((unix_sock= socket(AF_UNIX, SOCK_STREAM, 0)) < 0) @@ -2121,7 +2121,7 @@ the thread stack. Please read http://www.mysql.com/doc/en/Linux.html\n\n", #ifdef HAVE_STACKTRACE if (!(test_flags & TEST_NO_STACKTRACE)) { - fprintf(stderr,"thd=%p\n",thd); + fprintf(stderr,"thd: 0x%lx\n",(long) thd); print_stacktrace(thd ? (gptr) thd->thread_stack : (gptr) 0, thread_stack); } @@ -3149,11 +3149,6 @@ with --log-bin instead."); } if (global_system_variables.binlog_format == BINLOG_FORMAT_UNSPEC) { -#if defined(HAVE_NDB_BINLOG) && defined(HAVE_ROW_BASED_REPLICATION) - if (opt_bin_log && have_ndbcluster == SHOW_OPTION_YES) - global_system_variables.binlog_format= BINLOG_FORMAT_ROW; - else -#endif #if defined(HAVE_ROW_BASED_REPLICATION) global_system_variables.binlog_format= BINLOG_FORMAT_MIXED; #else @@ -3213,7 +3208,7 @@ server."); using_update_log=1; } - if (plugin_init(0)) + if (plugin_init(opt_bootstrap)) { sql_print_error("Failed to init plugins."); return 1; @@ -3531,7 +3526,7 @@ 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", + 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; @@ -4077,7 +4072,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, @@ -5165,9 +5160,6 @@ Disable with --skip-innodb-doublewrite.", (gptr*) &innobase_use_doublewrite, (gptr*) &global_system_variables.innodb_table_locks, 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0}, #endif /* End WITH_INNOBASE_STORAGE_ENGINE */ - {"isam", OPT_ISAM, "Obsolete. ISAM storage engine is no longer supported.", - (gptr*) &opt_isam, (gptr*) &opt_isam, 0, GET_BOOL, NO_ARG, 0, 0, 0, - 0, 0, 0}, {"language", 'L', "Client error messages in given language. May be given as a full path.", (gptr*) &language_ptr, (gptr*) &language_ptr, 0, GET_STR, REQUIRED_ARG, @@ -5339,9 +5331,6 @@ master-ssl", #endif /* HAVE_REPLICATION */ {"memlock", OPT_MEMLOCK, "Lock mysqld in memory.", (gptr*) &locked_in_memory, (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, 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, @@ -6337,6 +6326,16 @@ static int show_open_tables(THD *thd, SHOW_VAR *var, char *buff) return 0; } +static int show_prepared_stmt_count(THD *thd, SHOW_VAR *var, char *buff) +{ + var->type= SHOW_LONG; + var->value= buff; + pthread_mutex_lock(&LOCK_prepared_stmt_count); + *((long *)buff)= (long)prepared_stmt_count; + pthread_mutex_unlock(&LOCK_prepared_stmt_count); + return 0; +} + static int show_table_definitions(THD *thd, SHOW_VAR *var, char *buff) { var->type= SHOW_LONG; @@ -6747,6 +6746,7 @@ SHOW_VAR status_vars[]= { {"Open_table_definitions", (char*) &show_table_definitions, SHOW_FUNC}, {"Open_tables", (char*) &show_open_tables, SHOW_FUNC}, {"Opened_tables", (char*) offsetof(STATUS_VAR, opened_tables), SHOW_LONG_STATUS}, + {"Prepared_stmt_count", (char*) &show_prepared_stmt_count, SHOW_FUNC}, #ifdef HAVE_QUERY_CACHE {"Qcache_free_blocks", (char*) &query_cache.free_memory_blocks, SHOW_LONG_NOFLUSH}, {"Qcache_free_memory", (char*) &query_cache.free_memory, SHOW_LONG_NOFLUSH}, @@ -6926,6 +6926,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)); @@ -7016,36 +7017,11 @@ static void mysql_init_variables(void) "d:t:i:o,/tmp/mysqld.trace"); #endif opt_error_log= IF_WIN(1,0); -#ifdef WITH_MYISAMMRG_STORAGE_ENGINE - have_merge_db= SHOW_OPTION_YES; -#else - have_merge_db= SHOW_OPTION_NO; -#endif #ifdef WITH_INNOBASE_STORAGE_ENGINE have_innodb= SHOW_OPTION_YES; #else have_innodb= SHOW_OPTION_NO; #endif -#ifdef WITH_EXAMPLE_STORAGE_ENGINE - have_example_db= SHOW_OPTION_YES; -#else - have_example_db= SHOW_OPTION_NO; -#endif -#ifdef WITH_ARCHIVE_STORAGE_ENGINE - have_archive_db= SHOW_OPTION_YES; -#else - have_archive_db= SHOW_OPTION_NO; -#endif -#ifdef WITH_BLACKHOLE_STORAGE_ENGINE - have_blackhole_db= SHOW_OPTION_YES; -#else - have_blackhole_db= SHOW_OPTION_NO; -#endif -#ifdef WITH_FEDERATED_STORAGE_ENGINE - have_federated_db= SHOW_OPTION_YES; -#else - have_federated_db= SHOW_OPTION_NO; -#endif #ifdef WITH_CSV_STORAGE_ENGINE have_csv_db= SHOW_OPTION_YES; #else @@ -7549,10 +7525,6 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), break; } case OPT_MERGE: - if (opt_merge) - have_merge_db= SHOW_OPTION_YES; - else - have_merge_db= SHOW_OPTION_DISABLED; case OPT_BDB: break; case OPT_NDBCLUSTER: @@ -7784,10 +7756,6 @@ static void get_options(int argc,char **argv) if (opt_innodb) sql_print_warning("this binary does not contain INNODB storage engine"); #endif -#ifndef WITH_ISAM_STORAGE_ENGINE - if (opt_isam) - sql_print_warning("this binary does not contain ISAM storage engine"); -#endif if ((opt_log_slow_admin_statements || opt_log_queries_not_using_indexes) && !opt_slow_log) sql_print_warning("options --log-slow-admin-statements and --log-queries-not-using-indexes have no effect if --log-slow-queries is not set"); @@ -8136,23 +8104,12 @@ void refresh_status(THD *thd) *****************************************************************************/ #undef have_innodb #undef have_ndbcluster -#undef have_example_db -#undef have_archive_db #undef have_csv_db -#undef have_federated_db -#undef have_partition_db -#undef have_blackhole_db -#undef have_merge_db SHOW_COMP_OPTION have_innodb= SHOW_OPTION_NO; SHOW_COMP_OPTION have_ndbcluster= SHOW_OPTION_NO; -SHOW_COMP_OPTION have_example_db= SHOW_OPTION_NO; -SHOW_COMP_OPTION have_archive_db= SHOW_OPTION_NO; SHOW_COMP_OPTION have_csv_db= SHOW_OPTION_NO; -SHOW_COMP_OPTION have_federated_db= SHOW_OPTION_NO; SHOW_COMP_OPTION have_partition_db= SHOW_OPTION_NO; -SHOW_COMP_OPTION have_blackhole_db= SHOW_OPTION_NO; -SHOW_COMP_OPTION have_merge_db= SHOW_OPTION_NO; #ifndef WITH_INNOBASE_STORAGE_ENGINE uint innobase_flush_log_at_trx_commit; diff --git a/sql/mysqld.cc.rej b/sql/mysqld.cc.rej new file mode 100644 index 00000000000..62f0357622d --- /dev/null +++ b/sql/mysqld.cc.rej @@ -0,0 +1,17 @@ +*************** +*** 5316,5322 **** + (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}, + {"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, +--- 5336,5342 ---- + (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, 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, diff --git a/sql/net_serv.cc b/sql/net_serv.cc index a55fef5555c..ec4c4675e76 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -809,7 +809,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(MYSQL_SERVER) /* diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 79b3e023a5f..bcf2bce82b7 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -1003,7 +1003,7 @@ QUICK_RANGE_SELECT::~QUICK_RANGE_SELECT() range_end(); 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->ha_external_lock(current_thd, F_UNLCK); file->close(); @@ -2011,7 +2011,7 @@ 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->stats.records)); delete quick; @@ -3396,7 +3396,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 @@ -3420,7 +3420,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); } @@ -3514,7 +3514,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*)* @@ -3558,7 +3558,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->stats.records) && read_time != DBL_MAX) @@ -4172,7 +4172,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) @@ -9700,8 +9700,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; } @@ -10814,7 +10814,7 @@ static void print_sel_tree(PARAM *param, SEL_TREE *tree, key_map *tree_map, if (!tmp.length()) tmp.append(STRING_WITH_LEN("(empty)")); - DBUG_PRINT("info", ("SEL_TREE %p (%s) scans:%s", tree, msg, tmp.ptr())); + DBUG_PRINT("info", ("SEL_TREE: 0x%lx (%s) scans: %s", (long) tree, msg, tmp.ptr())); DBUG_VOID_RETURN; } @@ -11056,7 +11056,7 @@ void QUICK_GROUP_MIN_MAX_SELECT::dbug_dump(int indent, bool verbose) #endif /* NOT_USED */ /***************************************************************************** -** Instantiate templates +** Instantiate templates *****************************************************************************/ #ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION diff --git a/sql/parse_file.cc b/sql/parse_file.cc index 0071d59242e..0a2d4012af4 100644 --- a/sql/parse_file.cc +++ b/sql/parse_file.cc @@ -368,32 +368,33 @@ my_bool rename_in_schema_file(const char *schema, const char *old_name, { char old_path[FN_REFLEN], new_path[FN_REFLEN], arc_path[FN_REFLEN]; - strxnmov(old_path, FN_REFLEN-1, mysql_data_home, "/", schema, "/", - old_name, reg_ext, NullS); - (void) unpack_filename(old_path, old_path); - - strxnmov(new_path, FN_REFLEN-1, mysql_data_home, "/", schema, "/", - new_name, reg_ext, NullS); - (void) unpack_filename(new_path, new_path); + build_table_filename(old_path, sizeof(old_path) - 1, + schema, old_name, reg_ext, 0); + build_table_filename(new_path, sizeof(new_path) - 1, + schema, new_name, reg_ext, 0); if (my_rename(old_path, new_path, MYF(MY_WME))) return 1; /* check if arc_dir exists */ - strxnmov(arc_path, FN_REFLEN-1, mysql_data_home, "/", schema, "/arc", NullS); - (void) unpack_filename(arc_path, arc_path); + build_table_filename(arc_path, sizeof(arc_path) - 1, schema, "arc", "", 0); if (revision > 0 && !access(arc_path, F_OK)) { + char old_name_buf[FN_REFLEN], new_name_buf[FN_REFLEN]; ulonglong limit= ((revision > num_view_backups) ? revision - num_view_backups : 0); + + VOID(tablename_to_filename(old_name, old_name_buf, sizeof(old_name_buf))); + VOID(tablename_to_filename(new_name, new_name_buf, sizeof(new_name_buf))); + for (; revision > limit ; revision--) { my_snprintf(old_path, FN_REFLEN, "%s/%s%s-%04lu", - arc_path, old_name, reg_ext, (ulong)revision); + arc_path, old_name_buf, reg_ext, (ulong) revision); (void) unpack_filename(old_path, old_path); my_snprintf(new_path, FN_REFLEN, "%s/%s%s-%04lu", - arc_path, new_name, reg_ext, (ulong)revision); + arc_path, new_name_buf, reg_ext, (ulong) revision); (void) unpack_filename(new_path, new_path); my_rename(old_path, new_path, MYF(0)); } diff --git a/sql/parse_file.h b/sql/parse_file.h index 5fb65b4c7ec..0a02bf7eb75 100644 --- a/sql/parse_file.h +++ b/sql/parse_file.h @@ -106,21 +106,4 @@ public: MEM_ROOT *mem_root, bool bad_format_errors); }; - - -/* - Custom version of standard offsetof() macro which can be used to get - offsets of members in class for non-POD types (according to the current - version of C++ standard offsetof() macro can't be used in such cases and - attempt to do so causes warnings to be emitted, OTOH in many cases it is - still OK to assume that all instances of the class has the same offsets - for the same members). - - This is temporary solution which should be removed once File_parser class - and related routines are refactored. -*/ - -#define my_offsetof(TYPE, MEMBER) \ - ((size_t)((char *)&(((TYPE *)0x10)->MEMBER) - (char*)0x10)) - #endif /* _PARSE_FILE_H_ */ diff --git a/sql/protocol.cc b/sql/protocol.cc index a2ae194c374..6fe4e34d5a9 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; @@ -282,8 +282,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", @@ -458,7 +458,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) @@ -481,7 +481,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; } @@ -490,7 +490,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; } @@ -499,7 +499,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; } @@ -563,7 +563,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 b2505600b22..f8b6a7d1df9 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); @@ -251,6 +251,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) @@ -260,7 +261,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(); @@ -356,7 +357,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/repl_failsafe.cc b/sql/repl_failsafe.cc index 66e2aa1c31c..762fcfb7a6a 100644 --- a/sql/repl_failsafe.cc +++ b/sql/repl_failsafe.cc @@ -564,8 +564,8 @@ err: mysql_free_result(res); if (error) { - sql_print_error("While trying to obtain the list of slaves from the master \ -'%s:%d', user '%s' got the following error: '%s'", + sql_print_error("While trying to obtain the list of slaves from the master " + "'%s:%d', user '%s' got the following error: '%s'", mi->host, mi->port, mi->user, error); DBUG_RETURN(1); } @@ -962,7 +962,7 @@ bool load_master_data(THD* thd) Cancel the previous START SLAVE UNTIL, as the fact to download a new copy logically makes UNTIL irrelevant. */ - clear_until_condition(&active_mi->rli); + active_mi->rli.clear_until_condition(); /* No need to update rli.event* coordinates, they will be when the slave diff --git a/sql/rpl_injector.cc b/sql/rpl_injector.cc index 5a74fd58755..3a0fca4dfa5 100644 --- a/sql/rpl_injector.cc +++ b/sql/rpl_injector.cc @@ -39,6 +39,8 @@ injector::transaction::transaction(MYSQL_BIN_LOG *log, THD *thd) m_start_pos.m_file_pos= log_info.pos; begin_trans(m_thd); + + thd->set_current_stmt_binlog_row_based(); } injector::transaction::~transaction() diff --git a/sql/rpl_mi.cc b/sql/rpl_mi.cc new file mode 100644 index 00000000000..c89c8aa131e --- /dev/null +++ b/sql/rpl_mi.cc @@ -0,0 +1,386 @@ +/* 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 <my_global.h> // For HAVE_REPLICATION +#include "mysql_priv.h" +#include <my_dir.h> + +#include "rpl_mi.h" + +#ifdef HAVE_REPLICATION + + +// Defined in slave.cc +int init_intvar_from_file(int* var, IO_CACHE* f, int default_val); +int init_strvar_from_file(char *var, int max_size, IO_CACHE *f, + const char *default_val); + +MASTER_INFO::MASTER_INFO() + :ssl(0), fd(-1), io_thd(0), inited(0), + abort_slave(0),slave_running(0), slave_run_id(0) +{ + host[0] = 0; user[0] = 0; password[0] = 0; + ssl_ca[0]= 0; ssl_capath[0]= 0; ssl_cert[0]= 0; + ssl_cipher[0]= 0; ssl_key[0]= 0; + + bzero((char*) &file, sizeof(file)); + pthread_mutex_init(&run_lock, MY_MUTEX_INIT_FAST); + pthread_mutex_init(&data_lock, MY_MUTEX_INIT_FAST); + pthread_cond_init(&data_cond, NULL); + pthread_cond_init(&start_cond, NULL); + pthread_cond_init(&stop_cond, NULL); +} + +MASTER_INFO::~MASTER_INFO() +{ + pthread_mutex_destroy(&run_lock); + pthread_mutex_destroy(&data_lock); + pthread_cond_destroy(&data_cond); + pthread_cond_destroy(&start_cond); + pthread_cond_destroy(&stop_cond); +} + + +void init_master_info_with_options(MASTER_INFO* mi) +{ + DBUG_ENTER("init_master_info_with_options"); + + mi->master_log_name[0] = 0; + mi->master_log_pos = BIN_LOG_HEADER_SIZE; // skip magic number + + if (master_host) + strmake(mi->host, master_host, sizeof(mi->host) - 1); + if (master_user) + strmake(mi->user, master_user, sizeof(mi->user) - 1); + if (master_password) + strmake(mi->password, master_password, MAX_PASSWORD_LENGTH); + mi->port = master_port; + mi->connect_retry = master_connect_retry; + + mi->ssl= master_ssl; + if (master_ssl_ca) + strmake(mi->ssl_ca, master_ssl_ca, sizeof(mi->ssl_ca)-1); + if (master_ssl_capath) + strmake(mi->ssl_capath, master_ssl_capath, sizeof(mi->ssl_capath)-1); + if (master_ssl_cert) + strmake(mi->ssl_cert, master_ssl_cert, sizeof(mi->ssl_cert)-1); + if (master_ssl_cipher) + strmake(mi->ssl_cipher, master_ssl_cipher, sizeof(mi->ssl_cipher)-1); + if (master_ssl_key) + strmake(mi->ssl_key, master_ssl_key, sizeof(mi->ssl_key)-1); + DBUG_VOID_RETURN; +} + + +#define LINES_IN_MASTER_INFO_WITH_SSL 14 + + +int init_master_info(MASTER_INFO* mi, const char* master_info_fname, + const char* slave_info_fname, + bool abort_if_no_master_info_file, + int thread_mask) +{ + int fd,error; + char fname[FN_REFLEN+128]; + DBUG_ENTER("init_master_info"); + + if (mi->inited) + { + /* + We have to reset read position of relay-log-bin as we may have + already been reading from 'hotlog' when the slave was stopped + last time. If this case pos_in_file would be set and we would + get a crash when trying to read the signature for the binary + relay log. + + We only rewind the read position if we are starting the SQL + thread. The handle_slave_sql thread assumes that the read + position is at the beginning of the file, and will read the + "signature" and then fast-forward to the last position read. + */ + if (thread_mask & SLAVE_SQL) + { + my_b_seek(mi->rli.cur_log, (my_off_t) 0); + } + DBUG_RETURN(0); + } + + mi->mysql=0; + mi->file_id=1; + fn_format(fname, master_info_fname, mysql_data_home, "", 4+32); + + /* + We need a mutex while we are changing master info parameters to + keep other threads from reading bogus info + */ + + pthread_mutex_lock(&mi->data_lock); + fd = mi->fd; + + /* does master.info exist ? */ + + if (access(fname,F_OK)) + { + if (abort_if_no_master_info_file) + { + pthread_mutex_unlock(&mi->data_lock); + DBUG_RETURN(0); + } + /* + if someone removed the file from underneath our feet, just close + the old descriptor and re-create the old file + */ + if (fd >= 0) + my_close(fd, MYF(MY_WME)); + if ((fd = my_open(fname, O_CREAT|O_RDWR|O_BINARY, MYF(MY_WME))) < 0 ) + { + sql_print_error("Failed to create a new master info file (\ +file '%s', errno %d)", fname, my_errno); + goto err; + } + if (init_io_cache(&mi->file, fd, IO_SIZE*2, READ_CACHE, 0L,0, + MYF(MY_WME))) + { + sql_print_error("Failed to create a cache on master info file (\ +file '%s')", fname); + goto err; + } + + mi->fd = fd; + init_master_info_with_options(mi); + + } + else // file exists + { + if (fd >= 0) + reinit_io_cache(&mi->file, READ_CACHE, 0L,0,0); + else + { + if ((fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0 ) + { + sql_print_error("Failed to open the existing master info file (\ +file '%s', errno %d)", fname, my_errno); + goto err; + } + if (init_io_cache(&mi->file, fd, IO_SIZE*2, READ_CACHE, 0L, + 0, MYF(MY_WME))) + { + sql_print_error("Failed to create a cache on master info file (\ +file '%s')", fname); + goto err; + } + } + + mi->fd = fd; + int port, connect_retry, master_log_pos, ssl= 0, lines; + char *first_non_digit; + + /* + Starting from 4.1.x master.info has new format. Now its + first line contains number of lines in file. By reading this + number we will be always distinguish to which version our + master.info corresponds to. We can't simply count lines in + file since versions before 4.1.x could generate files with more + lines than needed. + If first line doesn't contain a number or contain number less than + 14 then such file is treated like file from pre 4.1.1 version. + There is no ambiguity when reading an old master.info, as before + 4.1.1, the first line contained the binlog's name, which is either + empty or has an extension (contains a '.'), so can't be confused + with an integer. + + So we're just reading first line and trying to figure which version + is this. + */ + + /* + The first row is temporarily stored in mi->master_log_name, + if it is line count and not binlog name (new format) it will be + overwritten by the second row later. + */ + if (init_strvar_from_file(mi->master_log_name, + sizeof(mi->master_log_name), &mi->file, + "")) + goto errwithmsg; + + lines= strtoul(mi->master_log_name, &first_non_digit, 10); + + if (mi->master_log_name[0]!='\0' && + *first_non_digit=='\0' && lines >= LINES_IN_MASTER_INFO_WITH_SSL) + { // Seems to be new format + if (init_strvar_from_file(mi->master_log_name, + sizeof(mi->master_log_name), &mi->file, "")) + goto errwithmsg; + } + else + lines= 7; + + if (init_intvar_from_file(&master_log_pos, &mi->file, 4) || + init_strvar_from_file(mi->host, sizeof(mi->host), &mi->file, + master_host) || + init_strvar_from_file(mi->user, sizeof(mi->user), &mi->file, + master_user) || + init_strvar_from_file(mi->password, SCRAMBLED_PASSWORD_CHAR_LENGTH+1, + &mi->file, master_password) || + init_intvar_from_file(&port, &mi->file, master_port) || + init_intvar_from_file(&connect_retry, &mi->file, + master_connect_retry)) + goto errwithmsg; + + /* + If file has ssl part use it even if we have server without + SSL support. But these option will be ignored later when + slave will try connect to master, so in this case warning + is printed. + */ + if (lines >= LINES_IN_MASTER_INFO_WITH_SSL && + (init_intvar_from_file(&ssl, &mi->file, master_ssl) || + init_strvar_from_file(mi->ssl_ca, sizeof(mi->ssl_ca), + &mi->file, master_ssl_ca) || + init_strvar_from_file(mi->ssl_capath, sizeof(mi->ssl_capath), + &mi->file, master_ssl_capath) || + init_strvar_from_file(mi->ssl_cert, sizeof(mi->ssl_cert), + &mi->file, master_ssl_cert) || + init_strvar_from_file(mi->ssl_cipher, sizeof(mi->ssl_cipher), + &mi->file, master_ssl_cipher) || + init_strvar_from_file(mi->ssl_key, sizeof(mi->ssl_key), + &mi->file, master_ssl_key))) + goto errwithmsg; +#ifndef HAVE_OPENSSL + if (ssl) + sql_print_warning("SSL information in the master info file " + "('%s') are ignored because this MySQL slave was compiled " + "without SSL support.", fname); +#endif /* HAVE_OPENSSL */ + + /* + This has to be handled here as init_intvar_from_file can't handle + my_off_t types + */ + mi->master_log_pos= (my_off_t) master_log_pos; + mi->port= (uint) port; + mi->connect_retry= (uint) connect_retry; + mi->ssl= (my_bool) ssl; + } + DBUG_PRINT("master_info",("log_file_name: %s position: %ld", + mi->master_log_name, + (ulong) mi->master_log_pos)); + + mi->rli.mi = mi; + if (init_relay_log_info(&mi->rli, slave_info_fname)) + goto err; + + mi->inited = 1; + // now change cache READ -> WRITE - must do this before flush_master_info + reinit_io_cache(&mi->file, WRITE_CACHE, 0L, 0, 1); + if ((error=test(flush_master_info(mi, 1)))) + sql_print_error("Failed to flush master info file"); + pthread_mutex_unlock(&mi->data_lock); + DBUG_RETURN(error); + +errwithmsg: + sql_print_error("Error reading master configuration"); + +err: + if (fd >= 0) + { + my_close(fd, MYF(0)); + end_io_cache(&mi->file); + } + mi->fd= -1; + pthread_mutex_unlock(&mi->data_lock); + DBUG_RETURN(1); +} + + +/* + RETURN + 2 - flush relay log failed + 1 - flush master info failed + 0 - all ok +*/ +int flush_master_info(MASTER_INFO* mi, bool flush_relay_log_cache) +{ + IO_CACHE* file = &mi->file; + char lbuf[22]; + DBUG_ENTER("flush_master_info"); + DBUG_PRINT("enter",("master_pos: %ld", (long) mi->master_log_pos)); + + /* + Flush the relay log to disk. If we don't do it, then the relay log while + have some part (its last kilobytes) in memory only, so if the slave server + dies now, with, say, from master's position 100 to 150 in memory only (not + on disk), and with position 150 in master.info, then when the slave + restarts, the I/O thread will fetch binlogs from 150, so in the relay log + we will have "[0, 100] U [150, infinity[" and nobody will notice it, so the + SQL thread will jump from 100 to 150, and replication will silently break. + + When we come to this place in code, relay log may or not be initialized; + the caller is responsible for setting 'flush_relay_log_cache' accordingly. + */ + if (flush_relay_log_cache && + flush_io_cache(mi->rli.relay_log.get_log_file())) + DBUG_RETURN(2); + + /* + We flushed the relay log BEFORE the master.info file, because if we crash + now, we will get a duplicate event in the relay log at restart. If we + flushed in the other order, we would get a hole in the relay log. + And duplicate is better than hole (with a duplicate, in later versions we + can add detection and scrap one event; with a hole there's nothing we can + do). + */ + + /* + In certain cases this code may create master.info files that seems + corrupted, because of extra lines filled with garbage in the end + file (this happens if new contents take less space than previous + contents of file). But because of number of lines in the first line + of file we don't care about this garbage. + */ + + my_b_seek(file, 0L); + my_b_printf(file, "%u\n%s\n%s\n%s\n%s\n%s\n%d\n%d\n%d\n%s\n%s\n%s\n%s\n%s\n", + LINES_IN_MASTER_INFO_WITH_SSL, + mi->master_log_name, llstr(mi->master_log_pos, lbuf), + mi->host, mi->user, + mi->password, mi->port, mi->connect_retry, + (int)(mi->ssl), mi->ssl_ca, mi->ssl_capath, mi->ssl_cert, + mi->ssl_cipher, mi->ssl_key); + DBUG_RETURN(-flush_io_cache(file)); +} + + +void end_master_info(MASTER_INFO* mi) +{ + DBUG_ENTER("end_master_info"); + + if (!mi->inited) + DBUG_VOID_RETURN; + end_relay_log_info(&mi->rli); + if (mi->fd >= 0) + { + end_io_cache(&mi->file); + (void)my_close(mi->fd, MYF(MY_WME)); + mi->fd = -1; + } + mi->inited = 0; + + DBUG_VOID_RETURN; +} + + +#endif /* HAVE_REPLICATION */ diff --git a/sql/rpl_mi.h b/sql/rpl_mi.h new file mode 100644 index 00000000000..f0a7d6681fe --- /dev/null +++ b/sql/rpl_mi.h @@ -0,0 +1,110 @@ +/* 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 */ + +#ifndef RPL_MI_H +#define RPL_MI_H + +#ifdef HAVE_REPLICATION + +/***************************************************************************** + + Replication IO Thread + + MASTER_INFO contains: + - information about how to connect to a master + - current master log name + - current master log offset + - misc control variables + + MASTER_INFO is initialized once from the master.info file if such + exists. Otherwise, data members corresponding to master.info fields + are initialized with defaults specified by master-* options. The + initialization is done through init_master_info() call. + + The format of master.info file: + + log_name + log_pos + master_host + master_user + master_pass + master_port + master_connect_retry + + To write out the contents of master.info file to disk ( needed every + time we read and queue data from the master ), a call to + flush_master_info() is required. + + To clean up, call end_master_info() + +*****************************************************************************/ + +class MASTER_INFO +{ + public: + MASTER_INFO(); + ~MASTER_INFO(); + + /* the variables below are needed because we can change masters on the fly */ + char master_log_name[FN_REFLEN]; + char host[HOSTNAME_LENGTH+1]; + char user[USERNAME_LENGTH+1]; + char password[MAX_PASSWORD_LENGTH+1]; + my_bool ssl; // enables use of SSL connection if true + char ssl_ca[FN_REFLEN], ssl_capath[FN_REFLEN], ssl_cert[FN_REFLEN]; + char ssl_cipher[FN_REFLEN], ssl_key[FN_REFLEN]; + + my_off_t master_log_pos; + File fd; // we keep the file open, so we need to remember the file pointer + IO_CACHE file; + + pthread_mutex_t data_lock,run_lock; + pthread_cond_t data_cond,start_cond,stop_cond; + THD *io_thd; + MYSQL* mysql; + uint32 file_id; /* for 3.23 load data infile */ + RELAY_LOG_INFO rli; + uint port; + uint connect_retry; +#ifndef DBUG_OFF + int events_till_disconnect; +#endif + bool inited; + volatile bool abort_slave; + volatile uint slave_running; + volatile ulong slave_run_id; + /* + The difference in seconds between the clock of the master and the clock of + the slave (second - first). It must be signed as it may be <0 or >0. + clock_diff_with_master is computed when the I/O thread starts; for this the + I/O thread does a SELECT UNIX_TIMESTAMP() on the master. + "how late the slave is compared to the master" is computed like this: + clock_of_slave - last_timestamp_executed_by_SQL_thread - clock_diff_with_master + + */ + long clock_diff_with_master; +}; + +void init_master_info_with_options(MASTER_INFO* mi); +int init_master_info(MASTER_INFO* mi, const char* master_info_fname, + const char* slave_info_fname, + bool abort_if_no_master_info_file, + int thread_mask); +void end_master_info(MASTER_INFO* mi); +int flush_master_info(MASTER_INFO* mi, bool flush_relay_log_cache); + +#endif /* HAVE_REPLICATION */ +#endif /* RPL_MI_H */ diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc new file mode 100644 index 00000000000..a2edb9dc8a8 --- /dev/null +++ b/sql/rpl_rli.cc @@ -0,0 +1,1112 @@ +/* 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 "mysql_priv.h" + +#include "rpl_rli.h" +#include <my_dir.h> // For MY_STAT +#include "sql_repl.h" // For check_binlog_magic + +static int count_relay_log_space(RELAY_LOG_INFO* rli); + +// Defined in slave.cc +int init_intvar_from_file(int* var, IO_CACHE* f, int default_val); +int init_strvar_from_file(char *var, int max_size, IO_CACHE *f, + const char *default_val); + + +st_relay_log_info::st_relay_log_info() + :no_storage(FALSE), info_fd(-1), cur_log_fd(-1), save_temporary_tables(0), + cur_log_old_open_count(0), group_master_log_pos(0), log_space_total(0), + ignore_log_space_limit(0), last_master_timestamp(0), slave_skip_counter(0), + abort_pos_wait(0), slave_run_id(0), sql_thd(0), last_slave_errno(0), + inited(0), abort_slave(0), slave_running(0), until_condition(UNTIL_NONE), + until_log_pos(0), retried_trans(0), + tables_to_lock(0), tables_to_lock_count(0), + unsafe_to_stop_at(0) +{ + DBUG_ENTER("st_relay_log_info::st_relay_log_info"); + + group_relay_log_name[0]= event_relay_log_name[0]= + group_master_log_name[0]= 0; + last_slave_error[0]= until_log_name[0]= ign_master_log_name_end[0]= 0; + bzero((char*) &info_file, sizeof(info_file)); + bzero((char*) &cache_buf, sizeof(cache_buf)); + cached_charset_invalidate(); + pthread_mutex_init(&run_lock, MY_MUTEX_INIT_FAST); + pthread_mutex_init(&data_lock, MY_MUTEX_INIT_FAST); + pthread_mutex_init(&log_space_lock, MY_MUTEX_INIT_FAST); + pthread_cond_init(&data_cond, NULL); + pthread_cond_init(&start_cond, NULL); + pthread_cond_init(&stop_cond, NULL); + pthread_cond_init(&log_space_cond, NULL); + relay_log.init_pthread_objects(); + DBUG_VOID_RETURN; +} + + +st_relay_log_info::~st_relay_log_info() +{ + DBUG_ENTER("st_relay_log_info::~st_relay_log_info"); + + pthread_mutex_destroy(&run_lock); + pthread_mutex_destroy(&data_lock); + pthread_mutex_destroy(&log_space_lock); + pthread_cond_destroy(&data_cond); + pthread_cond_destroy(&start_cond); + pthread_cond_destroy(&stop_cond); + pthread_cond_destroy(&log_space_cond); + relay_log.cleanup(); + DBUG_VOID_RETURN; +} + + +int init_relay_log_info(RELAY_LOG_INFO* rli, + const char* info_fname) +{ + char fname[FN_REFLEN+128]; + int info_fd; + const char* msg = 0; + int error = 0; + DBUG_ENTER("init_relay_log_info"); + DBUG_ASSERT(!rli->no_storage); // Don't init if there is no storage + + if (rli->inited) // Set if this function called + DBUG_RETURN(0); + fn_format(fname, info_fname, mysql_data_home, "", 4+32); + pthread_mutex_lock(&rli->data_lock); + info_fd = rli->info_fd; + rli->cur_log_fd = -1; + rli->slave_skip_counter=0; + rli->abort_pos_wait=0; + rli->log_space_limit= relay_log_space_limit; + rli->log_space_total= 0; + rli->tables_to_lock= 0; + rli->tables_to_lock_count= 0; + + /* + The relay log will now be opened, as a SEQ_READ_APPEND IO_CACHE. + Note that the I/O thread flushes it to disk after writing every + event, in flush_master_info(mi, 1). + */ + + /* + For the maximum log size, we choose max_relay_log_size if it is + non-zero, max_binlog_size otherwise. If later the user does SET + GLOBAL on one of these variables, fix_max_binlog_size and + fix_max_relay_log_size will reconsider the choice (for example + if the user changes max_relay_log_size to zero, we have to + switch to using max_binlog_size for the relay log) and update + rli->relay_log.max_size (and mysql_bin_log.max_size). + */ + { + char buf[FN_REFLEN]; + const char *ln; + static bool name_warning_sent= 0; + ln= rli->relay_log.generate_name(opt_relay_logname, "-relay-bin", + 1, buf); + /* We send the warning only at startup, not after every RESET SLAVE */ + if (!opt_relay_logname && !opt_relaylog_index_name && !name_warning_sent) + { + /* + User didn't give us info to name the relay log index file. + Picking `hostname`-relay-bin.index like we do, causes replication to + fail if this slave's hostname is changed later. So, we would like to + instead require a name. But as we don't want to break many existing + setups, we only give warning, not error. + */ + sql_print_warning("Neither --relay-log nor --relay-log-index were used;" + " so replication " + "may break when this MySQL server acts as a " + "slave and has his hostname changed!! Please " + "use '--relay-log=%s' to avoid this problem.", ln); + name_warning_sent= 1; + } + /* + note, that if open() fails, we'll still have index file open + but a destructor will take care of that + */ + if (rli->relay_log.open_index_file(opt_relaylog_index_name, ln) || + rli->relay_log.open(ln, LOG_BIN, 0, SEQ_READ_APPEND, 0, + (max_relay_log_size ? max_relay_log_size : + max_binlog_size), 1)) + { + pthread_mutex_unlock(&rli->data_lock); + sql_print_error("Failed in open_log() called from init_relay_log_info()"); + DBUG_RETURN(1); + } + } + + /* if file does not exist */ + if (access(fname,F_OK)) + { + /* + If someone removed the file from underneath our feet, just close + the old descriptor and re-create the old file + */ + if (info_fd >= 0) + my_close(info_fd, MYF(MY_WME)); + if ((info_fd = my_open(fname, O_CREAT|O_RDWR|O_BINARY, MYF(MY_WME))) < 0) + { + sql_print_error("Failed to create a new relay log info file (\ +file '%s', errno %d)", fname, my_errno); + msg= current_thd->net.last_error; + goto err; + } + if (init_io_cache(&rli->info_file, info_fd, IO_SIZE*2, READ_CACHE, 0L,0, + MYF(MY_WME))) + { + sql_print_error("Failed to create a cache on relay log info file '%s'", + fname); + msg= current_thd->net.last_error; + goto err; + } + + /* Init relay log with first entry in the relay index file */ + if (init_relay_log_pos(rli,NullS,BIN_LOG_HEADER_SIZE,0 /* no data lock */, + &msg, 0)) + { + sql_print_error("Failed to open the relay log 'FIRST' (relay_log_pos 4)"); + goto err; + } + rli->group_master_log_name[0]= 0; + rli->group_master_log_pos= 0; + rli->info_fd= info_fd; + } + else // file exists + { + if (info_fd >= 0) + reinit_io_cache(&rli->info_file, READ_CACHE, 0L,0,0); + else + { + int error=0; + if ((info_fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0) + { + sql_print_error("\ +Failed to open the existing relay log info file '%s' (errno %d)", + fname, my_errno); + error= 1; + } + else if (init_io_cache(&rli->info_file, info_fd, + IO_SIZE*2, READ_CACHE, 0L, 0, MYF(MY_WME))) + { + sql_print_error("Failed to create a cache on relay log info file '%s'", + fname); + error= 1; + } + if (error) + { + if (info_fd >= 0) + my_close(info_fd, MYF(0)); + rli->info_fd= -1; + rli->relay_log.close(LOG_CLOSE_INDEX | LOG_CLOSE_STOP_EVENT); + pthread_mutex_unlock(&rli->data_lock); + DBUG_RETURN(1); + } + } + + rli->info_fd = info_fd; + int relay_log_pos, master_log_pos; + if (init_strvar_from_file(rli->group_relay_log_name, + sizeof(rli->group_relay_log_name), + &rli->info_file, "") || + init_intvar_from_file(&relay_log_pos, + &rli->info_file, BIN_LOG_HEADER_SIZE) || + init_strvar_from_file(rli->group_master_log_name, + sizeof(rli->group_master_log_name), + &rli->info_file, "") || + init_intvar_from_file(&master_log_pos, &rli->info_file, 0)) + { + msg="Error reading slave log configuration"; + goto err; + } + strmake(rli->event_relay_log_name,rli->group_relay_log_name, + sizeof(rli->event_relay_log_name)-1); + rli->group_relay_log_pos= rli->event_relay_log_pos= relay_log_pos; + rli->group_master_log_pos= master_log_pos; + + if (init_relay_log_pos(rli, + rli->group_relay_log_name, + rli->group_relay_log_pos, + 0 /* no data lock*/, + &msg, 0)) + { + char llbuf[22]; + sql_print_error("Failed to open the relay log '%s' (relay_log_pos %s)", + rli->group_relay_log_name, + llstr(rli->group_relay_log_pos, llbuf)); + goto err; + } + } + +#ifndef DBUG_OFF + { + char llbuf1[22], llbuf2[22]; + DBUG_PRINT("info", ("my_b_tell(rli->cur_log)=%s rli->event_relay_log_pos=%s", + llstr(my_b_tell(rli->cur_log),llbuf1), + llstr(rli->event_relay_log_pos,llbuf2))); + DBUG_ASSERT(rli->event_relay_log_pos >= BIN_LOG_HEADER_SIZE); + DBUG_ASSERT(my_b_tell(rli->cur_log) == rli->event_relay_log_pos); + } +#endif + + /* + Now change the cache from READ to WRITE - must do this + before flush_relay_log_info + */ + reinit_io_cache(&rli->info_file, WRITE_CACHE,0L,0,1); + if ((error= flush_relay_log_info(rli))) + sql_print_error("Failed to flush relay log info file"); + if (count_relay_log_space(rli)) + { + msg="Error counting relay log space"; + goto err; + } + rli->inited= 1; + pthread_mutex_unlock(&rli->data_lock); + DBUG_RETURN(error); + +err: + sql_print_error(msg); + end_io_cache(&rli->info_file); + if (info_fd >= 0) + my_close(info_fd, MYF(0)); + rli->info_fd= -1; + rli->relay_log.close(LOG_CLOSE_INDEX | LOG_CLOSE_STOP_EVENT); + pthread_mutex_unlock(&rli->data_lock); + DBUG_RETURN(1); +} + + +static inline int add_relay_log(RELAY_LOG_INFO* rli,LOG_INFO* linfo) +{ + MY_STAT s; + DBUG_ENTER("add_relay_log"); + if (!my_stat(linfo->log_file_name,&s,MYF(0))) + { + sql_print_error("log %s listed in the index, but failed to stat", + linfo->log_file_name); + DBUG_RETURN(1); + } + rli->log_space_total += s.st_size; +#ifndef DBUG_OFF + char buf[22]; + DBUG_PRINT("info",("log_space_total: %s", llstr(rli->log_space_total,buf))); +#endif + DBUG_RETURN(0); +} + + +static int count_relay_log_space(RELAY_LOG_INFO* rli) +{ + LOG_INFO linfo; + DBUG_ENTER("count_relay_log_space"); + rli->log_space_total= 0; + if (rli->relay_log.find_log_pos(&linfo, NullS, 1)) + { + sql_print_error("Could not find first log while counting relay log space"); + DBUG_RETURN(1); + } + do + { + if (add_relay_log(rli,&linfo)) + DBUG_RETURN(1); + } while (!rli->relay_log.find_next_log(&linfo, 1)); + /* + As we have counted everything, including what may have written in a + preceding write, we must reset bytes_written, or we may count some space + twice. + */ + rli->relay_log.reset_bytes_written(); + DBUG_RETURN(0); +} + + +void st_relay_log_info::clear_slave_error() +{ + DBUG_ENTER("clear_slave_error"); + + /* Clear the errors displayed by SHOW SLAVE STATUS */ + last_slave_error[0]= 0; + last_slave_errno= 0; + DBUG_VOID_RETURN; +} + +/* + Reset UNTIL condition for RELAY_LOG_INFO + + SYNOPSYS + clear_until_condition() + rli - RELAY_LOG_INFO structure where UNTIL condition should be reset + */ + +void st_relay_log_info::clear_until_condition() +{ + DBUG_ENTER("clear_until_condition"); + + until_condition= RELAY_LOG_INFO::UNTIL_NONE; + until_log_name[0]= 0; + until_log_pos= 0; + DBUG_VOID_RETURN; +} + + +/* + Open the given relay log + + SYNOPSIS + init_relay_log_pos() + rli Relay information (will be initialized) + log Name of relay log file to read from. NULL = First log + pos Position in relay log file + need_data_lock Set to 1 if this functions should do mutex locks + errmsg Store pointer to error message here + look_for_description_event + 1 if we should look for such an event. We only need + this when the SQL thread starts and opens an existing + relay log and has to execute it (possibly from an + offset >4); then we need to read the first event of + the relay log to be able to parse the events we have + to execute. + + DESCRIPTION + - Close old open relay log files. + - If we are using the same relay log as the running IO-thread, then set + rli->cur_log to point to the same IO_CACHE entry. + - If not, open the 'log' binary file. + + TODO + - check proper initialization of group_master_log_name/group_master_log_pos + + RETURN VALUES + 0 ok + 1 error. errmsg is set to point to the error message +*/ + +int init_relay_log_pos(RELAY_LOG_INFO* rli,const char* log, + ulonglong pos, bool need_data_lock, + const char** errmsg, + bool look_for_description_event) +{ + DBUG_ENTER("init_relay_log_pos"); + DBUG_PRINT("info", ("pos: %lu", (ulong) pos)); + + *errmsg=0; + pthread_mutex_t *log_lock=rli->relay_log.get_log_lock(); + + if (need_data_lock) + pthread_mutex_lock(&rli->data_lock); + + /* + Slave threads are not the only users of init_relay_log_pos(). CHANGE MASTER + is, too, and init_slave() too; these 2 functions allocate a description + event in init_relay_log_pos, which is not freed by the terminating SQL slave + thread as that thread is not started by these functions. So we have to free + the description_event here, in case, so that there is no memory leak in + running, say, CHANGE MASTER. + */ + delete rli->relay_log.description_event_for_exec; + /* + By default the relay log is in binlog format 3 (4.0). + Even if format is 4, this will work enough to read the first event + (Format_desc) (remember that format 4 is just lenghtened compared to format + 3; format 3 is a prefix of format 4). + */ + rli->relay_log.description_event_for_exec= new + Format_description_log_event(3); + + pthread_mutex_lock(log_lock); + + /* Close log file and free buffers if it's already open */ + if (rli->cur_log_fd >= 0) + { + end_io_cache(&rli->cache_buf); + my_close(rli->cur_log_fd, MYF(MY_WME)); + rli->cur_log_fd = -1; + } + + rli->group_relay_log_pos = rli->event_relay_log_pos = pos; + + /* + Test to see if the previous run was with the skip of purging + If yes, we do not purge when we restart + */ + if (rli->relay_log.find_log_pos(&rli->linfo, NullS, 1)) + { + *errmsg="Could not find first log during relay log initialization"; + goto err; + } + + if (log && rli->relay_log.find_log_pos(&rli->linfo, log, 1)) + { + *errmsg="Could not find target log during relay log initialization"; + goto err; + } + strmake(rli->group_relay_log_name,rli->linfo.log_file_name, + sizeof(rli->group_relay_log_name)-1); + strmake(rli->event_relay_log_name,rli->linfo.log_file_name, + sizeof(rli->event_relay_log_name)-1); + if (rli->relay_log.is_active(rli->linfo.log_file_name)) + { + /* + The IO thread is using this log file. + In this case, we will use the same IO_CACHE pointer to + read data as the IO thread is using to write data. + */ + my_b_seek((rli->cur_log=rli->relay_log.get_log_file()), (off_t)0); + if (check_binlog_magic(rli->cur_log,errmsg)) + goto err; + rli->cur_log_old_open_count=rli->relay_log.get_open_count(); + } + else + { + /* + Open the relay log and set rli->cur_log to point at this one + */ + if ((rli->cur_log_fd=open_binlog(&rli->cache_buf, + rli->linfo.log_file_name,errmsg)) < 0) + goto err; + rli->cur_log = &rli->cache_buf; + } + /* + In all cases, check_binlog_magic() has been called so we're at offset 4 for + sure. + */ + if (pos > BIN_LOG_HEADER_SIZE) /* If pos<=4, we stay at 4 */ + { + Log_event* ev; + while (look_for_description_event) + { + /* + Read the possible Format_description_log_event; if position + was 4, no need, it will be read naturally. + */ + DBUG_PRINT("info",("looking for a Format_description_log_event")); + + if (my_b_tell(rli->cur_log) >= pos) + break; + + /* + Because of we have rli->data_lock and log_lock, we can safely read an + event + */ + if (!(ev=Log_event::read_log_event(rli->cur_log,0, + rli->relay_log.description_event_for_exec))) + { + DBUG_PRINT("info",("could not read event, rli->cur_log->error=%d", + rli->cur_log->error)); + if (rli->cur_log->error) /* not EOF */ + { + *errmsg= "I/O error reading event at position 4"; + goto err; + } + break; + } + else if (ev->get_type_code() == FORMAT_DESCRIPTION_EVENT) + { + DBUG_PRINT("info",("found Format_description_log_event")); + delete rli->relay_log.description_event_for_exec; + rli->relay_log.description_event_for_exec= (Format_description_log_event*) ev; + /* + As ev was returned by read_log_event, it has passed is_valid(), so + my_malloc() in ctor worked, no need to check again. + */ + /* + Ok, we found a Format_description event. But it is not sure that this + describes the whole relay log; indeed, one can have this sequence + (starting from position 4): + Format_desc (of slave) + Rotate (of master) + Format_desc (of master) + So the Format_desc which really describes the rest of the relay log + is the 3rd event (it can't be further than that, because we rotate + the relay log when we queue a Rotate event from the master). + But what describes the Rotate is the first Format_desc. + So what we do is: + go on searching for Format_description events, until you exceed the + position (argument 'pos') or until you find another event than Rotate + or Format_desc. + */ + } + else + { + DBUG_PRINT("info",("found event of another type=%d", + ev->get_type_code())); + look_for_description_event= (ev->get_type_code() == ROTATE_EVENT); + delete ev; + } + } + my_b_seek(rli->cur_log,(off_t)pos); +#ifndef DBUG_OFF + { + char llbuf1[22], llbuf2[22]; + DBUG_PRINT("info", ("my_b_tell(rli->cur_log)=%s rli->event_relay_log_pos=%s", + llstr(my_b_tell(rli->cur_log),llbuf1), + llstr(rli->event_relay_log_pos,llbuf2))); + } +#endif + + } + +err: + /* + If we don't purge, we can't honour relay_log_space_limit ; + silently discard it + */ + if (!relay_log_purge) + rli->log_space_limit= 0; + pthread_cond_broadcast(&rli->data_cond); + + pthread_mutex_unlock(log_lock); + + if (need_data_lock) + pthread_mutex_unlock(&rli->data_lock); + if (!rli->relay_log.description_event_for_exec->is_valid() && !*errmsg) + *errmsg= "Invalid Format_description log event; could be out of memory"; + + DBUG_RETURN ((*errmsg) ? 1 : 0); +} + + +/* + Waits until the SQL thread reaches (has executed up to) the + log/position or timed out. + + SYNOPSIS + wait_for_pos() + thd client thread that sent SELECT MASTER_POS_WAIT + log_name log name to wait for + log_pos position to wait for + timeout timeout in seconds before giving up waiting + + NOTES + timeout is longlong whereas it should be ulong ; but this is + to catch if the user submitted a negative timeout. + + RETURN VALUES + -2 improper arguments (log_pos<0) + or slave not running, or master info changed + during the function's execution, + or client thread killed. -2 is translated to NULL by caller + -1 timed out + >=0 number of log events the function had to wait + before reaching the desired log/position + */ + +int st_relay_log_info::wait_for_pos(THD* thd, String* log_name, + longlong log_pos, + longlong timeout) +{ + int event_count = 0; + ulong init_abort_pos_wait; + int error=0; + struct timespec abstime; // for timeout checking + const char *msg; + DBUG_ENTER("st_relay_log_info::wait_for_pos"); + + if (!inited) + DBUG_RETURN(-1); + + DBUG_PRINT("enter",("log_name: '%s' log_pos: %lu timeout: %lu", + log_name->c_ptr(), (ulong) log_pos, (ulong) timeout)); + + set_timespec(abstime,timeout); + pthread_mutex_lock(&data_lock); + msg= thd->enter_cond(&data_cond, &data_lock, + "Waiting for the slave SQL thread to " + "advance position"); + /* + This function will abort when it notices that some CHANGE MASTER or + RESET MASTER has changed the master info. + To catch this, these commands modify abort_pos_wait ; We just monitor + abort_pos_wait and see if it has changed. + Why do we have this mechanism instead of simply monitoring slave_running + in the loop (we do this too), as CHANGE MASTER/RESET SLAVE require that + the SQL thread be stopped? + This is becasue if someones does: + STOP SLAVE;CHANGE MASTER/RESET SLAVE; START SLAVE; + the change may happen very quickly and we may not notice that + slave_running briefly switches between 1/0/1. + */ + init_abort_pos_wait= abort_pos_wait; + + /* + We'll need to + handle all possible log names comparisons (e.g. 999 vs 1000). + We use ulong for string->number conversion ; this is no + stronger limitation than in find_uniq_filename in sql/log.cc + */ + ulong log_name_extension; + char log_name_tmp[FN_REFLEN]; //make a char[] from String + + strmake(log_name_tmp, log_name->ptr(), min(log_name->length(), FN_REFLEN-1)); + + char *p= fn_ext(log_name_tmp); + char *p_end; + if (!*p || log_pos<0) + { + error= -2; //means improper arguments + goto err; + } + // Convert 0-3 to 4 + log_pos= max(log_pos, BIN_LOG_HEADER_SIZE); + /* p points to '.' */ + log_name_extension= strtoul(++p, &p_end, 10); + /* + p_end points to the first invalid character. + If it equals to p, no digits were found, error. + If it contains '\0' it means conversion went ok. + */ + if (p_end==p || *p_end) + { + error= -2; + goto err; + } + + /* The "compare and wait" main loop */ + while (!thd->killed && + init_abort_pos_wait == abort_pos_wait && + slave_running) + { + bool pos_reached; + int cmp_result= 0; + + DBUG_PRINT("info", + ("init_abort_pos_wait: %ld abort_pos_wait: %ld", + init_abort_pos_wait, abort_pos_wait)); + DBUG_PRINT("info",("group_master_log_name: '%s' pos: %lu", + group_master_log_name, (ulong) group_master_log_pos)); + + /* + group_master_log_name can be "", if we are just after a fresh + replication start or after a CHANGE MASTER TO MASTER_HOST/PORT + (before we have executed one Rotate event from the master) or + (rare) if the user is doing a weird slave setup (see next + paragraph). If group_master_log_name is "", we assume we don't + have enough info to do the comparison yet, so we just wait until + more data. In this case master_log_pos is always 0 except if + somebody (wrongly) sets this slave to be a slave of itself + without using --replicate-same-server-id (an unsupported + configuration which does nothing), then group_master_log_pos + will grow and group_master_log_name will stay "". + */ + if (*group_master_log_name) + { + char *basename= (group_master_log_name + + dirname_length(group_master_log_name)); + /* + First compare the parts before the extension. + Find the dot in the master's log basename, + and protect against user's input error : + if the names do not match up to '.' included, return error + */ + char *q= (char*)(fn_ext(basename)+1); + if (strncmp(basename, log_name_tmp, (int)(q-basename))) + { + error= -2; + break; + } + // Now compare extensions. + char *q_end; + ulong group_master_log_name_extension= strtoul(q, &q_end, 10); + if (group_master_log_name_extension < log_name_extension) + cmp_result= -1 ; + else + cmp_result= (group_master_log_name_extension > log_name_extension) ? 1 : 0 ; + + pos_reached= ((!cmp_result && group_master_log_pos >= (ulonglong)log_pos) || + cmp_result > 0); + if (pos_reached || thd->killed) + break; + } + + //wait for master update, with optional timeout. + + DBUG_PRINT("info",("Waiting for master update")); + /* + We are going to pthread_cond_(timed)wait(); if the SQL thread stops it + will wake us up. + */ + if (timeout > 0) + { + /* + Note that pthread_cond_timedwait checks for the timeout + before for the condition ; i.e. it returns ETIMEDOUT + if the system time equals or exceeds the time specified by abstime + before the condition variable is signaled or broadcast, _or_ if + the absolute time specified by abstime has already passed at the time + of the call. + For that reason, pthread_cond_timedwait will do the "timeoutting" job + even if its condition is always immediately signaled (case of a loaded + master). + */ + error=pthread_cond_timedwait(&data_cond, &data_lock, &abstime); + } + else + pthread_cond_wait(&data_cond, &data_lock); + DBUG_PRINT("info",("Got signal of master update or timed out")); + if (error == ETIMEDOUT || error == ETIME) + { + error= -1; + break; + } + error=0; + event_count++; + DBUG_PRINT("info",("Testing if killed or SQL thread not running")); + } + +err: + thd->exit_cond(msg); + DBUG_PRINT("exit",("killed: %d abort: %d slave_running: %d \ +improper_arguments: %d timed_out: %d", + thd->killed_errno(), + (int) (init_abort_pos_wait != abort_pos_wait), + (int) slave_running, + (int) (error == -2), + (int) (error == -1))); + if (thd->killed || init_abort_pos_wait != abort_pos_wait || + !slave_running) + { + error= -2; + } + DBUG_RETURN( error ? error : event_count ); +} + + +void st_relay_log_info::inc_group_relay_log_pos(ulonglong log_pos, + bool skip_lock) +{ + DBUG_ENTER("st_relay_log_info::inc_group_relay_log_pos"); + + if (!skip_lock) + pthread_mutex_lock(&data_lock); + inc_event_relay_log_pos(); + group_relay_log_pos= event_relay_log_pos; + strmake(group_relay_log_name,event_relay_log_name, + sizeof(group_relay_log_name)-1); + + notify_group_relay_log_name_update(); + + /* + If the slave does not support transactions and replicates a transaction, + users should not trust group_master_log_pos (which they can display with + SHOW SLAVE STATUS or read from relay-log.info), because to compute + group_master_log_pos the slave relies on log_pos stored in the master's + binlog, but if we are in a master's transaction these positions are always + the BEGIN's one (excepted for the COMMIT), so group_master_log_pos does + not advance as it should on the non-transactional slave (it advances by + big leaps, whereas it should advance by small leaps). + */ + /* + In 4.x we used the event's len to compute the positions here. This is + wrong if the event was 3.23/4.0 and has been converted to 5.0, because + then the event's len is not what is was in the master's binlog, so this + will make a wrong group_master_log_pos (yes it's a bug in 3.23->4.0 + replication: Exec_master_log_pos is wrong). Only way to solve this is to + have the original offset of the end of the event the relay log. This is + what we do in 5.0: log_pos has become "end_log_pos" (because the real use + of log_pos in 4.0 was to compute the end_log_pos; so better to store + end_log_pos instead of begin_log_pos. + If we had not done this fix here, the problem would also have appeared + when the slave and master are 5.0 but with different event length (for + example the slave is more recent than the master and features the event + UID). It would give false MASTER_POS_WAIT, false Exec_master_log_pos in + SHOW SLAVE STATUS, and so the user would do some CHANGE MASTER using this + value which would lead to badly broken replication. + Even the relay_log_pos will be corrupted in this case, because the len is + the relay log is not "val". + With the end_log_pos solution, we avoid computations involving lengthes. + */ + DBUG_PRINT("info", ("log_pos: %lu group_master_log_pos: %lu", + (long) log_pos, (long) group_master_log_pos)); + if (log_pos) // 3.23 binlogs don't have log_posx + { + group_master_log_pos= log_pos; + } + pthread_cond_broadcast(&data_cond); + if (!skip_lock) + pthread_mutex_unlock(&data_lock); + DBUG_VOID_RETURN; +} + + +void st_relay_log_info::close_temporary_tables() +{ + TABLE *table,*next; + DBUG_ENTER("st_relay_log_info::close_temporary_tables"); + + for (table=save_temporary_tables ; table ; table=next) + { + next=table->next; + /* + Don't ask for disk deletion. For now, anyway they will be deleted when + slave restarts, but it is a better intention to not delete them. + */ + DBUG_PRINT("info", ("table: 0x%lx", (long) table)); + close_temporary(table, 1, 0); + } + save_temporary_tables= 0; + slave_open_temp_tables= 0; + DBUG_VOID_RETURN; +} + +/* + purge_relay_logs() + + NOTES + Assumes to have a run lock on rli and that no slave thread are running. +*/ + +int purge_relay_logs(RELAY_LOG_INFO* rli, THD *thd, bool just_reset, + const char** errmsg) +{ + int error=0; + DBUG_ENTER("purge_relay_logs"); + + /* + Even if rli->inited==0, we still try to empty rli->master_log_* variables. + Indeed, rli->inited==0 does not imply that they already are empty. + It could be that slave's info initialization partly succeeded : + for example if relay-log.info existed but *relay-bin*.* + have been manually removed, init_relay_log_info reads the old + relay-log.info and fills rli->master_log_*, then init_relay_log_info + checks for the existence of the relay log, this fails and + init_relay_log_info leaves rli->inited to 0. + In that pathological case, rli->master_log_pos* will be properly reinited + at the next START SLAVE (as RESET SLAVE or CHANGE + MASTER, the callers of purge_relay_logs, will delete bogus *.info files + or replace them with correct files), however if the user does SHOW SLAVE + STATUS before START SLAVE, he will see old, confusing rli->master_log_*. + In other words, we reinit rli->master_log_* for SHOW SLAVE STATUS + to display fine in any case. + */ + + rli->group_master_log_name[0]= 0; + rli->group_master_log_pos= 0; + + if (!rli->inited) + { + DBUG_PRINT("info", ("rli->inited == 0")); + DBUG_RETURN(0); + } + + DBUG_ASSERT(rli->slave_running == 0); + DBUG_ASSERT(rli->mi->slave_running == 0); + + rli->slave_skip_counter=0; + pthread_mutex_lock(&rli->data_lock); + + /* + we close the relay log fd possibly left open by the slave SQL thread, + to be able to delete it; the relay log fd possibly left open by the slave + I/O thread will be closed naturally in reset_logs() by the + close(LOG_CLOSE_TO_BE_OPENED) call + */ + if (rli->cur_log_fd >= 0) + { + end_io_cache(&rli->cache_buf); + my_close(rli->cur_log_fd, MYF(MY_WME)); + rli->cur_log_fd= -1; + } + + if (rli->relay_log.reset_logs(thd)) + { + *errmsg = "Failed during log reset"; + error=1; + goto err; + } + /* Save name of used relay log file */ + strmake(rli->group_relay_log_name, rli->relay_log.get_log_fname(), + sizeof(rli->group_relay_log_name)-1); + strmake(rli->event_relay_log_name, rli->relay_log.get_log_fname(), + sizeof(rli->event_relay_log_name)-1); + rli->group_relay_log_pos= rli->event_relay_log_pos= BIN_LOG_HEADER_SIZE; + if (count_relay_log_space(rli)) + { + *errmsg= "Error counting relay log space"; + goto err; + } + if (!just_reset) + error= init_relay_log_pos(rli, rli->group_relay_log_name, + rli->group_relay_log_pos, + 0 /* do not need data lock */, errmsg, 0); + +err: +#ifndef DBUG_OFF + char buf[22]; +#endif + DBUG_PRINT("info",("log_space_total: %s",llstr(rli->log_space_total,buf))); + pthread_mutex_unlock(&rli->data_lock); + DBUG_RETURN(error); +} + + +/* + Check if condition stated in UNTIL clause of START SLAVE is reached. + SYNOPSYS + st_relay_log_info::is_until_satisfied() + DESCRIPTION + Checks if UNTIL condition is reached. Uses caching result of last + comparison of current log file name and target log file name. So cached + value should be invalidated if current log file name changes + (see st_relay_log_info::notify_... functions). + + This caching is needed to avoid of expensive string comparisons and + strtol() conversions needed for log names comparison. We don't need to + compare them each time this function is called, we only need to do this + when current log name changes. If we have UNTIL_MASTER_POS condition we + need to do this only after Rotate_log_event::exec_event() (which is + rare, so caching gives real benifit), and if we have UNTIL_RELAY_POS + condition then we should invalidate cached comarison value after + inc_group_relay_log_pos() which called for each group of events (so we + have some benefit if we have something like queries that use + autoincrement or if we have transactions). + + Should be called ONLY if until_condition != UNTIL_NONE ! + RETURN VALUE + true - condition met or error happened (condition seems to have + bad log file name) + false - condition not met +*/ + +bool st_relay_log_info::is_until_satisfied() +{ + const char *log_name; + ulonglong log_pos; + DBUG_ENTER("st_relay_log_info::is_until_satisfied"); + + DBUG_ASSERT(until_condition != UNTIL_NONE); + + if (until_condition == UNTIL_MASTER_POS) + { + log_name= group_master_log_name; + log_pos= group_master_log_pos; + } + else + { /* until_condition == UNTIL_RELAY_POS */ + log_name= group_relay_log_name; + log_pos= group_relay_log_pos; + } + + if (until_log_names_cmp_result == UNTIL_LOG_NAMES_CMP_UNKNOWN) + { + /* + We have no cached comparison results so we should compare log names + and cache result. + If we are after RESET SLAVE, and the SQL slave thread has not processed + any event yet, it could be that group_master_log_name is "". In that case, + just wait for more events (as there is no sensible comparison to do). + */ + + if (*log_name) + { + const char *basename= log_name + dirname_length(log_name); + + const char *q= (const char*)(fn_ext(basename)+1); + if (strncmp(basename, until_log_name, (int)(q-basename)) == 0) + { + /* Now compare extensions. */ + char *q_end; + ulong log_name_extension= strtoul(q, &q_end, 10); + if (log_name_extension < until_log_name_extension) + until_log_names_cmp_result= UNTIL_LOG_NAMES_CMP_LESS; + else + until_log_names_cmp_result= + (log_name_extension > until_log_name_extension) ? + UNTIL_LOG_NAMES_CMP_GREATER : UNTIL_LOG_NAMES_CMP_EQUAL ; + } + else + { + /* Probably error so we aborting */ + sql_print_error("Slave SQL thread is stopped because UNTIL " + "condition is bad."); + DBUG_RETURN(TRUE); + } + } + else + DBUG_RETURN(until_log_pos == 0); + } + + DBUG_RETURN(((until_log_names_cmp_result == UNTIL_LOG_NAMES_CMP_EQUAL && + log_pos >= until_log_pos) || + until_log_names_cmp_result == UNTIL_LOG_NAMES_CMP_GREATER)); +} + + +void st_relay_log_info::cached_charset_invalidate() +{ + DBUG_ENTER("st_relay_log_info::cached_charset_invalidate"); + + /* Full of zeroes means uninitialized. */ + bzero(cached_charset, sizeof(cached_charset)); + DBUG_VOID_RETURN; +} + + +bool st_relay_log_info::cached_charset_compare(char *charset) +{ + DBUG_ENTER("st_relay_log_info::cached_charset_compare"); + + if (bcmp(cached_charset, charset, sizeof(cached_charset))) + { + memcpy(cached_charset, charset, sizeof(cached_charset)); + DBUG_RETURN(1); + } + DBUG_RETURN(0); +} + + +void st_relay_log_info::transaction_end(THD* thd) +{ + DBUG_ENTER("st_relay_log_info::transaction_end"); + + /* + Nothing to do here right now. + */ + + DBUG_VOID_RETURN; +} + +#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) +void st_relay_log_info::cleanup_context(THD *thd, bool error) +{ + DBUG_ENTER("st_relay_log_info::cleanup_context"); + + DBUG_ASSERT(sql_thd == thd); + /* + 1) Instances of Table_map_log_event, if ::exec_event() was called on them, + may have opened tables, which we cannot be sure have been closed (because + maybe the Rows_log_event have not been found or will not be, because slave + SQL thread is stopping, or relay log has a missing tail etc). So we close + all thread's tables. And so the table mappings have to be cancelled. + 2) Rows_log_event::exec_event() may even have started statements or + transactions on them, which we need to rollback in case of error. + 3) If finding a Format_description_log_event after a BEGIN, we also need + to rollback before continuing with the next events. + 4) so we need this "context cleanup" function. + */ + if (error) + { + ha_autocommit_or_rollback(thd, 1); // if a "statement transaction" + end_trans(thd, ROLLBACK); // if a "real transaction" + } + m_table_map.clear_tables(); + close_thread_tables(thd); + clear_tables_to_lock(); + unsafe_to_stop_at= 0; + DBUG_VOID_RETURN; +} +#endif diff --git a/sql/rpl_rli.h b/sql/rpl_rli.h index 392f12c2a71..d737055baf2 100644 --- a/sql/rpl_rli.h +++ b/sql/rpl_rli.h @@ -21,6 +21,7 @@ #include "rpl_tblmap.h" + /**************************************************************************** Replication SQL Thread @@ -98,8 +99,8 @@ typedef struct st_relay_log_info */ pthread_cond_t start_cond, stop_cond, data_cond; - /* parent master info structure */ - struct st_master_info *mi; + /* parent MASTER_INFO structure */ + class MASTER_INFO *mi; /* Needed to deal properly with cur_log getting closed and re-opened with @@ -164,6 +165,9 @@ typedef struct st_relay_log_info time_t last_master_timestamp; + void clear_slave_error(); + void clear_until_condition(); + /* Needed for problems when slave stops and we want to restart it skipping one or more events in the master log that have caused @@ -289,22 +293,6 @@ typedef struct st_relay_log_info void cached_charset_invalidate(); bool cached_charset_compare(char *charset); - /* - To reload special tables when they are changes, we introduce a set - of functions that will mark whenever special functions need to be - called after modifying tables. Right now, the tables are either - ACL tables or grants tables. - */ - enum enum_reload_flag - { - RELOAD_NONE_F = 0UL, - RELOAD_GRANT_F = (1UL << 0), - RELOAD_ACCESS_F = (1UL << 1) - }; - - ulong m_reload_flags; - - void touching_table(char const* db, char const* table, ulong table_id); void transaction_end(THD*); void cleanup_context(THD *, bool); @@ -322,4 +310,9 @@ typedef struct st_relay_log_info time_t unsafe_to_stop_at; } RELAY_LOG_INFO; + +// Defined in rpl_rli.cc +int init_relay_log_info(RELAY_LOG_INFO* rli, const char* info_fname); + + #endif /* RPL_RLI_H */ diff --git a/sql/rpl_tblmap.cc b/sql/rpl_tblmap.cc index a0272b23ee8..97f0066233c 100644 --- a/sql/rpl_tblmap.cc +++ b/sql/rpl_tblmap.cc @@ -50,17 +50,17 @@ table_mapping::~table_mapping() st_table* table_mapping::get_table(ulong table_id) { DBUG_ENTER("table_mapping::get_table(ulong)"); - DBUG_PRINT("enter", ("table_id=%d", table_id)); + DBUG_PRINT("enter", ("table_id: %lu", table_id)); entry *e= find_entry(table_id); if (e) { - DBUG_PRINT("info", ("tid %d -> table %p (%s)", - table_id, e->table, + DBUG_PRINT("info", ("tid %lu -> table 0x%lx (%s)", + table_id, (long) e->table, MAYBE_TABLE_NAME(e->table))); DBUG_RETURN(e->table); } - DBUG_PRINT("info", ("tid %d is not mapped!", table_id)); + DBUG_PRINT("info", ("tid %lu is not mapped!", table_id)); DBUG_RETURN(NULL); } @@ -93,9 +93,9 @@ int table_mapping::expand() int table_mapping::set_table(ulong table_id, TABLE* table) { DBUG_ENTER("table_mapping::set_table(ulong,TABLE*)"); - DBUG_PRINT("enter", ("table_id=%d, table=%p (%s)", + DBUG_PRINT("enter", ("table_id: %lu table: 0x%lx (%s)", table_id, - table, MAYBE_TABLE_NAME(table))); + (long) table, MAYBE_TABLE_NAME(table))); entry *e= find_entry(table_id); if (e == 0) { @@ -111,8 +111,8 @@ int table_mapping::set_table(ulong table_id, TABLE* table) e->table= table; my_hash_insert(&m_table_ids,(byte *)e); - DBUG_PRINT("info", ("tid %d -> table %p (%s)", - table_id, e->table, + DBUG_PRINT("info", ("tid %lu -> table 0x%lx (%s)", + table_id, (long) e->table, MAYBE_TABLE_NAME(e->table))); DBUG_RETURN(0); // All OK } diff --git a/sql/rpl_utility.cc b/sql/rpl_utility.cc index c80b6dc3f69..4bed1343e55 100644 --- a/sql/rpl_utility.cc +++ b/sql/rpl_utility.cc @@ -25,7 +25,7 @@ field_length_from_packed(enum_field_types const field_type, switch (field_type) { case MYSQL_TYPE_DECIMAL: case MYSQL_TYPE_NEWDECIMAL: - length= ~0UL; + length= ~(uint32) 0; break; case MYSQL_TYPE_YEAR: case MYSQL_TYPE_TINY: @@ -71,7 +71,7 @@ field_length_from_packed(enum_field_types const field_type, break; break; case MYSQL_TYPE_BIT: - length= ~0UL; + length= ~(uint32) 0; break; default: /* This case should never be chosen */ @@ -85,7 +85,7 @@ field_length_from_packed(enum_field_types const field_type, case MYSQL_TYPE_SET: case MYSQL_TYPE_VAR_STRING: case MYSQL_TYPE_VARCHAR: - length= ~0UL; // NYI + length= ~(uint32) 0; // NYI break; case MYSQL_TYPE_TINY_BLOB: @@ -93,7 +93,7 @@ field_length_from_packed(enum_field_types const field_type, case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_BLOB: case MYSQL_TYPE_GEOMETRY: - length= ~0UL; // NYI + length= ~(uint32) 0; // NYI break; } @@ -131,7 +131,8 @@ table_def::compatible_with(RELAY_LOG_INFO *rli, TABLE *table) slave_print_msg(ERROR_LEVEL, rli, ER_BINLOG_ROW_WRONG_TABLE_DEF, "Table width mismatch - " "received %u columns, %s.%s has %u columns", - size(), tsh->db.str, tsh->table_name.str, tsh->fields); + (uint) size(), tsh->db.str, tsh->table_name.str, + tsh->fields); } for (uint col= 0 ; col < cols_to_check ; ++col) diff --git a/sql/set_var.cc b/sql/set_var.cc index 5590e71c810..daca62400e2 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -155,7 +155,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_tmpdir(THD *thd); static int sys_check_log_path(THD *thd, set_var *var); static bool sys_update_general_log_path(THD *thd, set_var * var); @@ -639,9 +638,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 @@ -660,20 +656,12 @@ sys_var_thd_time_zone sys_time_zone("time_zone"); /* Read only variables */ -sys_var_have_variable sys_have_archive_db("have_archive", &have_archive_db); -sys_var_have_variable sys_have_blackhole_db("have_blackhole_engine", - &have_blackhole_db); sys_var_have_variable sys_have_compress("have_compress", &have_compress); sys_var_have_variable sys_have_crypt("have_crypt", &have_crypt); sys_var_have_variable sys_have_csv_db("have_csv", &have_csv_db); sys_var_have_variable sys_have_dlopen("have_dynamic_loading", &have_dlopen); -sys_var_have_variable sys_have_example_db("have_example_engine", - &have_example_db); -sys_var_have_variable sys_have_federated_db("have_federated_engine", - &have_federated_db); sys_var_have_variable sys_have_geometry("have_geometry", &have_geometry); sys_var_have_variable sys_have_innodb("have_innodb", &have_innodb); -sys_var_have_variable sys_have_merge_db("have_merge", &have_merge_db); sys_var_have_variable sys_have_ndbcluster("have_ndbcluster", &have_ndbcluster); sys_var_have_variable sys_have_openssl("have_openssl", &have_openssl); sys_var_have_variable sys_have_partition_db("have_partitioning", @@ -794,17 +782,12 @@ SHOW_VAR init_vars[]= { {sys_var_general_log.name, (char*) &opt_log, SHOW_MY_BOOL}, {sys_var_general_log_path.name, (char*) &sys_var_general_log_path, SHOW_SYS}, {sys_group_concat_max_len.name, (char*) &sys_group_concat_max_len, SHOW_SYS}, - {sys_have_archive_db.name, (char*) &have_archive_db, SHOW_HAVE}, - {sys_have_blackhole_db.name,(char*) &have_blackhole_db, SHOW_HAVE}, {sys_have_compress.name, (char*) &have_compress, SHOW_HAVE}, {sys_have_crypt.name, (char*) &have_crypt, SHOW_HAVE}, {sys_have_csv_db.name, (char*) &have_csv_db, SHOW_HAVE}, {sys_have_dlopen.name, (char*) &have_dlopen, SHOW_HAVE}, - {sys_have_example_db.name, (char*) &have_example_db, SHOW_HAVE}, - {sys_have_federated_db.name,(char*) &have_federated_db, SHOW_HAVE}, {sys_have_geometry.name, (char*) &have_geometry, SHOW_HAVE}, {sys_have_innodb.name, (char*) &have_innodb, SHOW_HAVE}, - {sys_have_merge_db.name, (char*) &have_merge_db, SHOW_HAVE}, {sys_have_ndbcluster.name, (char*) &have_ndbcluster, SHOW_HAVE}, {sys_have_openssl.name, (char*) &have_openssl, SHOW_HAVE}, {sys_have_partition_db.name,(char*) &have_partition_db, SHOW_HAVE}, @@ -956,7 +939,6 @@ SHOW_VAR init_vars[]= { {"plugin_dir", (char*) opt_plugin_dir, 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}, @@ -3151,14 +3133,6 @@ static byte *get_error_count(THD *thd) return (byte*) &thd->sys_var_tmp.long_value; } -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 @@ -3943,7 +3917,7 @@ sys_var_event_scheduler::update(THD *thd, set_var *var) DBUG_RETURN(TRUE); } - DBUG_PRINT("new_value", ("%lu", (bool)var->save_result.ulong_value)); + DBUG_PRINT("info", ("new_value: %d", (int) var->save_result.ulong_value)); Item_result var_type= var->value->result_type(); diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 3022967eeeb..5f9b9e6d563 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -6010,4 +6010,6 @@ ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT 42000 eng "Incorrect parameter count in the call to native function '%-.64s'" ER_WRONG_PARAMETERS_TO_NATIVE_FCT 42000 eng "Incorrect parameters in the call to native function '%-.64s'" +ER_NATIVE_FCT_NAME_COLLISION + eng "This function '%-.64s' has the same name as a native function." diff --git a/sql/slave.cc b/sql/slave.cc index 00d6d168fb8..4c5f0fc4764 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -31,13 +31,15 @@ #include "rpl_tblmap.h" +int queue_event(MASTER_INFO* mi,const char* buf,ulong event_len); + + #define MAX_SLAVE_RETRY_PAUSE 5 bool use_slave_mask = 0; MY_BITMAP slave_error_mask; typedef bool (*CHECK_KILLED_FUNC)(THD*,void*); -volatile bool slave_sql_running = 0, slave_io_running = 0; char* slave_load_tmpdir = 0; MASTER_INFO *active_mi= 0; my_bool replicate_same_server_id; @@ -59,7 +61,6 @@ static int process_io_create_file(MASTER_INFO* mi, Create_file_log_event* cev); static bool wait_for_relay_log_space(RELAY_LOG_INFO* rli); static inline bool io_slave_killed(THD* thd,MASTER_INFO* mi); static inline bool sql_slave_killed(THD* thd,RELAY_LOG_INFO* rli); -static int count_relay_log_space(RELAY_LOG_INFO* rli); static int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type); static int safe_connect(THD* thd, MYSQL* mysql, MASTER_INFO* mi); static int safe_reconnect(THD* thd, MYSQL* mysql, MASTER_INFO* mi, @@ -202,223 +203,6 @@ err: /* - Open the given relay log - - SYNOPSIS - init_relay_log_pos() - rli Relay information (will be initialized) - log Name of relay log file to read from. NULL = First log - pos Position in relay log file - need_data_lock Set to 1 if this functions should do mutex locks - errmsg Store pointer to error message here - look_for_description_event - 1 if we should look for such an event. We only need - this when the SQL thread starts and opens an existing - relay log and has to execute it (possibly from an - offset >4); then we need to read the first event of - the relay log to be able to parse the events we have - to execute. - - DESCRIPTION - - Close old open relay log files. - - If we are using the same relay log as the running IO-thread, then set - rli->cur_log to point to the same IO_CACHE entry. - - If not, open the 'log' binary file. - - TODO - - check proper initialization of group_master_log_name/group_master_log_pos - - RETURN VALUES - 0 ok - 1 error. errmsg is set to point to the error message -*/ - -int init_relay_log_pos(RELAY_LOG_INFO* rli,const char* log, - ulonglong pos, bool need_data_lock, - const char** errmsg, - bool look_for_description_event) -{ - DBUG_ENTER("init_relay_log_pos"); - DBUG_PRINT("info", ("pos=%lu", pos)); - - *errmsg=0; - pthread_mutex_t *log_lock=rli->relay_log.get_log_lock(); - - if (need_data_lock) - pthread_mutex_lock(&rli->data_lock); - - /* - Slave threads are not the only users of init_relay_log_pos(). CHANGE MASTER - is, too, and init_slave() too; these 2 functions allocate a description - event in init_relay_log_pos, which is not freed by the terminating SQL slave - thread as that thread is not started by these functions. So we have to free - the description_event here, in case, so that there is no memory leak in - running, say, CHANGE MASTER. - */ - delete rli->relay_log.description_event_for_exec; - /* - By default the relay log is in binlog format 3 (4.0). - Even if format is 4, this will work enough to read the first event - (Format_desc) (remember that format 4 is just lenghtened compared to format - 3; format 3 is a prefix of format 4). - */ - rli->relay_log.description_event_for_exec= new - Format_description_log_event(3); - - pthread_mutex_lock(log_lock); - - /* Close log file and free buffers if it's already open */ - if (rli->cur_log_fd >= 0) - { - end_io_cache(&rli->cache_buf); - my_close(rli->cur_log_fd, MYF(MY_WME)); - rli->cur_log_fd = -1; - } - - rli->group_relay_log_pos = rli->event_relay_log_pos = pos; - - /* - Test to see if the previous run was with the skip of purging - If yes, we do not purge when we restart - */ - if (rli->relay_log.find_log_pos(&rli->linfo, NullS, 1)) - { - *errmsg="Could not find first log during relay log initialization"; - goto err; - } - - if (log && rli->relay_log.find_log_pos(&rli->linfo, log, 1)) - { - *errmsg="Could not find target log during relay log initialization"; - goto err; - } - strmake(rli->group_relay_log_name,rli->linfo.log_file_name, - sizeof(rli->group_relay_log_name)-1); - strmake(rli->event_relay_log_name,rli->linfo.log_file_name, - sizeof(rli->event_relay_log_name)-1); - if (rli->relay_log.is_active(rli->linfo.log_file_name)) - { - /* - The IO thread is using this log file. - In this case, we will use the same IO_CACHE pointer to - read data as the IO thread is using to write data. - */ - my_b_seek((rli->cur_log=rli->relay_log.get_log_file()), (off_t)0); - if (check_binlog_magic(rli->cur_log,errmsg)) - goto err; - rli->cur_log_old_open_count=rli->relay_log.get_open_count(); - } - else - { - /* - Open the relay log and set rli->cur_log to point at this one - */ - if ((rli->cur_log_fd=open_binlog(&rli->cache_buf, - rli->linfo.log_file_name,errmsg)) < 0) - goto err; - rli->cur_log = &rli->cache_buf; - } - /* - In all cases, check_binlog_magic() has been called so we're at offset 4 for - sure. - */ - if (pos > BIN_LOG_HEADER_SIZE) /* If pos<=4, we stay at 4 */ - { - Log_event* ev; - while (look_for_description_event) - { - /* - Read the possible Format_description_log_event; if position - was 4, no need, it will be read naturally. - */ - DBUG_PRINT("info",("looking for a Format_description_log_event")); - - if (my_b_tell(rli->cur_log) >= pos) - break; - - /* - Because of we have rli->data_lock and log_lock, we can safely read an - event - */ - if (!(ev=Log_event::read_log_event(rli->cur_log,0, - rli->relay_log.description_event_for_exec))) - { - DBUG_PRINT("info",("could not read event, rli->cur_log->error=%d", - rli->cur_log->error)); - if (rli->cur_log->error) /* not EOF */ - { - *errmsg= "I/O error reading event at position 4"; - goto err; - } - break; - } - else if (ev->get_type_code() == FORMAT_DESCRIPTION_EVENT) - { - DBUG_PRINT("info",("found Format_description_log_event")); - delete rli->relay_log.description_event_for_exec; - rli->relay_log.description_event_for_exec= (Format_description_log_event*) ev; - /* - As ev was returned by read_log_event, it has passed is_valid(), so - my_malloc() in ctor worked, no need to check again. - */ - /* - Ok, we found a Format_description event. But it is not sure that this - describes the whole relay log; indeed, one can have this sequence - (starting from position 4): - Format_desc (of slave) - Rotate (of master) - Format_desc (of master) - So the Format_desc which really describes the rest of the relay log - is the 3rd event (it can't be further than that, because we rotate - the relay log when we queue a Rotate event from the master). - But what describes the Rotate is the first Format_desc. - So what we do is: - go on searching for Format_description events, until you exceed the - position (argument 'pos') or until you find another event than Rotate - or Format_desc. - */ - } - else - { - DBUG_PRINT("info",("found event of another type=%d", - ev->get_type_code())); - look_for_description_event= (ev->get_type_code() == ROTATE_EVENT); - delete ev; - } - } - my_b_seek(rli->cur_log,(off_t)pos); -#ifndef DBUG_OFF - { - char llbuf1[22], llbuf2[22]; - DBUG_PRINT("info", ("my_b_tell(rli->cur_log)=%s rli->event_relay_log_pos=%s", - llstr(my_b_tell(rli->cur_log),llbuf1), - llstr(rli->event_relay_log_pos,llbuf2))); - } -#endif - - } - -err: - /* - If we don't purge, we can't honour relay_log_space_limit ; - silently discard it - */ - if (!relay_log_purge) - rli->log_space_limit= 0; - pthread_cond_broadcast(&rli->data_cond); - - pthread_mutex_unlock(log_lock); - - if (need_data_lock) - pthread_mutex_unlock(&rli->data_lock); - if (!rli->relay_log.description_event_for_exec->is_valid() && !*errmsg) - *errmsg= "Invalid Format_description log event; could be out of memory"; - - DBUG_RETURN ((*errmsg) ? 1 : 0); -} - - -/* Init function to set up array for errors that should be skipped for slave SYNOPSIS @@ -461,174 +245,6 @@ void init_slave_skip_errors(const char* arg) } -void st_relay_log_info::inc_group_relay_log_pos(ulonglong log_pos, - bool skip_lock) -{ - DBUG_ENTER("st_relay_log_info::inc_group_relay_log_pos"); - - if (!skip_lock) - pthread_mutex_lock(&data_lock); - inc_event_relay_log_pos(); - group_relay_log_pos= event_relay_log_pos; - strmake(group_relay_log_name,event_relay_log_name, - sizeof(group_relay_log_name)-1); - - notify_group_relay_log_name_update(); - - /* - If the slave does not support transactions and replicates a transaction, - users should not trust group_master_log_pos (which they can display with - SHOW SLAVE STATUS or read from relay-log.info), because to compute - group_master_log_pos the slave relies on log_pos stored in the master's - binlog, but if we are in a master's transaction these positions are always - the BEGIN's one (excepted for the COMMIT), so group_master_log_pos does - not advance as it should on the non-transactional slave (it advances by - big leaps, whereas it should advance by small leaps). - */ - /* - In 4.x we used the event's len to compute the positions here. This is - wrong if the event was 3.23/4.0 and has been converted to 5.0, because - then the event's len is not what is was in the master's binlog, so this - will make a wrong group_master_log_pos (yes it's a bug in 3.23->4.0 - replication: Exec_master_log_pos is wrong). Only way to solve this is to - have the original offset of the end of the event the relay log. This is - what we do in 5.0: log_pos has become "end_log_pos" (because the real use - of log_pos in 4.0 was to compute the end_log_pos; so better to store - end_log_pos instead of begin_log_pos. - If we had not done this fix here, the problem would also have appeared - when the slave and master are 5.0 but with different event length (for - example the slave is more recent than the master and features the event - UID). It would give false MASTER_POS_WAIT, false Exec_master_log_pos in - SHOW SLAVE STATUS, and so the user would do some CHANGE MASTER using this - value which would lead to badly broken replication. - Even the relay_log_pos will be corrupted in this case, because the len is - the relay log is not "val". - With the end_log_pos solution, we avoid computations involving lengthes. - */ - DBUG_PRINT("info", ("log_pos: %lu group_master_log_pos: %lu", - (long) log_pos, (long) group_master_log_pos)); - if (log_pos) // 3.23 binlogs don't have log_posx - { - group_master_log_pos= log_pos; - } - pthread_cond_broadcast(&data_cond); - if (!skip_lock) - pthread_mutex_unlock(&data_lock); - DBUG_VOID_RETURN; -} - - -void st_relay_log_info::close_temporary_tables() -{ - TABLE *table,*next; - DBUG_ENTER("st_relay_log_info::close_temporary_tables"); - - for (table=save_temporary_tables ; table ; table=next) - { - next=table->next; - /* - Don't ask for disk deletion. For now, anyway they will be deleted when - slave restarts, but it is a better intention to not delete them. - */ - DBUG_PRINT("info", ("table: %p", table)); - close_temporary(table, 1, 0); - } - save_temporary_tables= 0; - slave_open_temp_tables= 0; - DBUG_VOID_RETURN; -} - -/* - purge_relay_logs() - - NOTES - Assumes to have a run lock on rli and that no slave thread are running. -*/ - -int purge_relay_logs(RELAY_LOG_INFO* rli, THD *thd, bool just_reset, - const char** errmsg) -{ - int error=0; - DBUG_ENTER("purge_relay_logs"); - - /* - Even if rli->inited==0, we still try to empty rli->master_log_* variables. - Indeed, rli->inited==0 does not imply that they already are empty. - It could be that slave's info initialization partly succeeded : - for example if relay-log.info existed but *relay-bin*.* - have been manually removed, init_relay_log_info reads the old - relay-log.info and fills rli->master_log_*, then init_relay_log_info - checks for the existence of the relay log, this fails and - init_relay_log_info leaves rli->inited to 0. - In that pathological case, rli->master_log_pos* will be properly reinited - at the next START SLAVE (as RESET SLAVE or CHANGE - MASTER, the callers of purge_relay_logs, will delete bogus *.info files - or replace them with correct files), however if the user does SHOW SLAVE - STATUS before START SLAVE, he will see old, confusing rli->master_log_*. - In other words, we reinit rli->master_log_* for SHOW SLAVE STATUS - to display fine in any case. - */ - - rli->group_master_log_name[0]= 0; - rli->group_master_log_pos= 0; - - if (!rli->inited) - { - DBUG_PRINT("info", ("rli->inited == 0")); - DBUG_RETURN(0); - } - - DBUG_ASSERT(rli->slave_running == 0); - DBUG_ASSERT(rli->mi->slave_running == 0); - - rli->slave_skip_counter=0; - pthread_mutex_lock(&rli->data_lock); - - /* - we close the relay log fd possibly left open by the slave SQL thread, - to be able to delete it; the relay log fd possibly left open by the slave - I/O thread will be closed naturally in reset_logs() by the - close(LOG_CLOSE_TO_BE_OPENED) call - */ - if (rli->cur_log_fd >= 0) - { - end_io_cache(&rli->cache_buf); - my_close(rli->cur_log_fd, MYF(MY_WME)); - rli->cur_log_fd= -1; - } - - if (rli->relay_log.reset_logs(thd)) - { - *errmsg = "Failed during log reset"; - error=1; - goto err; - } - /* Save name of used relay log file */ - strmake(rli->group_relay_log_name, rli->relay_log.get_log_fname(), - sizeof(rli->group_relay_log_name)-1); - strmake(rli->event_relay_log_name, rli->relay_log.get_log_fname(), - sizeof(rli->event_relay_log_name)-1); - rli->group_relay_log_pos= rli->event_relay_log_pos= BIN_LOG_HEADER_SIZE; - if (count_relay_log_space(rli)) - { - *errmsg= "Error counting relay log space"; - goto err; - } - if (!just_reset) - error= init_relay_log_pos(rli, rli->group_relay_log_name, - rli->group_relay_log_pos, - 0 /* do not need data lock */, errmsg, 0); - -err: -#ifndef DBUG_OFF - char buf[22]; -#endif - DBUG_PRINT("info",("log_space_total: %s",llstr(rli->log_space_total,buf))); - pthread_mutex_unlock(&rli->data_lock); - DBUG_RETURN(error); -} - - int terminate_slave_threads(MASTER_INFO* mi,int thread_mask,bool skip_lock) { DBUG_ENTER("terminate_slave_threads"); @@ -1023,7 +639,7 @@ const char *print_slave_db_safe(const char* db) DBUG_RETURN((db ? db : "")); } -static int init_strvar_from_file(char *var, int max_size, IO_CACHE *f, +int init_strvar_from_file(char *var, int max_size, IO_CACHE *f, const char *default_val) { uint length; @@ -1054,7 +670,7 @@ static int init_strvar_from_file(char *var, int max_size, IO_CACHE *f, } -static int init_intvar_from_file(int* var, IO_CACHE* f, int default_val) +int init_intvar_from_file(int* var, IO_CACHE* f, int default_val) { char buf[32]; DBUG_ENTER("init_intvar_from_file"); @@ -1456,261 +1072,6 @@ int fetch_master_table(THD *thd, const char *db_name, const char *table_name, } -void end_master_info(MASTER_INFO* mi) -{ - DBUG_ENTER("end_master_info"); - - if (!mi->inited) - DBUG_VOID_RETURN; - end_relay_log_info(&mi->rli); - if (mi->fd >= 0) - { - end_io_cache(&mi->file); - (void)my_close(mi->fd, MYF(MY_WME)); - mi->fd = -1; - } - mi->inited = 0; - - DBUG_VOID_RETURN; -} - - -static int init_relay_log_info(RELAY_LOG_INFO* rli, - const char* info_fname) -{ - char fname[FN_REFLEN+128]; - int info_fd; - const char* msg = 0; - int error = 0; - DBUG_ENTER("init_relay_log_info"); - DBUG_ASSERT(!rli->no_storage); // Don't init if there is no storage - - if (rli->inited) // Set if this function called - DBUG_RETURN(0); - fn_format(fname, info_fname, mysql_data_home, "", 4+32); - pthread_mutex_lock(&rli->data_lock); - info_fd = rli->info_fd; - rli->cur_log_fd = -1; - rli->slave_skip_counter=0; - rli->abort_pos_wait=0; - rli->log_space_limit= relay_log_space_limit; - rli->log_space_total= 0; - rli->tables_to_lock= 0; - rli->tables_to_lock_count= 0; - - /* - The relay log will now be opened, as a SEQ_READ_APPEND IO_CACHE. - Note that the I/O thread flushes it to disk after writing every - event, in flush_master_info(mi, 1). - */ - - /* - For the maximum log size, we choose max_relay_log_size if it is - non-zero, max_binlog_size otherwise. If later the user does SET - GLOBAL on one of these variables, fix_max_binlog_size and - fix_max_relay_log_size will reconsider the choice (for example - if the user changes max_relay_log_size to zero, we have to - switch to using max_binlog_size for the relay log) and update - rli->relay_log.max_size (and mysql_bin_log.max_size). - */ - { - char buf[FN_REFLEN]; - const char *ln; - static bool name_warning_sent= 0; - ln= rli->relay_log.generate_name(opt_relay_logname, "-relay-bin", - 1, buf); - /* We send the warning only at startup, not after every RESET SLAVE */ - if (!opt_relay_logname && !opt_relaylog_index_name && !name_warning_sent) - { - /* - User didn't give us info to name the relay log index file. - Picking `hostname`-relay-bin.index like we do, causes replication to - fail if this slave's hostname is changed later. So, we would like to - instead require a name. But as we don't want to break many existing - setups, we only give warning, not error. - */ - sql_print_warning("Neither --relay-log nor --relay-log-index were used;" - " so replication " - "may break when this MySQL server acts as a " - "slave and has his hostname changed!! Please " - "use '--relay-log=%s' to avoid this problem.", ln); - name_warning_sent= 1; - } - /* - note, that if open() fails, we'll still have index file open - but a destructor will take care of that - */ - if (rli->relay_log.open_index_file(opt_relaylog_index_name, ln) || - rli->relay_log.open(ln, LOG_BIN, 0, SEQ_READ_APPEND, 0, - (max_relay_log_size ? max_relay_log_size : - max_binlog_size), 1)) - { - pthread_mutex_unlock(&rli->data_lock); - sql_print_error("Failed in open_log() called from init_relay_log_info()"); - DBUG_RETURN(1); - } - } - - /* if file does not exist */ - if (access(fname,F_OK)) - { - /* - If someone removed the file from underneath our feet, just close - the old descriptor and re-create the old file - */ - if (info_fd >= 0) - my_close(info_fd, MYF(MY_WME)); - if ((info_fd = my_open(fname, O_CREAT|O_RDWR|O_BINARY, MYF(MY_WME))) < 0) - { - sql_print_error("Failed to create a new relay log info file (\ -file '%s', errno %d)", fname, my_errno); - msg= current_thd->net.last_error; - goto err; - } - if (init_io_cache(&rli->info_file, info_fd, IO_SIZE*2, READ_CACHE, 0L,0, - MYF(MY_WME))) - { - sql_print_error("Failed to create a cache on relay log info file '%s'", - fname); - msg= current_thd->net.last_error; - goto err; - } - - /* Init relay log with first entry in the relay index file */ - if (init_relay_log_pos(rli,NullS,BIN_LOG_HEADER_SIZE,0 /* no data lock */, - &msg, 0)) - { - sql_print_error("Failed to open the relay log 'FIRST' (relay_log_pos 4)"); - goto err; - } - rli->group_master_log_name[0]= 0; - rli->group_master_log_pos= 0; - rli->info_fd= info_fd; - } - else // file exists - { - if (info_fd >= 0) - reinit_io_cache(&rli->info_file, READ_CACHE, 0L,0,0); - else - { - int error=0; - if ((info_fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0) - { - sql_print_error("\ -Failed to open the existing relay log info file '%s' (errno %d)", - fname, my_errno); - error= 1; - } - else if (init_io_cache(&rli->info_file, info_fd, - IO_SIZE*2, READ_CACHE, 0L, 0, MYF(MY_WME))) - { - sql_print_error("Failed to create a cache on relay log info file '%s'", - fname); - error= 1; - } - if (error) - { - if (info_fd >= 0) - my_close(info_fd, MYF(0)); - rli->info_fd= -1; - rli->relay_log.close(LOG_CLOSE_INDEX | LOG_CLOSE_STOP_EVENT); - pthread_mutex_unlock(&rli->data_lock); - DBUG_RETURN(1); - } - } - - rli->info_fd = info_fd; - int relay_log_pos, master_log_pos; - if (init_strvar_from_file(rli->group_relay_log_name, - sizeof(rli->group_relay_log_name), - &rli->info_file, "") || - init_intvar_from_file(&relay_log_pos, - &rli->info_file, BIN_LOG_HEADER_SIZE) || - init_strvar_from_file(rli->group_master_log_name, - sizeof(rli->group_master_log_name), - &rli->info_file, "") || - init_intvar_from_file(&master_log_pos, &rli->info_file, 0)) - { - msg="Error reading slave log configuration"; - goto err; - } - strmake(rli->event_relay_log_name,rli->group_relay_log_name, - sizeof(rli->event_relay_log_name)-1); - rli->group_relay_log_pos= rli->event_relay_log_pos= relay_log_pos; - rli->group_master_log_pos= master_log_pos; - - if (init_relay_log_pos(rli, - rli->group_relay_log_name, - rli->group_relay_log_pos, - 0 /* no data lock*/, - &msg, 0)) - { - char llbuf[22]; - sql_print_error("Failed to open the relay log '%s' (relay_log_pos %s)", - rli->group_relay_log_name, - llstr(rli->group_relay_log_pos, llbuf)); - goto err; - } - } - -#ifndef DBUG_OFF - { - char llbuf1[22], llbuf2[22]; - DBUG_PRINT("info", ("my_b_tell(rli->cur_log)=%s rli->event_relay_log_pos=%s", - llstr(my_b_tell(rli->cur_log),llbuf1), - llstr(rli->event_relay_log_pos,llbuf2))); - DBUG_ASSERT(rli->event_relay_log_pos >= BIN_LOG_HEADER_SIZE); - DBUG_ASSERT(my_b_tell(rli->cur_log) == rli->event_relay_log_pos); - } -#endif - - /* - Now change the cache from READ to WRITE - must do this - before flush_relay_log_info - */ - reinit_io_cache(&rli->info_file, WRITE_CACHE,0L,0,1); - if ((error= flush_relay_log_info(rli))) - sql_print_error("Failed to flush relay log info file"); - if (count_relay_log_space(rli)) - { - msg="Error counting relay log space"; - goto err; - } - rli->inited= 1; - pthread_mutex_unlock(&rli->data_lock); - DBUG_RETURN(error); - -err: - sql_print_error(msg); - end_io_cache(&rli->info_file); - if (info_fd >= 0) - my_close(info_fd, MYF(0)); - rli->info_fd= -1; - rli->relay_log.close(LOG_CLOSE_INDEX | LOG_CLOSE_STOP_EVENT); - pthread_mutex_unlock(&rli->data_lock); - DBUG_RETURN(1); -} - - -static inline int add_relay_log(RELAY_LOG_INFO* rli,LOG_INFO* linfo) -{ - MY_STAT s; - DBUG_ENTER("add_relay_log"); - if (!my_stat(linfo->log_file_name,&s,MYF(0))) - { - sql_print_error("log %s listed in the index, but failed to stat", - linfo->log_file_name); - DBUG_RETURN(1); - } - rli->log_space_total += s.st_size; -#ifndef DBUG_OFF - char buf[22]; - DBUG_PRINT("info",("log_space_total: %s", llstr(rli->log_space_total,buf))); -#endif - DBUG_RETURN(0); -} - - static bool wait_for_relay_log_space(RELAY_LOG_INFO* rli) { bool slave_killed=0; @@ -1733,31 +1094,6 @@ Waiting for the slave SQL thread to free enough relay log space"); } -static int count_relay_log_space(RELAY_LOG_INFO* rli) -{ - LOG_INFO linfo; - DBUG_ENTER("count_relay_log_space"); - rli->log_space_total= 0; - if (rli->relay_log.find_log_pos(&linfo, NullS, 1)) - { - sql_print_error("Could not find first log while counting relay log space"); - DBUG_RETURN(1); - } - do - { - if (add_relay_log(rli,&linfo)) - DBUG_RETURN(1); - } while (!rli->relay_log.find_next_log(&linfo, 1)); - /* - As we have counted everything, including what may have written in a - preceding write, we must reset bytes_written, or we may count some space - twice. - */ - rli->relay_log.reset_bytes_written(); - DBUG_RETURN(0); -} - - /* Builds a Rotate from the ignored events' info and writes it to relay log. @@ -1811,284 +1147,6 @@ static void write_ignored_events_info_to_relay_log(THD *thd, MASTER_INFO *mi) } -void init_master_info_with_options(MASTER_INFO* mi) -{ - DBUG_ENTER("init_master_info_with_options"); - - mi->master_log_name[0] = 0; - mi->master_log_pos = BIN_LOG_HEADER_SIZE; // skip magic number - - if (master_host) - strmake(mi->host, master_host, sizeof(mi->host) - 1); - if (master_user) - strmake(mi->user, master_user, sizeof(mi->user) - 1); - if (master_password) - strmake(mi->password, master_password, MAX_PASSWORD_LENGTH); - mi->port = master_port; - mi->connect_retry = master_connect_retry; - - mi->ssl= master_ssl; - if (master_ssl_ca) - strmake(mi->ssl_ca, master_ssl_ca, sizeof(mi->ssl_ca)-1); - if (master_ssl_capath) - strmake(mi->ssl_capath, master_ssl_capath, sizeof(mi->ssl_capath)-1); - if (master_ssl_cert) - strmake(mi->ssl_cert, master_ssl_cert, sizeof(mi->ssl_cert)-1); - if (master_ssl_cipher) - strmake(mi->ssl_cipher, master_ssl_cipher, sizeof(mi->ssl_cipher)-1); - if (master_ssl_key) - strmake(mi->ssl_key, master_ssl_key, sizeof(mi->ssl_key)-1); - DBUG_VOID_RETURN; -} - -void clear_slave_error(RELAY_LOG_INFO* rli) -{ - DBUG_ENTER("clear_slave_error"); - - /* Clear the errors displayed by SHOW SLAVE STATUS */ - rli->last_slave_error[0]= 0; - rli->last_slave_errno= 0; - DBUG_VOID_RETURN; -} - -/* - Reset UNTIL condition for RELAY_LOG_INFO - SYNOPSYS - clear_until_condition() - rli - RELAY_LOG_INFO structure where UNTIL condition should be reset - */ -void clear_until_condition(RELAY_LOG_INFO* rli) -{ - DBUG_ENTER("clear_until_condition"); - - rli->until_condition= RELAY_LOG_INFO::UNTIL_NONE; - rli->until_log_name[0]= 0; - rli->until_log_pos= 0; - DBUG_VOID_RETURN; -} - - -#define LINES_IN_MASTER_INFO_WITH_SSL 14 - - -int init_master_info(MASTER_INFO* mi, const char* master_info_fname, - const char* slave_info_fname, - bool abort_if_no_master_info_file, - int thread_mask) -{ - int fd,error; - char fname[FN_REFLEN+128]; - DBUG_ENTER("init_master_info"); - - if (mi->inited) - { - /* - We have to reset read position of relay-log-bin as we may have - already been reading from 'hotlog' when the slave was stopped - last time. If this case pos_in_file would be set and we would - get a crash when trying to read the signature for the binary - relay log. - - We only rewind the read position if we are starting the SQL - thread. The handle_slave_sql thread assumes that the read - position is at the beginning of the file, and will read the - "signature" and then fast-forward to the last position read. - */ - if (thread_mask & SLAVE_SQL) - { - my_b_seek(mi->rli.cur_log, (my_off_t) 0); - } - DBUG_RETURN(0); - } - - mi->mysql=0; - mi->file_id=1; - fn_format(fname, master_info_fname, mysql_data_home, "", 4+32); - - /* - We need a mutex while we are changing master info parameters to - keep other threads from reading bogus info - */ - - pthread_mutex_lock(&mi->data_lock); - fd = mi->fd; - - /* does master.info exist ? */ - - if (access(fname,F_OK)) - { - if (abort_if_no_master_info_file) - { - pthread_mutex_unlock(&mi->data_lock); - DBUG_RETURN(0); - } - /* - if someone removed the file from underneath our feet, just close - the old descriptor and re-create the old file - */ - if (fd >= 0) - my_close(fd, MYF(MY_WME)); - if ((fd = my_open(fname, O_CREAT|O_RDWR|O_BINARY, MYF(MY_WME))) < 0 ) - { - sql_print_error("Failed to create a new master info file (\ -file '%s', errno %d)", fname, my_errno); - goto err; - } - if (init_io_cache(&mi->file, fd, IO_SIZE*2, READ_CACHE, 0L,0, - MYF(MY_WME))) - { - sql_print_error("Failed to create a cache on master info file (\ -file '%s')", fname); - goto err; - } - - mi->fd = fd; - init_master_info_with_options(mi); - - } - else // file exists - { - if (fd >= 0) - reinit_io_cache(&mi->file, READ_CACHE, 0L,0,0); - else - { - if ((fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0 ) - { - sql_print_error("Failed to open the existing master info file (\ -file '%s', errno %d)", fname, my_errno); - goto err; - } - if (init_io_cache(&mi->file, fd, IO_SIZE*2, READ_CACHE, 0L, - 0, MYF(MY_WME))) - { - sql_print_error("Failed to create a cache on master info file (\ -file '%s')", fname); - goto err; - } - } - - mi->fd = fd; - int port, connect_retry, master_log_pos, ssl= 0, lines; - char *first_non_digit; - - /* - Starting from 4.1.x master.info has new format. Now its - first line contains number of lines in file. By reading this - number we will be always distinguish to which version our - master.info corresponds to. We can't simply count lines in - file since versions before 4.1.x could generate files with more - lines than needed. - If first line doesn't contain a number or contain number less than - 14 then such file is treated like file from pre 4.1.1 version. - There is no ambiguity when reading an old master.info, as before - 4.1.1, the first line contained the binlog's name, which is either - empty or has an extension (contains a '.'), so can't be confused - with an integer. - - So we're just reading first line and trying to figure which version - is this. - */ - - /* - The first row is temporarily stored in mi->master_log_name, - if it is line count and not binlog name (new format) it will be - overwritten by the second row later. - */ - if (init_strvar_from_file(mi->master_log_name, - sizeof(mi->master_log_name), &mi->file, - "")) - goto errwithmsg; - - lines= strtoul(mi->master_log_name, &first_non_digit, 10); - - if (mi->master_log_name[0]!='\0' && - *first_non_digit=='\0' && lines >= LINES_IN_MASTER_INFO_WITH_SSL) - { // Seems to be new format - if (init_strvar_from_file(mi->master_log_name, - sizeof(mi->master_log_name), &mi->file, "")) - goto errwithmsg; - } - else - lines= 7; - - if (init_intvar_from_file(&master_log_pos, &mi->file, 4) || - init_strvar_from_file(mi->host, sizeof(mi->host), &mi->file, - master_host) || - init_strvar_from_file(mi->user, sizeof(mi->user), &mi->file, - master_user) || - init_strvar_from_file(mi->password, SCRAMBLED_PASSWORD_CHAR_LENGTH+1, - &mi->file, master_password) || - init_intvar_from_file(&port, &mi->file, master_port) || - init_intvar_from_file(&connect_retry, &mi->file, - master_connect_retry)) - goto errwithmsg; - - /* - If file has ssl part use it even if we have server without - SSL support. But these option will be ignored later when - slave will try connect to master, so in this case warning - is printed. - */ - if (lines >= LINES_IN_MASTER_INFO_WITH_SSL && - (init_intvar_from_file(&ssl, &mi->file, master_ssl) || - init_strvar_from_file(mi->ssl_ca, sizeof(mi->ssl_ca), - &mi->file, master_ssl_ca) || - init_strvar_from_file(mi->ssl_capath, sizeof(mi->ssl_capath), - &mi->file, master_ssl_capath) || - init_strvar_from_file(mi->ssl_cert, sizeof(mi->ssl_cert), - &mi->file, master_ssl_cert) || - init_strvar_from_file(mi->ssl_cipher, sizeof(mi->ssl_cipher), - &mi->file, master_ssl_cipher) || - init_strvar_from_file(mi->ssl_key, sizeof(mi->ssl_key), - &mi->file, master_ssl_key))) - goto errwithmsg; -#ifndef HAVE_OPENSSL - if (ssl) - sql_print_warning("SSL information in the master info file " - "('%s') are ignored because this MySQL slave was compiled " - "without SSL support.", fname); -#endif /* HAVE_OPENSSL */ - - /* - This has to be handled here as init_intvar_from_file can't handle - my_off_t types - */ - mi->master_log_pos= (my_off_t) master_log_pos; - mi->port= (uint) port; - mi->connect_retry= (uint) connect_retry; - mi->ssl= (my_bool) ssl; - } - DBUG_PRINT("master_info",("log_file_name: %s position: %ld", - mi->master_log_name, - (ulong) mi->master_log_pos)); - - mi->rli.mi = mi; - if (init_relay_log_info(&mi->rli, slave_info_fname)) - goto err; - - mi->inited = 1; - // now change cache READ -> WRITE - must do this before flush_master_info - reinit_io_cache(&mi->file, WRITE_CACHE, 0L, 0, 1); - if ((error=test(flush_master_info(mi, 1)))) - sql_print_error("Failed to flush master info file"); - pthread_mutex_unlock(&mi->data_lock); - DBUG_RETURN(error); - -errwithmsg: - sql_print_error("Error reading master configuration"); - -err: - if (fd >= 0) - { - my_close(fd, MYF(0)); - end_io_cache(&mi->file); - } - mi->fd= -1; - pthread_mutex_unlock(&mi->data_lock); - DBUG_RETURN(1); -} - - int register_slave_on_master(MYSQL* mysql) { char buf[1024], *pos= buf; @@ -2307,313 +1365,6 @@ bool show_master_info(THD* thd, MASTER_INFO* mi) DBUG_RETURN(FALSE); } -/* - RETURN - 2 - flush relay log failed - 1 - flush master info failed - 0 - all ok -*/ -int flush_master_info(MASTER_INFO* mi, bool flush_relay_log_cache) -{ - IO_CACHE* file = &mi->file; - char lbuf[22]; - DBUG_ENTER("flush_master_info"); - DBUG_PRINT("enter",("master_pos: %ld", (long) mi->master_log_pos)); - - /* - Flush the relay log to disk. If we don't do it, then the relay log while - have some part (its last kilobytes) in memory only, so if the slave server - dies now, with, say, from master's position 100 to 150 in memory only (not - on disk), and with position 150 in master.info, then when the slave - restarts, the I/O thread will fetch binlogs from 150, so in the relay log - we will have "[0, 100] U [150, infinity[" and nobody will notice it, so the - SQL thread will jump from 100 to 150, and replication will silently break. - - When we come to this place in code, relay log may or not be initialized; - the caller is responsible for setting 'flush_relay_log_cache' accordingly. - */ - if (flush_relay_log_cache && - flush_io_cache(mi->rli.relay_log.get_log_file())) - DBUG_RETURN(2); - - /* - We flushed the relay log BEFORE the master.info file, because if we crash - now, we will get a duplicate event in the relay log at restart. If we - flushed in the other order, we would get a hole in the relay log. - And duplicate is better than hole (with a duplicate, in later versions we - can add detection and scrap one event; with a hole there's nothing we can - do). - */ - - /* - In certain cases this code may create master.info files that seems - corrupted, because of extra lines filled with garbage in the end - file (this happens if new contents take less space than previous - contents of file). But because of number of lines in the first line - of file we don't care about this garbage. - */ - - my_b_seek(file, 0L); - my_b_printf(file, "%u\n%s\n%s\n%s\n%s\n%s\n%d\n%d\n%d\n%s\n%s\n%s\n%s\n%s\n", - LINES_IN_MASTER_INFO_WITH_SSL, - mi->master_log_name, llstr(mi->master_log_pos, lbuf), - mi->host, mi->user, - mi->password, mi->port, mi->connect_retry, - (int)(mi->ssl), mi->ssl_ca, mi->ssl_capath, mi->ssl_cert, - mi->ssl_cipher, mi->ssl_key); - DBUG_RETURN(-flush_io_cache(file)); -} - - -st_relay_log_info::st_relay_log_info() - :no_storage(FALSE), info_fd(-1), cur_log_fd(-1), save_temporary_tables(0), - cur_log_old_open_count(0), group_master_log_pos(0), log_space_total(0), - ignore_log_space_limit(0), last_master_timestamp(0), slave_skip_counter(0), - abort_pos_wait(0), slave_run_id(0), sql_thd(0), last_slave_errno(0), - inited(0), abort_slave(0), slave_running(0), until_condition(UNTIL_NONE), - until_log_pos(0), retried_trans(0), - tables_to_lock(0), tables_to_lock_count(0), - m_reload_flags(RELOAD_NONE_F), - unsafe_to_stop_at(0) -{ - DBUG_ENTER("st_relay_log_info::st_relay_log_info"); - - group_relay_log_name[0]= event_relay_log_name[0]= - group_master_log_name[0]= 0; - last_slave_error[0]= until_log_name[0]= ign_master_log_name_end[0]= 0; - bzero((char*) &info_file, sizeof(info_file)); - bzero((char*) &cache_buf, sizeof(cache_buf)); - cached_charset_invalidate(); - pthread_mutex_init(&run_lock, MY_MUTEX_INIT_FAST); - pthread_mutex_init(&data_lock, MY_MUTEX_INIT_FAST); - pthread_mutex_init(&log_space_lock, MY_MUTEX_INIT_FAST); - pthread_cond_init(&data_cond, NULL); - pthread_cond_init(&start_cond, NULL); - pthread_cond_init(&stop_cond, NULL); - pthread_cond_init(&log_space_cond, NULL); - relay_log.init_pthread_objects(); - DBUG_VOID_RETURN; -} - - -st_relay_log_info::~st_relay_log_info() -{ - DBUG_ENTER("st_relay_log_info::~st_relay_log_info"); - - pthread_mutex_destroy(&run_lock); - pthread_mutex_destroy(&data_lock); - pthread_mutex_destroy(&log_space_lock); - pthread_cond_destroy(&data_cond); - pthread_cond_destroy(&start_cond); - pthread_cond_destroy(&stop_cond); - pthread_cond_destroy(&log_space_cond); - relay_log.cleanup(); - DBUG_VOID_RETURN; -} - -/* - Waits until the SQL thread reaches (has executed up to) the - log/position or timed out. - - SYNOPSIS - wait_for_pos() - thd client thread that sent SELECT MASTER_POS_WAIT - log_name log name to wait for - log_pos position to wait for - timeout timeout in seconds before giving up waiting - - NOTES - timeout is longlong whereas it should be ulong ; but this is - to catch if the user submitted a negative timeout. - - RETURN VALUES - -2 improper arguments (log_pos<0) - or slave not running, or master info changed - during the function's execution, - or client thread killed. -2 is translated to NULL by caller - -1 timed out - >=0 number of log events the function had to wait - before reaching the desired log/position - */ - -int st_relay_log_info::wait_for_pos(THD* thd, String* log_name, - longlong log_pos, - longlong timeout) -{ - int event_count = 0; - ulong init_abort_pos_wait; - int error=0; - struct timespec abstime; // for timeout checking - const char *msg; - DBUG_ENTER("st_relay_log_info::wait_for_pos"); - - if (!inited) - DBUG_RETURN(-1); - - DBUG_PRINT("enter",("log_name: '%s' log_pos: %lu timeout: %lu", - log_name->c_ptr(), (ulong) log_pos, (ulong) timeout)); - - set_timespec(abstime,timeout); - pthread_mutex_lock(&data_lock); - msg= thd->enter_cond(&data_cond, &data_lock, - "Waiting for the slave SQL thread to " - "advance position"); - /* - This function will abort when it notices that some CHANGE MASTER or - RESET MASTER has changed the master info. - To catch this, these commands modify abort_pos_wait ; We just monitor - abort_pos_wait and see if it has changed. - Why do we have this mechanism instead of simply monitoring slave_running - in the loop (we do this too), as CHANGE MASTER/RESET SLAVE require that - the SQL thread be stopped? - This is becasue if someones does: - STOP SLAVE;CHANGE MASTER/RESET SLAVE; START SLAVE; - the change may happen very quickly and we may not notice that - slave_running briefly switches between 1/0/1. - */ - init_abort_pos_wait= abort_pos_wait; - - /* - We'll need to - handle all possible log names comparisons (e.g. 999 vs 1000). - We use ulong for string->number conversion ; this is no - stronger limitation than in find_uniq_filename in sql/log.cc - */ - ulong log_name_extension; - char log_name_tmp[FN_REFLEN]; //make a char[] from String - - strmake(log_name_tmp, log_name->ptr(), min(log_name->length(), FN_REFLEN-1)); - - char *p= fn_ext(log_name_tmp); - char *p_end; - if (!*p || log_pos<0) - { - error= -2; //means improper arguments - goto err; - } - // Convert 0-3 to 4 - log_pos= max(log_pos, BIN_LOG_HEADER_SIZE); - /* p points to '.' */ - log_name_extension= strtoul(++p, &p_end, 10); - /* - p_end points to the first invalid character. - If it equals to p, no digits were found, error. - If it contains '\0' it means conversion went ok. - */ - if (p_end==p || *p_end) - { - error= -2; - goto err; - } - - /* The "compare and wait" main loop */ - while (!thd->killed && - init_abort_pos_wait == abort_pos_wait && - slave_running) - { - bool pos_reached; - int cmp_result= 0; - - DBUG_PRINT("info", - ("init_abort_pos_wait: %ld abort_pos_wait: %ld", - init_abort_pos_wait, abort_pos_wait)); - DBUG_PRINT("info",("group_master_log_name: '%s' pos: %lu", - group_master_log_name, (ulong) group_master_log_pos)); - - /* - group_master_log_name can be "", if we are just after a fresh - replication start or after a CHANGE MASTER TO MASTER_HOST/PORT - (before we have executed one Rotate event from the master) or - (rare) if the user is doing a weird slave setup (see next - paragraph). If group_master_log_name is "", we assume we don't - have enough info to do the comparison yet, so we just wait until - more data. In this case master_log_pos is always 0 except if - somebody (wrongly) sets this slave to be a slave of itself - without using --replicate-same-server-id (an unsupported - configuration which does nothing), then group_master_log_pos - will grow and group_master_log_name will stay "". - */ - if (*group_master_log_name) - { - char *basename= (group_master_log_name + - dirname_length(group_master_log_name)); - /* - First compare the parts before the extension. - Find the dot in the master's log basename, - and protect against user's input error : - if the names do not match up to '.' included, return error - */ - char *q= (char*)(fn_ext(basename)+1); - if (strncmp(basename, log_name_tmp, (int)(q-basename))) - { - error= -2; - break; - } - // Now compare extensions. - char *q_end; - ulong group_master_log_name_extension= strtoul(q, &q_end, 10); - if (group_master_log_name_extension < log_name_extension) - cmp_result= -1 ; - else - cmp_result= (group_master_log_name_extension > log_name_extension) ? 1 : 0 ; - - pos_reached= ((!cmp_result && group_master_log_pos >= (ulonglong)log_pos) || - cmp_result > 0); - if (pos_reached || thd->killed) - break; - } - - //wait for master update, with optional timeout. - - DBUG_PRINT("info",("Waiting for master update")); - /* - We are going to pthread_cond_(timed)wait(); if the SQL thread stops it - will wake us up. - */ - if (timeout > 0) - { - /* - Note that pthread_cond_timedwait checks for the timeout - before for the condition ; i.e. it returns ETIMEDOUT - if the system time equals or exceeds the time specified by abstime - before the condition variable is signaled or broadcast, _or_ if - the absolute time specified by abstime has already passed at the time - of the call. - For that reason, pthread_cond_timedwait will do the "timeoutting" job - even if its condition is always immediately signaled (case of a loaded - master). - */ - error=pthread_cond_timedwait(&data_cond, &data_lock, &abstime); - } - else - pthread_cond_wait(&data_cond, &data_lock); - DBUG_PRINT("info",("Got signal of master update or timed out")); - if (error == ETIMEDOUT || error == ETIME) - { - error= -1; - break; - } - error=0; - event_count++; - DBUG_PRINT("info",("Testing if killed or SQL thread not running")); - } - -err: - thd->exit_cond(msg); - DBUG_PRINT("exit",("killed: %d abort: %d slave_running: %d \ -improper_arguments: %d timed_out: %d", - thd->killed_errno(), - (int) (init_abort_pos_wait != abort_pos_wait), - (int) slave_running, - (int) (error == -2), - (int) (error == -1))); - if (thd->killed || init_abort_pos_wait != abort_pos_wait || - !slave_running) - { - error= -2; - } - DBUG_RETURN( error ? error : event_count ); -} void set_slave_thread_options(THD* thd) { @@ -2663,6 +1414,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); @@ -2851,7 +1609,7 @@ static ulong read_event(MYSQL* mysql, MASTER_INFO *mi, bool* suppress_warnings) DBUG_RETURN(packet_error); } - DBUG_PRINT("info",( "len=%u, net->read_pos[4] = %d\n", + DBUG_PRINT("exit", ("len: %lu net->read_pos[4]: %d", len, mysql->net.read_pos[4])); DBUG_RETURN(len - 1); } @@ -2872,119 +1630,6 @@ int check_expected_error(THD* thd, RELAY_LOG_INFO* rli, int expected_error) } } -/* - Check if condition stated in UNTIL clause of START SLAVE is reached. - SYNOPSYS - st_relay_log_info::is_until_satisfied() - DESCRIPTION - Checks if UNTIL condition is reached. Uses caching result of last - comparison of current log file name and target log file name. So cached - value should be invalidated if current log file name changes - (see st_relay_log_info::notify_... functions). - - This caching is needed to avoid of expensive string comparisons and - strtol() conversions needed for log names comparison. We don't need to - compare them each time this function is called, we only need to do this - when current log name changes. If we have UNTIL_MASTER_POS condition we - need to do this only after Rotate_log_event::exec_event() (which is - rare, so caching gives real benifit), and if we have UNTIL_RELAY_POS - condition then we should invalidate cached comarison value after - inc_group_relay_log_pos() which called for each group of events (so we - have some benefit if we have something like queries that use - autoincrement or if we have transactions). - - Should be called ONLY if until_condition != UNTIL_NONE ! - RETURN VALUE - true - condition met or error happened (condition seems to have - bad log file name) - false - condition not met -*/ - -bool st_relay_log_info::is_until_satisfied() -{ - const char *log_name; - ulonglong log_pos; - DBUG_ENTER("st_relay_log_info::is_until_satisfied"); - - DBUG_ASSERT(until_condition != UNTIL_NONE); - - if (until_condition == UNTIL_MASTER_POS) - { - log_name= group_master_log_name; - log_pos= group_master_log_pos; - } - else - { /* until_condition == UNTIL_RELAY_POS */ - log_name= group_relay_log_name; - log_pos= group_relay_log_pos; - } - - if (until_log_names_cmp_result == UNTIL_LOG_NAMES_CMP_UNKNOWN) - { - /* - We have no cached comparison results so we should compare log names - and cache result. - If we are after RESET SLAVE, and the SQL slave thread has not processed - any event yet, it could be that group_master_log_name is "". In that case, - just wait for more events (as there is no sensible comparison to do). - */ - - if (*log_name) - { - const char *basename= log_name + dirname_length(log_name); - - const char *q= (const char*)(fn_ext(basename)+1); - if (strncmp(basename, until_log_name, (int)(q-basename)) == 0) - { - /* Now compare extensions. */ - char *q_end; - ulong log_name_extension= strtoul(q, &q_end, 10); - if (log_name_extension < until_log_name_extension) - until_log_names_cmp_result= UNTIL_LOG_NAMES_CMP_LESS; - else - until_log_names_cmp_result= - (log_name_extension > until_log_name_extension) ? - UNTIL_LOG_NAMES_CMP_GREATER : UNTIL_LOG_NAMES_CMP_EQUAL ; - } - else - { - /* Probably error so we aborting */ - sql_print_error("Slave SQL thread is stopped because UNTIL " - "condition is bad."); - DBUG_RETURN(TRUE); - } - } - else - DBUG_RETURN(until_log_pos == 0); - } - - DBUG_RETURN(((until_log_names_cmp_result == UNTIL_LOG_NAMES_CMP_EQUAL && - log_pos >= until_log_pos) || - until_log_names_cmp_result == UNTIL_LOG_NAMES_CMP_GREATER)); -} - - -void st_relay_log_info::cached_charset_invalidate() -{ - DBUG_ENTER("st_relay_log_info::cached_charset_invalidate"); - - /* Full of zeroes means uninitialized. */ - bzero(cached_charset, sizeof(cached_charset)); - DBUG_VOID_RETURN; -} - - -bool st_relay_log_info::cached_charset_compare(char *charset) -{ - DBUG_ENTER("st_relay_log_info::cached_charset_compare"); - - if (bcmp(cached_charset, charset, sizeof(cached_charset))) - { - memcpy(cached_charset, charset, sizeof(cached_charset)); - DBUG_RETURN(1); - } - DBUG_RETURN(0); -} /* Check if the current error is of temporary nature of not. @@ -3155,7 +1800,7 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli) ev->when = time(NULL); ev->thd = thd; // because up to this point, ev->thd == 0 exec_res = ev->exec_event(rli); - DBUG_PRINT("info", ("exec_event result = %d", exec_res)); + DBUG_PRINT("info", ("exec_event result: %d", exec_res)); DBUG_ASSERT(rli->sql_thd==thd); /* Format_description_log_event should not be deleted because it will be @@ -3176,6 +1821,8 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli) We were in a transaction which has been rolled back because of a temporary error; let's seek back to BEGIN log event and retry it all again. + Note, if lock wait timeout (innodb_lock_wait_timeout exceeded) + there is no rollback since 5.0.13 (ref: manual). 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 @@ -3303,11 +1950,19 @@ pthread_handler_t handle_slave_io(void *arg) 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)); + { + 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)); + /* + 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"); @@ -3632,7 +2287,7 @@ pthread_handler_t handle_slave_sql(void *arg) now. But the master timestamp is reset by RESET SLAVE & CHANGE MASTER. */ - clear_slave_error(rli); + rli->clear_slave_error(); //tell the I/O thread to take relay_log_space_limit into account from now on pthread_mutex_lock(&rli->log_space_lock); @@ -3949,7 +2604,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 /* @@ -4066,7 +2721,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); @@ -4093,7 +2748,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); } @@ -4149,7 +2804,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); } @@ -4322,7 +2977,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 { @@ -4330,7 +2986,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 @@ -4451,11 +3107,11 @@ static int connect_to_master(THD* thd, MYSQL* mysql, MASTER_INFO* mi, { last_errno=mysql_errno(mysql); suppress_warnings= 0; - sql_print_error("Slave I/O thread: error %s to master \ -'%s@%s:%d': \ + sql_print_error("Slave I/O thread: error %s to master " + "'%s@%s:%d': \ Error: '%s' errno: %d retry-time: %d retries: %lu", (reconnect ? "reconnecting" : "connecting"), - mi->user,mi->host,mi->port, + mi->user, mi->host, mi->port, mysql_error(mysql), last_errno, mi->connect_retry, master_retry_count); @@ -4990,121 +3646,6 @@ end: DBUG_VOID_RETURN; } -/* - Some system tables needed to be re-read by the MySQL server after it has - updated them; in statement-based replication, the GRANT and other commands - are sent verbatim to the slave which then reloads; in row-based replication, - changes to these tables are done through ordinary Rows binlog events, so - master must add some flag for the slave to know it has to reload the tables. -*/ -struct st_reload_entry -{ - char const *table; - st_relay_log_info::enum_reload_flag flag; -}; - -/* - Sorted array of table names, please keep it sorted since we are - using bsearch() on it below. - */ -static st_reload_entry s_mysql_tables[] = -{ - { "columns_priv", st_relay_log_info::RELOAD_GRANT_F }, - { "db", st_relay_log_info::RELOAD_ACCESS_F }, - { "host", st_relay_log_info::RELOAD_ACCESS_F }, - { "procs_priv", st_relay_log_info::RELOAD_GRANT_F }, - { "tables_priv", st_relay_log_info::RELOAD_GRANT_F }, - { "user", st_relay_log_info::RELOAD_ACCESS_F } -}; - -static const my_size_t s_mysql_tables_size = - sizeof(s_mysql_tables)/sizeof(*s_mysql_tables); - -static int reload_entry_compare(const void *lhs, const void *rhs) -{ - const char *lstr = static_cast<const char *>(lhs); - const char *rstr = static_cast<const st_reload_entry*>(rhs)->table; - DBUG_ENTER("reload_entry_compare"); - - DBUG_RETURN(strcmp(lstr, rstr)); -} - -void st_relay_log_info::touching_table(char const* db, char const* table, - ulong table_id) -{ - DBUG_ENTER("st_relay_log_info::touching_table"); - - if (strcmp(db,"mysql") == 0) - { -#if defined(HAVE_BSEARCH) && defined(HAVE_SIZE_T) - void *const ptr= bsearch(table, s_mysql_tables, - s_mysql_tables_size, - sizeof(*s_mysql_tables), reload_entry_compare); - st_reload_entry const *const entry= static_cast<st_reload_entry*>(ptr); -#else - /* - Fall back to full scan, there are few rows anyway and updating the - "mysql" database is rare. - */ - st_reload_entry const *entry= s_mysql_tables; - for ( ; entry < s_mysql_tables + s_mysql_tables_size ; entry++) - if (reload_entry_compare(table, entry) == 0) - break; -#endif - if (entry) - m_reload_flags|= entry->flag; - } - DBUG_VOID_RETURN; -} - -void st_relay_log_info::transaction_end(THD* thd) -{ - DBUG_ENTER("st_relay_log_info::transaction_end"); - - if (m_reload_flags != RELOAD_NONE_F) - { - if (m_reload_flags & RELOAD_ACCESS_F) - acl_reload(thd); - - if (m_reload_flags & RELOAD_GRANT_F) - grant_reload(thd); - - m_reload_flags= RELOAD_NONE_F; - } - DBUG_VOID_RETURN; -} - -#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) -void st_relay_log_info::cleanup_context(THD *thd, bool error) -{ - DBUG_ENTER("st_relay_log_info::cleanup_context"); - - DBUG_ASSERT(sql_thd == thd); - /* - 1) Instances of Table_map_log_event, if ::exec_event() was called on them, - may have opened tables, which we cannot be sure have been closed (because - maybe the Rows_log_event have not been found or will not be, because slave - SQL thread is stopping, or relay log has a missing tail etc). So we close - all thread's tables. And so the table mappings have to be cancelled. - 2) Rows_log_event::exec_event() may even have started statements or - transactions on them, which we need to rollback in case of error. - 3) If finding a Format_description_log_event after a BEGIN, we also need - to rollback before continuing with the next events. - 4) so we need this "context cleanup" function. - */ - if (error) - { - ha_autocommit_or_rollback(thd, 1); // if a "statement transaction" - end_trans(thd, ROLLBACK); // if a "real transaction" - } - m_table_map.clear_tables(); - close_thread_tables(thd); - clear_tables_to_lock(); - unsafe_to_stop_at= 0; - DBUG_VOID_RETURN; -} -#endif - #ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION template class I_List_iterator<i_string>; diff --git a/sql/slave.h b/sql/slave.h index e70b2e4b326..24ba09d78d3 100644 --- a/sql/slave.h +++ b/sql/slave.h @@ -24,6 +24,7 @@ #include "rpl_filter.h" #include "rpl_tblmap.h" #include "rpl_rli.h" +#include "rpl_mi.h" #define SLAVE_NET_TIMEOUT 3600 @@ -38,11 +39,11 @@ I/O Thread - One of these threads is started for each master server. They maintain a connection to their master server, read log events from the master as they arrive, and queues them into - a single, shared relay log file. A MASTER_INFO struct + a single, shared relay log file. A MASTER_INFO represents each of these threads. SQL Thread - One of these threads is started and reads from the relay log - file, executing each event. A RELAY_LOG_INFO struct + file, executing each event. A RELAY_LOG_INFO represents this thread. Buffering in the relay log file makes it unnecessary to reread events from @@ -95,7 +96,6 @@ extern my_string opt_relay_logname, opt_relaylog_index_name; extern my_bool opt_skip_slave_start, opt_reckless_slave; extern my_bool opt_log_slave_updates; extern ulonglong relay_log_space_limit; -struct st_master_info; /* 3 possible values for MASTER_INFO::slave_running and @@ -114,110 +114,6 @@ struct st_master_info; static Log_event* next_event(RELAY_LOG_INFO* rli); -/***************************************************************************** - - Replication IO Thread - - st_master_info contains: - - information about how to connect to a master - - current master log name - - current master log offset - - misc control variables - - st_master_info is initialized once from the master.info file if such - exists. Otherwise, data members corresponding to master.info fields - are initialized with defaults specified by master-* options. The - initialization is done through init_master_info() call. - - The format of master.info file: - - log_name - log_pos - master_host - master_user - master_pass - master_port - master_connect_retry - - To write out the contents of master.info file to disk ( needed every - time we read and queue data from the master ), a call to - flush_master_info() is required. - - To clean up, call end_master_info() - -*****************************************************************************/ - -typedef struct st_master_info -{ - /* the variables below are needed because we can change masters on the fly */ - char master_log_name[FN_REFLEN]; - char host[HOSTNAME_LENGTH+1]; - char user[USERNAME_LENGTH+1]; - char password[MAX_PASSWORD_LENGTH+1]; - my_bool ssl; // enables use of SSL connection if true - char ssl_ca[FN_REFLEN], ssl_capath[FN_REFLEN], ssl_cert[FN_REFLEN]; - char ssl_cipher[FN_REFLEN], ssl_key[FN_REFLEN]; - - my_off_t master_log_pos; - File fd; // we keep the file open, so we need to remember the file pointer - IO_CACHE file; - - pthread_mutex_t data_lock,run_lock; - pthread_cond_t data_cond,start_cond,stop_cond; - THD *io_thd; - MYSQL* mysql; - uint32 file_id; /* for 3.23 load data infile */ - RELAY_LOG_INFO rli; - uint port; - uint connect_retry; -#ifndef DBUG_OFF - int events_till_disconnect; -#endif - bool inited; - volatile bool abort_slave; - volatile uint slave_running; - volatile ulong slave_run_id; - /* - The difference in seconds between the clock of the master and the clock of - the slave (second - first). It must be signed as it may be <0 or >0. - clock_diff_with_master is computed when the I/O thread starts; for this the - I/O thread does a SELECT UNIX_TIMESTAMP() on the master. - "how late the slave is compared to the master" is computed like this: - clock_of_slave - last_timestamp_executed_by_SQL_thread - clock_diff_with_master - - */ - long clock_diff_with_master; - - st_master_info() - :ssl(0), fd(-1), io_thd(0), inited(0), - abort_slave(0),slave_running(0), slave_run_id(0) - { - host[0] = 0; user[0] = 0; password[0] = 0; - ssl_ca[0]= 0; ssl_capath[0]= 0; ssl_cert[0]= 0; - ssl_cipher[0]= 0; ssl_key[0]= 0; - - bzero((char*) &file, sizeof(file)); - pthread_mutex_init(&run_lock, MY_MUTEX_INIT_FAST); - pthread_mutex_init(&data_lock, MY_MUTEX_INIT_FAST); - pthread_cond_init(&data_cond, NULL); - pthread_cond_init(&start_cond, NULL); - pthread_cond_init(&stop_cond, NULL); - } - - ~st_master_info() - { - pthread_mutex_destroy(&run_lock); - pthread_mutex_destroy(&data_lock); - pthread_cond_destroy(&data_cond); - pthread_cond_destroy(&start_cond); - pthread_cond_destroy(&stop_cond); - } - -} MASTER_INFO; - - -int queue_event(MASTER_INFO* mi,const char* buf,ulong event_len); - #define RPL_LOG_NAME (rli->group_master_log_name[0] ? rli->group_master_log_name :\ "FIRST") #define IO_RPL_LOG_NAME (mi->master_log_name[0] ? mi->master_log_name :\ @@ -231,7 +127,6 @@ int queue_event(MASTER_INFO* mi,const char* buf,ulong event_len); int init_slave(); void init_slave_skip_errors(const char* arg); -int flush_master_info(MASTER_INFO* mi, bool flush_relay_log_cache); bool flush_relay_log_info(RELAY_LOG_INFO* rli); int register_slave_on_master(MYSQL* mysql); int terminate_slave_threads(MASTER_INFO* mi, int thread_mask, @@ -276,14 +171,8 @@ void slave_print_msg(enum loglevel level, RELAY_LOG_INFO* rli, ATTRIBUTE_FORMAT(printf, 4, 5); void end_slave(); /* clean up */ -void init_master_info_with_options(MASTER_INFO* mi); void clear_until_condition(RELAY_LOG_INFO* rli); void clear_slave_error(RELAY_LOG_INFO* rli); -int init_master_info(MASTER_INFO* mi, const char* master_info_fname, - const char* slave_info_fname, - bool abort_if_no_master_info_file, - int thread_mask); -void end_master_info(MASTER_INFO* mi); void end_relay_log_info(RELAY_LOG_INFO* rli); void lock_slave_threads(MASTER_INFO* mi); void unlock_slave_threads(MASTER_INFO* mi); diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 47a623ec749..622d9efdde0 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -899,7 +899,7 @@ subst_spvars(THD *thd, sp_instr *instr, LEX_STRING *query_str) break; val= (*splocal)->this_item(); - DBUG_PRINT("info", ("print %p", val)); + DBUG_PRINT("info", ("print 0x%lx", (long) val)); str_value= sp_get_item_value(val, &str_value_holder); if (str_value) res|= qbuf.append(*str_value); diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index aa13c2f08f4..721b6b5a003 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -3871,7 +3871,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 28bc1e9dcbf..75becc31bc1 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1087,7 +1087,7 @@ void close_thread_tables(THD *thd, bool lock_in_use, bool skip_derived) if (!lock_in_use) VOID(pthread_mutex_lock(&LOCK_open)); - DBUG_PRINT("info", ("thd->open_tables: %p", thd->open_tables)); + DBUG_PRINT("info", ("thd->open_tables: 0x%lx", (long) thd->open_tables)); found_old_table= 0; while (thd->open_tables) @@ -1177,6 +1177,16 @@ static inline uint tmpkeyval(THD *thd, TABLE *table) void close_temporary_tables(THD *thd) { TABLE *table; + TABLE *next; + /* + TODO: 5.1 maintains prev link in temporary_tables + double-linked list so we could fix it. But it is not necessary + at this time when the list is being destroyed + */ + TABLE *prev_table; + /* Assume thd->options has OPTION_QUOTE_SHOW_CREATE */ + bool was_quote_show= TRUE; + if (!thd->temporary_tables) return; @@ -1192,12 +1202,7 @@ void close_temporary_tables(THD *thd) return; } - TABLE *next, - *prev_table /* TODO: 5.1 maintaines prev link in temporary_tables - double-linked list so we could fix it. But it is not necessary - at this time when the list is being destroyed */; - bool was_quote_show= true; /* to assume thd->options has OPTION_QUOTE_SHOW_CREATE */ - // Better add "if exists", in case a RESET MASTER has been done + /* Better add "if exists", in case a RESET MASTER has been done */ const char stub[]= "DROP /*!40005 TEMPORARY */ TABLE IF EXISTS "; uint stub_len= sizeof(stub) - 1; char buf[256]; @@ -1303,7 +1308,7 @@ void close_temporary_tables(THD *thd) } } if (!was_quote_show) - thd->options &= ~OPTION_QUOTE_SHOW_CREATE; /* restore option */ + thd->options&= ~OPTION_QUOTE_SHOW_CREATE; /* restore option */ thd->temporary_tables=0; } @@ -2069,7 +2074,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, VOID(pthread_mutex_unlock(&LOCK_open)); DBUG_RETURN(0); // VIEW } - DBUG_PRINT("info", ("inserting table %p into the cache", table)); + DBUG_PRINT("info", ("inserting table 0x%lx into the cache", (long) table)); VOID(my_hash_insert(&open_cache,(byte*) table)); } @@ -2110,6 +2115,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 table->clear_column_bitmaps(); DBUG_ASSERT(table->key_read == 0); @@ -2399,7 +2405,7 @@ bool table_is_used(TABLE *table, bool wait_for_name_lock) { DBUG_PRINT("info", ("share: 0x%lx locked_by_logger: %d " "locked_by_flush: %d locked_by_name: %d " - "db_stat: %u version: %u", + "db_stat: %u version: %lu", (ulong) search->s, search->locked_by_logger, search->locked_by_flush, search->locked_by_name, search->db_stat, @@ -3553,6 +3559,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); } diff --git a/sql/sql_binlog.cc b/sql/sql_binlog.cc index 23ca5330053..37094b992e5 100644 --- a/sql/sql_binlog.cc +++ b/sql/sql_binlog.cc @@ -79,9 +79,16 @@ void mysql_client_binlog_statement(THD* thd) char const *endptr= 0; int bytes_decoded= base64_decode(strptr, coded_len, buf, &endptr); +#ifndef HAVE_purify + /* + This debug printout should not be used for valgrind builds + since it will read from unassigned memory. + */ DBUG_PRINT("info", - ("bytes_decoded=%d; strptr=0x%lu; endptr=0x%lu ('%c':%d)", - bytes_decoded, strptr, endptr, *endptr, *endptr)); + ("bytes_decoded: %d strptr: 0x%lx endptr: 0x%lx ('%c':%d)", + bytes_decoded, (long) strptr, (long) endptr, *endptr, + *endptr)); +#endif if (bytes_decoded < 0) { @@ -107,8 +114,8 @@ void mysql_client_binlog_statement(THD* thd) order to be able to read exactly what is necessary. */ - DBUG_PRINT("info",("binlog base64 decoded_len=%d, bytes_decoded=%d", - decoded_len, bytes_decoded)); + DBUG_PRINT("info",("binlog base64 decoded_len: %lu bytes_decoded: %d", + (ulong) decoded_len, bytes_decoded)); /* Now we start to read events of the buffer, until there are no @@ -145,14 +152,21 @@ void mysql_client_binlog_statement(THD* thd) bufptr += event_len; DBUG_PRINT("info",("ev->get_type_code()=%d", ev->get_type_code())); - DBUG_PRINT("info",("bufptr+EVENT_TYPE_OFFSET=0x%lx", - bufptr+EVENT_TYPE_OFFSET)); - DBUG_PRINT("info", ("bytes_decoded=%d; bufptr=0x%lx; buf[EVENT_LEN_OFFSET]=%u", - bytes_decoded, bufptr, uint4korr(bufptr+EVENT_LEN_OFFSET))); +#ifndef HAVE_purify + /* + This debug printout should not be used for valgrind builds + since it will read from unassigned memory. + */ + DBUG_PRINT("info",("bufptr+EVENT_TYPE_OFFSET: 0x%lx", + (long) (bufptr+EVENT_TYPE_OFFSET))); + DBUG_PRINT("info", ("bytes_decoded: %d bufptr: 0x%lx buf[EVENT_LEN_OFFSET]: %lu", + bytes_decoded, (long) bufptr, + (ulong) uint4korr(bufptr+EVENT_LEN_OFFSET))); +#endif ev->thd= thd; if (int err= ev->exec_event(thd->rli_fake)) { - DBUG_PRINT("info", ("exec_event() - error=%d", error)); + DBUG_PRINT("error", ("exec_event() returned: %d", err)); /* TODO: Maybe a better error message since the BINLOG statement now contains several events. diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index a9234307ae8..a6e15c55641 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -523,7 +523,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; } @@ -532,7 +533,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 @@ -698,6 +700,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. */ @@ -713,13 +716,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); @@ -738,26 +737,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); - } - 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; } @@ -874,8 +872,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)); @@ -1118,8 +1116,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)); @@ -1233,9 +1231,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 @@ -1256,10 +1254,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(), @@ -2033,7 +2031,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) { @@ -2475,11 +2473,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 @@ -2987,7 +2985,7 @@ static TABLE_COUNTER_TYPE process_and_count_tables(TABLE_LIST *tables_used, DBUG_PRINT("qcache", ("table: %s db: %s type: %u", tables_used->table->s->table_name.str, tables_used->table->s->db.str, - tables_used->table->s->db_type)); + tables_used->table->s->db_type->db_type)); if (tables_used->derived) { table_count--; @@ -3042,10 +3040,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); @@ -3061,10 +3059,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 +3527,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 +3539,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 +3664,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, @@ -3764,7 +3774,7 @@ my_bool Query_cache::check_integrity(bool locked) { DBUG_PRINT("error", ("block 0x%lx do not aligned by %d", (ulong) block, - ALIGN_SIZE(1))); + (int) ALIGN_SIZE(1))); result = 1; } // Check memory allocation @@ -3875,9 +3885,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 +3984,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 776ba4dabea..07510c1fbb0 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -551,7 +551,7 @@ void add_diff_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var, void THD::awake(THD::killed_state state_to_set) { DBUG_ENTER("THD::awake"); - DBUG_PRINT("enter", ("this=0x%lx", this)); + DBUG_PRINT("enter", ("this: 0x%lx", (long) this)); THD_CHECK_SENTRY(this); safe_mutex_assert_owner(&LOCK_delete); @@ -799,7 +799,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) @@ -809,7 +809,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; } @@ -821,7 +821,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; } @@ -2518,7 +2518,9 @@ my_size_t THD::max_row_length_blob(TABLE *table, const byte *data) const for (uint *ptr= beg ; ptr != end ; ++ptr) { Field_blob* const blob= (Field_blob*) table->field[*ptr]; - length+= blob->get_length((const char *) (data + blob->offset())) + 2; + length+= blob->get_length((const char*) (data + + blob->offset(table->record[0]))) + + HA_KEY_BLOB_LENGTH; } return length; @@ -2552,6 +2554,128 @@ my_size_t THD::pack_row(TABLE *table, MY_BITMAP const* cols, byte *row_data, } +namespace { + /** + Class to handle temporary allocation of memory for row data. + + The responsibilities of the class is to provide memory for + packing one or two rows of packed data (depending on what + constructor is called). + + In order to make the allocation more efficient for "simple" rows, + i.e., rows that do not contain any blobs, a pointer to the + allocated memory is of memory is stored in the table structure + for simple rows. If memory for a table containing a blob field + is requested, only memory for that is allocated, and subsequently + released when the object is destroyed. + + */ + class Row_data_memory { + public: + /** + Build an object to keep track of a block-local piece of memory + for storing a row of data. + + @param table + Table where the pre-allocated memory is stored. + + @param length + Length of data that is needed, if the record contain blobs. + */ + Row_data_memory(TABLE *table, my_size_t const len1) + : m_memory(0) + { +#ifndef DBUG_OFF + m_alloc_checked= false; +#endif + allocate_memory(table, len1); + m_ptr[0]= has_memory() ? m_memory : 0; + m_ptr[1]= 0; + } + + Row_data_memory(TABLE *table, my_size_t const len1, my_size_t const len2) + : m_memory(0) + { +#ifndef DBUG_OFF + m_alloc_checked= false; +#endif + allocate_memory(table, len1 + len2); + m_ptr[0]= has_memory() ? m_memory : 0; + m_ptr[1]= has_memory() ? m_memory + len1 : 0; + } + + ~Row_data_memory() + { + if (m_memory != 0 && m_release_memory_on_destruction) + my_free((gptr) m_memory, MYF(MY_WME)); + } + + /** + Is there memory allocated? + + @retval true There is memory allocated + @retval false Memory allocation failed + */ + bool has_memory() const { +#ifndef DBUG_OFF + m_alloc_checked= true; +#endif + return m_memory != 0; + } + + byte *slot(uint s) + { + DBUG_ASSERT(s < sizeof(m_ptr)/sizeof(*m_ptr)); + DBUG_ASSERT(m_ptr[s] != 0); + DBUG_ASSERT(m_alloc_checked == true); + return m_ptr[s]; + } + + private: + void allocate_memory(TABLE *const table, my_size_t const total_length) + { + if (table->s->blob_fields == 0) + { + /* + The maximum length of a packed record is less than this + length. We use this value instead of the supplied length + when allocating memory for records, since we don't know how + the memory will be used in future allocations. + + Since table->s->reclength is for unpacked records, we have + to add two bytes for each field, which can potentially be + added to hold the length of a packed field. + */ + my_size_t const maxlen= table->s->reclength + 2 * table->s->fields; + + /* + Allocate memory for two records if memory hasn't been + allocated. We allocate memory for two records so that it can + be used when processing update rows as well. + */ + if (table->write_row_record == 0) + table->write_row_record= + (byte *) alloc_root(&table->mem_root, 2 * maxlen); + m_memory= table->write_row_record; + m_release_memory_on_destruction= false; + } + else + { + m_memory= (byte *) my_malloc(total_length, MYF(MY_WME)); + m_release_memory_on_destruction= true; + } + } + +#ifndef DBUG_OFF + mutable bool m_alloc_checked; +#endif + bool m_release_memory_on_destruction; + byte *m_memory; + byte *m_ptr[2]; + }; +} + + int THD::binlog_write_row(TABLE* table, bool is_trans, MY_BITMAP const* cols, my_size_t colcnt, byte const *record) @@ -2562,40 +2686,25 @@ int THD::binlog_write_row(TABLE* table, bool is_trans, Pack records into format for transfer. We are allocating more memory than needed, but that doesn't matter. */ - bool error= 0; - byte *row_data= table->write_row_record; - my_size_t const max_len= max_row_length(table, record); - my_size_t len; - Rows_log_event *ev; - - /* Allocate room for a row (if needed) */ - if (!row_data) - { - if (!table->s->blob_fields) - { - /* multiply max_len by 2 so it can be used for update_row as well */ - table->write_row_record= (byte *) alloc_root(&table->mem_root, - 2*max_len); - if (!table->write_row_record) - return HA_ERR_OUT_OF_MEM; - row_data= table->write_row_record; - } - else if (unlikely(!(row_data= (byte *) my_malloc(max_len, MYF(MY_WME))))) - return HA_ERR_OUT_OF_MEM; - } - len= pack_row(table, cols, row_data, record); + int error= 0; - ev= binlog_prepare_pending_rows_event(table, server_id, cols, colcnt, - len, is_trans, - static_cast<Write_rows_log_event*>(0)); + Row_data_memory memory(table, max_row_length(table, record)); + if (!memory.has_memory()) + return HA_ERR_OUT_OF_MEM; - /* add_row_data copies row_data to internal buffer */ - error= likely(ev != 0) ? ev->add_row_data(row_data,len) : HA_ERR_OUT_OF_MEM ; + byte *row_data= memory.slot(0); - if (table->write_row_record == 0) - my_free((gptr) row_data, MYF(MY_WME)); + my_size_t const len= pack_row(table, cols, row_data, record); - return error; + Rows_log_event* const ev= + binlog_prepare_pending_rows_event(table, server_id, cols, colcnt, + len, is_trans, + static_cast<Write_rows_log_event*>(0)); + + if (unlikely(ev == 0)) + return HA_ERR_OUT_OF_MEM; + + return ev->add_row_data(row_data, len); } int THD::binlog_update_row(TABLE* table, bool is_trans, @@ -2605,53 +2714,44 @@ int THD::binlog_update_row(TABLE* table, bool is_trans, { DBUG_ASSERT(current_stmt_binlog_row_based && mysql_bin_log.is_open()); - bool error= 0; + int error= 0; my_size_t const before_maxlen = max_row_length(table, before_record); my_size_t const after_maxlen = max_row_length(table, after_record); - byte *row_data= table->write_row_record; - byte *before_row, *after_row; - if (row_data != 0) - { - before_row= row_data; - after_row= before_row + before_maxlen; - } - else - { - if (unlikely(!(row_data= (byte*)my_multi_malloc(MYF(MY_WME), - &before_row, before_maxlen, - &after_row, after_maxlen, - NULL)))) - return HA_ERR_OUT_OF_MEM; - } + Row_data_memory row_data(table, before_maxlen, after_maxlen); + if (!row_data.has_memory()) + return HA_ERR_OUT_OF_MEM; + + byte *before_row= row_data.slot(0); + byte *after_row= row_data.slot(1); my_size_t const before_size= pack_row(table, cols, before_row, before_record); my_size_t const after_size= pack_row(table, cols, after_row, after_record); - + + /* + Don't print debug messages when running valgrind since they can + trigger false warnings. + */ +#ifndef HAVE_purify DBUG_DUMP("before_record", (const char *)before_record, table->s->reclength); DBUG_DUMP("after_record", (const char *)after_record, table->s->reclength); DBUG_DUMP("before_row", (const char *)before_row, before_size); DBUG_DUMP("after_row", (const char *)after_row, after_size); +#endif Rows_log_event* const ev= binlog_prepare_pending_rows_event(table, server_id, cols, colcnt, before_size + after_size, is_trans, static_cast<Update_rows_log_event*>(0)); - error= - unlikely(!ev) || + if (unlikely(ev == 0)) + return HA_ERR_OUT_OF_MEM; + + return ev->add_row_data(before_row, before_size) || ev->add_row_data(after_row, after_size); - - if (!table->write_row_record) - { - /* add_row_data copies row_data to internal buffer */ - my_free((gptr)row_data, MYF(MY_WME)); - } - - return error; } int THD::binlog_delete_row(TABLE* table, bool is_trans, @@ -2664,11 +2764,14 @@ int THD::binlog_delete_row(TABLE* table, bool is_trans, Pack records into format for transfer. We are allocating more memory than needed, but that doesn't matter. */ - bool error= 0; - my_size_t const max_len= max_row_length(table, record); - byte *row_data= table->write_row_record; - if (!row_data && unlikely(!(row_data= (byte*)my_malloc(max_len, MYF(MY_WME))))) + int error= 0; + + Row_data_memory memory(table, max_row_length(table, record)); + if (unlikely(!memory.has_memory())) return HA_ERR_OUT_OF_MEM; + + byte *row_data= memory.slot(0); + my_size_t const len= pack_row(table, cols, row_data, record); Rows_log_event* const ev= @@ -2676,13 +2779,10 @@ int THD::binlog_delete_row(TABLE* table, bool is_trans, len, is_trans, static_cast<Delete_rows_log_event*>(0)); - error= (unlikely(!ev)) || ev->add_row_data(row_data, len); - - /* add_row_data copies row_data */ - if (table->write_row_record == 0) - my_free((gptr)row_data, MYF(MY_WME)); + if (unlikely(ev == 0)) + return HA_ERR_OUT_OF_MEM; - return error; + return ev->add_row_data(row_data, len); } @@ -2776,6 +2876,12 @@ int THD::binlog_query(THD::enum_binlog_query_type qtype, #endif /*HAVE_ROW_BASED_REPLICATION*/ switch (qtype) { + case THD::ROW_QUERY_TYPE: +#ifdef HAVE_ROW_BASED_REPLICATION + if (current_stmt_binlog_row_based) + DBUG_RETURN(0); +#endif + /* Otherwise, we fall through */ case THD::MYSQL_QUERY_TYPE: /* Using this query type is a conveniece hack, since we have been @@ -2785,12 +2891,6 @@ int THD::binlog_query(THD::enum_binlog_query_type qtype, Make sure to change in check_table_binlog_row_based() according to how you treat this. */ - case THD::ROW_QUERY_TYPE: -#ifdef HAVE_ROW_BASED_REPLICATION - if (current_stmt_binlog_row_based) - DBUG_RETURN(0); -#endif - /* Otherwise, we fall through */ case THD::STMT_QUERY_TYPE: /* The MYSQL_LOG::write() function will set the STMT_END_F flag and diff --git a/sql/sql_class.h b/sql/sql_class.h index 2cf7de5ee9e..218c56959a3 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -425,6 +425,12 @@ public: { return strdup_root(mem_root,str); } inline char *strmake(const char *str, uint size) { return strmake_root(mem_root,str,size); } + inline bool LEX_STRING_make(LEX_STRING *lex_str, const char *str, uint size) + { + return ((lex_str->str= + strmake_root(mem_root, str, (lex_str->length= size)))) == 0; + } + inline char *memdup(const char *str, uint size) { return memdup_root(mem_root,str,size); } inline char *memdup_w_gap(const char *str, uint size, uint gap) @@ -838,6 +844,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 @@ -1628,8 +1640,7 @@ public: return TRUE; } *p_db= strmake(db, db_length); - if (p_db_length) - *p_db_length= db_length; + *p_db_length= db_length; return FALSE; } }; @@ -2065,7 +2076,7 @@ public: 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)); diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 37096fd897e..0c154069bd6 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -1302,8 +1302,8 @@ err: bool mysql_change_db(THD *thd, const char *name, bool no_access_check) { - int path_length, db_length; - char *db_name; + int path_length; + LEX_STRING db_name; bool system_db= 0; #ifndef NO_EMBEDDED_ACCESS_CHECKS ulong db_access; @@ -1323,25 +1323,26 @@ bool mysql_change_db(THD *thd, const char *name, bool no_access_check) /* Called from SP to restore the original database, which was NULL */ DBUG_ASSERT(no_access_check); system_db= 1; - db_name= NULL; - db_length= 0; + db_name.str= NULL; + db_name.length= 0; goto end; } /* Now we need to make a copy because check_db_name requires a non-constant argument. TODO: fix check_db_name. */ - if ((db_name= my_strdup(name, MYF(MY_WME))) == NULL) + if ((db_name.str= my_strdup(name, MYF(MY_WME))) == NULL) DBUG_RETURN(1); /* the error is set */ - db_length= strlen(db_name); - if (check_db_name(db_name)) + db_name.length= strlen(db_name.str); + if (check_db_name(&db_name)) { - my_error(ER_WRONG_DB_NAME, MYF(0), db_name); - my_free(db_name, MYF(0)); + my_error(ER_WRONG_DB_NAME, MYF(0), db_name.str); + my_free(db_name.str, MYF(0)); DBUG_RETURN(1); } - DBUG_PRINT("info",("Use database: %s", db_name)); - if (!my_strcasecmp(system_charset_info, db_name, information_schema_name.str)) + DBUG_PRINT("info",("Use database: %s", db_name.str)); + if (!my_strcasecmp(system_charset_info, db_name.str, + information_schema_name.str)) { system_db= 1; #ifndef NO_EMBEDDED_ACCESS_CHECKS @@ -1356,34 +1357,35 @@ bool mysql_change_db(THD *thd, const char *name, bool no_access_check) if (test_all_bits(sctx->master_access, DB_ACLS)) db_access=DB_ACLS; else - db_access= (acl_get(sctx->host, sctx->ip, sctx->priv_user, db_name, 0) | + db_access= (acl_get(sctx->host, sctx->ip, sctx->priv_user, + db_name.str, 0) | sctx->master_access); if (!(db_access & DB_ACLS) && (!grant_option || - check_grant_db(thd,db_name))) + check_grant_db(thd, db_name.str))) { my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), sctx->priv_user, sctx->priv_host, - db_name); + db_name.str); general_log_print(thd, COM_INIT_DB, ER(ER_DBACCESS_DENIED_ERROR), - sctx->priv_user, sctx->priv_host, db_name); - my_free(db_name,MYF(0)); + sctx->priv_user, sctx->priv_host, db_name.str); + my_free(db_name.str, MYF(0)); DBUG_RETURN(1); } } #endif - if (check_db_dir_existence(db_name)) + if (check_db_dir_existence(db_name.str)) { - my_error(ER_BAD_DB_ERROR, MYF(0), db_name); - my_free(db_name, MYF(0)); + my_error(ER_BAD_DB_ERROR, MYF(0), db_name.str); + my_free(db_name.str, MYF(0)); DBUG_RETURN(1); } end: x_free(thd->db); - DBUG_ASSERT(db_name == NULL || db_name[0] != '\0'); - thd->reset_db(db_name, db_length); // THD::~THD will free this + DBUG_ASSERT(db_name.str == NULL || db_name.str[0] != '\0'); + thd->reset_db(db_name.str, db_name.length); // THD::~THD will free this #ifndef NO_EMBEDDED_ACCESS_CHECKS if (!no_access_check) sctx->db_access= db_access; @@ -1397,7 +1399,7 @@ end: { HA_CREATE_INFO create; - load_db_opt_by_name(thd, db_name, &create); + load_db_opt_by_name(thd, db_name.str, &create); thd->db_charset= create.default_table_charset ? create.default_table_charset : diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index a0cd419e6c6..5da2a7660a4 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -354,7 +354,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); } diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index 0d893a6c9be..c448be04ac5 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -367,9 +367,9 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables, strlen(tables->alias) + 1))) { table= hash_tables->table; - DBUG_PRINT("info-in-hash",("'%s'.'%s' as '%s' tab %p", + DBUG_PRINT("info-in-hash",("'%s'.'%s' as '%s' table: 0x%lx", hash_tables->db, hash_tables->table_name, - hash_tables->alias, table)); + hash_tables->alias, (long) table)); if (!table) { /* @@ -633,7 +633,8 @@ int mysql_ha_flush(THD *thd, TABLE_LIST *tables, uint mode_flags, TABLE **table_ptr; bool did_lock= FALSE; DBUG_ENTER("mysql_ha_flush"); - DBUG_PRINT("enter", ("tables: %p mode_flags: 0x%02x", tables, mode_flags)); + DBUG_PRINT("enter", ("tables: 0x%lx mode_flags: 0x%02x", + (long) tables, mode_flags)); if (tables) { diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index c35ef4079d3..47704570720 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -164,6 +164,7 @@ void lex_start(THD *thd, const 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->ignore_space=test(thd->variables.sql_mode & MODE_IGNORE_SPACE); lex->sql_command= SQLCOM_END; lex->duplicates= DUP_ERROR; @@ -176,7 +177,8 @@ void lex_start(THD *thd, const uchar *buf, uint length) lex->reset_query_tables_list(FALSE); lex->expr_allows_subselect= TRUE; - lex->name= 0; + lex->name.str= 0; + lex->name.length= 0; lex->event_parse_data= NULL; lex->nest_level=0 ; @@ -242,6 +244,12 @@ bool is_keyword(const char *name, uint len) return get_hash_symbol(name,len,0)!=0; } +bool is_lex_native_function(const LEX_STRING *name) +{ + DBUG_ASSERT(name != NULL); + return (get_hash_symbol(name->str, name->length, 1) != 0); +} + /* make a copy of token before ptr and set yytoklen */ static LEX_STRING get_token(LEX *lex,uint length) @@ -1174,6 +1182,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(); @@ -1187,7 +1196,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; } /* @@ -1381,6 +1390,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; } @@ -1443,7 +1454,7 @@ bool st_select_lex::add_order_to_list(THD *thd, Item *item, bool asc) bool st_select_lex::add_item_to_list(THD *thd, Item *item) { DBUG_ENTER("st_select_lex::add_item_to_list"); - DBUG_PRINT("info", ("Item: %p", item)); + DBUG_PRINT("info", ("Item: 0x%lx", (long) item)); DBUG_RETURN(item_list.push_back(item)); } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 7e09675cb0a..3166928420a 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -496,7 +496,7 @@ public: void set_thd(THD *thd_arg) { thd= thd_arg; } friend void lex_start(THD *thd, const uchar *buf, uint length); - friend int subselect_union_engine::exec(); + friend int subselect_union_engine::exec(bool); List<Item> *get_unit_column_types(); }; @@ -588,6 +588,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 @@ -607,6 +609,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(); @@ -908,7 +912,8 @@ typedef struct st_lex : public Query_tables_list /* The values of tok_start/tok_end as they were one call of MYSQLlex before */ const uchar *tok_start_prev, *tok_end_prev; - char *length,*dec,*change,*name; + char *length,*dec,*change; + LEX_STRING name; Table_ident *like_name; char *help_arg; char *backup_dir; /* For RESTORE/BACKUP */ @@ -1230,4 +1235,6 @@ extern void lex_end(LEX *lex); extern int MYSQLlex(void *arg, void *yythd); extern const uchar *skip_rear_comments(const uchar *ubegin, const uchar *uend); +extern bool is_lex_native_function(const LEX_STRING *name); + #endif /* MYSQL_SERVER */ diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index d88478b9702..f0aa90fa84f 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -394,9 +394,9 @@ int check_user(THD *thd, enum enum_server_command command, NO_ACCESS)) // authentication is OK { DBUG_PRINT("info", - ("Capabilities: %lx 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, @@ -1002,7 +1002,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. */ @@ -1055,11 +1055,14 @@ static int check_connection(THD *thd) Old clients send null-terminated string as password; new clients send the size (1 byte) + string (not null-terminated). Hence in case of empty password both send '\0'. + + This strlen() can't be easily deleted without changing protocol. */ uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ? *passwd++ : strlen(passwd); db= thd->client_capabilities & CLIENT_CONNECT_WITH_DB ? db + passwd_len + 1 : 0; + /* strlen() can't be easily deleted without changing protocol */ uint db_len= db ? strlen(db) : 0; if (passwd + passwd_len + db_len > (char *)net->read_pos + pkt_len) @@ -1158,7 +1161,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_* */ @@ -1321,28 +1324,31 @@ pthread_handler_t handle_bootstrap(void *arg) thd->init_for_queries(); while (fgets(buff, thd->net.max_packet, file)) { - ulong length= (ulong) strlen(buff); - while (buff[length-1] != '\n' && !feof(file)) - { - /* - We got only a part of the current string. Will try to increase - net buffer then read the rest of the current string. - */ - if (net_realloc(&(thd->net), 2 * thd->net.max_packet)) - { - net_send_error(thd, ER_NET_PACKET_TOO_LARGE, NullS); - thd->fatal_error(); - break; - } - buff= (char*) thd->net.buff; - fgets(buff + length, thd->net.max_packet - length, file); - length+= (ulong) strlen(buff + length); - } - if (thd->is_fatal_error) - break; + /* strlen() can't be deleted because fgets() doesn't return length */ + ulong length= (ulong) strlen(buff); + while (buff[length-1] != '\n' && !feof(file)) + { + /* + We got only a part of the current string. Will try to increase + net buffer then read the rest of the current string. + */ + /* purecov: begin tested */ + if (net_realloc(&(thd->net), 2 * thd->net.max_packet)) + { + net_send_error(thd, ER_NET_PACKET_TOO_LARGE, NullS); + thd->fatal_error(); + break; + } + buff= (char*) thd->net.buff; + fgets(buff + length, thd->net.max_packet - length, file); + length+= (ulong) strlen(buff + length); + /* purecov: end */ + } + if (thd->is_fatal_error) + break; /* purecov: inspected */ while (length && (my_isspace(thd->charset(), buff[length-1]) || - buff[length-1] == ';')) + buff[length-1] == ';')) length--; buff[length]=0; thd->query_length=length; @@ -1427,24 +1433,30 @@ void cleanup_items(Item *item) */ static -int mysql_table_dump(THD* thd, char* db, char* tbl_name) +int mysql_table_dump(THD *thd, LEX_STRING *db, char *tbl_name) { TABLE* table; TABLE_LIST* table_list; int error = 0; DBUG_ENTER("mysql_table_dump"); - db = (db && db[0]) ? db : thd->db; + if (db->length == 0) + { + db->str= thd->db; /* purecov: inspected */ + db->length= thd->db_length; /* purecov: inspected */ + } if (!(table_list = (TABLE_LIST*) thd->calloc(sizeof(TABLE_LIST)))) DBUG_RETURN(1); // out of memory - table_list->db= db; + table_list->db= db->str; table_list->table_name= table_list->alias= tbl_name; table_list->lock_type= TL_READ_NO_INSERT; table_list->prev_global= &table_list; // can be removed after merge with 4.1 - if (!db || check_db_name(db)) + if (check_db_name(db)) { - my_error(ER_WRONG_DB_NAME ,MYF(0), db ? db : "NULL"); + /* purecov: begin inspected */ + my_error(ER_WRONG_DB_NAME ,MYF(0), db->str ? db->str : "NULL"); goto err; + /* purecov: end */ } if (lower_case_table_names) my_casedn_str(files_charset_info, tbl_name); @@ -1604,7 +1616,7 @@ bool do_command(THD *thd) command= COM_END; // Wrong command DBUG_PRINT("info",("Command on %s = %d (%s)", vio_description(net->vio), command, - command_name[command])); + command_name[command].str)); } net->read_timeout=old_timeout; // restore it /* @@ -1673,7 +1685,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, statistic_increment(thd->status_var.com_stat[SQLCOM_CHANGE_DB], &LOCK_status); thd->convert_string(&tmp, system_charset_info, - packet, strlen(packet), thd->charset()); + packet, packet_length-1, thd->charset()); if (!mysql_change_db(thd, tmp.str, FALSE)) { general_log_print(thd, command, "%s",thd->db); @@ -1691,7 +1703,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd, #endif case COM_TABLE_DUMP: { - char *db, *tbl_name; + char *tbl_name; + LEX_STRING db; uint db_len= *(uchar*) packet; if (db_len >= packet_length || db_len > NAME_LEN) { @@ -1707,34 +1720,41 @@ bool dispatch_command(enum enum_server_command command, THD *thd, statistic_increment(thd->status_var.com_other, &LOCK_status); thd->enable_slow_log= opt_log_slow_admin_statements; - db= thd->alloc(db_len + tbl_len + 2); - if (!db) + db.str= thd->alloc(db_len + tbl_len + 2); + db.length= db_len; + if (!db.str) { my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0)); break; } - tbl_name= strmake(db, packet + 1, db_len)+1; + tbl_name= strmake(db.str, packet + 1, db_len)+1; strmake(tbl_name, packet + db_len + 2, tbl_len); - mysql_table_dump(thd, db, tbl_name); + mysql_table_dump(thd, &db, tbl_name); break; } case COM_CHANGE_USER: { + statistic_increment(thd->status_var.com_other, &LOCK_status); + char *user= (char*) packet, *packet_end= packet+ packet_length; + char *passwd= strend(user)+1; + thd->change_user(); thd->clear_error(); // if errors from rollback - statistic_increment(thd->status_var.com_other, &LOCK_status); - char *user= (char*) packet; - char *passwd= strend(user)+1; /* Old clients send null-terminated string ('\0' for empty string) for password. New clients send the size (1 byte) + string (not null terminated, so also '\0' for empty string). */ - char db_buff[NAME_LEN+1]; // buffer to store db in utf8 + char db_buff[NAME_LEN+1]; // buffer to store db in utf8 char *db= passwd; - uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ? - *passwd++ : strlen(passwd); + char *save_db; + uint passwd_len= (thd->client_capabilities & CLIENT_SECURE_CONNECTION ? + *passwd++ : strlen(passwd)); + uint dummy_errors, save_db_length, db_length, res; + Security_context save_security_ctx= *thd->security_ctx; + USER_CONN *save_user_connect; + db+= passwd_len + 1; #ifndef EMBEDDED_LIBRARY /* Small check for incoming packet */ @@ -1745,17 +1765,22 @@ bool dispatch_command(enum enum_server_command command, THD *thd, } #endif /* Convert database name to utf8 */ - uint dummy_errors; + /* + Handle problem with old bug in client protocol where db had an extra + \0 + */ + db_length= (packet_end - db); + if (db_length > 0 && db[db_length-1] == 0) + db_length--; db_buff[copy_and_convert(db_buff, sizeof(db_buff)-1, - system_charset_info, db, strlen(db), + system_charset_info, db, db_length, thd->charset(), &dummy_errors)]= 0; db= db_buff; /* Save user and privileges */ - uint save_db_length= thd->db_length; - char *save_db= thd->db; - Security_context save_security_ctx= *thd->security_ctx; - USER_CONN *save_user_connect= thd->user_connect; + save_db_length= thd->db_length; + save_db= thd->db; + save_user_connect= thd->user_connect; if (!(thd->security_ctx->user= my_strdup(user, MYF(0)))) { @@ -1766,7 +1791,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, /* Clear variables that are allocated */ thd->user_connect= 0; - int res= check_user(thd, COM_CHANGE_USER, passwd, passwd_len, db, FALSE); + res= check_user(thd, COM_CHANGE_USER, passwd, passwd_len, db, FALSE); if (res) { @@ -1826,7 +1851,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; - general_log_print(thd, command, "%.*b", thd->query_length, thd->query); + /* 'b' stands for 'buffer' parameter', special for 'my_snprintf' */ + const char *format= "%.*b"; + general_log_print(thd, command, format, thd->query_length, thd->query); DBUG_PRINT("query",("%-.4096s",thd->query)); if (!(specialflag & SPECIAL_NO_PRIOR)) @@ -1876,29 +1903,31 @@ bool dispatch_command(enum enum_server_command command, THD *thd, break; #else { - char *fields, *pend; + char *fields, *packet_end= packet + packet_length - 1, *arg_end; /* Locked closure of all tables */ TABLE_LIST *locked_tables= NULL; TABLE_LIST table_list; LEX_STRING conv_name; /* Saved variable value */ my_bool old_innodb_table_locks= thd->variables.innodb_table_locks; - + uint dummy; /* used as fields initializator */ lex_start(thd, 0, 0); - statistic_increment(thd->status_var.com_stat[SQLCOM_SHOW_FIELDS], &LOCK_status); bzero((char*) &table_list,sizeof(table_list)); - if (thd->copy_db_to(&table_list.db, 0)) + if (thd->copy_db_to(&table_list.db, &dummy)) break; - pend= strend(packet); + /* + We have name + wildcard in packet, separated by endzero + */ + arg_end= strend(packet); thd->convert_string(&conv_name, system_charset_info, - packet, (uint) (pend-packet), thd->charset()); + packet, (uint) (arg_end - packet), thd->charset()); table_list.alias= table_list.table_name= conv_name.str; - packet= pend+1; + packet= arg_end + 1; if (!my_strcasecmp(system_charset_info, table_list.db, information_schema_name.str)) @@ -1908,7 +1937,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, table_list.schema_table= schema_table; } - thd->query_length= strlen(packet); // for simplicity: don't optimize + thd->query_length= (uint) (packet_end - packet); // Don't count end \0 if (!(thd->query=fields=thd->memdup(packet,thd->query_length+1))) break; general_log_print(thd, command, "%s %s", table_list.table_name, fields); @@ -1944,24 +1973,27 @@ bool dispatch_command(enum enum_server_command command, THD *thd, error=TRUE; // End server break; +#ifdef REMOVED case COM_CREATE_DB: // QQ: To be removed { - char *db=thd->strdup(packet), *alias; + LEX_STRING db, alias; HA_CREATE_INFO create_info; statistic_increment(thd->status_var.com_stat[SQLCOM_CREATE_DB], &LOCK_status); - // null test to handle EOM - if (!db || !(alias= thd->strdup(db)) || check_db_name(db)) + if (thd->LEX_STRING_make(&db, packet, packet_length -1) || + thd->LEX_STRING_make(&alias, db.str, db.length) || + check_db_name(&db)) { - my_error(ER_WRONG_DB_NAME, MYF(0), db ? db : "NULL"); + my_error(ER_WRONG_DB_NAME, MYF(0), db.str ? db.str : "NULL"); break; } - if (check_access(thd,CREATE_ACL,db,0,1,0,is_schema_db(db))) + if (check_access(thd, CREATE_ACL, db.str , 0, 1, 0, + is_schema_db(db.str))) break; general_log_print(thd, command, packet); bzero(&create_info, sizeof(create_info)); - mysql_create_db(thd, (lower_case_table_names == 2 ? alias : db), + mysql_create_db(thd, (lower_case_table_names == 2 ? alias.str : db.str), &create_info, 0); break; } @@ -1969,14 +2001,15 @@ bool dispatch_command(enum enum_server_command command, THD *thd, { statistic_increment(thd->status_var.com_stat[SQLCOM_DROP_DB], &LOCK_status); - char *db=thd->strdup(packet); - /* null test to handle EOM */ - if (!db || check_db_name(db)) + LEX_STRING db; + + if (thd->LEX_STRING_make(&db, packet, packet_length - 1) || + check_db_name(&db)) { - my_error(ER_WRONG_DB_NAME, MYF(0), db ? db : "NULL"); + my_error(ER_WRONG_DB_NAME, MYF(0), db.str ? db.str : "NULL"); break; } - if (check_access(thd,DROP_ACL,db,0,1,0,is_schema_db(db))) + if (check_access(thd, DROP_ACL, db.str, 0, 1, 0, is_schema_db(db.str))) break; if (thd->locked_tables || thd->active_transaction()) { @@ -1984,10 +2017,11 @@ bool dispatch_command(enum enum_server_command command, THD *thd, ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0)); break; } - general_log_print(thd, command, db); - mysql_rm_db(thd, db, 0, 0); + general_log_print(thd, command, db.str); + mysql_rm_db(thd, db.str, 0, 0); break; } +#endif #ifndef EMBEDDED_LIBRARY case COM_BINLOG_DUMP: { @@ -2069,37 +2103,47 @@ bool dispatch_command(enum enum_server_command command, THD *thd, #endif case COM_STATISTICS: { - general_log_print(thd, command, NullS); - statistic_increment(thd->status_var.com_stat[SQLCOM_SHOW_STATUS], - &LOCK_status); + STATUS_VAR current_global_status_var; + ulong uptime; + uint length; #ifndef EMBEDDED_LIBRARY - char buff[200]; + char buff[250]; + uint buff_len= sizeof(buff); #else char *buff= thd->net.last_error; + uint buff_len= sizeof(thd->net.last_error); #endif - STATUS_VAR current_global_status_var; + general_log_print(thd, command, NullS); + statistic_increment(thd->status_var.com_stat[SQLCOM_SHOW_STATUS], + &LOCK_status); calc_sum_of_all_status(¤t_global_status_var); - - ulong uptime = (ulong) (thd->start_time - start_time); - sprintf((char*) buff, - "Uptime: %lu Threads: %d Questions: %lu Slow queries: %lu Opens: %lu Flush tables: %lu Open tables: %u Queries per second avg: %.3f", - uptime, - (int) thread_count, (ulong) thd->query_id, - current_global_status_var.long_query_count, - current_global_status_var.opened_tables, refresh_version, - cached_open_tables(), - (uptime ? (ulonglong2double(thd->query_id) / (double) uptime) : - (double) 0)); + uptime= (ulong) (thd->start_time - start_time); + length= my_snprintf((char*) buff, buff_len - 1, + "Uptime: %lu Threads: %d Questions: %lu " + "Slow queries: %lu Opens: %lu Flush tables: %lu " + "Open tables: %u Queries per second avg: %.3f", + uptime, + (int) thread_count, (ulong) thd->query_id, + current_global_status_var.long_query_count, + current_global_status_var.opened_tables, + refresh_version, + cached_open_tables(), + (uptime ? (ulonglong2double(thd->query_id) / + (double) uptime) : (double) 0)); #ifdef SAFEMALLOC if (sf_malloc_cur_memory) // Using SAFEMALLOC - sprintf(strend(buff), " Memory in use: %ldK Max memory used: %ldK", - (sf_malloc_cur_memory+1023L)/1024L, - (sf_malloc_max_memory+1023L)/1024L); + { + char *end= buff + length; + length+= my_snprintf(end, buff_len - length - 1, + end," Memory in use: %ldK Max memory used: %ldK", + (sf_malloc_cur_memory+1023L)/1024L, + (sf_malloc_max_memory+1023L)/1024L); + } #endif #ifndef EMBEDDED_LIBRARY - VOID(my_net_write(net, buff,(uint) strlen(buff))); - VOID(net_flush(net)); + VOID(my_net_write(net, buff, length)); + VOID(net_flush(net)); #endif break; } @@ -2296,26 +2340,28 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident, DBUG_RETURN(1); #else { - char *db; + LEX_STRING db; + uint dummy; if (lex->select_lex.db == NULL && - thd->copy_db_to(&lex->select_lex.db, 0)) + thd->copy_db_to(&lex->select_lex.db, &dummy)) { DBUG_RETURN(1); } - db= lex->select_lex.db; - if (check_db_name(db)) + db.str= lex->select_lex.db; + db.length= strlen(db.str); + if (check_db_name(&db)) { - my_error(ER_WRONG_DB_NAME, MYF(0), db); + my_error(ER_WRONG_DB_NAME, MYF(0), db.str); DBUG_RETURN(1); } - if (check_access(thd, SELECT_ACL, db, &thd->col_access, 0, 0, - is_schema_db(db))) + if (check_access(thd, SELECT_ACL, db.str, &thd->col_access, 0, 0, + is_schema_db(db.str))) DBUG_RETURN(1); /* purecov: inspected */ - if (!thd->col_access && check_grant_db(thd,db)) + if (!thd->col_access && check_grant_db(thd, db.str)) { my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), thd->security_ctx->priv_user, thd->security_ctx->priv_host, - db); + db.str); DBUG_RETURN(1); } break; @@ -2550,7 +2596,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); } } @@ -2855,11 +2917,6 @@ mysql_execute_command(THD *thd) if (check_grant(thd, CREATE_ACL, all_tables, 0, 1, 0)) goto error; } - if (strlen(first_table->table_name) > NAME_LEN) - { - my_error(ER_WRONG_TABLE_NAME, MYF(0), first_table->table_name); - break; - } pthread_mutex_lock(&LOCK_active_mi); /* fetch_master_table will send the error to the client on failure. @@ -3089,11 +3146,6 @@ end_with_restore_list: if (lex->alter_info.flags & ALTER_DROP_PARTITION) priv_needed|= DROP_ACL; - if (lex->name && (!lex->name[0] || strlen(lex->name) > NAME_LEN)) - { - my_error(ER_WRONG_TABLE_NAME, MYF(0), lex->name); - goto error; - } /* Must be set in the parser */ DBUG_ASSERT(select_lex->db); if (check_access(thd, priv_needed, first_table->db, @@ -3109,11 +3161,11 @@ end_with_restore_list: { if (check_grant(thd, priv_needed, all_tables, 0, UINT_MAX, 0)) goto error; - if (lex->name && !test_all_bits(priv,INSERT_ACL | CREATE_ACL)) + if (lex->name.str && !test_all_bits(priv,INSERT_ACL | CREATE_ACL)) { // Rename of table TABLE_LIST tmp_table; bzero((char*) &tmp_table,sizeof(tmp_table)); - tmp_table.table_name=lex->name; + tmp_table.table_name= lex->name.str; tmp_table.db=select_lex->db; tmp_table.grant.privilege=priv; if (check_grant(thd, INSERT_ACL | CREATE_ACL, &tmp_table, 0, @@ -3141,7 +3193,7 @@ end_with_restore_list: } thd->enable_slow_log= opt_log_slow_admin_statements; - res= mysql_alter_table(thd, select_lex->db, lex->name, + res= mysql_alter_table(thd, select_lex->db, lex->name.str, &lex->create_info, first_table, lex->create_list, lex->key_list, @@ -3459,8 +3511,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; @@ -3753,9 +3809,10 @@ end_with_restore_list: break; } char *alias; - if (!(alias=thd->strdup(lex->name)) || check_db_name(lex->name)) + if (!(alias=thd->strmake(lex->name.str, lex->name.length)) || + check_db_name(&lex->name)) { - my_error(ER_WRONG_DB_NAME, MYF(0), lex->name); + my_error(ER_WRONG_DB_NAME, MYF(0), lex->name.str); break; } /* @@ -3767,17 +3824,18 @@ end_with_restore_list: */ #ifdef HAVE_REPLICATION if (thd->slave_thread && - (!rpl_filter->db_ok(lex->name) || - !rpl_filter->db_ok_with_wild_table(lex->name))) + (!rpl_filter->db_ok(lex->name.str) || + !rpl_filter->db_ok_with_wild_table(lex->name.str))) { my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0)); break; } #endif - if (check_access(thd,CREATE_ACL,lex->name,0,1,0,is_schema_db(lex->name))) + if (check_access(thd,CREATE_ACL,lex->name.str, 0, 1, 0, + is_schema_db(lex->name.str))) break; - res= mysql_create_db(thd,(lower_case_table_names == 2 ? alias : lex->name), - &lex->create_info, 0); + res= mysql_create_db(thd,(lower_case_table_names == 2 ? alias : + lex->name.str), &lex->create_info, 0); break; } case SQLCOM_DROP_DB: @@ -3787,9 +3845,9 @@ end_with_restore_list: res= -1; break; } - if (check_db_name(lex->name)) + if (check_db_name(&lex->name)) { - my_error(ER_WRONG_DB_NAME, MYF(0), lex->name); + my_error(ER_WRONG_DB_NAME, MYF(0), lex->name.str); break; } /* @@ -3801,14 +3859,15 @@ end_with_restore_list: */ #ifdef HAVE_REPLICATION if (thd->slave_thread && - (!rpl_filter->db_ok(lex->name) || - !rpl_filter->db_ok_with_wild_table(lex->name))) + (!rpl_filter->db_ok(lex->name.str) || + !rpl_filter->db_ok_with_wild_table(lex->name.str))) { my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0)); break; } #endif - if (check_access(thd,DROP_ACL,lex->name,0,1,0,is_schema_db(lex->name))) + if (check_access(thd,DROP_ACL,lex->name.str,0,1,0, + is_schema_db(lex->name.str))) break; if (thd->locked_tables || thd->active_transaction()) { @@ -3816,7 +3875,7 @@ end_with_restore_list: ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0)); goto error; } - res= mysql_rm_db(thd, lex->name, lex->drop_if_exists, 0); + res= mysql_rm_db(thd, lex->name.str, lex->drop_if_exists, 0); break; } case SQLCOM_RENAME_DB: @@ -3842,6 +3901,11 @@ end_with_restore_list: break; } #endif + if (check_db_name(newdb)) + { + my_error(ER_WRONG_DB_NAME, MYF(0), newdb->str); + break; + } if (check_access(thd,ALTER_ACL,olddb->str,0,1,0,is_schema_db(olddb->str)) || check_access(thd,DROP_ACL,olddb->str,0,1,0,is_schema_db(olddb->str)) || check_access(thd,CREATE_ACL,newdb->str,0,1,0,is_schema_db(newdb->str))) @@ -3863,11 +3927,10 @@ end_with_restore_list: } case SQLCOM_ALTER_DB: { - char *db= lex->name; - DBUG_ASSERT(db); /* Must be set in the parser */ - if (!strip_sp(db) || check_db_name(db)) + LEX_STRING *db= &lex->name; + if (check_db_name(db)) { - my_error(ER_WRONG_DB_NAME, MYF(0), db); + my_error(ER_WRONG_DB_NAME, MYF(0), db->str); break; } /* @@ -3879,14 +3942,14 @@ end_with_restore_list: */ #ifdef HAVE_REPLICATION if (thd->slave_thread && - (!rpl_filter->db_ok(db) || - !rpl_filter->db_ok_with_wild_table(db))) + (!rpl_filter->db_ok(db->str) || + !rpl_filter->db_ok_with_wild_table(db->str))) { my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0)); break; } #endif - if (check_access(thd, ALTER_ACL, db, 0, 1, 0, is_schema_db(db))) + if (check_access(thd, ALTER_ACL, db->str, 0, 1, 0, is_schema_db(db->str))) break; if (thd->locked_tables || thd->active_transaction()) { @@ -3894,21 +3957,22 @@ end_with_restore_list: ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0)); goto error; } - res= mysql_alter_db(thd, db, &lex->create_info); + res= mysql_alter_db(thd, db->str, &lex->create_info); break; } case SQLCOM_SHOW_CREATE_DB: { - if (!strip_sp(lex->name) || check_db_name(lex->name)) + if (check_db_name(&lex->name)) { - my_error(ER_WRONG_DB_NAME, MYF(0), lex->name); + my_error(ER_WRONG_DB_NAME, MYF(0), lex->name.str); break; } - res=mysqld_show_create_db(thd,lex->name,&lex->create_info); + res= mysqld_show_create_db(thd, lex->name.str, &lex->create_info); break; } case SQLCOM_CREATE_EVENT: case SQLCOM_ALTER_EVENT: + do { DBUG_ASSERT(lex->event_parse_data); if (lex->table_or_sp_used()) @@ -3934,16 +3998,15 @@ end_with_restore_list: if (!res) send_ok(thd); - /* Don't do it, if we are inside a SP */ - if (!thd->spcont) - { - delete lex->sphead; - lex->sphead= NULL; - } - - /* lex->unit.cleanup() is called outside, no need to call it here */ - break; + } while (0); + /* Don't do it, if we are inside a SP */ + if (!thd->spcont) + { + delete lex->sphead; + lex->sphead= NULL; } + /* lex->unit.cleanup() is called outside, no need to call it here */ + break; case SQLCOM_DROP_EVENT: case SQLCOM_SHOW_CREATE_EVENT: { @@ -6290,7 +6353,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, } if (table->is_derived_table() == FALSE && table->db.str && - check_db_name(table->db.str)) + check_db_name(&table->db)) { my_error(ER_WRONG_DB_NAME, MYF(0), table->db.str); DBUG_RETURN(0); @@ -6319,7 +6382,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; @@ -7574,7 +7637,7 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables, #ifdef NOT_NECESSARY_TO_CHECK_CREATE_TABLE_EXIST_WHEN_PREPARING_STATEMENT /* This code throws an ill error for CREATE TABLE t1 SELECT * FROM t1 */ /* - Only do the check for PS, becasue we on execute we have to check that + Only do the check for PS, because we on execute we have to check that against the opened tables to ensure we don't use a table that is part of the view (which can only be done after the table has been opened). */ diff --git a/sql/sql_parse.cc.rej b/sql/sql_parse.cc.rej new file mode 100644 index 00000000000..6e2bd03867d --- /dev/null +++ b/sql/sql_parse.cc.rej @@ -0,0 +1,166 @@ +*************** +*** 67,109 **** + static void decrease_user_connections(USER_CONN *uc); + #endif /* NO_EMBEDDED_ACCESS_CHECKS */ + static bool check_multi_update_lock(THD *thd); +- static void remove_escape(char *name); + static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables); + + const char *any_db="*any*"; // Special symbol for check_access + +! LEX_STRING command_name[]={ +! (char *)STRING_WITH_LEN("Sleep"), +! (char *)STRING_WITH_LEN("Quit"), +! (char *)STRING_WITH_LEN("Init DB"), +! (char *)STRING_WITH_LEN("Query"), +! (char *)STRING_WITH_LEN("Field List"), +! (char *)STRING_WITH_LEN("Create DB"), +! (char *)STRING_WITH_LEN("Drop DB"), +! (char *)STRING_WITH_LEN("Refresh"), +! (char *)STRING_WITH_LEN("Shutdown"), +! (char *)STRING_WITH_LEN("Statistics"), +! (char *)STRING_WITH_LEN("Processlist"), +! (char *)STRING_WITH_LEN("Connect"), +! (char *)STRING_WITH_LEN("Kill"), +! (char *)STRING_WITH_LEN("Debug"), +! (char *)STRING_WITH_LEN("Ping"), +! (char *)STRING_WITH_LEN("Time"), +! (char *)STRING_WITH_LEN("Delayed insert"), +! (char *)STRING_WITH_LEN("Change user"), +! (char *)STRING_WITH_LEN("Binlog Dump"), +! (char *)STRING_WITH_LEN("Table Dump"), +! (char *)STRING_WITH_LEN("Connect Out"), +! (char *)STRING_WITH_LEN("Register Slave"), +! (char *)STRING_WITH_LEN("Prepare"), +! (char *)STRING_WITH_LEN("Execute"), +! (char *)STRING_WITH_LEN("Long Data"), +! (char *)STRING_WITH_LEN("Close stmt"), +! (char *)STRING_WITH_LEN("Reset stmt"), +! (char *)STRING_WITH_LEN("Set option"), +! (char *)STRING_WITH_LEN("Fetch"), +! (char *)STRING_WITH_LEN("Daemon"), +! (char *)STRING_WITH_LEN("Error") // Last command number + }; + + const char *xa_state_names[]={ +--- 67,108 ---- + static void decrease_user_connections(USER_CONN *uc); + #endif /* NO_EMBEDDED_ACCESS_CHECKS */ + static bool check_multi_update_lock(THD *thd); + static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables); + + const char *any_db="*any*"; // Special symbol for check_access + +! const LEX_STRING command_name[]={ +! C_STRING_WITH_LEN("Sleep"), +! C_STRING_WITH_LEN("Quit"), +! C_STRING_WITH_LEN("Init DB"), +! C_STRING_WITH_LEN("Query"), +! C_STRING_WITH_LEN("Field List"), +! C_STRING_WITH_LEN("Create DB"), +! C_STRING_WITH_LEN("Drop DB"), +! C_STRING_WITH_LEN("Refresh"), +! C_STRING_WITH_LEN("Shutdown"), +! C_STRING_WITH_LEN("Statistics"), +! C_STRING_WITH_LEN("Processlist"), +! C_STRING_WITH_LEN("Connect"), +! C_STRING_WITH_LEN("Kill"), +! C_STRING_WITH_LEN("Debug"), +! C_STRING_WITH_LEN("Ping"), +! C_STRING_WITH_LEN("Time"), +! C_STRING_WITH_LEN("Delayed insert"), +! C_STRING_WITH_LEN("Change user"), +! C_STRING_WITH_LEN("Binlog Dump"), +! C_STRING_WITH_LEN("Table Dump"), +! C_STRING_WITH_LEN("Connect Out"), +! C_STRING_WITH_LEN("Register Slave"), +! C_STRING_WITH_LEN("Prepare"), +! C_STRING_WITH_LEN("Execute"), +! C_STRING_WITH_LEN("Long Data"), +! C_STRING_WITH_LEN("Close stmt"), +! C_STRING_WITH_LEN("Reset stmt"), +! C_STRING_WITH_LEN("Set option"), +! C_STRING_WITH_LEN("Fetch"), +! C_STRING_WITH_LEN("Daemon"), +! C_STRING_WITH_LEN("Error") // Last command number + }; + + const char *xa_state_names[]={ +*************** +*** 1738,1744 **** + password. New clients send the size (1 byte) + string (not null + terminated, so also '\0' for empty string). + */ +! char db_buff[NAME_LEN+1]; // buffer to store db in utf8 + char *db= passwd; + uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ? + *passwd++ : strlen(passwd); +--- 1736,1742 ---- + password. New clients send the size (1 byte) + string (not null + terminated, so also '\0' for empty string). + */ +! char db_buff[NAME_LEN+1]; // buffer to store db in utf8 + char *db= passwd; + uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ? + *passwd++ : strlen(passwd); +*************** +*** 2315,2321 **** + DBUG_RETURN(1); + } + db= lex->select_lex.db; +- remove_escape(db); // Fix escaped '_' + if (check_db_name(db)) + { + my_error(ER_WRONG_DB_NAME, MYF(0), db); +--- 2312,2317 ---- + DBUG_RETURN(1); + } + db= lex->select_lex.db; + if (check_db_name(db)) + { + my_error(ER_WRONG_DB_NAME, MYF(0), db); +*************** +*** 6310,6345 **** + } + + +- /* Fix escaping of _, % and \ in database and table names (for ODBC) */ +- +- static void remove_escape(char *name) +- { +- if (!*name) // For empty DB names +- return; +- char *to; +- #ifdef USE_MB +- char *strend=name+(uint) strlen(name); +- #endif +- for (to=name; *name ; name++) +- { +- #ifdef USE_MB +- int l; +- if (use_mb(system_charset_info) && +- (l = my_ismbchar(system_charset_info, name, strend))) +- { +- while (l--) +- *to++ = *name++; +- name--; +- continue; +- } +- #endif +- if (*name == '\\' && name[1]) +- name++; // Skip '\\' +- *to++= *name; +- } +- *to=0; +- } +- + /**************************************************************************** + ** save order by and tables in own lists + ****************************************************************************/ +--- 6296,6301 ---- + } + + + /**************************************************************************** + ** save order by and tables in own lists + ****************************************************************************/ diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 8df527fd25b..266a5bad34d 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -4480,7 +4480,7 @@ that are reorganised. { if (!alt_part_info->use_default_partitions) { - DBUG_PRINT("info", ("part_info= %x", tab_part_info)); + DBUG_PRINT("info", ("part_info: 0x%lx", (long) tab_part_info)); tab_part_info->use_default_partitions= FALSE; } tab_part_info->use_default_no_partitions= FALSE; diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 7a0a143dcc9..8982db9e6b3 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -23,21 +23,26 @@ extern struct st_mysql_plugin *mysqld_builtins[]; char *opt_plugin_dir_ptr; char opt_plugin_dir[FN_REFLEN]; +/* + When you ad a new plugin type, add both a string and make sure that the + init and deinit array are correctly updated. +*/ const LEX_STRING plugin_type_names[MYSQL_MAX_PLUGIN_TYPE_NUM]= { { C_STRING_WITH_LEN("UDF") }, { C_STRING_WITH_LEN("STORAGE ENGINE") }, - { C_STRING_WITH_LEN("FTPARSER") } + { C_STRING_WITH_LEN("FTPARSER") }, + { C_STRING_WITH_LEN("DAEMON") } }; plugin_type_init plugin_type_initialize[MYSQL_MAX_PLUGIN_TYPE_NUM]= { - 0,ha_initialize_handlerton,0 + 0,ha_initialize_handlerton,0,0 }; plugin_type_init plugin_type_deinitialize[MYSQL_MAX_PLUGIN_TYPE_NUM]= { - 0,ha_finalize_handlerton,0 + 0,ha_finalize_handlerton,0,0 }; static const char *plugin_interface_version_sym= @@ -53,13 +58,15 @@ static int min_plugin_info_interface_version[MYSQL_MAX_PLUGIN_TYPE_NUM]= { 0x0000, MYSQL_HANDLERTON_INTERFACE_VERSION, - MYSQL_FTPARSER_INTERFACE_VERSION + MYSQL_FTPARSER_INTERFACE_VERSION, + MYSQL_DAEMON_INTERFACE_VERSION }; static int cur_plugin_info_interface_version[MYSQL_MAX_PLUGIN_TYPE_NUM]= { 0x0000, /* UDF: not implemented */ MYSQL_HANDLERTON_INTERFACE_VERSION, - MYSQL_FTPARSER_INTERFACE_VERSION + MYSQL_FTPARSER_INTERFACE_VERSION, + MYSQL_DAEMON_INTERFACE_VERSION }; static DYNAMIC_ARRAY plugin_dl_array; @@ -508,7 +515,7 @@ void plugin_deinitialize(struct st_plugin_int *plugin) else if (plugin->plugin->deinit) { DBUG_PRINT("info", ("Deinitializing plugin: '%s'", plugin->name.str)); - if (plugin->plugin->deinit(NULL)) + if (plugin->plugin->deinit(plugin)) { DBUG_PRINT("warning", ("Plugin '%s' deinit function returned error.", plugin->name.str)); @@ -568,7 +575,7 @@ static int plugin_initialize(struct st_plugin_int *plugin) } else if (plugin->plugin->init) { - if (plugin->plugin->init(NULL)) + if (plugin->plugin->init(plugin)) { sql_print_error("Plugin '%s' init function returned error.", plugin->name.str); diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 013c3a17fd6..0c6a5fe5846 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1665,7 +1665,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(); @@ -1916,9 +1916,12 @@ void mysql_stmt_prepare(THD *thd, const char *packet, uint packet_length) thd->stmt_map.erase(stmt); } else - general_log_print(thd, COM_STMT_PREPARE, "[%lu] %.*b", stmt->id, + { + const char *format= "[%lu] %.*b"; + general_log_print(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; } @@ -2262,7 +2265,7 @@ void mysql_stmt_execute(THD *thd, char *packet_arg, uint packet_length) DBUG_VOID_RETURN; DBUG_PRINT("exec_query", ("%s", stmt->query)); - DBUG_PRINT("info",("stmt: %p", stmt)); + DBUG_PRINT("info",("stmt: 0x%lx", (long) stmt)); sp_cache_flush_obsolete(&thd->sp_proc_cache); sp_cache_flush_obsolete(&thd->sp_func_cache); @@ -2300,9 +2303,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) - general_log_print(thd, COM_STMT_EXECUTE, "[%lu] %.*b", stmt->id, + { + const char *format= "[%lu] %.*b"; + general_log_print(thd, COM_STMT_EXECUTE, format, stmt->id, thd->query_length, thd->query); - + } DBUG_VOID_RETURN; set_params_data_err: @@ -2355,7 +2360,7 @@ void mysql_sql_stmt_execute(THD *thd) DBUG_VOID_RETURN; } - DBUG_PRINT("info",("stmt: %p", stmt)); + DBUG_PRINT("info",("stmt: 0x%lx", (long) stmt)); /* If the free_list is not empty, we'll wrongly free some externally @@ -2719,7 +2724,8 @@ void Prepared_statement::setup_set_params() Prepared_statement::~Prepared_statement() { DBUG_ENTER("Prepared_statement::~Prepared_statement"); - DBUG_PRINT("enter",("stmt: %p cursor: %p", this, cursor)); + DBUG_PRINT("enter",("stmt: 0x%lx cursor: 0x%lx", + (long) this, (long) cursor)); delete cursor; /* We have to call free on the items even if cleanup is called as some items, @@ -2740,7 +2746,7 @@ Query_arena::Type Prepared_statement::type() const void Prepared_statement::cleanup_stmt() { DBUG_ENTER("Prepared_statement::cleanup_stmt"); - DBUG_PRINT("enter",("stmt: %p", this)); + DBUG_PRINT("enter",("stmt: 0x%lx", (long) this)); /* The order is important */ lex->unit.cleanup(); diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 52489087b02..d4f6288c298 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -431,6 +431,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 @@ -805,7 +811,7 @@ int start_slave(THD* thd , MASTER_INFO* mi, bool net_report) sizeof(mi->rli.until_log_name)-1); } else - clear_until_condition(&mi->rli); + mi->rli.clear_until_condition(); if (mi->rli.until_condition != RELAY_LOG_INFO::UNTIL_NONE) { @@ -978,8 +984,8 @@ int reset_slave(THD *thd, MASTER_INFO* mi) Reset errors (the idea is that we forget about the old master). */ - clear_slave_error(&mi->rli); - clear_until_condition(&mi->rli); + mi->rli.clear_slave_error(); + mi->rli.clear_until_condition(); // close master_info_file, relay_log_info_file, set mi->inited=rli->inited=0 end_master_info(mi); @@ -1105,7 +1111,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); @@ -1222,7 +1228,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, @@ -1244,8 +1250,8 @@ bool change_master(THD* thd, MASTER_INFO* mi) pthread_mutex_lock(&mi->rli.data_lock); mi->rli.abort_pos_wait++; /* for MASTER_POS_WAIT() to abort */ /* Clear the errors, for a clean start */ - clear_slave_error(&mi->rli); - clear_until_condition(&mi->rli); + mi->rli.clear_slave_error(); + mi->rli.clear_until_condition(); /* If we don't write new coordinates to disk now, then old will remain in relay-log.info until START SLAVE is issued; but if mysqld is shutdown diff --git a/sql/sql_select.cc b/sql/sql_select.cc index d40d9f16bb5..9a4e93dfb94 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -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); @@ -505,11 +505,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 @@ -544,6 +545,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 @@ -1028,9 +1058,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; @@ -1276,14 +1304,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); @@ -1446,6 +1474,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; @@ -2547,6 +2576,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 */ @@ -2848,6 +2880,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)++; } @@ -2906,7 +2939,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) { @@ -2919,28 +2952,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; @@ -3114,6 +3175,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)); } } @@ -3236,7 +3298,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) { @@ -3248,12 +3310,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); } @@ -3328,7 +3391,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); @@ -3350,8 +3414,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 */ @@ -3361,7 +3426,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); } } @@ -6257,7 +6323,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) @@ -8723,6 +8789,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, @@ -8908,7 +8975,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; } @@ -9488,7 +9557,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, bool maybe_null=(*cur_group->item)->maybe_null; key_part_info->null_bit=0; key_part_info->field= field; - key_part_info->offset= field->offset(); + key_part_info->offset= field->offset(table->record[0]); key_part_info->length= (uint16) field->key_length(); key_part_info->type= (uint8) field->key_type(); key_part_info->key_type = @@ -9585,7 +9654,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, { key_part_info->null_bit=0; key_part_info->field= *reg_field; - key_part_info->offset= (*reg_field)->offset(); + key_part_info->offset= (*reg_field)->offset(table->record[0]); key_part_info->length= (uint16) (*reg_field)->pack_length(); key_part_info->type= (uint8) (*reg_field)->key_type(); key_part_info->key_type = @@ -10177,7 +10246,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; @@ -11009,6 +11078,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) { @@ -11138,7 +11214,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; @@ -11154,7 +11230,7 @@ join_read_always_key_or_null(JOIN_TAB *tab) } -static int +int join_read_next_same_or_null(READ_RECORD *info) { int error; @@ -12424,6 +12500,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; @@ -12557,8 +12634,9 @@ remove_duplicates(JOIN *join, TABLE *entry,List<Item> &fields, Item *having) DBUG_RETURN(0); } Field **first_field=entry->field+entry->s->fields - field_count; - offset= field_count ? - entry->field[entry->s->fields - field_count]->offset() : 0; + offset= (field_count ? + entry->field[entry->s->fields - field_count]-> + offset(entry->record[0]) : 0); reclength=entry->s->reclength-offset; free_io_cache(entry); // Safety @@ -13758,9 +13836,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 a66529a6459..323df568271 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; @@ -494,10 +496,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) { @@ -540,6 +543,7 @@ class store_key_field: public store_key table->write_set); copy_field.do_copy(©_field); dbug_tmp_restore_column_map(table->write_set, old_map); + null_key= to_field->is_null(); return err != 0 ? STORE_KEY_FATAL : STORE_KEY_OK; } const char *name() const { return field_name; } @@ -564,8 +568,8 @@ public: table->write_set); int res= item->save_in_field(to_field, 1); dbug_tmp_restore_column_map(table->write_set, old_map); + 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"; } }; @@ -595,6 +599,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 6cb2ed6a826..f582e9508a6 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1052,6 +1052,9 @@ int store_create_info(THD *thd, TABLE_LIST *table_list, String *packet, packet->append(STRING_WITH_LEN("CREATE TEMPORARY TABLE ")); else packet->append(STRING_WITH_LEN("CREATE TABLE ")); + if (create_info_arg && + (create_info_arg->options & HA_LEX_CREATE_IF_NOT_EXISTS)) + packet->append(STRING_WITH_LEN("IF NOT EXISTS ")); if (table_list->schema_table) alias= table_list->schema_table->table_name; else @@ -4990,7 +4993,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 6e4d3f2ed0a..29b53560067 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -844,6 +844,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 b1d417be2c2..a72b24ae9d0 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -30,6 +30,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 { diff --git a/sql/sql_table.cc b/sql/sql_table.cc index b4fdca61222..17643efe1ed 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -3743,7 +3743,7 @@ static void wait_while_table_is_used(THD *thd,TABLE *table, enum ha_extra_function function) { DBUG_ENTER("wait_while_table_is_used"); - DBUG_PRINT("enter", ("table: '%s' share: 0x%lx db_stat: %u version: %u", + DBUG_PRINT("enter", ("table: '%s' share: 0x%lx db_stat: %u version: %lu", table->s->table_name.str, (ulong) table->s, table->db_stat, table->s->version)); @@ -4168,7 +4168,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]; @@ -4631,7 +4630,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, my_error(ER_WRONG_TABLE_NAME, MYF(0), src_table); DBUG_RETURN(TRUE); } - if (!src_db || check_db_name(src_db)) + if (!src_db || check_db_name(&table_ident->db)) { my_error(ER_WRONG_DB_NAME, MYF(0), src_db ? src_db : "NULL"); DBUG_RETURN(-1); @@ -6789,8 +6788,6 @@ bool mysql_checksum_table(THD *thd, TABLE_LIST *tables, } else { - t->pos_in_table_list= table; - if (t->file->ha_table_flags() & HA_HAS_CHECKSUM && !(check_opt->flags & T_EXTEND)) protocol->store((ulonglong)t->file->checksum()); diff --git a/sql/sql_test.cc b/sql/sql_test.cc index c4c40ea63c8..219ca8260ed 100644 --- a/sql/sql_test.cc +++ b/sql/sql_test.cc @@ -248,14 +248,15 @@ print_plan(JOIN* join, uint idx, double record_count, double read_time, if (join->best_read == DBL_MAX) { fprintf(DBUG_FILE, - "%s; idx:%u, best: DBL_MAX, atime: %g, itime: %g, count: %g\n", - info, idx, current_read_time, read_time, record_count); + "%s; idx: %u best: DBL_MAX atime: %g itime: %g count: %g\n", + info, idx, current_read_time, read_time, record_count); } else { fprintf(DBUG_FILE, - "%s; idx:%u, best: %g, accumulated: %g, increment: %g, count: %g\n", - info, idx, join->best_read, current_read_time, read_time, record_count); + "%s; idx :%u best: %g accumulated: %g increment: %g count: %g\n", + info, idx, join->best_read, current_read_time, read_time, + record_count); } /* Print the tables in JOIN->positions */ diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index fb56b7ae3b0..e835de4dedd 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,30 +199,13 @@ 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); - - /* - Check that the user has TRIGGER privilege on the subject table. - */ - { - bool err_status; - TABLE_LIST **save_query_tables_own_last= thd->lex->query_tables_own_last; - thd->lex->query_tables_own_last= 0; - - err_status= check_table_access(thd, TRIGGER_ACL, tables, 0); - - thd->lex->query_tables_own_last= save_query_tables_own_last; - - if (err_status) - DBUG_RETURN(TRUE); - } - /* There is no DETERMINISTIC clause for triggers, so can't check it. But a trigger can in theory be used to do nasty things (if it supported - DROP for example) so we do the check for privileges. Triggers have the - same nature as functions regarding binlogging: their body is implicitely + 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 implicitly binlogged, so they share the same danger, so trust_function_creators applies to them too. */ @@ -228,24 +216,68 @@ 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)) - { - 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; + } + } + + /* + Check that the user has TRIGGER privilege on the subject table. + */ + { + bool err_status; + TABLE_LIST **save_query_tables_own_last= thd->lex->query_tables_own_last; + thd->lex->query_tables_own_last= 0; + + err_status= check_table_access(thd, TRIGGER_ACL, tables, 0); + + thd->lex->query_tables_own_last= save_query_tables_own_last; + + if (err_status) + 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; @@ -1141,13 +1173,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]; @@ -1158,6 +1194,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); path.length= build_table_filename(path_buff, FN_REFLEN-1, trig->m_db.str, trig->m_name.str, @@ -1166,30 +1203,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); } @@ -1612,7 +1664,7 @@ Handle_old_incorrect_sql_modes_hook::process_unknown_string(char *&unknown_key, char *end) { DBUG_ENTER("Handle_old_incorrect_sql_modes_hook::process_unknown_string"); - DBUG_PRINT("info", ("unknown key:%60s", unknown_key)); + DBUG_PRINT("info", ("unknown key: %60s", unknown_key)); if (unknown_key + INVALID_SQL_MODES_LENGTH + 1 < end && unknown_key[INVALID_SQL_MODES_LENGTH] == '=' && @@ -1654,7 +1706,7 @@ process_unknown_string(char *&unknown_key, gptr base, MEM_ROOT *mem_root, char *end) { DBUG_ENTER("Handle_old_incorrect_trigger_table_hook::process_unknown_string"); - DBUG_PRINT("info", ("unknown key:%60s", unknown_key)); + DBUG_PRINT("info", ("unknown key: %60s", unknown_key)); if (unknown_key + INVALID_TRIGGER_TABLE_LENGTH + 1 < end && unknown_key[INVALID_TRIGGER_TABLE_LENGTH] == '=' && diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 1d119b99df0..2575f17d256 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -691,7 +691,7 @@ int mysql_update(THD *thd, thd->row_count_func= (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated; send_ok(thd, (ulong) thd->row_count_func, id, 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; @@ -788,7 +788,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 5bf67af9271..98226c1651b 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -1695,24 +1695,23 @@ mysql_rename_view(THD *thd, const char *new_name, TABLE_LIST *view) { - LEX_STRING pathstr, file; + LEX_STRING pathstr; File_parser *parser; - char view_path[FN_REFLEN]; + char path_buff[FN_REFLEN]; bool error= TRUE; DBUG_ENTER("mysql_rename_view"); - strxnmov(view_path, FN_REFLEN-1, mysql_data_home, "/", view->db, "/", - view->table_name, reg_ext, NullS); - (void) unpack_filename(view_path, view_path); - - pathstr.str= (char *)view_path; - pathstr.length= strlen(view_path); + pathstr.str= (char *) path_buff; + pathstr.length= build_table_filename(path_buff, sizeof(path_buff) - 1, + view->db, view->table_name, + reg_ext, 0); if ((parser= sql_parse_prepare(&pathstr, thd->mem_root, 1)) && is_equal(&view_type, parser->type())) { TABLE_LIST view_def; - char dir_buff[FN_REFLEN], file_buff[FN_REFLEN]; + char dir_buff[FN_REFLEN]; + LEX_STRING dir, file; /* To be PS-friendly we should either to restore state of @@ -1735,18 +1734,18 @@ mysql_rename_view(THD *thd, view_def.revision - 1, num_view_backups)) goto err; - strxnmov(dir_buff, FN_REFLEN-1, mysql_data_home, "/", view->db, "/", - NullS); - (void) unpack_filename(dir_buff, dir_buff); + dir.str= dir_buff; + dir.length= build_table_filename(dir_buff, sizeof(dir_buff) - 1, + view->db, "", "", 0); - pathstr.str= (char*)dir_buff; - pathstr.length= strlen(dir_buff); + pathstr.str= path_buff; + pathstr.length= build_table_filename(path_buff, sizeof(path_buff) - 1, + view->db, new_name, reg_ext, 0); - file.str= file_buff; - file.length= (strxnmov(file_buff, FN_REFLEN, new_name, reg_ext, NullS) - - file_buff); + file.str= pathstr.str + dir.length; + file.length= pathstr.length - dir.length; - if (sql_create_definition_file(&pathstr, &file, view_file_type, + if (sql_create_definition_file(&dir, &file, view_file_type, (gptr)&view_def, view_parameters, num_view_backups)) { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 6a829171125..ec3094ca721 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -97,6 +97,17 @@ void turn_parser_debug_on() } #endif +static bool is_native_function(THD *thd, const LEX_STRING *name) +{ + if (find_native_function_builder(thd, *name)) + return true; + + if (is_lex_native_function(name)) + return true; + + return false; +} + %} %union { int num; @@ -735,7 +746,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); LEX_HOSTNAME ULONGLONG_NUM field_ident select_alias ident ident_or_text UNDERSCORE_CHARSET IDENT_sys TEXT_STRING_sys TEXT_STRING_literal NCHAR_STRING opt_component key_cache_name - sp_opt_label BIN_NUM label_ident TEXT_STRING_filesystem + sp_opt_label BIN_NUM label_ident TEXT_STRING_filesystem ident_or_empty %type <lex_str_ptr> opt_table_alias @@ -745,7 +756,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %type <simple_string> remember_name remember_end opt_ident opt_db text_or_password - opt_constraint constraint ident_or_empty + opt_constraint constraint %type <string> text_string opt_gconcat_separator @@ -797,8 +808,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 - expr_list_opt + ident_list ident_list_arg opt_expr_list %type <var_type> option_type opt_var_type opt_var_ident_type @@ -1229,7 +1239,8 @@ create: lex->create_info.options=$2 | $4; lex->create_info.db_type= lex->thd->variables.table_type; lex->create_info.default_table_charset= NULL; - lex->name= 0; + lex->name.str= 0; + lex->name.length= 0; lex->like_name= 0; } create2 @@ -1269,7 +1280,7 @@ create: { LEX *lex=Lex; lex->sql_command=SQLCOM_CREATE_DB; - lex->name=$4.str; + lex->name= $4; lex->create_info.options=$3; } | CREATE @@ -1504,7 +1515,7 @@ clear_privileges: sp_name: ident '.' ident { - if (!$1.str || check_db_name($1.str)) + if (!$1.str || check_db_name(&$1)) { my_error(ER_WRONG_DB_NAME, MYF(0), $1.str); YYABORT; @@ -1537,6 +1548,7 @@ sp_name: create_function_tail: RETURNS_SYM udf_type SONAME_SYM TEXT_STRING_sys { + THD *thd= YYTHD; LEX *lex=Lex; if (lex->definer != NULL) { @@ -1549,6 +1561,12 @@ create_function_tail: my_error(ER_WRONG_USAGE, MYF(0), "SONAME", "DEFINER"); YYABORT; } + if (is_native_function(thd, & lex->spname->m_name)) + { + my_error(ER_NATIVE_FCT_NAME_COLLISION, MYF(0), + lex->spname->m_name.str); + YYABORT; + } lex->sql_command = SQLCOM_CREATE_FUNCTION; lex->udf.name = lex->spname->m_name; lex->udf.returns=(Item_result) $2; @@ -1637,6 +1655,7 @@ create_function_tail: } sp_proc_stmt { + THD *thd= YYTHD; LEX *lex= Lex; sp_head *sp= lex->sphead; @@ -1644,15 +1663,50 @@ create_function_tail: YYABORT; lex->sql_command= SQLCOM_CREATE_SPFUNCTION; - sp->init_strings(YYTHD, lex); + sp->init_strings(thd, lex); if (!(sp->m_flags & sp_head::HAS_RETURN)) { my_error(ER_SP_NORETURN, MYF(0), sp->m_qname.str); YYABORT; } + if (is_native_function(thd, & sp->m_name)) + { + /* + This warning will be printed when + [1] A client query is parsed, + [2] A stored function is loaded by db_load_routine. + Printing the warning for [2] is intentional, to cover the + following scenario: + - A user define a SF 'foo' using MySQL 5.N + - An application uses select foo(), and works. + - MySQL 5.{N+1} defines a new native function 'foo', as + part of a new feature. + - MySQL 5.{N+1} documentation is updated, and should mention + that there is a potential incompatible change in case of + existing stored function named 'foo'. + - The user deploys 5.{N+1}. At this point, 'select foo()' + means something different, and the user code is most likely + broken (it's only safe if the code is 'select db.foo()'). + With a warning printed when the SF is loaded (which has to occur + before the call), the warning will provide a hint explaining + the root cause of a later failure of 'select foo()'. + With no warning printed, the user code will fail with no + apparent reason. + Printing a warning each time db_load_routine is executed for + an ambiguous function is annoying, since that can happen a lot, + but in practice should not happen unless there *are* name + collisions. + If a collision exists, it should not be silenced but fixed. + */ + push_warning_printf(thd, + MYSQL_ERROR::WARN_LEVEL_NOTE, + ER_NATIVE_FCT_NAME_COLLISION, + ER(ER_NATIVE_FCT_NAME_COLLISION), + sp->m_name.str); + } /* Restore flag if it was cleared above */ - YYTHD->client_capabilities |= $<ulong_num>2; - sp->restore_thd_mem_root(YYTHD); + thd->client_capabilities |= $<ulong_num>2; + sp->restore_thd_mem_root(thd); } ; @@ -3094,7 +3148,7 @@ size_number: uint text_shift_number= 0; longlong prefix_number; char *start_ptr= $1.str; - uint str_len= strlen(start_ptr); + uint str_len= $1.length; char *end_ptr= start_ptr + str_len; int error; prefix_number= my_strtoll10(start_ptr, &end_ptr, &error); @@ -4618,7 +4672,8 @@ alter: { THD *thd= YYTHD; LEX *lex= thd->lex; - lex->name= 0; + lex->name.str= 0; + lex->name.length= 0; lex->sql_command= SQLCOM_ALTER_TABLE; lex->duplicates= DUP_ERROR; if (!lex->select_lex.add_table_to_list(thd, $4, NULL, @@ -4628,7 +4683,6 @@ alter: lex->key_list.empty(); lex->col_list.empty(); lex->select_lex.init_order(); - lex->name= 0; lex->like_name= 0; lex->select_lex.db= ((TABLE_LIST*) lex->select_lex.table_list.first)->db; @@ -4653,7 +4707,8 @@ alter: THD *thd= Lex->thd; lex->sql_command=SQLCOM_ALTER_DB; lex->name= $3; - if (lex->name == NULL && thd->copy_db_to(&lex->name, NULL)) + if (lex->name.str == NULL && + thd->copy_db_to(&lex->name.str, &lex->name.length)) YYABORT; } | ALTER PROCEDURE sp_name @@ -4803,8 +4858,8 @@ opt_ev_sql_stmt: /* empty*/ { $$= 0;} ident_or_empty: - /* empty */ { $$= 0; } - | ident { $$= $1.str; }; + /* empty */ { $$.str= 0; $$.length= 0; } + | ident { $$= $1; }; alter_commands: | DISCARD TABLESPACE { Lex->alter_info.tablespace_op= DISCARD_TABLESPACE; } @@ -5082,19 +5137,20 @@ alter_list_item: { LEX *lex=Lex; THD *thd= lex->thd; + uint dummy; lex->select_lex.db=$3->db.str; if (lex->select_lex.db == NULL && - thd->copy_db_to(&lex->select_lex.db, NULL)) + thd->copy_db_to(&lex->select_lex.db, &dummy)) { YYABORT; } if (check_table_name($3->table.str,$3->table.length) || - $3->db.str && check_db_name($3->db.str)) + $3->db.str && check_db_name(&$3->db)) { my_error(ER_WRONG_TABLE_NAME, MYF(0), $3->table.str); YYABORT; } - lex->name= $3->table.str; + lex->name= $3->table; lex->alter_info.flags|= ALTER_RENAME; } | CONVERT_SYM TO_SYM charset charset_name_or_default opt_collate @@ -6361,11 +6417,11 @@ function_call_generic: { #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)); @@ -6373,10 +6429,10 @@ function_call_generic: } } /* Temporary placing the result of find_udf in $3 */ - $<udf>$= udf; + lex->current_select->udf_list.push_front(udf); #endif } - expr_list_opt ')' + udf_expr_list ')' { THD *thd= YYTHD; LEX *lex= Lex; @@ -6401,9 +6457,10 @@ function_call_generic: { #ifdef HAVE_DLOPEN /* Retrieving the result of find_udf */ - udf_func *udf= $<udf>3; + udf_func *udf; + LEX *lex= Lex; - if (udf) + if (NULL != (udf= lex->current_select->udf_list.pop())) { if (udf->type == UDFTYPE_AGGREGATE) { @@ -6426,7 +6483,7 @@ function_call_generic: YYABORT; } } - | ident '.' ident '(' udf_expr_list ')' + | ident '.' ident '(' opt_expr_list ')' { THD *thd= YYTHD; Create_qfunc *builder; @@ -6499,12 +6556,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; } @@ -6665,12 +6739,10 @@ cast_type: | DECIMAL_SYM float_options { $$=ITEM_CAST_DECIMAL; Lex->charset= NULL; } ; -expr_list_opt: - /* empty */ - { $$ = NULL; } - | expr_list - { $$ = $1;} - ; +opt_expr_list: + /* empty */ { $$= NULL; } + | expr_list { $$= $1;} + ; expr_list: { Select->expr_list.push_front(new List<Item>); } @@ -7627,7 +7699,7 @@ drop: LEX *lex=Lex; lex->sql_command= SQLCOM_DROP_DB; lex->drop_if_exists=$3; - lex->name=$4.str; + lex->name= $4; } | DROP FUNCTION_SYM if_exists sp_name { @@ -7669,11 +7741,12 @@ drop: Lex->spname= $4; Lex->sql_command = SQLCOM_DROP_EVENT; } - | 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; } | DROP TABLESPACE tablespace_name opt_ts_engine opt_ts_wait { @@ -7684,7 +7757,7 @@ drop: { LEX *lex= Lex; lex->alter_tablespace_info->ts_cmd_type= DROP_LOGFILE_GROUP; - } + } ; table_list: @@ -8274,7 +8347,7 @@ show_param: { Lex->sql_command=SQLCOM_SHOW_CREATE_DB; Lex->create_info.options=$3; - Lex->name=$4.str; + Lex->name= $4; } | CREATE TABLE_SYM table_ident { @@ -8640,6 +8713,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; } @@ -10279,7 +10354,8 @@ grant_ident: { LEX *lex= Lex; THD *thd= lex->thd; - if (thd->copy_db_to(&lex->current_select->db, NULL)) + uint dummy; + if (thd->copy_db_to(&lex->current_select->db, &dummy)) YYABORT; if (lex->grant == GLOBAL_ACLS) lex->grant = DB_ACLS & ~GRANT_ACL; diff --git a/sql/strfunc.cc b/sql/strfunc.cc index ef769a5b16e..2d2530eb876 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 7f80b95c954..926b44dedbc 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -30,7 +30,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, File file); static void fix_type_pointers(const char ***array, TYPELIB *point_to_type, uint types, char **names); -static uint find_field(Field **fields, uint start, uint length); +static uint find_field(Field **fields, byte *record, uint start, uint length); /* Get column name from column hash */ @@ -1069,6 +1069,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, Field *field; if (new_field_pack_flag <= 1) key_part->fieldnr= (uint16) find_field(share->field, + share->default_values, (uint) key_part->offset, (uint) key_part->length); if (!key_part->fieldnr) @@ -1232,24 +1233,19 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, if (share->found_next_number_field) { - /* - We must have a table object for find_ref_key to calculate field offset - */ - TABLE tmp_table; - tmp_table.record[0]= share->default_values; - reg_field= *share->found_next_number_field; - reg_field->table= &tmp_table; if ((int) (share->next_number_index= (uint) - find_ref_key(share->key_info, share->keys, reg_field, + find_ref_key(share->key_info, share->keys, + share->default_values, reg_field, &share->next_number_key_offset)) < 0) { + /* Wrong field definition */ + DBUG_ASSERT(0); reg_field->unireg_check= Field::NONE; /* purecov: inspected */ share->found_next_number_field= 0; } else reg_field->flags |= AUTO_INCREMENT_FLAG; - reg_field->table= 0; } if (share->blob_fields) @@ -1343,7 +1339,7 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias, Field **field_ptr; DBUG_ENTER("open_table_from_share"); DBUG_PRINT("enter",("name: '%s.%s' form: 0x%lx", share->db.str, - share->table_name.str, outparam)); + share->table_name.str, (long) outparam)); error= 1; bzero((char*) outparam, sizeof(*outparam)); @@ -1969,7 +1965,7 @@ TYPELIB *typelib(MEM_ROOT *mem_root, List<String> &strings) # field number +1 */ -static uint find_field(Field **fields, uint start, uint length) +static uint find_field(Field **fields, byte *record, uint start, uint length) { Field **field; uint i, pos; @@ -1977,7 +1973,7 @@ static uint find_field(Field **fields, uint start, uint length) pos= 0; for (field= fields, i=1 ; *field ; i++,field++) { - if ((*field)->offset() == start) + if ((*field)->offset(record) == start) { if ((*field)->key_length() == length) return (i); @@ -2258,7 +2254,7 @@ char *get_field(MEM_ROOT *mem, Field *field) SYNPOSIS check_db_name() - name Name of database + org_name Name of database and length NOTES If lower_case_table_names is set then database is converted to lower case @@ -2268,35 +2264,35 @@ char *get_field(MEM_ROOT *mem, Field *field) 1 error */ -bool check_db_name(char *name) +bool check_db_name(LEX_STRING *org_name) { - char *start= name; - /* Used to catch empty names and names with end space */ - bool last_char_is_space= TRUE; + char *name= org_name->str; + + if (!org_name->length || org_name->length > NAME_LEN) + return 1; if (lower_case_table_names && name != any_db) my_casedn_str(files_charset_info, name); - while (*name) - { #if defined(USE_MB) && defined(USE_MB_IDENT) - last_char_is_space= my_isspace(system_charset_info, *name); - if (use_mb(system_charset_info)) + if (use_mb(system_charset_info)) + { + bool last_char_is_space= TRUE; + char *end= name + org_name->length; + while (name < end) { - int len=my_ismbchar(system_charset_info, name, - name+system_charset_info->mbmaxlen); - if (len) - { - name += len; - continue; - } + int len; + last_char_is_space= my_isspace(system_charset_info, *name); + len= my_ismbchar(system_charset_info, name, end); + if (!len) + len= 1; + name+= len; } -#else - last_char_is_space= *name==' '; -#endif - name++; + return last_char_is_space; } - return last_char_is_space || (uint) (name - start) > NAME_LEN; + else +#endif + return org_name->str[org_name->length - 1] != ' '; /* purecov: inspected */ } @@ -2405,8 +2401,8 @@ table_check_intact(TABLE *table, const uint table_f_count, my_bool error= FALSE; my_bool fields_diff_count; DBUG_ENTER("table_check_intact"); - DBUG_PRINT("info",("table=%s expected_count=%d",table->alias, table_f_count)); - DBUG_PRINT("info",("last_create_time=%d", *last_create_time)); + DBUG_PRINT("info",("table: %s expected_count: %d last_create_time: %ld", + table->alias, table_f_count, *last_create_time)); if ((fields_diff_count= (table->s->fields != table_f_count)) || (*last_create_time != table->file->stats.create_time)) @@ -4096,6 +4092,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.cc.rej b/sql/table.cc.rej new file mode 100644 index 00000000000..fd728ba9965 --- /dev/null +++ b/sql/table.cc.rej @@ -0,0 +1,17 @@ +*************** +*** 2246,2252 **** + + bool check_db_name(char *name) + { +! char *start=name; + /* Used to catch empty names and names with end space */ + bool last_char_is_space= TRUE; + +--- 2257,2263 ---- + + bool check_db_name(char *name) + { +! char *start= name; + /* Used to catch empty names and names with end space */ + bool last_char_is_space= TRUE; + diff --git a/sql/table.h b/sql/table.h index 434fb5a4d11..55f889f42b9 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; @@ -74,6 +75,9 @@ enum release_type { RELEASE_NORMAL, RELEASE_WAIT_FOR_DROP }; 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 */ @@ -859,6 +863,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 3d9f278b3f7..6acf17520d9 100644 --- a/sql/tztime.cc +++ b/sql/tztime.cc @@ -961,13 +961,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) @@ -1744,8 +1743,8 @@ 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, + ("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]); @@ -2058,8 +2057,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/unireg.cc b/sql/unireg.cc index a20c59fd796..4514f969913 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -469,16 +469,16 @@ static uint pack_keys(uchar *keybuff, uint key_count, KEY *keyinfo, int2store(pos+6, key->block_size); 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/storage/archive/ha_archive.cc b/storage/archive/ha_archive.cc index b2b07981bdb..d181be138ad 100644 --- a/storage/archive/ha_archive.cc +++ b/storage/archive/ha_archive.cc @@ -114,8 +114,6 @@ data - The data is stored in a "row +blobs" format. */ -/* If the archive storage engine has been inited */ -static bool archive_inited= FALSE; /* Variables for archive share methods */ pthread_mutex_t archive_mutex; static HASH archive_open_tables; @@ -142,7 +140,6 @@ static HASH archive_open_tables; static handler *archive_create_handler(handlerton *hton, TABLE_SHARE *table, MEM_ROOT *mem_root); -int archive_db_end(handlerton *hton, ha_panic_function type); /* Number of rows that will force a bulk insert. @@ -183,13 +180,11 @@ int archive_db_init(void *p) { DBUG_ENTER("archive_db_init"); handlerton *archive_hton; - if (archive_inited) - DBUG_RETURN(FALSE); + archive_hton= (handlerton *)p; archive_hton->state=SHOW_OPTION_YES; archive_hton->db_type=DB_TYPE_ARCHIVE_DB; archive_hton->create=archive_create_handler; - archive_hton->panic=archive_db_end; archive_hton->flags=HTON_NO_FLAGS; if (pthread_mutex_init(&archive_mutex, MY_MUTEX_INIT_FAST)) @@ -201,7 +196,6 @@ int archive_db_init(void *p) } else { - archive_inited= TRUE; DBUG_RETURN(FALSE); } error: @@ -221,21 +215,13 @@ error: int archive_db_done(void *p) { - if (archive_inited) - { - hash_free(&archive_open_tables); - VOID(pthread_mutex_destroy(&archive_mutex)); - } - archive_inited= 0; + hash_free(&archive_open_tables); + VOID(pthread_mutex_destroy(&archive_mutex)); + return 0; } -int archive_db_end(handlerton *hton, ha_panic_function type) -{ - return archive_db_done(NULL); -} - ha_archive::ha_archive(handlerton *hton, TABLE_SHARE *table_arg) :handler(hton, table_arg), delayed_insert(0), bulk_insert(0) { @@ -329,10 +315,12 @@ 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 %llu", *rows)); - DBUG_PRINT("ha_archive::read_meta_file", ("Checkpoint %llu", check_point)); - DBUG_PRINT("ha_archive::read_meta_file", ("Auto-Increment %llu", *auto_increment)); - DBUG_PRINT("ha_archive::read_meta_file", ("Forced Flushes %llu", *forced_flushes)); + 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", ("Auto-Increment %lu", + (ulong) *auto_increment)); + DBUG_PRINT("ha_archive::read_meta_file", ("Forced Flushes %lu", + (ulong) *forced_flushes)); DBUG_PRINT("ha_archive::read_meta_file", ("Real Path %s", real_path)); DBUG_PRINT("ha_archive::read_meta_file", ("Dirty %d", (int)(*ptr))); @@ -385,12 +373,12 @@ int ha_archive::write_meta_file(File meta_file, ha_rows rows, (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", ("Auto Increment %llu", - auto_increment)); - DBUG_PRINT("ha_archive::write_meta_file", ("Forced Flushes %llu", - forced_flushes)); + 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", ("Auto Increment %lu", + (ulong) auto_increment)); + DBUG_PRINT("ha_archive::write_meta_file", ("Forced Flushes %lu", + (ulong) forced_flushes)); DBUG_PRINT("ha_archive::write_meta_file", ("Real path %s", real_path)); DBUG_PRINT("ha_archive::write_meta_file", ("Dirty %d", (uint)dirty)); @@ -773,8 +761,8 @@ int ha_archive::real_write_row(byte *buf, azio_stream *writer) DBUG_ENTER("ha_archive::real_write_row"); written= azwrite(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; @@ -817,10 +805,11 @@ int ha_archive::write_row(byte *buf) int rc; byte *read_buf= NULL; ulonglong temp_auto; + byte *record= table->record[0]; DBUG_ENTER("ha_archive::write_row"); if (share->crashed) - DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE); + DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE); ha_statistic_increment(&SSV::ha_write_count); if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) @@ -883,7 +872,8 @@ int ha_archive::write_row(byte *buf) while (!(get_row(&archive, read_buf))) { - if (!memcmp(read_buf + mfield->offset(), table->next_number_field->ptr, + if (!memcmp(read_buf + mfield->offset(record), + table->next_number_field->ptr, mfield->max_length())) { rc= HA_ERR_FOUND_DUPP_KEY; @@ -906,28 +896,6 @@ int ha_archive::write_row(byte *buf) if (init_archive_writer()) DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE); - /* - Varchar structures are constant in size but are not cleaned up request - to request. The following sets all unused space to null to improve - compression. - */ - for (Field **field=table->field ; *field ; field++) - { - DBUG_PRINT("archive",("Pack is %d\n", (*field)->pack_length())); - DBUG_PRINT("archive",("MyPack is %d\n", (*field)->data_length((char*) buf + (*field)->offset()))); - if ((*field)->real_type() == MYSQL_TYPE_VARCHAR) - { - uint actual_length= (*field)->data_length((char*) buf + (*field)->offset()); - uint offset= (*field)->offset() + actual_length + - (actual_length > 255 ? 2 : 1); - DBUG_PRINT("archive",("Offset is %d -> %d\n", actual_length, offset)); - /* - if ((*field)->pack_length() + (*field)->offset() != offset) - bzero(buf + offset, (size_t)((*field)->pack_length() + (actual_length > 255 ? 2 : 1) - (*field)->data_length)); - */ - } - } - share->rows_recorded++; rc= real_write_row(buf, &(share->archive_write)); error: @@ -1054,7 +1022,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)); stats.records= 0; /* @@ -1096,7 +1064,7 @@ int ha_archive::get_row(azio_stream *file_to_read, byte *buf) DBUG_ENTER("ha_archive::get_row"); read= azread(file_to_read, buf, table->s->reclength); - DBUG_PRINT("ha_archive::get_row", ("Read %d bytes expected %d", read, + DBUG_PRINT("ha_archive::get_row", ("Read %d bytes expected %lu", (int) read, table->s->reclength)); if (read == Z_STREAM_ERROR) @@ -1306,7 +1274,8 @@ int ha_archive::optimize(THD* thd, HA_CHECK_OPT* check_opt) { Field *field= table->found_next_number_field; ulonglong auto_value= - (ulonglong) field->val_int((char*)(buf + field->offset())); + (ulonglong) field->val_int((char*)(buf + + field->offset(table->record[0]))); if (share->auto_increment_value < auto_value) stats.auto_increment_value= share->auto_increment_value= auto_value; @@ -1314,7 +1283,7 @@ 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/storage/csv/ha_tina.cc b/storage/csv/ha_tina.cc index f7e5aa9d50c..7051bd41cb1 100644 --- a/storage/csv/ha_tina.cc +++ b/storage/csv/ha_tina.cc @@ -73,11 +73,9 @@ static int write_meta_file(File meta_file, ha_rows rows, bool dirty); /* Stuff for shares */ pthread_mutex_t tina_mutex; static HASH tina_open_tables; -static int tina_init= 0; static handler *tina_create_handler(handlerton *hton, TABLE_SHARE *table, MEM_ROOT *mem_root); -int tina_end(handlerton *hton, ha_panic_function type); off_t Transparent_file::read_next() @@ -155,35 +153,23 @@ static int tina_init_func(void *p) { handlerton *tina_hton; - if (!tina_init) - { - tina_hton= (handlerton *)p; - tina_init++; - VOID(pthread_mutex_init(&tina_mutex,MY_MUTEX_INIT_FAST)); - (void) hash_init(&tina_open_tables,system_charset_info,32,0,0, - (hash_get_key) tina_get_key,0,0); - tina_hton->state= SHOW_OPTION_YES; - tina_hton->db_type= DB_TYPE_CSV_DB; - tina_hton->create= tina_create_handler; - tina_hton->panic= tina_end; - tina_hton->flags= (HTON_CAN_RECREATE | HTON_SUPPORT_LOG_TABLES | - HTON_NO_PARTITION); - } + tina_hton= (handlerton *)p; + VOID(pthread_mutex_init(&tina_mutex,MY_MUTEX_INIT_FAST)); + (void) hash_init(&tina_open_tables,system_charset_info,32,0,0, + (hash_get_key) tina_get_key,0,0); + tina_hton->state= SHOW_OPTION_YES; + tina_hton->db_type= DB_TYPE_CSV_DB; + tina_hton->create= tina_create_handler; + tina_hton->flags= (HTON_CAN_RECREATE | HTON_SUPPORT_LOG_TABLES | + HTON_NO_PARTITION); return 0; } static int tina_done_func(void *p) { - if (tina_init) - { - if (tina_open_tables.records) - { - return 1; - } - hash_free(&tina_open_tables); - pthread_mutex_destroy(&tina_mutex); - tina_init--; - } + hash_free(&tina_open_tables); + pthread_mutex_destroy(&tina_mutex); + return 0; } @@ -199,9 +185,6 @@ static TINA_SHARE *get_share(const char *table_name, TABLE *table) char *tmp_name; uint length; - if (!tina_init) - tina_init_func(NULL); - pthread_mutex_lock(&tina_mutex); length=(uint) strlen(table_name); @@ -455,11 +438,6 @@ static int free_share(TINA_SHARE *share) DBUG_RETURN(result_code); } -int tina_end(handlerton *hton, ha_panic_function type) -{ - return tina_done_func(NULL); -} - /* This function finds the end of a line and returns the length diff --git a/storage/example/ha_example.cc b/storage/example/ha_example.cc index 6d199d4391f..1ef6da9f300 100644 --- a/storage/example/ha_example.cc +++ b/storage/example/ha_example.cc @@ -77,8 +77,6 @@ static handler *example_create_handler(handlerton *hton, TABLE_SHARE *table, MEM_ROOT *mem_root); static int example_init_func(); -static bool example_init_func_for_handlerton(); -static int example_panic(enum ha_panic_function flag); handlerton *example_hton; @@ -101,19 +99,17 @@ static byte* example_get_key(EXAMPLE_SHARE *share,uint *length, static int example_init_func(void *p) { DBUG_ENTER("example_init_func"); - if (!example_init) - { - example_hton= (handlerton *)p; - example_init= 1; - VOID(pthread_mutex_init(&example_mutex,MY_MUTEX_INIT_FAST)); - (void) hash_init(&example_open_tables,system_charset_info,32,0,0, - (hash_get_key) example_get_key,0,0); - - example_hton->state= SHOW_OPTION_YES; - example_hton->db_type= DB_TYPE_EXAMPLE_DB; - example_hton->create= example_create_handler; - example_hton->flags= HTON_CAN_RECREATE; - } + + example_hton= (handlerton *)p; + VOID(pthread_mutex_init(&example_mutex,MY_MUTEX_INIT_FAST)); + (void) hash_init(&example_open_tables,system_charset_info,32,0,0, + (hash_get_key) example_get_key,0,0); + + example_hton->state= SHOW_OPTION_YES; + example_hton->db_type= DB_TYPE_EXAMPLE_DB; + example_hton->create= example_create_handler; + example_hton->flags= HTON_CAN_RECREATE; + DBUG_RETURN(0); } @@ -122,14 +118,11 @@ static int example_done_func(void *p) int error= 0; DBUG_ENTER("example_done_func"); - if (example_init) - { - example_init= 0; - if (example_open_tables.records) - error= 1; - hash_free(&example_open_tables); - pthread_mutex_destroy(&example_mutex); - } + if (example_open_tables.records) + error= 1; + hash_free(&example_open_tables); + pthread_mutex_destroy(&example_mutex); + DBUG_RETURN(0); } @@ -354,20 +347,6 @@ int ha_example::index_read(byte * buf, const byte * key, /* - Positions an index cursor to the index specified in key. Fetches the - row if any. This is only used to read whole keys. -*/ -int ha_example::index_read_idx(byte * buf, uint index, const byte * key, - uint key_len __attribute__((unused)), - enum ha_rkey_function find_flag - __attribute__((unused))) -{ - DBUG_ENTER("ha_example::index_read_idx"); - DBUG_RETURN(HA_ERR_WRONG_COMMAND); -} - - -/* Used to read forward through the index. */ int ha_example::index_next(byte * buf) @@ -550,19 +529,6 @@ int ha_example::extra(enum ha_extra_function operation) /* - Deprecated and likely to be removed in the future. Storage engines normally - just make a call like: - ha_example::extra(HA_EXTRA_RESET); - to handle it. -*/ -int ha_example::reset(void) -{ - DBUG_ENTER("ha_example::reset"); - DBUG_RETURN(0); -} - - -/* Used to delete all rows in a table. Both for cases of truncate and for cases where the optimizer realizes that all rows will be removed as a result of a SQL statement. diff --git a/storage/example/ha_example.h b/storage/example/ha_example.h index f98377ee157..4e2de9be3d3 100644 --- a/storage/example/ha_example.h +++ b/storage/example/ha_example.h @@ -117,8 +117,6 @@ public: int delete_row(const byte * buf); int index_read(byte * buf, const byte * key, uint key_len, enum ha_rkey_function find_flag); - int index_read_idx(byte * buf, uint idx, const byte * key, - uint key_len, enum ha_rkey_function find_flag); int index_next(byte * buf); int index_prev(byte * buf); int index_first(byte * buf); @@ -139,7 +137,6 @@ public: int info(uint); //required int extra(enum ha_extra_function operation); - int reset(void); int external_lock(THD *thd, int lock_type); //required int delete_all_rows(void); ha_rows records_in_range(uint inx, key_range *min_key, diff --git a/storage/example/plug.in b/storage/example/plug.in index bf5bb49b429..ba35b1ea117 100644 --- a/storage/example/plug.in +++ b/storage/example/plug.in @@ -1,4 +1,3 @@ MYSQL_STORAGE_ENGINE(example,, [Example Storage Engine], [Skeleton for Storage Engines for developers], [max,max-no-ndb]) -MYSQL_PLUGIN_STATIC(example, [libexample.a]) MYSQL_PLUGIN_DYNAMIC(example, [ha_example.la]) diff --git a/storage/federated/ha_federated.cc b/storage/federated/ha_federated.cc index 51c9f4c192e..693544dde36 100644 --- a/storage/federated/ha_federated.cc +++ b/storage/federated/ha_federated.cc @@ -350,7 +350,6 @@ /* Variables for federated share methods */ static HASH federated_open_tables; // To track open tables pthread_mutex_t federated_mutex; // To init the hash -static int federated_init= FALSE; // Checking the state of hash /* Variables used when chopping off trailing characters */ static const uint sizeof_trailing_comma= sizeof(", ") - 1; @@ -365,7 +364,6 @@ static handler *federated_create_handler(handlerton *hton, static int federated_commit(handlerton *hton, THD *thd, bool all); static int federated_rollback(handlerton *hton, THD *thd, bool all); static int federated_db_init(void); -static int federated_db_end(handlerton *hton, ha_panic_function type); /* Federated storage engine handlerton */ @@ -408,7 +406,6 @@ int federated_db_init(void *p) federated_hton->commit= federated_commit; federated_hton->rollback= federated_rollback; federated_hton->create= federated_create_handler; - federated_hton->panic= federated_db_end; federated_hton->flags= HTON_ALTER_NOT_SUPPORTED; if (pthread_mutex_init(&federated_mutex, MY_MUTEX_INIT_FAST)) @@ -416,13 +413,11 @@ int federated_db_init(void *p) if (!hash_init(&federated_open_tables, &my_charset_bin, 32, 0, 0, (hash_get_key) federated_get_key, 0, 0)) { - federated_init= TRUE; DBUG_RETURN(FALSE); } VOID(pthread_mutex_destroy(&federated_mutex)); error: - have_federated_db= SHOW_OPTION_DISABLED; // If we couldn't use handler DBUG_RETURN(TRUE); } @@ -437,14 +432,11 @@ error: FALSE OK */ -int federated_db_end(handlerton *hton, ha_panic_function type) +int federated_done(void *p) { - if (federated_init) - { - hash_free(&federated_open_tables); - VOID(pthread_mutex_destroy(&federated_mutex)); - } - federated_init= 0; + hash_free(&federated_open_tables); + VOID(pthread_mutex_destroy(&federated_mutex)); + return 0; } @@ -560,8 +552,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; } @@ -627,7 +619,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 @@ -1534,7 +1526,7 @@ int ha_federated::close(void) 0 otherwise */ -inline uint field_in_record_is_null(TABLE *table, +static inline uint field_in_record_is_null(TABLE *table, Field *field, char *record) { @@ -1750,7 +1742,7 @@ void ha_federated::update_auto_increment(void) thd->first_successful_insert_id_in_cur_stmt= mysql->last_used_con->insert_id; - DBUG_PRINT("info",("last_insert_id %d", stats.auto_increment_value)); + DBUG_PRINT("info",("last_insert_id: %ld", (long) stats.auto_increment_value)); DBUG_VOID_RETURN; } @@ -1856,6 +1848,7 @@ int ha_federated::update_row(const byte *old_data, byte *new_data) String where_string(where_buffer, sizeof(where_buffer), &my_charset_bin); + byte *record= table->record[0]; DBUG_ENTER("ha_federated::update_row"); /* set string lengths to 0 to avoid misc chars in string @@ -1914,7 +1907,7 @@ int ha_federated::update_row(const byte *old_data, byte *new_data) bool needs_quote= (*field)->str_needs_quotes(); where_string.append(STRING_WITH_LEN(" = ")); (*field)->val_str(&field_value, - (char*) (old_data + (*field)->offset())); + (char*) (old_data + (*field)->offset(record))); if (needs_quote) where_string.append('\''); field_value.print(&where_string); @@ -2022,8 +2015,8 @@ int ha_federated::delete_row(const byte *buf) stats.deleted+= (ha_rows)mysql->affected_rows; stats.records-= (ha_rows)mysql->affected_rows; DBUG_PRINT("info", - ("rows deleted %d rows deleted for all time %d", - int(mysql->affected_rows), stats.deleted)); + ("rows deleted %ld rows deleted for all time %ld", + (long) mysql->affected_rows, (long) stats.deleted)); DBUG_RETURN(0); } @@ -2156,7 +2149,7 @@ error: int ha_federated::index_init(uint keynr, bool sorted) { DBUG_ENTER("ha_federated::index_init"); - DBUG_PRINT("info", ("table: '%s' key: %u", table->s->table_name, keynr)); + DBUG_PRINT("info", ("table: '%s' key: %u", table->s->table_name.str, keynr)); active_index= keynr; DBUG_RETURN(0); } @@ -2897,7 +2890,7 @@ mysql_declare_plugin(federated) "Federated MySQL storage engine", PLUGIN_LICENSE_GPL, federated_db_init, /* Plugin Init */ - NULL, /* Plugin Deinit */ + federated_done, /* Plugin Deinit */ 0x0100 /* 1.0 */, NULL, /* status variables */ NULL, /* system variables */ diff --git a/storage/heap/_check.c b/storage/heap/_check.c index cc832f8ed5b..c861fdb582f 100644 --- a/storage/heap/_check.c +++ b/storage/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/storage/heap/hp_delete.c b/storage/heap/hp_delete.c index f18c5e7054c..2ef57624e77 100644 --- a/storage/heap/hp_delete.c +++ b/storage/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/storage/heap/hp_hash.c b/storage/heap/hp_hash.c index 77f3cf6d80b..6a537906929 100644 --- a/storage/heap/hp_hash.c +++ b/storage/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/storage/heap/hp_open.c b/storage/heap/hp_open.c index fd937229b0d..f50478c8b3d 100644 --- a/storage/heap/hp_open.c +++ b/storage/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/storage/heap/hp_rkey.c b/storage/heap/hp_rkey.c index f5f22a877a1..f02d44cc456 100644 --- a/storage/heap/hp_rkey.c +++ b/storage/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/storage/heap/hp_rrnd.c b/storage/heap/hp_rrnd.c index 4daa3a06377..2f8556484a4 100644 --- a/storage/heap/hp_rrnd.c +++ b/storage/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/storage/heap/hp_write.c b/storage/heap/hp_write.c index bc94e3bfae4..c83ae65c966 100644 --- a/storage/heap/hp_write.c +++ b/storage/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/storage/innobase/btr/btr0btr.c b/storage/innobase/btr/btr0btr.c index 7a8e5626e25..50a349e78d6 100644 --- a/storage/innobase/btr/btr0btr.c +++ b/storage/innobase/btr/btr0btr.c @@ -1949,7 +1949,12 @@ btr_lift_page_up( mtr_t* mtr) /* in: mtr */ { page_t* father_page; + page_t* iter_page; + page_t* pages[BTR_MAX_LEVELS]; ulint page_level; + ulint root_page_no; + ulint ancestors; + ulint i; ut_ad(btr_page_get_prev(page, mtr) == FIL_NULL); ut_ad(btr_page_get_next(page, mtr) == FIL_NULL); @@ -1959,6 +1964,30 @@ btr_lift_page_up( btr_page_get_father_node_ptr(index, page, mtr)); page_level = btr_page_get_level(page, mtr); + root_page_no = dict_index_get_page(index); + + ancestors = 1; + pages[0] = father_page; + + /* Store all ancestor pages so we can reset their levels later on. + We have to do all the searches on the tree now because later on, + after we've replaced the first level, the tree is in an inconsistent + state and can not be searched. */ + iter_page = father_page; + for (;;) { + if (buf_block_get_page_no(buf_block_align(iter_page)) + == root_page_no) { + + break; + } + + ut_a(ancestors < BTR_MAX_LEVELS); + + iter_page = buf_frame_align( + btr_page_get_father_node_ptr(index, iter_page, mtr)); + + pages[ancestors++] = iter_page; + } btr_search_drop_page_hash_index(page); @@ -1970,7 +1999,15 @@ btr_lift_page_up( index, mtr); lock_update_copy_and_discard(father_page, page); - btr_page_set_level(father_page, page_level, mtr); + /* Go upward to root page, decreasing levels by one. */ + for (i = 0; i < ancestors; i++) { + iter_page = pages[i]; + + ut_ad(btr_page_get_level(iter_page, mtr) == (page_level + 1)); + + btr_page_set_level(iter_page, page_level, mtr); + page_level++; + } /* Free the file page */ btr_page_free(index, page, mtr); diff --git a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c index 222acc015a6..99e365d6129 100644 --- a/storage/innobase/buf/buf0buf.c +++ b/storage/innobase/buf/buf0buf.c @@ -221,6 +221,9 @@ in the free list to the frames. 5) When we have AWE enabled, we disable adaptive hash indexes. */ +/* Value in microseconds */ +static const int WAIT_FOR_READ = 20000; + buf_pool_t* buf_pool = NULL; /* The buffer buf_pool of the database */ #ifdef UNIV_DEBUG @@ -539,6 +542,8 @@ buf_block_init( block->n_pointers = 0; + mutex_create(&block->mutex, SYNC_BUF_BLOCK); + rw_lock_create(&block->lock, SYNC_LEVEL_VARYING); ut_ad(rw_lock_validate(&(block->lock))); @@ -813,8 +818,15 @@ buf_awe_map_page_to_frame( bck = UT_LIST_GET_LAST(buf_pool->awe_LRU_free_mapped); while (bck) { - if (bck->state == BUF_BLOCK_FILE_PAGE - && (bck->buf_fix_count != 0 || bck->io_fix != 0)) { + ibool skip; + + mutex_enter(&bck->mutex); + + skip = (bck->state == BUF_BLOCK_FILE_PAGE + && (bck->buf_fix_count != 0 || bck->io_fix != 0)); + + if (skip) { + mutex_exit(&bck->mutex); /* We have to skip this */ bck = UT_LIST_GET_PREV(awe_LRU_free_mapped, bck); @@ -848,6 +860,8 @@ buf_awe_map_page_to_frame( buf_pool->n_pages_awe_remapped++; + mutex_exit(&bck->mutex); + return; } } @@ -886,13 +900,22 @@ buf_block_make_young( /*=================*/ buf_block_t* block) /* in: block to make younger */ { +#ifdef UNIV_SYNC_DEBUG + ut_ad(!mutex_own(&(buf_pool->mutex))); +#endif /* UNIV_SYNC_DEBUG */ + + /* Note that we read freed_page_clock's without holding any mutex: + this is allowed since the result is used only in heuristics */ + if (buf_pool->freed_page_clock >= block->freed_page_clock - + 1 + (buf_pool->curr_size / 1024)) { + + 1 + (buf_pool->curr_size / 4)) { + mutex_enter(&buf_pool->mutex); /* There has been freeing activity in the LRU list: best to move to the head of the LRU list */ buf_LRU_make_block_young(block); + mutex_exit(&buf_pool->mutex); } } @@ -927,12 +950,16 @@ buf_block_free( /*===========*/ buf_block_t* block) /* in, own: block to be freed */ { - ut_a(block->state != BUF_BLOCK_FILE_PAGE); - mutex_enter(&(buf_pool->mutex)); + mutex_enter(&block->mutex); + + ut_a(block->state != BUF_BLOCK_FILE_PAGE); + buf_LRU_block_free_non_file_page(block); + mutex_exit(&block->mutex); + mutex_exit(&(buf_pool->mutex)); } @@ -1151,9 +1178,8 @@ buf_page_get_gen( #endif buf_pool->n_page_gets++; loop: - mutex_enter_fast(&(buf_pool->mutex)); - block = NULL; + mutex_enter_fast(&(buf_pool->mutex)); if (guess) { block = buf_block_align(guess); @@ -1191,6 +1217,8 @@ loop: goto loop; } + mutex_enter(&block->mutex); + ut_a(block->state == BUF_BLOCK_FILE_PAGE); must_read = FALSE; @@ -1200,9 +1228,9 @@ loop: must_read = TRUE; if (mode == BUF_GET_IF_IN_POOL) { - /* The page is only being read to buffer */ - mutex_exit(&(buf_pool->mutex)); + mutex_exit(&buf_pool->mutex); + mutex_exit(&block->mutex); return(NULL); } @@ -1226,7 +1254,7 @@ loop: #else buf_block_buf_fix_inc(block); #endif - buf_block_make_young(block); + mutex_exit(&buf_pool->mutex); /* Check if this is the first access to the page */ @@ -1234,10 +1262,13 @@ loop: block->accessed = TRUE; + mutex_exit(&block->mutex); + + buf_block_make_young(block); + #ifdef UNIV_DEBUG_FILE_ACCESSES ut_a(block->file_page_was_freed == FALSE); #endif - mutex_exit(&(buf_pool->mutex)); #ifdef UNIV_DEBUG buf_dbg_counter++; @@ -1262,13 +1293,14 @@ loop: } if (!success) { - mutex_enter(&(buf_pool->mutex)); + mutex_enter(&block->mutex); block->buf_fix_count--; + + mutex_exit(&block->mutex); #ifdef UNIV_SYNC_DEBUG rw_lock_s_unlock(&(block->debug_latch)); #endif - mutex_exit(&(buf_pool->mutex)); return(NULL); } @@ -1279,18 +1311,16 @@ loop: completes */ for (;;) { - mutex_enter(&(buf_pool->mutex)); + mutex_enter(&block->mutex); if (block->io_fix == BUF_IO_READ) { - mutex_exit(&(buf_pool->mutex)); - - /* Sleep 20 milliseconds */ + mutex_exit(&block->mutex); - os_thread_sleep(20000); + os_thread_sleep(WAIT_FOR_READ); } else { - mutex_exit(&(buf_pool->mutex)); + mutex_exit(&block->mutex); break; } @@ -1349,14 +1379,14 @@ buf_page_optimistic_get_func( ut_ad(mtr && block); ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH)); - mutex_enter(&(buf_pool->mutex)); - /* If AWE is used, block may have a different frame now, e.g., NULL */ + mutex_enter(&block->mutex); + if (UNIV_UNLIKELY(block->state != BUF_BLOCK_FILE_PAGE) || UNIV_UNLIKELY(block->frame != guess)) { -exit_func: - mutex_exit(&(buf_pool->mutex)); + + mutex_exit(&block->mutex); return(FALSE); } @@ -1366,15 +1396,14 @@ exit_func: #else buf_block_buf_fix_inc(block); #endif - buf_block_make_young(block); - - /* Check if this is the first access to the page */ - accessed = block->accessed; - block->accessed = TRUE; - mutex_exit(&(buf_pool->mutex)); + mutex_exit(&block->mutex); + + buf_block_make_young(block); + + /* Check if this is the first access to the page */ ut_ad(!ibuf_inside() || ibuf_page(block->space, block->offset)); @@ -1389,13 +1418,16 @@ exit_func: } if (UNIV_UNLIKELY(!success)) { - mutex_enter(&(buf_pool->mutex)); + mutex_enter(&block->mutex); block->buf_fix_count--; + + mutex_exit(&block->mutex); + #ifdef UNIV_SYNC_DEBUG rw_lock_s_unlock(&(block->debug_latch)); #endif - goto exit_func; + return(FALSE); } if (UNIV_UNLIKELY(!UT_DULINT_EQ(modify_clock, block->modify_clock))) { @@ -1408,13 +1440,16 @@ exit_func: rw_lock_x_unlock(&(block->lock)); } - mutex_enter(&(buf_pool->mutex)); + mutex_enter(&block->mutex); block->buf_fix_count--; + + mutex_exit(&block->mutex); + #ifdef UNIV_SYNC_DEBUG rw_lock_s_unlock(&(block->debug_latch)); #endif - goto exit_func; + return(FALSE); } mtr_memo_push(mtr, block, fix_type); @@ -1471,10 +1506,10 @@ buf_page_get_known_nowait( ut_ad(mtr); ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH)); - mutex_enter(&(buf_pool->mutex)); - block = buf_block_align(guess); + mutex_enter(&block->mutex); + if (block->state == BUF_BLOCK_REMOVE_HASH) { /* Another thread is just freeing the block from the LRU list of the buffer pool: do not try to access this page; this @@ -1483,7 +1518,7 @@ buf_page_get_known_nowait( we have already removed it from the page address hash table of the buffer pool. */ - mutex_exit(&(buf_pool->mutex)); + mutex_exit(&block->mutex); return(FALSE); } @@ -1495,12 +1530,12 @@ buf_page_get_known_nowait( #else buf_block_buf_fix_inc(block); #endif + mutex_exit(&block->mutex); + if (mode == BUF_MAKE_YOUNG) { buf_block_make_young(block); } - mutex_exit(&(buf_pool->mutex)); - ut_ad(!ibuf_inside() || (mode == BUF_KEEP_OLD)); if (rw_latch == RW_S_LATCH) { @@ -1514,13 +1549,15 @@ buf_page_get_known_nowait( } if (!success) { - mutex_enter(&(buf_pool->mutex)); + mutex_enter(&block->mutex); block->buf_fix_count--; + + mutex_exit(&block->mutex); + #ifdef UNIV_SYNC_DEBUG rw_lock_s_unlock(&(block->debug_latch)); #endif - mutex_exit(&(buf_pool->mutex)); return(FALSE); } @@ -1568,7 +1605,6 @@ buf_page_init_for_backup_restore( block->offset = offset; block->lock_hash_val = 0; - block->lock_mutex = NULL; block->freed_page_clock = 0; @@ -1601,6 +1637,7 @@ buf_page_init( { #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(buf_pool->mutex))); + ut_ad(mutex_own(&(block->mutex))); #endif /* UNIV_SYNC_DEBUG */ ut_a(block->state != BUF_BLOCK_FILE_PAGE); @@ -1615,7 +1652,6 @@ buf_page_init( block->index = NULL; block->lock_hash_val = lock_rec_hash(space, offset); - block->lock_mutex = NULL; /* Insert into the hash table of file pages */ @@ -1709,6 +1745,7 @@ buf_page_init_for_read( ut_a(block); mutex_enter(&(buf_pool->mutex)); + mutex_enter(&block->mutex); if (fil_tablespace_deleted_or_being_deleted_in_mem( space, tablespace_version)) { @@ -1722,7 +1759,9 @@ buf_page_init_for_read( deleted or is being deleted, or the page is already in buf_pool, return */ + mutex_exit(&block->mutex); mutex_exit(&(buf_pool->mutex)); + buf_block_free(block); if (mode == BUF_READ_IBUF_PAGES_ONLY) { @@ -1742,6 +1781,7 @@ buf_page_init_for_read( buf_LRU_add_block(block, TRUE); /* TRUE == to old blocks */ block->io_fix = BUF_IO_READ; + buf_pool->n_pend_reads++; /* We set a pass-type x-lock on the frame because then the same @@ -1753,6 +1793,7 @@ buf_page_init_for_read( rw_lock_x_lock_gen(&(block->lock), BUF_IO_READ); + mutex_exit(&block->mutex); mutex_exit(&(buf_pool->mutex)); if (mode == BUF_READ_IBUF_PAGES_ONLY) { @@ -1817,6 +1858,8 @@ buf_page_create( block = free_block; + mutex_enter(&block->mutex); + buf_page_init(space, offset, block); /* The block must be put to the LRU list */ @@ -1827,13 +1870,15 @@ buf_page_create( #else buf_block_buf_fix_inc(block); #endif + buf_pool->n_pages_created++; + + mutex_exit(&(buf_pool->mutex)); + mtr_memo_push(mtr, block, MTR_MEMO_BUF_FIX); block->accessed = TRUE; - buf_pool->n_pages_created++; - - mutex_exit(&(buf_pool->mutex)); + mutex_exit(&block->mutex); /* Delete possible entries for the page from the insert buffer: such can exist if the page belonged to an index which was dropped */ @@ -1885,6 +1930,12 @@ buf_page_io_complete( ut_a(block->state == BUF_BLOCK_FILE_PAGE); + /* We do not need protect block->io_fix here by block->mutex to read + it because this is the only function where we can change the value + from BUF_IO_READ or BUF_IO_WRITE to some other value, and our code + ensures that this is the only thread that handles the i/o for this + block. */ + io_type = block->io_fix; if (io_type == BUF_IO_READ) { @@ -1986,11 +2037,12 @@ buf_page_io_complete( } } + mutex_enter(&(buf_pool->mutex)); + mutex_enter(&block->mutex); + #ifdef UNIV_IBUF_DEBUG ut_a(ibuf_count_get(block->space, block->offset) == 0); #endif - mutex_enter(&(buf_pool->mutex)); - /* Because this thread which does the unlocking is not the same that did the locking, we use a pass value != 0 in unlock, which simply removes the newest lock debug record, without checking the thread @@ -2033,6 +2085,7 @@ buf_page_io_complete( #endif /* UNIV_DEBUG */ } + mutex_exit(&block->mutex); mutex_exit(&(buf_pool->mutex)); #ifdef UNIV_DEBUG @@ -2095,6 +2148,8 @@ buf_validate(void) block = buf_pool_get_nth_block(buf_pool, i); + mutex_enter(&block->mutex); + if (block->state == BUF_BLOCK_FILE_PAGE) { ut_a(buf_page_hash_get(block->space, @@ -2139,6 +2194,8 @@ buf_validate(void) } else if (block->state == BUF_BLOCK_NOT_USED) { n_free++; } + + mutex_exit(&block->mutex); } if (n_lru + n_free > buf_pool->curr_size) { @@ -2286,9 +2343,14 @@ buf_get_latched_pages_number(void) block = buf_pool_get_nth_block(buf_pool, i); - if (((block->buf_fix_count != 0) || (block->io_fix != 0)) - && block->magic_n == BUF_BLOCK_MAGIC_N) { - fixed_pages_number++; + if (block->magic_n == BUF_BLOCK_MAGIC_N) { + mutex_enter(&block->mutex); + + if (block->buf_fix_count != 0 || block->io_fix != 0) { + fixed_pages_number++; + } + + mutex_exit(&block->mutex); } } @@ -2458,6 +2520,8 @@ buf_all_freed(void) block = buf_pool_get_nth_block(buf_pool, i); + mutex_enter(&block->mutex); + if (block->state == BUF_BLOCK_FILE_PAGE) { if (!buf_flush_ready_for_replace(block)) { @@ -2469,6 +2533,8 @@ buf_all_freed(void) ut_error; } } + + mutex_exit(&block->mutex); } mutex_exit(&(buf_pool->mutex)); diff --git a/storage/innobase/buf/buf0flu.c b/storage/innobase/buf/buf0flu.c index 8ef8c3b9358..49b81196a64 100644 --- a/storage/innobase/buf/buf0flu.c +++ b/storage/innobase/buf/buf0flu.c @@ -113,6 +113,7 @@ buf_flush_ready_for_replace( { #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(buf_pool->mutex))); + ut_ad(mutex_own(&block->mutex)); #endif /* UNIV_SYNC_DEBUG */ if (block->state != BUF_BLOCK_FILE_PAGE) { ut_print_timestamp(stderr); @@ -148,6 +149,7 @@ buf_flush_ready_for_flush( { #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(buf_pool->mutex))); + ut_ad(mutex_own(&(block->mutex))); #endif /* UNIV_SYNC_DEBUG */ ut_a(block->state == BUF_BLOCK_FILE_PAGE); @@ -559,8 +561,15 @@ buf_flush_try_page( ut_a(!block || block->state == BUF_BLOCK_FILE_PAGE); + if (!block) { + mutex_exit(&(buf_pool->mutex)); + return(0); + } + + mutex_enter(&block->mutex); + if (flush_type == BUF_FLUSH_LIST - && block && buf_flush_ready_for_flush(block, flush_type)) { + && buf_flush_ready_for_flush(block, flush_type)) { block->io_fix = BUF_IO_WRITE; @@ -598,6 +607,7 @@ buf_flush_try_page( locked = TRUE; } + mutex_exit(&block->mutex); mutex_exit(&(buf_pool->mutex)); if (!locked) { @@ -618,7 +628,7 @@ buf_flush_try_page( return(1); - } else if (flush_type == BUF_FLUSH_LRU && block + } else if (flush_type == BUF_FLUSH_LRU && buf_flush_ready_for_flush(block, flush_type)) { /* VERY IMPORTANT: @@ -659,13 +669,14 @@ buf_flush_try_page( buf_pool mutex: this ensures that the latch is acquired immediately. */ + mutex_exit(&block->mutex); mutex_exit(&(buf_pool->mutex)); buf_flush_write_block_low(block); return(1); - } else if (flush_type == BUF_FLUSH_SINGLE_PAGE && block + } else if (flush_type == BUF_FLUSH_SINGLE_PAGE && buf_flush_ready_for_flush(block, flush_type)) { block->io_fix = BUF_IO_WRITE; @@ -692,6 +703,7 @@ buf_flush_try_page( (buf_pool->n_flush[flush_type])++; + mutex_exit(&block->mutex); mutex_exit(&(buf_pool->mutex)); rw_lock_s_lock_gen(&(block->lock), BUF_IO_WRITE); @@ -709,11 +721,12 @@ buf_flush_try_page( buf_flush_write_block_low(block); return(1); - } else { - mutex_exit(&(buf_pool->mutex)); - - return(0); } + + mutex_exit(&block->mutex); + mutex_exit(&(buf_pool->mutex)); + + return(0); } /*************************************************************** @@ -758,34 +771,48 @@ buf_flush_try_neighbors( block = buf_page_hash_get(space, i); ut_a(!block || block->state == BUF_BLOCK_FILE_PAGE); - if (block && flush_type == BUF_FLUSH_LRU && i != offset - && !block->old) { + if (!block) { + + continue; + + } else if (flush_type == BUF_FLUSH_LRU && i != offset + && !block->old) { /* We avoid flushing 'non-old' blocks in an LRU flush, because the flushed blocks are soon freed */ continue; - } + } else { - if (block && buf_flush_ready_for_flush(block, flush_type) - && (i == offset || block->buf_fix_count == 0)) { - /* We only try to flush those neighbors != offset - where the buf fix count is zero, as we then know that - we probably can latch the page without a semaphore - wait. Semaphore waits are expensive because we must - flush the doublewrite buffer before we start - waiting. */ + mutex_enter(&block->mutex); - mutex_exit(&(buf_pool->mutex)); + if (buf_flush_ready_for_flush(block, flush_type) + && (i == offset || block->buf_fix_count == 0)) { + /* We only try to flush those + neighbors != offset where the buf fix count is + zero, as we then know that we probably can + latch the page without a semaphore wait. + Semaphore waits are expensive because we must + flush the doublewrite buffer before we start + waiting. */ - /* Note: as we release the buf_pool mutex above, in - buf_flush_try_page we cannot be sure the page is still - in a flushable state: therefore we check it again - inside that function. */ + mutex_exit(&block->mutex); - count += buf_flush_try_page(space, i, flush_type); + mutex_exit(&(buf_pool->mutex)); - mutex_enter(&(buf_pool->mutex)); + /* Note: as we release the buf_pool mutex + above, in buf_flush_try_page we cannot be sure + the page is still in a flushable state: + therefore we check it again inside that + function. */ + + count += buf_flush_try_page(space, i, + flush_type); + + mutex_enter(&(buf_pool->mutex)); + } else { + mutex_exit(&block->mutex); + } } } @@ -879,12 +906,15 @@ buf_flush_batch( while ((block != NULL) && !found) { ut_a(block->state == BUF_BLOCK_FILE_PAGE); + mutex_enter(&block->mutex); + if (buf_flush_ready_for_flush(block, flush_type)) { found = TRUE; space = block->space; offset = block->offset; + mutex_exit(&block->mutex); mutex_exit(&(buf_pool->mutex)); old_page_count = page_count; @@ -901,10 +931,14 @@ buf_flush_batch( } else if (flush_type == BUF_FLUSH_LRU) { + mutex_exit(&block->mutex); + block = UT_LIST_GET_PREV(LRU, block); } else { ut_ad(flush_type == BUF_FLUSH_LIST); + mutex_exit(&block->mutex); + block = UT_LIST_GET_PREV(flush_list, block); } } @@ -986,10 +1020,14 @@ buf_flush_LRU_recommendation(void) + BUF_FLUSH_EXTRA_MARGIN) && (distance < BUF_LRU_FREE_SEARCH_LEN)) { + mutex_enter(&block->mutex); + if (buf_flush_ready_for_replace(block)) { n_replaceable++; } + mutex_exit(&block->mutex); + distance++; block = UT_LIST_GET_PREV(LRU, block); diff --git a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c index 4ebe94c40ec..377552ece6c 100644 --- a/storage/innobase/buf/buf0lru.c +++ b/storage/innobase/buf/buf0lru.c @@ -86,6 +86,11 @@ scan_again: block = UT_LIST_GET_LAST(buf_pool->LRU); while (block != NULL) { + buf_block_t* prev_block; + + mutex_enter(&block->mutex); + prev_block = UT_LIST_GET_PREV(LRU, block); + ut_a(block->state == BUF_BLOCK_FILE_PAGE); if (block->space == id @@ -112,6 +117,8 @@ scan_again: if (block->is_hashed) { page_no = block->offset; + mutex_exit(&block->mutex); + mutex_exit(&(buf_pool->mutex)); /* Note that the following call will acquire @@ -138,7 +145,8 @@ scan_again: buf_LRU_block_free_hashed_page(block); } next_page: - block = UT_LIST_GET_PREV(LRU, block); + mutex_exit(&block->mutex); + block = prev_block; } mutex_exit(&(buf_pool->mutex)); @@ -211,6 +219,9 @@ buf_LRU_search_and_free_block( while (block != NULL) { ut_a(block->in_LRU_list); + + mutex_enter(&block->mutex); + if (buf_flush_ready_for_replace(block)) { #ifdef UNIV_DEBUG @@ -226,6 +237,7 @@ buf_LRU_search_and_free_block( buf_LRU_block_remove_hashed_page(block); mutex_exit(&(buf_pool->mutex)); + mutex_exit(&block->mutex); /* Remove possible adaptive hash index built on the page; in the case of AWE the block may not have a @@ -234,15 +246,21 @@ buf_LRU_search_and_free_block( if (block->frame) { btr_search_drop_page_hash_index(block->frame); } - mutex_enter(&(buf_pool->mutex)); ut_a(block->buf_fix_count == 0); + mutex_enter(&(buf_pool->mutex)); + mutex_enter(&block->mutex); + buf_LRU_block_free_hashed_page(block); freed = TRUE; + mutex_exit(&block->mutex); break; } + + mutex_exit(&block->mutex); + block = UT_LIST_GET_PREV(LRU, block); distance++; @@ -428,8 +446,12 @@ loop: } } + mutex_enter(&block->mutex); + block->state = BUF_BLOCK_READY_FOR_USE; + mutex_exit(&block->mutex); + mutex_exit(&(buf_pool->mutex)); if (started_monitor) { @@ -838,6 +860,7 @@ buf_LRU_block_free_non_file_page( { #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(buf_pool->mutex))); + ut_ad(mutex_own(&block->mutex)); #endif /* UNIV_SYNC_DEBUG */ ut_ad(block); @@ -877,6 +900,7 @@ buf_LRU_block_remove_hashed_page( { #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(buf_pool->mutex))); + ut_ad(mutex_own(&block->mutex)); #endif /* UNIV_SYNC_DEBUG */ ut_ad(block); @@ -939,6 +963,7 @@ buf_LRU_block_free_hashed_page( { #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(buf_pool->mutex))); + ut_ad(mutex_own(&block->mutex)); #endif /* UNIV_SYNC_DEBUG */ ut_a(block->state == BUF_BLOCK_REMOVE_HASH); diff --git a/storage/innobase/dict/dict0crea.c b/storage/innobase/dict/dict0crea.c index 75422b929b1..33e328d1e0b 100644 --- a/storage/innobase/dict/dict0crea.c +++ b/storage/innobase/dict/dict0crea.c @@ -700,8 +700,10 @@ dict_truncate_index_tree( /* out: new root page number, or FIL_NULL on failure */ dict_table_t* table, /* in: the table the index belongs to */ - rec_t* rec, /* in: record in the clustered index of - SYS_INDEXES table */ + btr_pcur_t* pcur, /* in/out: persistent cursor pointing to + record in the clustered index of + SYS_INDEXES table. The cursor may be + repositioned in this call. */ mtr_t* mtr) /* in: mtr having the latch on the record page. The mtr may be committed and restarted in this call. */ @@ -710,6 +712,7 @@ dict_truncate_index_tree( ulint space; ulint type; dulint index_id; + rec_t* rec; byte* ptr; ulint len; ulint comp; @@ -720,6 +723,7 @@ dict_truncate_index_tree( #endif /* UNIV_SYNC_DEBUG */ ut_a(!dict_table_is_comp(dict_sys->sys_indexes)); + rec = btr_pcur_get_rec(pcur); ptr = rec_get_nth_field_old(rec, DICT_SYS_INDEXES_PAGE_NO_FIELD, &len); ut_ad(len == 4); @@ -785,10 +789,11 @@ dict_truncate_index_tree( /* We will need to commit the mini-transaction in order to avoid deadlocks in the btr_create() call, because otherwise we would be freeing and allocating pages in the same mini-transaction. */ + btr_pcur_store_position(pcur, mtr); mtr_commit(mtr); - /* mtr_commit() will invalidate rec. */ - rec = NULL; + mtr_start(mtr); + btr_pcur_restore_position(BTR_MODIFY_LEAF, pcur, mtr); /* Find the index corresponding to this SYS_INDEXES record. */ for (index = UT_LIST_GET_FIRST(table->indexes); diff --git a/storage/innobase/fil/fil0fil.c b/storage/innobase/fil/fil0fil.c index 1aff3739103..883fbd09ee4 100644 --- a/storage/innobase/fil/fil0fil.c +++ b/storage/innobase/fil/fil0fil.c @@ -4416,29 +4416,47 @@ fil_flush_file_spaces( { fil_system_t* system = fil_system; fil_space_t* space; + ulint* space_ids; + ulint n_space_ids; + ulint i; mutex_enter(&(system->mutex)); - space = UT_LIST_GET_FIRST(system->unflushed_spaces); + n_space_ids = UT_LIST_GET_LEN(system->unflushed_spaces); + if (n_space_ids == 0) { - while (space) { - if (space->purpose == purpose && !space->is_being_deleted) { + mutex_exit(&system->mutex); + return; + } - space->n_pending_flushes++; /* prevent dropping of - the space while we are - flushing */ - mutex_exit(&(system->mutex)); + /* Assemble a list of space ids to flush. Previously, we + traversed system->unflushed_spaces and called UT_LIST_GET_NEXT() + on a space that was just removed from the list by fil_flush(). + Thus, the space could be dropped and the memory overwritten. */ + space_ids = mem_alloc(n_space_ids * sizeof *space_ids); - fil_flush(space->id); + n_space_ids = 0; - mutex_enter(&(system->mutex)); + for (space = UT_LIST_GET_FIRST(system->unflushed_spaces); + space; + space = UT_LIST_GET_NEXT(unflushed_spaces, space)) { - space->n_pending_flushes--; + if (space->purpose == purpose && !space->is_being_deleted) { + + space_ids[n_space_ids++] = space->id; } - space = UT_LIST_GET_NEXT(unflushed_spaces, space); } - mutex_exit(&(system->mutex)); + mutex_exit(&system->mutex); + + /* Flush the spaces. It will not hurt to call fil_flush() on + a non-existing space id. */ + for (i = 0; i < n_space_ids; i++) { + + fil_flush(space_ids[i]); + } + + mem_free(space_ids); } /********************************************************************** diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index ec86b9a2e68..4ca767f811d 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -2510,7 +2510,7 @@ get_field_offset( /****************************************************************** Checks if a field in a record is SQL NULL. Uses the record format information in table to track the null bit in record. */ -inline +static inline uint field_in_record_is_null( /*====================*/ @@ -4445,7 +4445,7 @@ ha_innobase::rnd_pos( } if (error) { - DBUG_PRINT("error", ("Got error: %ld", error)); + DBUG_PRINT("error", ("Got error: %d", error)); DBUG_RETURN(error); } @@ -4455,7 +4455,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); @@ -6630,7 +6630,7 @@ innodb_mutex_show_status( mutex->count_spin_rounds, mutex->count_os_wait, mutex->count_os_yield, - (ulong) mutex->lspent_time/1000); + (ulong) (mutex->lspent_time/1000)); if (stat_print(thd, innobase_hton_name, hton_name_len, buf1, buf1len, @@ -6660,7 +6660,7 @@ innodb_mutex_show_status( rw_lock_count, rw_lock_count_spin_loop, rw_lock_count_spin_rounds, rw_lock_count_os_wait, rw_lock_count_os_yield, - (ulong) rw_lock_wait_time/1000); + (ulong) (rw_lock_wait_time/1000)); if (stat_print(thd, innobase_hton_name, hton_name_len, STRING_WITH_LEN("rw_lock_mutexes"), buf2, buf2len)) { diff --git a/storage/innobase/include/btr0btr.h b/storage/innobase/include/btr0btr.h index 664607a26aa..1573de7e818 100644 --- a/storage/innobase/include/btr0btr.h +++ b/storage/innobase/include/btr0btr.h @@ -23,7 +23,17 @@ special big record storage structure */ #define BTR_PAGE_MAX_REC_SIZE (UNIV_PAGE_SIZE / 2 - 200) -/* Latching modes for the search function (in btr0cur.*) */ +/* Maximum depth of a B-tree in InnoDB. Note that this isn't a maximum as +such; none of the tree operations avoid producing trees bigger than this. It +is instead a "max depth that other code must work with", useful for e.g. +fixed-size arrays that must store some information about each level in a +tree. In other words: if a B-tree with bigger depth than this is +encountered, it is not acceptable for it to lead to mysterious memory +corruption, but it is acceptable for the program to die with a clear assert +failure. */ +#define BTR_MAX_LEVELS 100 + +/* Latching modes for btr_cur_search_to_nth_level(). */ #define BTR_SEARCH_LEAF RW_S_LATCH #define BTR_MODIFY_LEAF RW_X_LATCH #define BTR_NO_LATCHES RW_NO_LATCH diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h index 2fc6bf4bcb9..979c28f64ed 100644 --- a/storage/innobase/include/buf0buf.h +++ b/storage/innobase/include/buf0buf.h @@ -461,8 +461,8 @@ Gets the mutex number protecting the page record lock hash chain in the lock table. */ UNIV_INLINE mutex_t* -buf_frame_get_lock_mutex( -/*=====================*/ +buf_frame_get_mutex( +/*================*/ /* out: mutex */ byte* ptr); /* in: pointer to within a buffer frame */ /*********************************************************************** @@ -713,7 +713,10 @@ struct buf_block_struct{ ulint magic_n; /* magic number to check */ ulint state; /* state of the control block: - BUF_BLOCK_NOT_USED, ... */ + BUF_BLOCK_NOT_USED, ...; changing + this is only allowed when a thread + has BOTH the buffer pool mutex AND + block->mutex locked */ byte* frame; /* pointer to buffer frame which is of size UNIV_PAGE_SIZE, and aligned to an address divisible by @@ -731,8 +734,12 @@ struct buf_block_struct{ ulint offset; /* page number within the space */ ulint lock_hash_val; /* hashed value of the page address in the record lock hash table */ - mutex_t* lock_mutex; /* mutex protecting the chain in the - record lock hash table */ + mutex_t mutex; /* mutex protecting this block: + state (also protected by the buffer + pool mutex), io_fix, buf_fix_count, + and accessed; we introduce this new + mutex in InnoDB-5.1 to relieve + contention on the buffer pool mutex */ rw_lock_t lock; /* read-write lock of the buffer frame */ buf_block_t* hash; /* node used in chaining to the page @@ -788,20 +795,27 @@ struct buf_block_struct{ in heuristic algorithms, because of the possibility of a wrap-around! */ ulint freed_page_clock;/* the value of freed_page_clock - buffer pool when this block was - last time put to the head of the - LRU list */ + of the buffer pool when this block was + the last time put to the head of the + LRU list; a thread is allowed to + read this for heuristic purposes + without holding any mutex or latch */ ibool old; /* TRUE if the block is in the old blocks in the LRU list */ ibool accessed; /* TRUE if the page has been accessed while in the buffer pool: read-ahead may read in pages which have not been - accessed yet */ + accessed yet; this is protected by + block->mutex; a thread is allowed to + read this for heuristic purposes + without holding any mutex or latch */ ulint buf_fix_count; /* count of how manyfold this block - is currently bufferfixed */ + is currently bufferfixed; this is + protected by block->mutex */ ulint io_fix; /* if a read is pending to the frame, io_fix is BUF_IO_READ, in the case - of a write BUF_IO_WRITE, otherwise 0 */ + of a write BUF_IO_WRITE, otherwise 0; + this is protected by block->mutex */ /* 4. Optimistic search field */ dulint modify_clock; /* this clock is incremented every @@ -959,7 +973,9 @@ struct buf_pool_struct{ number of buffer blocks removed from the end of the LRU list; NOTE that this counter may wrap around at 4 - billion! */ + billion! A thread is allowed to + read this for heuristic purposes + without holding any mutex or latch */ ulint LRU_flush_ended;/* when an LRU flush ends for a page, this is incremented by one; this is set to zero when a buffer block is diff --git a/storage/innobase/include/buf0buf.ic b/storage/innobase/include/buf0buf.ic index 015de862705..43895295734 100644 --- a/storage/innobase/include/buf0buf.ic +++ b/storage/innobase/include/buf0buf.ic @@ -337,8 +337,8 @@ Gets the mutex number protecting the page record lock hash chain in the lock table. */ UNIV_INLINE mutex_t* -buf_frame_get_lock_mutex( -/*=====================*/ +buf_frame_get_mutex( +/*================*/ /* out: mutex */ byte* ptr) /* in: pointer to within a buffer frame */ { @@ -346,7 +346,7 @@ buf_frame_get_lock_mutex( block = buf_block_align(ptr); - return(block->lock_mutex); + return(&block->mutex); } /************************************************************************* @@ -519,6 +519,7 @@ buf_block_buf_fix_inc_debug( ret = rw_lock_s_lock_func_nowait(&(block->debug_latch), file, line); ut_ad(ret == TRUE); + ut_ad(mutex_own(&block->mutex)); #endif block->buf_fix_count++; } @@ -531,6 +532,9 @@ buf_block_buf_fix_inc( /*==================*/ buf_block_t* block) /* in: block to bufferfix */ { +#ifdef UNIV_SYNC_DEBUG + ut_ad(mutex_own(&block->mutex)); +#endif block->buf_fix_count++; } #endif /* UNIV_SYNC_DEBUG */ @@ -625,23 +629,24 @@ buf_page_release( ut_ad(block); - mutex_enter_fast(&(buf_pool->mutex)); - ut_a(block->state == BUF_BLOCK_FILE_PAGE); ut_a(block->buf_fix_count > 0); if (rw_latch == RW_X_LATCH && mtr->modifications) { - + mutex_enter(&buf_pool->mutex); buf_flush_note_modification(block, mtr); + mutex_exit(&buf_pool->mutex); } + mutex_enter(&block->mutex); + #ifdef UNIV_SYNC_DEBUG rw_lock_s_unlock(&(block->debug_latch)); #endif buf_fix_count = block->buf_fix_count; block->buf_fix_count = buf_fix_count - 1; - mutex_exit(&(buf_pool->mutex)); + mutex_exit(&block->mutex); if (rw_latch == RW_S_LATCH) { rw_lock_s_unlock(&(block->lock)); diff --git a/storage/innobase/include/dict0crea.h b/storage/innobase/include/dict0crea.h index bd0890dbfa7..f0f30481abe 100644 --- a/storage/innobase/include/dict0crea.h +++ b/storage/innobase/include/dict0crea.h @@ -62,8 +62,10 @@ dict_truncate_index_tree( /* out: new root page number, or FIL_NULL on failure */ dict_table_t* table, /* in: the table the index belongs to */ - rec_t* rec, /* in: record in the clustered index of - SYS_INDEXES table */ + btr_pcur_t* pcur, /* in/out: persistent cursor pointing to + record in the clustered index of + SYS_INDEXES table. The cursor may be + repositioned in this call. */ mtr_t* mtr); /* in: mtr having the latch on the record page. The mtr may be committed and restarted in this call. */ diff --git a/storage/innobase/include/ut0lst.h b/storage/innobase/include/ut0lst.h index 819f2e770ba..d19885d6edc 100644 --- a/storage/innobase/include/ut0lst.h +++ b/storage/innobase/include/ut0lst.h @@ -123,27 +123,36 @@ name, NODE1 and NODE2 are pointers to nodes. */ }\ }\ +/* Invalidate the pointers in a list node. */ +#ifdef UNIV_DEBUG +# define UT_LIST_REMOVE_CLEAR(NAME, N) \ +((N)->NAME.prev = (N)->NAME.next = (void*) -1) +#else +# define UT_LIST_REMOVE_CLEAR(NAME, N) while (0) +#endif + /*********************************************************************** Removes a node from a two-way linked list. BASE has to be the base node (not a pointer to it). N has to be the pointer to the node to be removed from the list. NAME is the list name. */ -#define UT_LIST_REMOVE(NAME, BASE, N)\ -{\ - ut_ad(N);\ - ut_a((BASE).count > 0);\ - ((BASE).count)--;\ - if (((N)->NAME).next != NULL) {\ - ((((N)->NAME).next)->NAME).prev = ((N)->NAME).prev;\ - } else {\ - (BASE).end = ((N)->NAME).prev;\ - }\ - if (((N)->NAME).prev != NULL) {\ - ((((N)->NAME).prev)->NAME).next = ((N)->NAME).next;\ - } else {\ - (BASE).start = ((N)->NAME).next;\ - }\ -}\ +#define UT_LIST_REMOVE(NAME, BASE, N) \ +do { \ + ut_ad(N); \ + ut_a((BASE).count > 0); \ + ((BASE).count)--; \ + if (((N)->NAME).next != NULL) { \ + ((((N)->NAME).next)->NAME).prev = ((N)->NAME).prev; \ + } else { \ + (BASE).end = ((N)->NAME).prev; \ + } \ + if (((N)->NAME).prev != NULL) { \ + ((((N)->NAME).prev)->NAME).next = ((N)->NAME).next; \ + } else { \ + (BASE).start = ((N)->NAME).next; \ + } \ + UT_LIST_REMOVE_CLEAR(NAME, N); \ +} while (0) /************************************************************************ Gets the next node in a two-way list. NAME is the name of the list diff --git a/storage/innobase/os/os0file.c b/storage/innobase/os/os0file.c index a4acb0cd485..c4d051ec771 100644 --- a/storage/innobase/os/os0file.c +++ b/storage/innobase/os/os0file.c @@ -1733,7 +1733,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/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c index a2895bae71a..41a468e5026 100644 --- a/storage/innobase/row/row0mysql.c +++ b/storage/innobase/row/row0mysql.c @@ -2820,12 +2820,10 @@ row_truncate_table_for_mysql( goto next_rec; } - btr_pcur_store_position(&pcur, &mtr); + /* This call may commit and restart mtr + and reposition pcur. */ + root_page_no = dict_truncate_index_tree(table, &pcur, &mtr); - /* This call may commit and restart mtr. */ - root_page_no = dict_truncate_index_tree(table, rec, &mtr); - - btr_pcur_restore_position(BTR_MODIFY_LEAF, &pcur, &mtr); rec = btr_pcur_get_rec(&pcur); if (root_page_no != FIL_NULL) { diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc index 85968110a77..f407f62fa0c 100644 --- a/storage/myisam/ha_myisam.cc +++ b/storage/myisam/ha_myisam.cc @@ -609,7 +609,7 @@ int ha_myisam::repair(THD* thd, HA_CHECK_OPT *check_opt) { param.testflag&= ~T_RETRY_WITHOUT_QUICK; sql_print_information("Retrying repair of: '%s' without quick", - table->s->path); + table->s->path.str); continue; } param.testflag&= ~T_QUICK; @@ -617,7 +617,7 @@ int ha_myisam::repair(THD* thd, HA_CHECK_OPT *check_opt) { param.testflag= (param.testflag & ~T_REP_BY_SORT) | T_REP; sql_print_information("Retrying repair of: '%s' with keycache", - table->s->path); + table->s->path.str); continue; } break; @@ -629,7 +629,7 @@ int ha_myisam::repair(THD* thd, HA_CHECK_OPT *check_opt) sql_print_information("Found %s of %s rows when repairing '%s'", llstr(file->state->records, llbuff), llstr(start_records, llbuff2), - table->s->path); + table->s->path.str); } return error; } @@ -1157,7 +1157,7 @@ bool ha_myisam::check_and_repair(THD *thd) // Don't use quick if deleted rows if (!file->state->del && (myisam_recover_options & HA_RECOVER_QUICK)) check_opt.flags|=T_QUICK; - sql_print_warning("Checking table: '%s'",table->s->path); + sql_print_warning("Checking table: '%s'",table->s->path.str); old_query= thd->query; old_query_length= thd->query_length; @@ -1168,7 +1168,7 @@ bool ha_myisam::check_and_repair(THD *thd) if ((marked_crashed= mi_is_crashed(file)) || check(thd, &check_opt)) { - sql_print_warning("Recovering table: '%s'",table->s->path); + sql_print_warning("Recovering table: '%s'",table->s->path.str); check_opt.flags= ((myisam_recover_options & HA_RECOVER_BACKUP ? T_BACKUP_DATA : 0) | (marked_crashed ? 0 : T_QUICK) | @@ -1460,6 +1460,7 @@ int ha_myisam::create(const char *name, register TABLE *table_arg, bool found_real_auto_increment=0; enum ha_base_keytype type; char buff[FN_REFLEN]; + byte *record; KEY *pos; MI_KEYDEF *keydef; MI_COLUMNDEF *recinfo,*recinfo_pos; @@ -1564,6 +1565,7 @@ int ha_myisam::create(const char *name, register TABLE *table_arg, found_real_auto_increment= share->next_number_key_offset == 0; } + record= table_arg->record[0]; recpos=0; recinfo_pos=recinfo; while (recpos < (uint) share->reclength) { @@ -1573,7 +1575,7 @@ int ha_myisam::create(const char *name, register TABLE *table_arg, for (field=table_arg->field ; *field ; field++) { - if ((fieldpos=(*field)->offset()) >= recpos && + if ((fieldpos=(*field)->offset(record)) >= recpos && fieldpos <= minpos) { /* skip null fields */ @@ -1587,7 +1589,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/storage/myisam/ha_myisam.h b/storage/myisam/ha_myisam.h index 7ad938c06a7..6e9108e8731 100644 --- a/storage/myisam/ha_myisam.h +++ b/storage/myisam/ha_myisam.h @@ -37,7 +37,7 @@ extern ulong myisam_recover_options; class ha_myisam: public handler { MI_INFO *file; - ulong int_table_flags; + ulonglong int_table_flags; char *data_file_name, *index_file_name; bool can_enable_indexes; int repair(THD *thd, MI_CHECK ¶m, bool optimize); diff --git a/storage/myisam/mi_close.c b/storage/myisam/mi_close.c index 9865ac72d62..0b7f98f4d06 100644 --- a/storage/myisam/mi_close.c +++ b/storage/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/storage/myisam/mi_delete.c b/storage/myisam/mi_delete.c index 85cc60bdd9d..471420d99c0 100644 --- a/storage/myisam/mi_delete.c +++ b/storage/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/storage/myisam/mi_dynrec.c b/storage/myisam/mi_dynrec.c index 8d45333137e..5f0c26a8607 100644 --- a/storage/myisam/mi_dynrec.c +++ b/storage/myisam/mi_dynrec.c @@ -1240,8 +1240,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/storage/myisam/mi_key.c b/storage/myisam/mi_key.c index 01bd0c43119..c6f9799bd67 100644 --- a/storage/myisam/mi_key.c +++ b/storage/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/storage/myisam/mi_keycache.c b/storage/myisam/mi_keycache.c index b4122089d1d..bf69a6233f9 100644 --- a/storage/myisam/mi_keycache.c +++ b/storage/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/storage/myisam/mi_open.c b/storage/myisam/mi_open.c index 7d1f18d3906..010f7233c32 100644 --- a/storage/myisam/mi_open.c +++ b/storage/myisam/mi_open.c @@ -348,6 +348,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) { diff --git a/storage/myisam/mi_page.c b/storage/myisam/mi_page.c index a5e2b01ed0f..33921c09a68 100644 --- a/storage/myisam/mi_page.c +++ b/storage/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/storage/myisam/mi_rsamepos.c b/storage/myisam/mi_rsamepos.c index c4bd5fa16fa..d2dba64b0fd 100644 --- a/storage/myisam/mi_rsamepos.c +++ b/storage/myisam/mi_rsamepos.c @@ -33,7 +33,8 @@ int mi_rsame_with_pos(MI_INFO *info, byte *record, int inx, my_off_t filepos) DBUG_ENTER("mi_rsame_with_pos"); DBUG_PRINT("enter",("index: %d filepos: %ld", inx, (long) filepos)); - if (inx < -1 || inx >= 0 && ! mi_is_key_active(info->s->state.key_map, inx)) + if (inx < -1 || + (inx >= 0 && ! mi_is_key_active(info->s->state.key_map, inx))) { DBUG_RETURN(my_errno=HA_ERR_WRONG_INDEX); } diff --git a/storage/myisam/mi_statrec.c b/storage/myisam/mi_statrec.c index 70e63ef8ce1..b3ebeb24bad 100644 --- a/storage/myisam/mi_statrec.c +++ b/storage/myisam/mi_statrec.c @@ -254,8 +254,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/storage/myisam/mi_write.c b/storage/myisam/mi_write.c index 7080875009b..32f2aac6859 100644 --- a/storage/myisam/mi_write.c +++ b/storage/myisam/mi_write.c @@ -351,7 +351,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+ @@ -474,7 +474,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); @@ -495,8 +495,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) @@ -689,7 +689,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 */ @@ -744,7 +745,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 */ @@ -780,7 +782,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 { @@ -789,7 +791,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/storage/myisam/myisampack.c b/storage/myisam/myisampack.c index be68ffbdc5a..98121cc6d90 100644 --- a/storage/myisam/myisampack.c +++ b/storage/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++) @@ -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). */ @@ -2279,8 +2279,8 @@ static my_off_t write_huff_tree(HUFF_TREE *huff_tree, uint trees) if (bits > 8 * sizeof(code)) { VOID(fflush(stdout)); - VOID(fprintf(stderr, "error: Huffman code too long: %u/%u\n", - bits, 8 * sizeof(code))); + VOID(fprintf(stderr, "error: Huffman code too long: %u/%lu\n", + bits, (ulong) (8 * sizeof(code)))); errors++; break; } @@ -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)) { diff --git a/storage/myisammrg/ha_myisammrg.cc b/storage/myisammrg/ha_myisammrg.cc index 57ef1dad6f7..9637173a3ad 100644 --- a/storage/myisammrg/ha_myisammrg.cc +++ b/storage/myisammrg/ha_myisammrg.cc @@ -92,7 +92,7 @@ int ha_myisammrg::open(const char *name, int mode, uint test_if_locked) if (table->s->reclength != stats.mean_rec_length && stats.mean_rec_length) { - DBUG_PRINT("error",("reclength: %d mean_rec_length: %d", + DBUG_PRINT("error",("reclength: %lu mean_rec_length: %lu", table->s->reclength, stats.mean_rec_length)); goto err; } @@ -577,7 +577,7 @@ static int myisammrg_init(void *p) myisammrg_hton= (handlerton *)p; - myisammrg_hton->state= have_merge_db; + myisammrg_hton->state= SHOW_OPTION_YES; myisammrg_hton->db_type= DB_TYPE_MRG_MYISAM; myisammrg_hton->create= myisammrg_create_handler; myisammrg_hton->panic= myisammrg_panic; diff --git a/storage/myisammrg/myrg_extra.c b/storage/myisammrg/myrg_extra.c index ef7eeb9d4d9..2d6f9423de9 100644 --- a/storage/myisammrg/myrg_extra.c +++ b/storage/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/storage/myisammrg/myrg_rkey.c b/storage/myisammrg/myrg_rkey.c index f87b264081e..8d3c0a4699a 100644 --- a/storage/myisammrg/myrg_rkey.c +++ b/storage/myisammrg/myrg_rkey.c @@ -87,8 +87,8 @@ 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)); + DBUG_PRINT("info", ("using table no: %u", + (uint) (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/storage/ndb/config/type_kernel.mk.am b/storage/ndb/config/type_kernel.mk.am index 710cdbd80fa..c2a602d4e19 100644 --- a/storage/ndb/config/type_kernel.mk.am +++ b/storage/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)/storage/ndb/include \ + -I$(top_srcdir)/include \ -I$(top_srcdir)/storage/ndb/include \ -I$(top_srcdir)/storage/ndb/src/kernel/vm \ -I$(top_srcdir)/storage/ndb/src/kernel/error \ diff --git a/storage/ndb/config/type_ndbapi.mk.am b/storage/ndb/config/type_ndbapi.mk.am index 29523e3378f..258322d6d9a 100644 --- a/storage/ndb/config/type_ndbapi.mk.am +++ b/storage/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)/storage/ndb/include \ + -I$(top_srcdir)/include \ -I$(top_srcdir)/mysys \ -I$(top_srcdir)/storage/ndb/include \ -I$(top_srcdir)/storage/ndb/include/kernel \ diff --git a/storage/ndb/config/type_ndbapitest.mk.am b/storage/ndb/config/type_ndbapitest.mk.am index f4a339b27c7..9a5a7d5a778 100644 --- a/storage/ndb/config/type_ndbapitest.mk.am +++ b/storage/ndb/config/type_ndbapitest.mk.am @@ -5,7 +5,10 @@ LDADD += $(top_builddir)/storage/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)/storage/ndb/include \ + -I$(top_srcdir)/include \ -I$(top_srcdir)/storage/ndb/include \ -I$(top_srcdir)/storage/ndb/include/ndbapi \ -I$(top_srcdir)/storage/ndb/include/util \ diff --git a/storage/ndb/config/type_ndbapitools.mk.am b/storage/ndb/config/type_ndbapitools.mk.am index d7ab5797f14..6003489f46e 100644 --- a/storage/ndb/config/type_ndbapitools.mk.am +++ b/storage/ndb/config/type_ndbapitools.mk.am @@ -5,7 +5,10 @@ LDADD += \ $(top_builddir)/mysys/libmysys.a \ $(top_builddir)/strings/libmystrings.a @NDB_SCI_LIBS@ @ZLIB_LIBS@ -INCLUDES += -I$(srcdir) -I$(top_srcdir)/include \ +INCLUDES += -I$(srcdir) \ + -I$(top_builddir)/include \ + -I$(top_builddir)/storage/ndb/include \ + -I$(top_srcdir)/include \ -I$(top_srcdir)/storage/ndb/include \ -I$(top_srcdir)/storage/ndb/include/ndbapi \ -I$(top_srcdir)/storage/ndb/include/util \ diff --git a/storage/ndb/config/type_util.mk.am b/storage/ndb/config/type_util.mk.am index 2b232d2010a..2ce75a2ce31 100644 --- a/storage/ndb/config/type_util.mk.am +++ b/storage/ndb/config/type_util.mk.am @@ -1,5 +1,7 @@ INCLUDES += -I$(srcdir) \ + -I$(top_builddir)/include \ + -I$(top_builddir)/storage/ndb/include \ -I$(top_srcdir)/include \ -I$(top_srcdir)/mysys \ -I$(top_srcdir)/storage/ndb/include \ diff --git a/storage/ndb/include/kernel/signaldata/DictTabInfo.hpp b/storage/ndb/include/kernel/signaldata/DictTabInfo.hpp index 86186929394..6e76840fc5f 100644 --- a/storage/ndb/include/kernel/signaldata/DictTabInfo.hpp +++ b/storage/ndb/include/kernel/signaldata/DictTabInfo.hpp @@ -47,17 +47,17 @@ inline int my_decimal_get_binary_size(uint precision, uint scale) #endif #define DTIMAP(x, y, z) \ - { DictTabInfo::y, offsetof(x, z), SimpleProperties::Uint32Value, 0, (~0), 0 } + { DictTabInfo::y, my_offsetof(x, z), SimpleProperties::Uint32Value, 0, (~0), 0 } #define DTIMAP2(x, y, z, u, v) \ - { DictTabInfo::y, offsetof(x, z), SimpleProperties::Uint32Value, u, v, 0 } + { DictTabInfo::y, my_offsetof(x, z), SimpleProperties::Uint32Value, u, v, 0 } #define DTIMAPS(x, y, z, u, v) \ - { DictTabInfo::y, offsetof(x, z), SimpleProperties::StringValue, u, v, 0 } + { DictTabInfo::y, my_offsetof(x, z), SimpleProperties::StringValue, u, v, 0 } #define DTIMAPB(x, y, z, u, v, l) \ - { DictTabInfo::y, offsetof(x, z), SimpleProperties::BinaryValue, u, v, \ - offsetof(x, l) } + { DictTabInfo::y, my_offsetof(x, z), SimpleProperties::BinaryValue, u, v, \ + my_offsetof(x, l) } #define DTIBREAK(x) \ { DictTabInfo::x, 0, SimpleProperties::InvalidValue, 0, 0, 0 } @@ -602,17 +602,17 @@ public: }; #define DFGIMAP(x, y, z) \ - { DictFilegroupInfo::y, offsetof(x, z), SimpleProperties::Uint32Value, 0, (~0), 0 } + { DictFilegroupInfo::y, my_offsetof(x, z), SimpleProperties::Uint32Value, 0, (~0), 0 } #define DFGIMAP2(x, y, z, u, v) \ - { DictFilegroupInfo::y, offsetof(x, z), SimpleProperties::Uint32Value, u, v, 0 } + { DictFilegroupInfo::y, my_offsetof(x, z), SimpleProperties::Uint32Value, u, v, 0 } #define DFGIMAPS(x, y, z, u, v) \ - { DictFilegroupInfo::y, offsetof(x, z), SimpleProperties::StringValue, u, v, 0 } + { DictFilegroupInfo::y, my_offsetof(x, z), SimpleProperties::StringValue, u, v, 0 } #define DFGIMAPB(x, y, z, u, v, l) \ - { DictFilegroupInfo::y, offsetof(x, z), SimpleProperties::BinaryValue, u, v, \ - offsetof(x, l) } + { DictFilegroupInfo::y, my_offsetof(x, z), SimpleProperties::BinaryValue, u, v, \ + my_offsetof(x, l) } #define DFGIBREAK(x) \ { DictFilegroupInfo::x, 0, SimpleProperties::InvalidValue, 0, 0, 0 } diff --git a/storage/ndb/include/logger/LogHandler.hpp b/storage/ndb/include/logger/LogHandler.hpp index 8b9aa43d7a9..efb87bb3104 100644 --- a/storage/ndb/include/logger/LogHandler.hpp +++ b/storage/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/storage/ndb/include/ndb_global.h.in b/storage/ndb/include/ndb_global.h.in index a427e5c820d..24e75f964a0 100644 --- a/storage/ndb/include/ndb_global.h.in +++ b/storage/ndb/include/ndb_global.h.in @@ -133,6 +133,12 @@ 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 + #ifndef MIN #define MIN(x,y) (((x)<(y))?(x):(y)) #endif diff --git a/storage/ndb/include/util/NdbOut.hpp b/storage/ndb/include/util/NdbOut.hpp index d85d5cc6305..911777be07d 100644 --- a/storage/ndb/include/util/NdbOut.hpp +++ b/storage/ndb/include/util/NdbOut.hpp @@ -106,7 +106,7 @@ inline NdbOut& dec(NdbOut& _NdbOut) { return _NdbOut.setHexFormat(0); } extern "C" -void ndbout_c(const char * fmt, ...); +void ndbout_c(const char * fmt, ...) ATTRIBUTE_FORMAT(printf, 1, 2); class FilteredNdbOut : public NdbOut { public: diff --git a/storage/ndb/include/util/SimpleProperties.hpp b/storage/ndb/include/util/SimpleProperties.hpp index bae91108518..f199790f416 100644 --- a/storage/ndb/include/util/SimpleProperties.hpp +++ b/storage/ndb/include/util/SimpleProperties.hpp @@ -167,13 +167,13 @@ public: class Writer { public: Writer() {} - virtual ~Writer() {} bool first(); bool add(Uint16 key, Uint32 value); 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; @@ -247,7 +247,6 @@ public: class SectionSegmentPool &); virtual ~SimplePropertiesSectionReader() {} - virtual void reset(); virtual bool step(Uint32 len); virtual bool getWord(Uint32 * dst); diff --git a/storage/ndb/src/common/debugger/EventLogger.cpp b/storage/ndb/src/common/debugger/EventLogger.cpp index a7a3ed970c0..45df07fefaf 100644 --- a/storage/ndb/src/common/debugger/EventLogger.cpp +++ b/storage/ndb/src/common/debugger/EventLogger.cpp @@ -115,8 +115,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/storage/ndb/src/common/debugger/signaldata/BackupSignalData.cpp b/storage/ndb/src/common/debugger/signaldata/BackupSignalData.cpp index 27fed22ac72..7410db44aa3 100644 --- a/storage/ndb/src/common/debugger/signaldata/BackupSignalData.cpp +++ b/storage/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/storage/ndb/src/common/logger/LogHandler.cpp b/storage/ndb/src/common/logger/LogHandler.cpp index c11f962d4fb..47333f81812 100644 --- a/storage/ndb/src/common/logger/LogHandler.cpp +++ b/storage/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/storage/ndb/src/common/portlib/NdbMutex.c b/storage/ndb/src/common/portlib/NdbMutex.c index 4a170d87e5c..f0a1614ba8e 100644 --- a/storage/ndb/src/common/portlib/NdbMutex.c +++ b/storage/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/storage/ndb/src/common/portlib/NdbThread.c b/storage/ndb/src/common/portlib/NdbThread.c index b91e9c6a5b3..d6eea08b9f0 100644 --- a/storage/ndb/src/common/portlib/NdbThread.c +++ b/storage/ndb/src/common/portlib/NdbThread.c @@ -142,7 +142,7 @@ struct NdbThread* NdbThread_Create(NDB_THREAD_FUNC *p_thread_func, } pthread_attr_destroy(&thread_attr); - DBUG_PRINT("exit",("ret: %lx", tmpThread)); + DBUG_PRINT("exit",("ret: 0x%lx", (long) tmpThread)); DBUG_RETURN(tmpThread); } @@ -151,7 +151,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/storage/ndb/src/common/transporter/Transporter.cpp b/storage/ndb/src/common/transporter/Transporter.cpp index 383456f1077..b2ee75e4754 100644 --- a/storage/ndb/src/common/transporter/Transporter.cpp +++ b/storage/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/storage/ndb/src/cw/cpcd/CPCD.hpp b/storage/ndb/src/cw/cpcd/CPCD.hpp index aecc43150c4..3a69a03aa3f 100644 --- a/storage/ndb/src/cw/cpcd/CPCD.hpp +++ b/storage/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/storage/ndb/src/kernel/Makefile.am b/storage/ndb/src/kernel/Makefile.am index d8a504d1994..610dc63d51e 100644 --- a/storage/ndb/src/kernel/Makefile.am +++ b/storage/ndb/src/kernel/Makefile.am @@ -9,22 +9,22 @@ ndbd_SOURCES = main.cpp SimBlockList.cpp include $(top_srcdir)/storage/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 \ - -Iblocks + -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 \ + -I$(srcdir)/blocks LDADD += \ blocks/libblocks.a \ diff --git a/storage/ndb/src/kernel/blocks/backup/Backup.cpp b/storage/ndb/src/kernel/blocks/backup/Backup.cpp index d6b557424e7..819255a79f5 100644 --- a/storage/ndb/src/kernel/blocks/backup/Backup.cpp +++ b/storage/ndb/src/kernel/blocks/backup/Backup.cpp @@ -228,7 +228,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); TablePtr tabPtr; ptr.p->tables.getPtr(tabPtr, tabPtr_I); @@ -239,7 +239,7 @@ Backup::execCONTINUEB(Signal* signal) FragmentPtr fragPtr; tabPtr.p->fragments.getPtr(fragPtr, fragPtr_I); - BackupFilePtr filePtr; + BackupFilePtr filePtr LINT_SET_PTR; ptr.p->files.getPtr(filePtr, ptr.p->ctlFilePtr); const Uint32 sz = sizeof(BackupFormat::CtlFile::FragmentInfo) >> 2; @@ -293,7 +293,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; @@ -302,7 +302,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; @@ -311,7 +311,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; @@ -320,16 +320,16 @@ Backup::execCONTINUEB(Signal* signal) case BackupContinueB::BUFFER_FULL_META: { jam(); - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; c_backupPool.getPtr(ptr, Tdata1); - BackupFilePtr filePtr; + BackupFilePtr filePtr LINT_SET_PTR; ptr.p->files.getPtr(filePtr, ptr.p->ctlFilePtr); FsBuffer & buf = filePtr.p->operation.dataBuffer; 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() @@ -344,7 +344,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(); @@ -416,7 +416,7 @@ Backup::execDUMP_STATE_ORD(Signal* signal) /** * Print records */ - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; for(c_backups.first(ptr); ptr.i != RNIL; c_backups.next(ptr)){ infoEvent("BackupRecord %d: BackupId: %d MasterRef: %x ClientRef: %x", ptr.i, ptr.p->backupId, ptr.p->masterRef, ptr.p->clientRef); @@ -870,6 +870,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: @@ -1053,7 +1056,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; @@ -1107,7 +1110,7 @@ Backup::execUTIL_SEQUENCE_CONF(Signal* signal) return; } - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; ptr.i = conf->senderData; c_backupPool.getPtr(ptr); @@ -1148,7 +1151,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); @@ -1169,7 +1172,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); @@ -1274,7 +1277,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); @@ -1291,7 +1294,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)) @@ -1469,7 +1472,7 @@ Backup::execCREATE_TRIG_CONF(Signal* signal) const TriggerEvent::Value type = conf->getTriggerEvent(); const Uint32 triggerId = conf->getTriggerId(); - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; c_backupPool.getPtr(ptr, ptrI); /** @@ -1498,7 +1501,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); /** @@ -1613,7 +1616,7 @@ Backup::execSTART_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); @@ -1630,7 +1633,7 @@ Backup::execSTART_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); startBackupReply(signal, ptr, nodeId); @@ -1682,7 +1685,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()); @@ -1706,7 +1709,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()); @@ -1847,7 +1850,7 @@ Backup::execBACKUP_FRAGMENT_CONF(Signal* signal) const Uint64 noOfRecords = conf->noOfRecordsLow + (((Uint64)conf->noOfRecordsHigh) << 32); - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; c_backupPool.getPtr(ptr, ptrI); ptr.p->noOfBytes += noOfBytes; @@ -1921,7 +1924,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; @@ -1974,7 +1977,7 @@ Backup::execBACKUP_FRAGMENT_COMPLETE_REP(Signal* signal) BackupFragmentCompleteRep * rep = (BackupFragmentCompleteRep*)signal->getDataPtr(); - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; c_backupPool.getPtr(ptr, rep->backupPtr); TablePtr tabPtr; @@ -2026,21 +2029,23 @@ Backup::sendDropTrig(Signal* signal, BackupRecordPtr ptr) * Insert footers */ { - BackupFilePtr filePtr; + BackupFilePtr filePtr LINT_SET_PTR; 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); } { - BackupFilePtr filePtr; + BackupFilePtr filePtr LINT_SET_PTR; ptr.p->files.getPtr(filePtr, ptr.p->ctlFilePtr); 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 = @@ -2110,10 +2115,10 @@ 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); - if(ref->getConf()->getTriggerId() != -1) + if(ref->getConf()->getTriggerId() != ~(Uint32) 0) { ndbout << "ERROR DROPPING TRIGGER: " << ref->getConf()->getTriggerId(); ndbout << " Err: " << (Uint32)ref->getErrorCode() << endl << endl; @@ -2131,7 +2136,7 @@ Backup::execDROP_TRIG_CONF(Signal* signal) const Uint32 ptrI = conf->getConnectionPtr(); const Uint32 triggerId= conf->getTriggerId(); - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; c_backupPool.getPtr(ptr, ptrI); dropTrigReply(signal, ptr); @@ -2170,7 +2175,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); @@ -2205,7 +2210,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; @@ -2383,7 +2388,7 @@ Backup::defineBackupRef(Signal* signal, BackupRecordPtr ptr, Uint32 errCode) { jam(); - BackupFilePtr filePtr; + BackupFilePtr filePtr LINT_SET_PTR; ptr.p->files.getPtr(filePtr, ptr.p->ctlFilePtr); if (filePtr.p->m_flags & BackupFile::BF_LCP_META) { @@ -2435,7 +2440,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; @@ -2639,7 +2644,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; @@ -2694,7 +2699,7 @@ Backup::openFiles(Signal* signal, BackupRecordPtr ptr) { jam(); - BackupFilePtr filePtr; + BackupFilePtr filePtr LINT_SET_PTR; FsOpenReq * req = (FsOpenReq *)signal->getDataPtrSend(); req->userReference = reference(); @@ -2756,10 +2761,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); @@ -2775,11 +2780,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->m_flags & BackupFile::BF_OPEN)); @@ -2960,10 +2965,10 @@ 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); - BackupFilePtr filePtr; + BackupFilePtr filePtr LINT_SET_PTR; ptr.p->files.getPtr(filePtr, ptr.p->ctlFilePtr); filePtr.p->m_flags &= ~(Uint32)BackupFile::BF_FILE_THREAD; @@ -2987,7 +2992,7 @@ Backup::execGET_TABINFO_CONF(Signal* signal) const Uint32 tableType = conf->tableType; const Uint32 tableId = conf->tableId; - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; c_backupPool.getPtr(ptr, senderData); SegmentedSectionPtr dictTabInfoPtr; @@ -2997,7 +3002,7 @@ Backup::execGET_TABINFO_CONF(Signal* signal) TablePtr tabPtr ; ndbrequire(findTable(ptr, tabPtr, tableId)); - BackupFilePtr filePtr; + BackupFilePtr filePtr LINT_SET_PTR; ptr.p->files.getPtr(filePtr, ptr.p->ctlFilePtr); FsBuffer & buf = filePtr.p->operation.dataBuffer; Uint32* dst = 0; @@ -3263,7 +3268,7 @@ Backup::execDI_FCOUNTCONF(Signal* signal) ndbrequire(userPtr == RNIL && signal->length() == 5); - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; c_backupPool.getPtr(ptr, senderData); TablePtr tabPtr; @@ -3278,7 +3283,7 @@ Backup::execDI_FCOUNTCONF(Signal* signal) fragPtr.p->scanning = 0; fragPtr.p->tableId = tableId; fragPtr.p->fragmentId = i; - fragPtr.p->node = RNIL; + fragPtr.p->node = 0; }//for /** @@ -3343,7 +3348,7 @@ Backup::execDIGETPRIMCONF(Signal* signal) ndbrequire(userPtr == RNIL && signal->length() == 9); ndbrequire(nodeCount > 0 && nodeCount <= MAX_REPLICAS); - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; c_backupPool.getPtr(ptr, senderData); TablePtr tabPtr; @@ -3385,7 +3390,7 @@ Backup::execSTART_BACKUP_REQ(Signal* signal) StartBackupReq* req = (StartBackupReq*)signal->getDataPtr(); const Uint32 ptrI = req->backupPtr; - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; c_backupPool.getPtr(ptr, ptrI); ptr.p->slaveState.setState(STARTED); @@ -3438,7 +3443,7 @@ Backup::execBACKUP_FRAGMENT_REQ(Signal* signal) /** * Get backup record */ - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; c_backupPool.getPtr(ptr, ptrI); ptr.p->slaveState.setState(SCANNING); @@ -3447,7 +3452,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); @@ -3591,12 +3596,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; @@ -3782,7 +3787,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; @@ -3801,7 +3806,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; @@ -3842,7 +3847,7 @@ Backup::fragmentCompleted(Signal* signal, BackupFilePtr filePtr) filePtr.p->m_flags &= ~(Uint32)BackupFile::BF_SCAN_THREAD; - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; c_backupPool.getPtr(ptr, filePtr.p->backupPtr); if (ptr.p->is_lcp()) @@ -3873,7 +3878,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; @@ -3929,7 +3934,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; @@ -3960,7 +3965,7 @@ 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->m_flags &= ~(Uint32)BackupFile::BF_FILE_THREAD; @@ -3980,7 +3985,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; @@ -4100,7 +4105,7 @@ Backup::checkFile(Signal* signal, BackupFilePtr filePtr) ndbrequire(flags & BackupFile::BF_OPEN); ndbrequire(flags & BackupFile::BF_FILE_THREAD); - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; c_backupPool.getPtr(ptr, filePtr.p->backupPtr); closeFile(signal, ptr, filePtr); } @@ -4117,8 +4122,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]; @@ -4149,7 +4154,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... @@ -4180,7 +4185,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(); @@ -4233,7 +4238,7 @@ Backup::execFIRE_TRIG_ORD(Signal* signal) const Uint32 trI = trg->getTriggerId(); const Uint32 fragId = trg->fragId; - TriggerPtr trigPtr; + TriggerPtr trigPtr LINT_SET_PTR; c_triggerPool.getPtr(trigPtr, trI); ndbrequire(trigPtr.p->event != ILLEGAL_TRIGGER_ID); @@ -4247,7 +4252,7 @@ Backup::execFIRE_TRIG_ORD(Signal* signal) Uint32 len = trigPtr.p->logEntry->Length; trigPtr.p->logEntry->FragId = htonl(fragId); - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; c_backupPool.getPtr(ptr, trigPtr.p->backupPtr); if(gci != ptr.p->currGCP) { @@ -4317,7 +4322,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); @@ -4412,10 +4417,10 @@ 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; + BackupRecordPtr ptr LINT_SET_PTR; c_backupPool.getPtr(ptr, filePtr.p->backupPtr); FsConf * conf = (FsConf*)signal->getDataPtr(); @@ -4432,7 +4437,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 @@ -4446,7 +4451,7 @@ Backup::execFSCLOSECONF(Signal* signal) filePtr.p->m_flags &= ~(Uint32)(BackupFile::BF_OPEN |BackupFile::BF_CLOSING); filePtr.p->operation.dataBuffer.reset(); - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; c_backupPool.getPtr(ptr, filePtr.p->backupPtr); closeFiles(signal, ptr); } @@ -4468,7 +4473,7 @@ Backup::closeFilesDone(Signal* signal, BackupRecordPtr ptr) conf->backupId = ptr.p->backupId; conf->backupPtr = ptr.i; - BackupFilePtr filePtr; + BackupFilePtr filePtr LINT_SET_PTR; if(ptr.p->logFilePtr != RNIL) { ptr.p->files.getPtr(filePtr, ptr.p->logFilePtr); @@ -4517,7 +4522,7 @@ Backup::execABORT_BACKUP_ORD(Signal* signal) dumpUsedResources(); #endif - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; if(requestType == AbortBackupOrd::ClientAbort) { if (getOwnNodeId() != getMasterNodeId()) { jam(); @@ -4637,7 +4642,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]); @@ -4672,7 +4677,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]); @@ -4748,7 +4753,7 @@ Backup::execFSREMOVECONF(Signal* signal){ /** * Get backup record */ - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; c_backupPool.getPtr(ptr, ptrI); c_backups.release(ptr); } @@ -4762,7 +4767,7 @@ Backup::execLCP_PREPARE_REQ(Signal* signal) jamEntry(); LcpPrepareReq req = *(LcpPrepareReq*)signal->getDataPtr(); - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; c_backupPool.getPtr(ptr, req.backupPtr); ptr.p->m_gsn = GSN_LCP_PREPARE_REQ; @@ -4822,7 +4827,7 @@ Backup::lcp_close_file_conf(Signal* signal, BackupRecordPtr ptr) ndbrequire(ptr.p->tables.first(tabPtr)); Uint32 tableId = tabPtr.p->tableId; - BackupFilePtr filePtr; + BackupFilePtr filePtr LINT_SET_PTR; c_backupFilePool.getPtr(filePtr, ptr.p->dataFilePtr); ndbrequire(filePtr.p->m_flags == 0); @@ -4878,7 +4883,7 @@ Backup::lcp_open_file(Signal* signal, BackupRecordPtr ptr) /** * Lcp file */ - BackupFilePtr filePtr; + BackupFilePtr filePtr LINT_SET_PTR; c_backupFilePool.getPtr(filePtr, ptr.p->dataFilePtr); ndbrequire(filePtr.p->m_flags == 0); filePtr.p->m_flags |= BackupFile::BF_OPENING; @@ -4901,7 +4906,7 @@ Backup::lcp_open_file_done(Signal* signal, BackupRecordPtr ptr) ndbrequire(ptr.p->tables.first(tabPtr)); tabPtr.p->fragments.getPtr(fragPtr, 0); - BackupFilePtr filePtr; + BackupFilePtr filePtr LINT_SET_PTR; c_backupFilePool.getPtr(filePtr, ptr.p->dataFilePtr); ndbrequire(filePtr.p->m_flags == (BackupFile::BF_OPEN | BackupFile::BF_LCP_META)); @@ -4933,11 +4938,11 @@ Backup::execEND_LCPREQ(Signal* signal) { EndLcpReq* req= (EndLcpReq*)signal->getDataPtr(); - BackupRecordPtr ptr; + BackupRecordPtr ptr LINT_SET_PTR; c_backupPool.getPtr(ptr, req->backupPtr); ndbrequire(ptr.p->backupId == req->backupId); - BackupFilePtr filePtr; + BackupFilePtr filePtr LINT_SET_PTR; ptr.p->files.getPtr(filePtr, ptr.p->ctlFilePtr); ndbrequire(filePtr.p->m_flags == 0); diff --git a/storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp b/storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp index a23aeec8548..ff05aac0b9b 100644 --- a/storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp +++ b/storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp @@ -971,10 +971,10 @@ void Dbacc::initOpRec(Signal* signal) Uint32 opbits = 0; opbits |= Treqinfo & 0x7; - opbits |= ((Treqinfo >> 4) & 0x3) ? Operationrec::OP_LOCK_MODE : 0; - opbits |= ((Treqinfo >> 4) & 0x3) ? Operationrec::OP_ACC_LOCK_MODE : 0; - opbits |= (dirtyReadFlag) ? Operationrec::OP_DIRTY_READ : 0; - opbits |= ((Treqinfo >> 31) & 0x1) ? Operationrec::OP_LOCK_REQ : 0; + opbits |= ((Treqinfo >> 4) & 0x3) ? (Uint32) Operationrec::OP_LOCK_MODE : 0; + opbits |= ((Treqinfo >> 4) & 0x3) ? (Uint32) Operationrec::OP_ACC_LOCK_MODE : 0; + opbits |= (dirtyReadFlag) ? (Uint32) Operationrec::OP_DIRTY_READ : 0; + opbits |= ((Treqinfo >> 31) & 0x1) ? (Uint32) Operationrec::OP_LOCK_REQ : 0; //operationRecPtr.p->nodeType = (Treqinfo >> 7) & 0x3; operationRecPtr.p->fid = fragrecptr.p->myfid; @@ -6948,10 +6948,10 @@ void Dbacc::initScanOpRec(Signal* signal) Uint32 opbits = 0; opbits |= ZSCAN_OP; - opbits |= scanPtr.p->scanLockMode ? Operationrec::OP_LOCK_MODE : 0; - opbits |= scanPtr.p->scanLockMode ? Operationrec::OP_ACC_LOCK_MODE : 0; - opbits |= scanPtr.p->scanReadCommittedFlag ? - Operationrec::OP_EXECUTED_DIRTY_READ : 0; + opbits |= scanPtr.p->scanLockMode ? (Uint32) Operationrec::OP_LOCK_MODE : 0; + opbits |= scanPtr.p->scanLockMode ? (Uint32) Operationrec::OP_ACC_LOCK_MODE : 0; + opbits |= (scanPtr.p->scanReadCommittedFlag ? + (Uint32) Operationrec::OP_EXECUTED_DIRTY_READ : 0); opbits |= Operationrec::OP_COMMIT_DELETE_CHECK; operationRecPtr.p->userptr = RNIL; operationRecPtr.p->scanRecPtr = scanPtr.i; @@ -7701,6 +7701,7 @@ void Dbacc::putOverflowRecInFrag(Signal* signal) OverflowRecordPtr tpifPrevOverrecPtr; tpifNextOverrecPtr.i = fragrecptr.p->firstOverflowRec; + LINT_INIT(tpifPrevOverrecPtr.p); tpifPrevOverrecPtr.i = RNIL; while (tpifNextOverrecPtr.i != RNIL) { ptrCheckGuard(tpifNextOverrecPtr, coverflowrecsize, overflowRecord); @@ -7750,6 +7751,7 @@ void Dbacc::putRecInFreeOverdir(Signal* signal) OverflowRecordPtr tpfoPrevOverrecPtr; tpfoNextOverrecPtr.i = fragrecptr.p->firstFreeDirindexRec; + LINT_INIT(tpfoPrevOverrecPtr.p); tpfoPrevOverrecPtr.i = RNIL; while (tpfoNextOverrecPtr.i != RNIL) { ptrCheckGuard(tpfoNextOverrecPtr, coverflowrecsize, overflowRecord); diff --git a/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp b/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp index 4d72bca706b..8d0c427d488 100644 --- a/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp +++ b/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp @@ -189,7 +189,7 @@ struct { &Dbdict::drop_undofile_prepare_start, 0, 0, 0, 0, - 0, 0 + 0, 0, 0 } }; @@ -13608,8 +13608,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; @@ -13761,7 +13761,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/storage/ndb/src/kernel/blocks/dbdict/printSchemaFile.cpp b/storage/ndb/src/kernel/blocks/dbdict/printSchemaFile.cpp index d3a4e72c3f0..9c66636980a 100644 --- a/storage/ndb/src/kernel/blocks/dbdict/printSchemaFile.cpp +++ b/storage/ndb/src/kernel/blocks/dbdict/printSchemaFile.cpp @@ -68,7 +68,7 @@ print_head(const char * filename, const SchemaFile * sf) if (! checkonly) { ndbout << "----- Schemafile: " << filename << " -----" << endl; ndbout_c("Magic: %.*s ByteOrder: %.8x NdbVersion: %s FileSize: %d", - sizeof(sf->Magic), + (int) sizeof(sf->Magic), sf->Magic, sf->ByteOrder, version(sf->NdbVersion), diff --git a/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp b/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp index 0e9157c38aa..1eee1badce3 100644 --- a/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp +++ b/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp @@ -2909,7 +2909,7 @@ Dbdih::nr_start_fragment(Signal* signal, } } - if (maxLcpIndex == ~0) + if (maxLcpIndex == ~ (Uint32) 0) { ndbout_c("Didnt find any LCP for node: %d tab: %d frag: %d", takeOverPtr.p->toStartingNode, @@ -5968,6 +5968,7 @@ Dbdih::sendMASTER_LCPCONF(Signal * signal){ break; default: ndbrequire(false); + lcpState= MasterLCPConf::LCP_STATUS_IDLE; // remove warning }//switch Uint32 failedNodeId = c_lcpState.m_MASTER_LCPREQ_FailedNodeId; @@ -6892,6 +6893,8 @@ void Dbdih::execDIADDTABREQ(Signal* signal) Uint32 align; }; SegmentedSectionPtr fragDataPtr; + LINT_INIT(fragDataPtr.i); + LINT_INIT(fragDataPtr.sz); signal->getSection(fragDataPtr, DiAddTabReq::FRAGMENTATION); copy((Uint32*)fragments, fragDataPtr); releaseSections(signal); @@ -6981,7 +6984,9 @@ Dbdih::sendAddFragreq(Signal* signal, ConnectRecordPtr connectPtr, TabRecordPtr tabPtr, Uint32 fragId){ jam(); const Uint32 fragCount = tabPtr.p->totalfragments; - ReplicaRecordPtr replicaPtr; replicaPtr.i = RNIL; + ReplicaRecordPtr replicaPtr; + LINT_INIT(replicaPtr.p); + replicaPtr.i = RNIL; FragmentstorePtr fragPtr; for(; fragId<fragCount; fragId++){ jam(); @@ -7541,7 +7546,11 @@ void Dbdih::execDI_FCOUNTREQ(Signal* signal) if(connectPtr.i == RNIL) ref->m_connectionData = RNIL; else + { + jam(); + ptrCheckGuard(connectPtr, cconnectFileSize, connectRecord); ref->m_connectionData = connectPtr.p->userpointer; + } ref->m_tableRef = tabPtr.i; ref->m_senderData = senderData; ref->m_error = DihFragCountRef::ErroneousTableState; @@ -11443,6 +11452,7 @@ Dbdih::findBestLogNode(CreateReplicaRecord* createReplica, { ConstPtr<ReplicaRecord> fblFoundReplicaPtr; ConstPtr<ReplicaRecord> fblReplicaPtr; + LINT_INIT(fblFoundReplicaPtr.p); /* --------------------------------------------------------------------- */ /* WE START WITH ZERO AS FOUND TO ENSURE THAT FIRST HIT WILL BE */ diff --git a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp index 9a7803efbec..53d7d98ae84 100644 --- a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp +++ b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp @@ -3417,9 +3417,9 @@ void Dblqh::execLQHKEYREQ(Signal* signal) } else { - regTcPtr->operation = op == ZREAD_EX ? ZREAD : op; + regTcPtr->operation = (Operation_t) op == ZREAD_EX ? ZREAD : (Operation_t) op; regTcPtr->lockType = - op == ZREAD_EX ? ZUPDATE : op == ZWRITE ? ZINSERT : op; + op == ZREAD_EX ? ZUPDATE : (Operation_t) op == ZWRITE ? ZINSERT : (Operation_t) op; } CRASH_INSERTION2(5041, regTcPtr->simpleRead && @@ -18520,7 +18520,7 @@ Dblqh::execDUMP_STATE_ORD(Signal* signal) do { ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord); - ndbout_c(" file %d(%d) FileChangeState: %d logFileStatus: %d currentMbyte: %d currentFilepage", + ndbout_c(" file %d(%d) FileChangeState: %d logFileStatus: %d currentMbyte: %d currentFilepage %d", logFilePtr.p->fileNo, logFilePtr.i, logFilePtr.p->fileChangeState, diff --git a/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp b/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp index 3fdd587afa5..af2925fa738 100644 --- a/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp +++ b/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp @@ -3194,7 +3194,7 @@ void Dbtc::sendlqhkeyreq(Signal* signal, if (unlikely(version < NDBD_ROWID_VERSION)) { Uint32 op = regTcPtr->operation; - Uint32 lock = op == ZREAD_EX ? ZUPDATE : op == ZWRITE ? ZINSERT : op; + Uint32 lock = (Operation_t) op == ZREAD_EX ? ZUPDATE : (Operation_t) op == ZWRITE ? ZINSERT : (Operation_t) op; LqhKeyReq::setLockType(Tdata10, lock); } /* ---------------------------------------------------------------------- */ diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp index fc3419e694a..23edd212991 100644 --- a/storage/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp +++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp @@ -43,7 +43,7 @@ void Dbtup::execTUP_DEALLOCREQ(Signal* signal) getFragmentrec(regFragPtr, frag_id, regTabPtr.p); ndbassert(regFragPtr.p != NULL); - if (! (((frag_page_id << MAX_TUPLES_BITS) + page_index) == ~0)) + if (! (((frag_page_id << MAX_TUPLES_BITS) + page_index) == ~ (Uint32) 0)) { Local_key tmp; tmp.m_page_no= getRealpid(regFragPtr.p, frag_page_id); diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupDiskAlloc.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupDiskAlloc.cpp index a055b18888b..7959606b7f4 100644 --- a/storage/ndb/src/kernel/blocks/dbtup/DbtupDiskAlloc.cpp +++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupDiskAlloc.cpp @@ -82,7 +82,7 @@ Dbtup::dump_disk_alloc(Dbtup::Disk_alloc_info & alloc) { ndbout << ptr << " "; } - ndbout_c(""); + ndbout_c(" "); } ndbout_c("page requests"); for(Uint32 i = 0; i<MAX_FREE_LIST; i++) @@ -95,7 +95,7 @@ Dbtup::dump_disk_alloc(Dbtup::Disk_alloc_info & alloc) { ndbout << ptr << " "; } - ndbout_c(""); + ndbout_c(" "); } ndbout_c("Extent matrix"); @@ -108,7 +108,7 @@ Dbtup::dump_disk_alloc(Dbtup::Disk_alloc_info & alloc) { ndbout << ptr << " "; } - ndbout_c(""); + ndbout_c(" "); } if (alloc.m_curr_extent_info_ptr_i != RNIL) diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp index d9710cc2549..d24483b8f1d 100644 --- a/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp +++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp @@ -684,7 +684,7 @@ void Dbtup::execTUPKEYREQ(Signal* signal) copyAttrinfo(regOperPtr, &cinBuffer[0]); Uint32 localkey = (pageid << MAX_TUPLES_BITS) + pageidx; - if(Roptype == ZINSERT && localkey == ~0) + if (Roptype == ZINSERT && localkey == ~ (Uint32) 0) { // No tuple allocatated yet goto do_insert; diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupFixAlloc.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupFixAlloc.cpp index 1ec7994dce7..1333e7be2de 100644 --- a/storage/ndb/src/kernel/blocks/dbtup/DbtupFixAlloc.cpp +++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupFixAlloc.cpp @@ -284,4 +284,5 @@ Dbtup::alloc_fix_rowid(Fragrecord* regFragPtr, case ZEMPTY_MM: ndbrequire(false); } + return 0; /* purify: deadcode */ } diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp index 677eff53559..5d4115c1d2d 100644 --- a/storage/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp +++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp @@ -1066,6 +1066,7 @@ Dbtup::updateVarSizeNotNULL(Uint32* in_buffer, terrorCode= ZAI_INCONSISTENCY_ERROR; return false; } + return false; } bool @@ -1485,6 +1486,7 @@ Dbtup::updateDiskVarSizeNotNULL(Uint32* in_buffer, terrorCode= ZAI_INCONSISTENCY_ERROR; return false; } + return false; } bool diff --git a/storage/ndb/src/kernel/blocks/dbtux/DbtuxSearch.cpp b/storage/ndb/src/kernel/blocks/dbtux/DbtuxSearch.cpp index 4b5c0b791f9..da2321bdf6f 100644 --- a/storage/ndb/src/kernel/blocks/dbtux/DbtuxSearch.cpp +++ b/storage/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/storage/ndb/src/kernel/blocks/lgman.cpp b/storage/ndb/src/kernel/blocks/lgman.cpp index d4cc0cb89e8..dff41ab8bca 100644 --- a/storage/ndb/src/kernel/blocks/lgman.cpp +++ b/storage/ndb/src/kernel/blocks/lgman.cpp @@ -1809,11 +1809,11 @@ Lgman::execLCP_FRAG_ORD(Signal* signal) if(0) ndbout_c - ("execLCP_FRAG_ORD (%d %d) (%d %d) (%d %d) free pages: %d", + ("execLCP_FRAG_ORD (%d %d) (%d %d) (%d %d) free pages: %ld", ptr.p->m_tail_pos[0].m_ptr_i, ptr.p->m_tail_pos[0].m_idx, ptr.p->m_tail_pos[1].m_ptr_i, ptr.p->m_tail_pos[1].m_idx, ptr.p->m_tail_pos[2].m_ptr_i, ptr.p->m_tail_pos[2].m_idx, - (ptr.p->m_free_file_words / File_formats::UNDO_PAGE_WORDS)); + (long) (ptr.p->m_free_file_words / File_formats::UNDO_PAGE_WORDS)); } m_logfile_group_list.next(ptr); } diff --git a/storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp b/storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp index 84e3279afaf..65d233a1a9d 100644 --- a/storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp +++ b/storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp @@ -1565,6 +1565,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; } } @@ -2326,7 +2331,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/storage/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp b/storage/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp index 3ad58399b1c..27e2d33002d 100644 --- a/storage/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp +++ b/storage/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp @@ -655,7 +655,7 @@ Ndbfs::createAsyncFile(){ // Print info about all open files for (unsigned i = 0; i < theFiles.size(); i++){ AsyncFile* file = theFiles[i]; - ndbout_c("%2d (0x%x): %s", i, file, file->isOpen()?"OPEN":"CLOSED"); + ndbout_c("%2d (0x%lx): %s", i, (long) file, file->isOpen()?"OPEN":"CLOSED"); } ERROR_SET(fatal, NDBD_EXIT_AFS_MAXOPEN,""," Ndbfs::createAsyncFile"); } @@ -1082,7 +1082,7 @@ Ndbfs::execDUMP_STATE_ORD(Signal* signal) ndbout << "All files: " << endl; for (unsigned i = 0; i < theFiles.size(); i++){ AsyncFile* file = theFiles[i]; - ndbout_c("%2d (0x%x): %s", i,file, file->isOpen()?"OPEN":"CLOSED"); + ndbout_c("%2d (0x%lx): %s", i, (long) file, file->isOpen()?"OPEN":"CLOSED"); } } }//Ndbfs::execDUMP_STATE_ORD() diff --git a/storage/ndb/src/kernel/blocks/pgman.cpp b/storage/ndb/src/kernel/blocks/pgman.cpp index 15f056f70a9..88ea0122268 100644 --- a/storage/ndb/src/kernel/blocks/pgman.cpp +++ b/storage/ndb/src/kernel/blocks/pgman.cpp @@ -1188,7 +1188,7 @@ Pgman::process_lcp(Signal* signal) pl_hash.next(m_lcp_curr_bucket, iter); Uint32 loop = 0; while (iter.curr.i != RNIL && - m_lcp_outstanding < max_count && + m_lcp_outstanding < (Uint32) max_count && (loop ++ < 32 || iter.bucket == m_lcp_curr_bucket)) { Ptr<Page_entry>& ptr = iter.curr; @@ -2324,7 +2324,7 @@ Pgman::execDUMP_STATE_ORD(Signal* signal) if (signal->theData[0] == 11004) { - ndbout << "Dump LCP bucket m_lcp_outstanding: %d", m_lcp_outstanding; + ndbout << "Dump LCP bucket m_lcp_outstanding: " << m_lcp_outstanding; if (m_lcp_curr_bucket != ~(Uint32)0) { Page_hashlist::Iterator iter; diff --git a/storage/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp b/storage/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp index 23152af2775..7be0943be5d 100644 --- a/storage/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp +++ b/storage/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/storage/ndb/src/kernel/blocks/restore.cpp b/storage/ndb/src/kernel/blocks/restore.cpp index b80bc88ec5b..0436347eeca 100644 --- a/storage/ndb/src/kernel/blocks/restore.cpp +++ b/storage/ndb/src/kernel/blocks/restore.cpp @@ -1137,7 +1137,7 @@ Restore::reorder_key(const KeyDescriptor* desc, } dst += sz; } - ndbassert((dst - Tmp) == len); + ndbassert((Uint32) (dst - Tmp) == len); memcpy(data, Tmp, 4*len); } diff --git a/storage/ndb/src/kernel/blocks/suma/Suma.cpp b/storage/ndb/src/kernel/blocks/suma/Suma.cpp index 4b38ac0f5ff..92efca36a35 100644 --- a/storage/ndb/src/kernel/blocks/suma/Suma.cpp +++ b/storage/ndb/src/kernel/blocks/suma/Suma.cpp @@ -1590,6 +1590,9 @@ Suma::execGET_TABINFOREF(Signal* signal){ break; case GetTabInfoRef::TableNameTooLong: ndbrequire(false); + break; + case GetTabInfoRef::NoFetchByName: + break; } if (do_resend_request) { @@ -4306,7 +4309,7 @@ Suma::Restart::sendSubStartReq(SubscriptionPtr subPtr, SubscriberPtr subbPtr, // restarting suma will not respond to this until startphase 5 // since it is not until then data copying has been completed - DBUG_PRINT("info",("Restarting subscriber: %u on key: [%u,%u]", + DBUG_PRINT("info",("Restarting subscriber: %u on key: [%u,%u] %u", subbPtr.i, subPtr.p->m_subscriptionId, subPtr.p->m_subscriptionKey, diff --git a/storage/ndb/src/kernel/error/ErrorReporter.cpp b/storage/ndb/src/kernel/error/ErrorReporter.cpp index 6c8bb1fe615..e95cd5c132f 100644 --- a/storage/ndb/src/kernel/error/ErrorReporter.cpp +++ b/storage/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/storage/ndb/src/kernel/error/ErrorReporter.hpp b/storage/ndb/src/kernel/error/ErrorReporter.hpp index 0ec84190238..dffec14dff2 100644 --- a/storage/ndb/src/kernel/error/ErrorReporter.hpp +++ b/storage/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/storage/ndb/src/kernel/error/ndbd_exit_codes.c b/storage/ndb/src/kernel/error/ndbd_exit_codes.c index 8ed3b3a5cbb..f6672c77fc9 100644 --- a/storage/ndb/src/kernel/error/ndbd_exit_codes.c +++ b/storage/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/storage/ndb/src/kernel/vm/Configuration.cpp b/storage/ndb/src/kernel/vm/Configuration.cpp index 81b87c818fb..48868309d25 100644 --- a/storage/ndb/src/kernel/vm/Configuration.cpp +++ b/storage/ndb/src/kernel/vm/Configuration.cpp @@ -191,7 +191,7 @@ Configuration::init(int argc, char** argv) } if (! (val > 0 && val < MAX_NDB_NODES)) { - ndbout_c("Invalid nodeid specified in nowait-nodes: %d : %s", + ndbout_c("Invalid nodeid specified in nowait-nodes: %ld : %s", val, _nowait_nodes); exit(-1); } diff --git a/storage/ndb/src/kernel/vm/DLHashTable.hpp b/storage/ndb/src/kernel/vm/DLHashTable.hpp index 4f580f937b7..7469dda7917 100644 --- a/storage/ndb/src/kernel/vm/DLHashTable.hpp +++ b/storage/ndb/src/kernel/vm/DLHashTable.hpp @@ -287,6 +287,7 @@ DLHashTableImpl<P, T, U>::remove(Ptr<T> & ptr, const T & key) Uint32 i; T * p; Ptr<T> prev; + LINT_INIT(prev.p); prev.i = RNIL; i = hashValues[hv]; diff --git a/storage/ndb/src/kernel/vm/RWPool.hpp b/storage/ndb/src/kernel/vm/RWPool.hpp index c1f4abeed79..a4ad12b52cf 100644 --- a/storage/ndb/src/kernel/vm/RWPool.hpp +++ b/storage/ndb/src/kernel/vm/RWPool.hpp @@ -70,6 +70,7 @@ RWPool::getPtr(Uint32 i) return record; } handle_invalid_get_ptr(i); + return 0; /* purify: deadcode */ } #endif diff --git a/storage/ndb/src/kernel/vm/Rope.cpp b/storage/ndb/src/kernel/vm/Rope.cpp index 0c90d8f65d5..afe08e063a9 100644 --- a/storage/ndb/src/kernel/vm/Rope.cpp +++ b/storage/ndb/src/kernel/vm/Rope.cpp @@ -30,8 +30,8 @@ ConstRope::copy(char* buf) const { int ConstRope::compare(const char * str, size_t len) const { if(DEBUG_ROPE) - ndbout_c("ConstRope[ %d 0x%x 0x%x ]::compare(%s, %d)", - head.used, head.firstItem, head.lastItem, str, len); + ndbout_c("ConstRope[ %d 0x%x 0x%x ]::compare(%s, %d)", + head.used, head.firstItem, head.lastItem, str, (int) len); Uint32 left = head.used > len ? len : head.used; Ptr<Segment> curr; curr.i = head.firstItem; @@ -60,7 +60,7 @@ ConstRope::compare(const char * str, size_t len) const { } } if(DEBUG_ROPE) - ndbout_c("ConstRope::compare(%s, %d) -> %d", str, len, head.used > len); + ndbout_c("ConstRope::compare(%s, %d) -> %d", str, (int) len, head.used > len); return head.used > len; } @@ -91,7 +91,7 @@ Rope::copy(char* buf) const { int Rope::compare(const char * str, size_t len) const { if(DEBUG_ROPE) - ndbout_c("Rope::compare(%s, %d)", str, len); + ndbout_c("Rope::compare(%s, %d)", str, (int) len); Uint32 left = head.used > len ? len : head.used; Ptr<Segment> curr; curr.i = head.firstItem; @@ -100,7 +100,7 @@ Rope::compare(const char * str, size_t len) const { int res = memcmp(str, (const char*)curr.p->data, 4 * getSegmentSize()); if(res != 0){ if(DEBUG_ROPE) - ndbout_c("Rope::compare(%s, %d, %s) -> %d", str, len, + ndbout_c("Rope::compare(%s, %d, %s) -> %d", str, (int) len, (const char*)curr.p->data, res); return res; } @@ -115,19 +115,19 @@ Rope::compare(const char * str, size_t len) const { int res = memcmp(str, (const char*)curr.p->data, left); if(res){ if(DEBUG_ROPE) - ndbout_c("Rope::compare(%s, %d) -> %d", str, len, res); + ndbout_c("Rope::compare(%s, %d) -> %d", str, (int) len, res); return res; } } if(DEBUG_ROPE) - ndbout_c("Rope::compare(%s, %d) -> %d", str, len, head.used > len); + ndbout_c("Rope::compare(%s, %d) -> %d", str, (int) len, head.used > len); return head.used > len; } bool Rope::assign(const char * s, size_t len, Uint32 hash){ if(DEBUG_ROPE) - ndbout_c("Rope::assign(%s, %d, 0x%x)", s, len, hash); + ndbout_c("Rope::assign(%s, %d, 0x%x)", s, (int) len, hash); m_hash = hash; head.used = (head.used + 3) / 4; release(); diff --git a/storage/ndb/src/kernel/vm/SimulatedBlock.cpp b/storage/ndb/src/kernel/vm/SimulatedBlock.cpp index 4e01038d343..1d6676287e8 100644 --- a/storage/ndb/src/kernel/vm/SimulatedBlock.cpp +++ b/storage/ndb/src/kernel/vm/SimulatedBlock.cpp @@ -1930,6 +1930,7 @@ SimulatedBlock::xfrm_attr(Uint32 attrDesc, CHARSET_INFO* cs, { jam(); Uint32 len; + LINT_INIT(len); switch(array){ case NDB_ARRAYTYPE_SHORT_VAR: len = 1 + srcPtr[0]; diff --git a/storage/ndb/src/kernel/vm/TransporterCallback.cpp b/storage/ndb/src/kernel/vm/TransporterCallback.cpp index f315918b871..badd2af669c 100644 --- a/storage/ndb/src/kernel/vm/TransporterCallback.cpp +++ b/storage/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/storage/ndb/src/kernel/vm/WOPool.hpp b/storage/ndb/src/kernel/vm/WOPool.hpp index 6b42218368c..ed0d09d2f04 100644 --- a/storage/ndb/src/kernel/vm/WOPool.hpp +++ b/storage/ndb/src/kernel/vm/WOPool.hpp @@ -115,6 +115,7 @@ WOPool::getPtr(Uint32 i) return record; } handle_invalid_get_ptr(i); + return 0; /* purify: deadcode */ } #endif diff --git a/storage/ndb/src/kernel/vm/ndbd_malloc_impl.cpp b/storage/ndb/src/kernel/vm/ndbd_malloc_impl.cpp index 7b8795f7ecb..4de8f8ee479 100644 --- a/storage/ndb/src/kernel/vm/ndbd_malloc_impl.cpp +++ b/storage/ndb/src/kernel/vm/ndbd_malloc_impl.cpp @@ -223,6 +223,10 @@ Ndbd_mem_manager::init(bool alloc_less_memory) InitChunk chunk; Uint32 remaining = pages - allocated; +#if defined(_lint) || defined(FORCE_INIT_OF_VARS) + memset((char*) &chunk, 0 , sizeof(chunk)); +#endif + if (do_malloc(pages - allocated, &chunk)) { Uint32 i = 0; diff --git a/storage/ndb/src/mgmapi/mgmapi.cpp b/storage/ndb/src/mgmapi/mgmapi.cpp index 9bac1ed43f3..e042a2a569a 100644 --- a/storage/ndb/src/mgmapi/mgmapi.cpp +++ b/storage/ndb/src/mgmapi/mgmapi.cpp @@ -184,7 +184,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", (ulong) h)); DBUG_RETURN(h); } @@ -201,7 +201,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", (ulong) handle)); handle->cfg.~LocalConfig(); new (&(handle->cfg)) LocalConfig; if (!handle->cfg.init(mgmsrv, 0) || @@ -243,7 +243,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", (ulong) (* handle))); /** * important! only disconnect if connected * other code relies on this @@ -2612,8 +2612,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/storage/ndb/src/mgmclient/CommandInterpreter.cpp b/storage/ndb/src/mgmclient/CommandInterpreter.cpp index 5ac4d1adf64..47204ff6b51 100644 --- a/storage/ndb/src/mgmclient/CommandInterpreter.cpp +++ b/storage/ndb/src/mgmclient/CommandInterpreter.cpp @@ -598,7 +598,7 @@ static const char* helpTextDebug = ; #endif -struct { +struct st_cmd_help { const char *cmd; const char * help; }help_items[]={ @@ -1558,6 +1558,8 @@ CommandInterpreter::executeShow(char* parameters) case NDB_MGM_NODE_TYPE_UNKNOWN: ndbout << "Error: Unknown Node Type" << endl; return -1; + case NDB_MGM_NODE_TYPE_MAX: + break; /* purify: deadcode */ } } @@ -2401,7 +2403,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/storage/ndb/src/mgmsrv/Makefile.am b/storage/ndb/src/mgmsrv/Makefile.am index 3ee39767834..d0c1b1219a4 100644 --- a/storage/ndb/src/mgmsrv/Makefile.am +++ b/storage/ndb/src/mgmsrv/Makefile.am @@ -23,7 +23,7 @@ INCLUDES_LOC = -I$(top_srcdir)/storage/ndb/src/ndbapi \ -I$(top_srcdir)/storage/ndb/src/common/mgmcommon \ -I$(top_srcdir)/storage/ndb/src/mgmclient -LDADD_LOC = $(top_srcdir)/storage/ndb/src/mgmclient/CommandInterpreter.o \ +LDADD_LOC = $(top_builddir)/storage/ndb/src/mgmclient/CommandInterpreter.o \ $(top_builddir)/storage/ndb/src/libndbclient.la \ $(top_builddir)/dbug/libdbug.a \ $(top_builddir)/mysys/libmysys.a \ diff --git a/storage/ndb/src/mgmsrv/MgmtSrvr.cpp b/storage/ndb/src/mgmsrv/MgmtSrvr.cpp index 222b71dbaac..58369141ba3 100644 --- a/storage/ndb/src/mgmsrv/MgmtSrvr.cpp +++ b/storage/ndb/src/mgmsrv/MgmtSrvr.cpp @@ -830,7 +830,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; @@ -1568,7 +1568,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; @@ -2075,8 +2075,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" @@ -2495,7 +2495,7 @@ MgmtSrvr::startBackup(Uint32& backupId, int waitCompleted) const BackupCompleteRep * const rep = CAST_CONSTPTR(BackupCompleteRep, signal->getDataPtr()); #ifdef VM_TRACE - ndbout_c("Backup(%d) completed %d", rep->backupId); + ndbout_c("Backup(%d) completed", rep->backupId); #endif event.Event = BackupEvent::BackupCompleted; event.Completed.BackupId = rep->backupId; @@ -2751,7 +2751,7 @@ MgmtSrvr::setDbParameter(int node, int param, const char * value, break; case 1: res = i2.set(param, val_64); - ndbout_c("Updating node %d param: %d to %Ld", node, param, val_32); + ndbout_c("Updating node %d param: %d to %u", node, param, val_32); break; case 2: res = i2.set(param, val_char); diff --git a/storage/ndb/src/mgmsrv/Services.cpp b/storage/ndb/src/mgmsrv/Services.cpp index 80dd040eb1b..d3272fc9de2 100644 --- a/storage/ndb/src/mgmsrv/Services.cpp +++ b/storage/ndb/src/mgmsrv/Services.cpp @@ -1716,7 +1716,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/storage/ndb/src/ndbapi/ClusterMgr.cpp b/storage/ndb/src/ndbapi/ClusterMgr.cpp index e5b835e4560..ef0bf51cc2b 100644 --- a/storage/ndb/src/ndbapi/ClusterMgr.cpp +++ b/storage/ndb/src/ndbapi/ClusterMgr.cpp @@ -195,7 +195,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/storage/ndb/src/ndbapi/DictCache.cpp b/storage/ndb/src/ndbapi/DictCache.cpp index c06bb6fc62a..aa42c1a1bab 100644 --- a/storage/ndb/src/ndbapi/DictCache.cpp +++ b/storage/ndb/src/ndbapi/DictCache.cpp @@ -129,7 +129,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(); @@ -416,7 +417,7 @@ GlobalDictCache::alter_table_rep(const char * name, { TableVersion & ver = (* vers)[i]; if(ver.m_version == tableVersion && ver.m_impl && - ver.m_impl->m_id == tableId) + (Uint32) ver.m_impl->m_id == tableId) { ver.m_status = DROPPED; ver.m_impl->m_status = altered ? diff --git a/storage/ndb/src/ndbapi/Ndb.cpp b/storage/ndb/src/ndbapi/Ndb.cpp index 15ef596deef..ca5fd07d724 100644 --- a/storage/ndb/src/ndbapi/Ndb.cpp +++ b/storage/ndb/src/ndbapi/Ndb.cpp @@ -342,8 +342,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 { @@ -364,7 +365,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){ @@ -389,8 +390,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); @@ -477,8 +479,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())); @@ -765,7 +768,7 @@ Ndb::getAutoIncrementValue(const char* aTableName, TupleIdRange & range = info->m_tuple_id_range; if (getTupleIdFromNdb(table, range, tupleId, cacheSize) == -1) DBUG_RETURN(-1); - DBUG_PRINT("info", ("value %llu", (ulonglong)tupleId)); + DBUG_PRINT("info", ("value %lu", (ulong) tupleId)); DBUG_RETURN(0); } @@ -788,7 +791,7 @@ Ndb::getAutoIncrementValue(const NdbDictionary::Table * aTable, TupleIdRange & range = info->m_tuple_id_range; if (getTupleIdFromNdb(table, range, tupleId, cacheSize) == -1) DBUG_RETURN(-1); - DBUG_PRINT("info", ("value %llu", (ulonglong)tupleId)); + DBUG_PRINT("info", ("value %lu", (ulong)tupleId)); DBUG_RETURN(0); } @@ -803,7 +806,7 @@ Ndb::getAutoIncrementValue(const NdbDictionary::Table * aTable, if (getTupleIdFromNdb(table, range, tupleId, cacheSize) == -1) DBUG_RETURN(-1); - DBUG_PRINT("info", ("value %llu", (ulonglong)tupleId)); + DBUG_PRINT("info", ("value %lu", (ulong)tupleId)); DBUG_RETURN(0); } @@ -816,7 +819,7 @@ Ndb::getTupleIdFromNdb(const NdbTableImpl* table, { assert(range.m_first_tuple_id < range.m_last_tuple_id); tupleId = ++range.m_first_tuple_id; - DBUG_PRINT("info", ("next cached value %llu", (ulonglong)tupleId)); + DBUG_PRINT("info", ("next cached value %lu", (ulong)tupleId)); } else { @@ -853,7 +856,7 @@ Ndb::readAutoIncrementValue(const char* aTableName, TupleIdRange & range = info->m_tuple_id_range; if (readTupleIdFromNdb(table, range, tupleId) == -1) DBUG_RETURN(-1); - DBUG_PRINT("info", ("value %llu", (ulonglong)tupleId)); + DBUG_PRINT("info", ("value %lu", (ulong)tupleId)); DBUG_RETURN(0); } @@ -876,7 +879,7 @@ Ndb::readAutoIncrementValue(const NdbDictionary::Table * aTable, TupleIdRange & range = info->m_tuple_id_range; if (readTupleIdFromNdb(table, range, tupleId) == -1) DBUG_RETURN(-1); - DBUG_PRINT("info", ("value %llu", (ulonglong)tupleId)); + DBUG_PRINT("info", ("value %lu", (ulong)tupleId)); DBUG_RETURN(0); } @@ -890,7 +893,7 @@ Ndb::readAutoIncrementValue(const NdbDictionary::Table * aTable, if (readTupleIdFromNdb(table, range, tupleId) == -1) DBUG_RETURN(-1); - DBUG_PRINT("info", ("value %llu", (ulonglong)tupleId)); + DBUG_PRINT("info", ("value %lu", (ulong)tupleId)); DBUG_RETURN(0); } @@ -991,8 +994,8 @@ Ndb::setTupleIdInNdb(const NdbTableImpl* table, { range.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); } } @@ -1046,7 +1049,8 @@ Ndb::opTupleIdOnNdb(const NdbTableImpl* table, { DBUG_ENTER("Ndb::opTupleIdOnNdb"); Uint32 aTableId = table->m_id; - 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 = NULL; NdbOperation* tOperation = NULL; @@ -1114,8 +1118,8 @@ Ndb::opTupleIdOnNdb(const NdbTableImpl* table, else { DBUG_PRINT("info", - ("Setting next auto increment value (db) to %llu", - (ulonglong)opValue)); + ("Setting next auto increment value (db) to %lu", + (ulong) opValue)); range.m_first_tuple_id = range.m_last_tuple_id = opValue - 1; } break; @@ -1241,9 +1245,9 @@ int Ndb::setDatabaseAndSchemaName(const NdbDictionary::Table* t) if (s2 && s2 != s1 + 1) { char buf[NAME_LEN + 1]; if (s1 - s0 <= NAME_LEN && s2 - (s1 + 1) <= NAME_LEN) { - sprintf(buf, "%.*s", s1 - s0, s0); + sprintf(buf, "%.*s", (int) (s1 - s0), s0); setDatabaseName(buf); - sprintf(buf, "%.*s", s2 - (s1 + 1), s1 + 1); + sprintf(buf, "%.*s", (int) (s2 - (s1 + 1)), s1 + 1); setDatabaseSchemaName(buf); return 0; } diff --git a/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp b/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp index d626be1bd72..40eb815d48b 100644 --- a/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp +++ b/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp @@ -3583,7 +3583,7 @@ NdbDictInterface::createEvent(class Ndb & ndb, evnt.mi_type = evntConf->getEventType(); evnt.setTable(dataPtr); } else { - if (evnt.m_tableImpl->m_id != evntConf->getTableId() || + if ((Uint32) evnt.m_tableImpl->m_id != evntConf->getTableId() || evnt.m_tableImpl->m_version != evntConf->getTableVersion() || //evnt.m_attrListBitmask != evntConf->getAttrListBitmask() || evnt.mi_type != evntConf->getEventType()) { @@ -3701,7 +3701,7 @@ NdbDictionaryImpl::getEvent(const char * eventName, NdbTableImpl* tab) DBUG_RETURN(NULL); } if ((tab->m_status != NdbDictionary::Object::Retrieved) || - (tab->m_id != ev->m_table_id) || + ((Uint32) tab->m_id != ev->m_table_id) || (table_version_major(tab->m_version) != table_version_major(ev->m_table_version))) { @@ -3731,7 +3731,7 @@ NdbDictionaryImpl::getEvent(const char * eventName, NdbTableImpl* tab) DBUG_PRINT("info",("Table: id: %d version: %d", table.m_id, table.m_version)); - if (table.m_id != ev->m_table_id || + if ((Uint32) table.m_id != ev->m_table_id || table_version_major(table.m_version) != table_version_major(ev->m_table_version)) { @@ -3747,7 +3747,7 @@ NdbDictionaryImpl::getEvent(const char * eventName, NdbTableImpl* tab) #endif - if ( attributeList_sz > table.getNoOfColumns() ) + if ( attributeList_sz > (uint) table.getNoOfColumns() ) { m_error.code = 241; DBUG_PRINT("error",("Invalid version, too many columns")); @@ -3757,7 +3757,7 @@ NdbDictionaryImpl::getEvent(const char * eventName, NdbTableImpl* tab) assert( (int)attributeList_sz <= table.getNoOfColumns() ); for(unsigned id= 0; ev->m_columns.size() < attributeList_sz; id++) { - if ( id >= table.getNoOfColumns()) + if ( id >= (uint) table.getNoOfColumns()) { m_error.code = 241; DBUG_PRINT("error",("Invalid version, column %d out of range", id)); diff --git a/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp b/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp index 08b98cf7b48..1996dec024a 100644 --- a/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp +++ b/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp @@ -58,7 +58,7 @@ print_std(const SubTableData * sdata, LinearSectionPtr ptr[3]) SubTableData::getOperation(sdata->requestInfo)); for (int i = 0; i <= 2; i++) { printf("sec=%d addr=%p sz=%d\n", i, (void*)ptr[i].p, ptr[i].sz); - for (int j = 0; j < ptr[i].sz; j++) + for (int j = 0; (uint) j < ptr[i].sz; j++) printf("%08x ", ptr[i].p[j]); printf("\n"); } @@ -199,11 +199,11 @@ NdbEventOperationImpl::init(NdbEventImpl& evnt) m_mergeEvents = false; #endif m_ref_count = 0; - DBUG_PRINT("info", ("m_ref_count = 0 for op: %p", this)); + DBUG_PRINT("info", ("m_ref_count = 0 for op: 0x%lx", (long) this)); m_has_error= 0; - DBUG_PRINT("exit",("this: 0x%x oid: %u", this, m_oid)); + DBUG_PRINT("exit",("this: 0x%lx oid: %u", (long) this, m_oid)); DBUG_VOID_RETURN; } @@ -739,8 +739,8 @@ NdbEventOperationImpl::receive_event() NdbTableImpl *tmp_table_impl= m_eventImpl->m_tableImpl; m_eventImpl->m_tableImpl = at; - DBUG_PRINT("info", ("switching table impl 0x%x -> 0x%x", - tmp_table_impl, at)); + DBUG_PRINT("info", ("switching table impl 0x%lx -> 0x%lx", + (long) tmp_table_impl, (long) at)); // change the rec attrs to refer to the new table object int i; @@ -751,9 +751,9 @@ NdbEventOperationImpl::receive_event() { int no = p->getColumn()->getColumnNo(); NdbColumnImpl *tAttrInfo = at->getColumn(no); - DBUG_PRINT("info", ("rec_attr: 0x%x " - "switching column impl 0x%x -> 0x%x", - p, p->m_column, tAttrInfo)); + DBUG_PRINT("info", ("rec_attr: 0x%lx " + "switching column impl 0x%lx -> 0x%lx", + (long) p, (long) p->m_column, (long) tAttrInfo)); p->m_column = tAttrInfo; p = p->next(); } @@ -765,9 +765,9 @@ NdbEventOperationImpl::receive_event() { int no = p->getColumn()->getColumnNo(); NdbColumnImpl *tAttrInfo = at->getColumn(no); - DBUG_PRINT("info", ("rec_attr: 0x%x " - "switching column impl 0x%x -> 0x%x", - p, p->m_column, tAttrInfo)); + DBUG_PRINT("info", ("rec_attr: 0x%lx " + "switching column impl 0x%lx -> 0x%lx", + (long) p, (long) p->m_column, (long) tAttrInfo)); p->m_column = tAttrInfo; p = p->next(); } @@ -1269,8 +1269,9 @@ NdbEventBuffer::getGCIEventOperations(Uint32* iter, Uint32* event_types) EventBufData_list::Gci_op g = gci_ops->m_gci_op_list[(*iter)++]; if (event_types != NULL) *event_types = g.event_types; - DBUG_PRINT("info", ("gci: %d g.op: %x g.event_types: %x", - (unsigned)gci_ops->m_gci, g.op, g.event_types)); + DBUG_PRINT("info", ("gci: %u g.op: 0x%lx g.event_types: 0x%lx", + (unsigned)gci_ops->m_gci, (long) g.op, + (long) g.event_types)); DBUG_RETURN(g.op); } DBUG_RETURN(NULL); @@ -1507,9 +1508,9 @@ NdbEventBuffer::execSUB_GCP_COMPLETE_REP(const SubGcpCompleteRep * const rep) else { /** out of order something */ - ndbout_c("out of order bucket: %d gci: %lld m_latestGCI: %lld", - bucket-(Gci_container*)m_active_gci.getBase(), - gci, m_latestGCI); + ndbout_c("out of order bucket: %d gci: %ld m_latestGCI: %ld", + (int) (bucket-(Gci_container*)m_active_gci.getBase()), + (long) gci, (long) m_latestGCI); bucket->m_state = Gci_container::GC_COMPLETE; bucket->m_gcp_complete_rep_count = 1; // Prevent from being reused m_latest_complete_GCI = gci; @@ -1563,8 +1564,8 @@ NdbEventBuffer::complete_outof_order_gcis() #endif m_complete_data.m_data.append_list(&bucket->m_data, start_gci); #ifdef VM_TRACE - ndbout_c(" moved %lld rows -> %lld", bucket->m_data.m_count, - m_complete_data.m_data.m_count); + ndbout_c(" moved %ld rows -> %ld", (long) bucket->m_data.m_count, + (long) m_complete_data.m_data.m_count); #else ndbout_c(""); #endif @@ -2180,7 +2181,7 @@ NdbEventBuffer::merge_data(const SubTableData * const sdata, Ev_t* tp = 0; int i; - for (i = 0; i < sizeof(ev_t)/sizeof(ev_t[0]); i++) { + for (i = 0; (uint) i < sizeof(ev_t)/sizeof(ev_t[0]); i++) { if (ev_t[i].t1 == t1 && ev_t[i].t2 == t2) { tp = &ev_t[i]; break; diff --git a/storage/ndb/src/ndbapi/NdbIndexOperation.cpp b/storage/ndb/src/ndbapi/NdbIndexOperation.cpp index 39dbab423d3..9faf66a1e98 100644 --- a/storage/ndb/src/ndbapi/NdbIndexOperation.cpp +++ b/storage/ndb/src/ndbapi/NdbIndexOperation.cpp @@ -64,6 +64,9 @@ NdbIndexOperation::indxInit(const NdbIndexImpl * anIndex, case(NdbDictionary::Index::OrderedIndex): setErrorCodeAbort(4003); return -1; + default: + DBUG_ASSERT(0); + break; } m_theIndex = anIndex; m_accessTable = anIndex->m_table; diff --git a/storage/ndb/src/ndbapi/NdbIndexStat.cpp b/storage/ndb/src/ndbapi/NdbIndexStat.cpp index e490290b6a2..4ae00348606 100644 --- a/storage/ndb/src/ndbapi/NdbIndexStat.cpp +++ b/storage/ndb/src/ndbapi/NdbIndexStat.cpp @@ -236,7 +236,7 @@ NdbIndexStat::stat_search(const Area& a, const Uint32* key, Uint32 keylen, Uint3 int NdbIndexStat::stat_oldest(const Area& a) { - Uint32 i, k, m; + Uint32 i, k= 0, m; bool found = false; m = ~(Uint32)0; // shut up incorrect CC warning for (i = 0; i < a.m_entries; i++) { diff --git a/storage/ndb/src/ndbapi/NdbOperationDefine.cpp b/storage/ndb/src/ndbapi/NdbOperationDefine.cpp index 6915a91dd12..d14fcf60ec4 100644 --- a/storage/ndb/src/ndbapi/NdbOperationDefine.cpp +++ b/storage/ndb/src/ndbapi/NdbOperationDefine.cpp @@ -408,9 +408,9 @@ NdbOperation::setValue( const NdbColumnImpl* tAttrInfo, const char* aValuePassed) { DBUG_ENTER("NdbOperation::setValue"); - DBUG_PRINT("enter", ("col=%s op=%d val=%p", + DBUG_PRINT("enter", ("col: %s op:%d val: 0x%lx", tAttrInfo->m_name.c_str(), theOperationType, - aValuePassed)); + (long) aValuePassed)); int tReturnCode; Uint32 tAttrId; diff --git a/storage/ndb/src/ndbapi/NdbOperationExec.cpp b/storage/ndb/src/ndbapi/NdbOperationExec.cpp index 3d8a1d1b93a..38e0b441346 100644 --- a/storage/ndb/src/ndbapi/NdbOperationExec.cpp +++ b/storage/ndb/src/ndbapi/NdbOperationExec.cpp @@ -207,7 +207,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/storage/ndb/src/ndbapi/NdbOperationInt.cpp b/storage/ndb/src/ndbapi/NdbOperationInt.cpp index e33e8b09dca..b7fda205450 100644 --- a/storage/ndb/src/ndbapi/NdbOperationInt.cpp +++ b/storage/ndb/src/ndbapi/NdbOperationInt.cpp @@ -1021,8 +1021,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); @@ -1091,53 +1091,61 @@ NdbOperation::branch_col(Uint32 type, int NdbOperation::branch_col_eq(Uint32 ColId, const void * val, Uint32 len, bool nopad, Uint32 Label){ - INT_DEBUG(("branch_col_eq %u %.*s(%u,%d) -> %u", ColId, len, val, len, nopad, Label)); + INT_DEBUG(("branch_col_eq %u %.*s(%u,%d) -> %u", ColId, len, (char*) val, len, + nopad, Label)); return branch_col(Interpreter::EQ, ColId, val, len, nopad, Label); } int NdbOperation::branch_col_ne(Uint32 ColId, const void * val, Uint32 len, bool nopad, Uint32 Label){ - INT_DEBUG(("branch_col_ne %u %.*s(%u,%d) -> %u", ColId, len, val, len, nopad, Label)); + INT_DEBUG(("branch_col_ne %u %.*s(%u,%d) -> %u", ColId, len, (char*) val, len, + nopad, Label)); return branch_col(Interpreter::NE, ColId, val, len, nopad, Label); } int NdbOperation::branch_col_lt(Uint32 ColId, const void * val, Uint32 len, bool nopad, Uint32 Label){ - INT_DEBUG(("branch_col_lt %u %.*s(%u,%d) -> %u", ColId, len, val, len, nopad, Label)); + INT_DEBUG(("branch_col_lt %u %.*s(%u,%d) -> %u", ColId, len, (char*) val, len, + nopad, Label)); return branch_col(Interpreter::LT, ColId, val, len, nopad, Label); } int NdbOperation::branch_col_le(Uint32 ColId, const void * val, Uint32 len, bool nopad, Uint32 Label){ - INT_DEBUG(("branch_col_le %u %.*s(%u,%d) -> %u", ColId, len, val, len, nopad, Label)); + INT_DEBUG(("branch_col_le %u %.*s(%u,%d) -> %u", ColId, len, (char*) val, len, + nopad, Label)); return branch_col(Interpreter::LE, ColId, val, len, nopad, Label); } int NdbOperation::branch_col_gt(Uint32 ColId, const void * val, Uint32 len, bool nopad, Uint32 Label){ - INT_DEBUG(("branch_col_gt %u %.*s(%u,%d) -> %u", ColId, len, val, len, nopad, Label)); + INT_DEBUG(("branch_col_gt %u %.*s(%u,%d) -> %u", ColId, len, (char*) val, len, + nopad, Label)); return branch_col(Interpreter::GT, ColId, val, len, nopad, Label); } int NdbOperation::branch_col_ge(Uint32 ColId, const void * val, Uint32 len, bool nopad, Uint32 Label){ - INT_DEBUG(("branch_col_ge %u %.*s(%u,%d) -> %u", ColId, len, val, len, nopad, Label)); + INT_DEBUG(("branch_col_ge %u %.*s(%u,%d) -> %u", ColId, len, (char*) val, len, + nopad, Label)); return branch_col(Interpreter::GE, ColId, val, len, nopad, Label); } int NdbOperation::branch_col_like(Uint32 ColId, const void * val, Uint32 len, bool nopad, Uint32 Label){ - INT_DEBUG(("branch_col_like %u %.*s(%u,%d) -> %u", ColId, len, val, len, nopad, Label)); + INT_DEBUG(("branch_col_like %u %.*s(%u,%d) -> %u", ColId, len, (char*) val, len, + nopad, Label)); return branch_col(Interpreter::LIKE, ColId, val, len, nopad, Label); } int NdbOperation::branch_col_notlike(Uint32 ColId, const void * val, Uint32 len, bool nopad, Uint32 Label){ - INT_DEBUG(("branch_col_notlike %u %.*s(%u,%d) -> %u", ColId,len,val,len,nopad,Label)); + INT_DEBUG(("branch_col_notlike %u %.*s(%u,%d) -> %u", ColId, len, (char*) val, len, + nopad, Label)); return branch_col(Interpreter::NOT_LIKE, ColId, val, len, nopad, Label); } diff --git a/storage/ndb/src/ndbapi/NdbOperationSearch.cpp b/storage/ndb/src/ndbapi/NdbOperationSearch.cpp index 65d50a55634..e7b8a59d9b2 100644 --- a/storage/ndb/src/ndbapi/NdbOperationSearch.cpp +++ b/storage/ndb/src/ndbapi/NdbOperationSearch.cpp @@ -57,9 +57,9 @@ NdbOperation::equal_impl(const NdbColumnImpl* tAttrInfo, const char* aValuePassed) { DBUG_ENTER("NdbOperation::equal_impl"); - DBUG_PRINT("enter", ("col=%s op=%d val=%p", + DBUG_PRINT("enter", ("col: %s op: %d val: 0x%lx", tAttrInfo->m_name.c_str(), theOperationType, - aValuePassed)); + (long) aValuePassed)); Uint32 tData; const char* aValue = aValuePassed; diff --git a/storage/ndb/src/ndbapi/NdbRecAttr.cpp b/storage/ndb/src/ndbapi/NdbRecAttr.cpp index 5931a00fcf7..edd48f50ce3 100644 --- a/storage/ndb/src/ndbapi/NdbRecAttr.cpp +++ b/storage/ndb/src/ndbapi/NdbRecAttr.cpp @@ -372,7 +372,12 @@ NdbOut& operator<<(NdbOut& out, const NdbRecAttr &r) j = length; } break; - unknown: + + case NdbDictionary::Column::Undefined: + case NdbDictionary::Column::Mediumint: + case NdbDictionary::Column::Mediumunsigned: + case NdbDictionary::Column::Longvarbinary: + unknown: //default: /* no print functions for the rest, just print type */ out << (int) r.getType(); j = length; diff --git a/storage/ndb/src/ndbapi/NdbScanOperation.cpp b/storage/ndb/src/ndbapi/NdbScanOperation.cpp index 2d47f79ee09..3e2081b6018 100644 --- a/storage/ndb/src/ndbapi/NdbScanOperation.cpp +++ b/storage/ndb/src/ndbapi/NdbScanOperation.cpp @@ -181,7 +181,8 @@ NdbScanOperation::readTuples(NdbScanOperation::LockMode lm, } bool rangeScan = false; - if (m_accessTable->m_indexType == NdbDictionary::Index::OrderedIndex) + if ( (int) m_accessTable->m_indexType == + (int) NdbDictionary::Index::OrderedIndex) { if (m_currentTable == m_accessTable){ // Old way of scanning indexes, should not be allowed @@ -588,7 +589,7 @@ err4: theNdbCon->theTransactionIsStarted = false; theNdbCon->theReleaseOnClose = true; - if(DEBUG_NEXT_RESULT) ndbout_c("return -1", retVal); + if(DEBUG_NEXT_RESULT) ndbout_c("return %d", retVal); return -1; } @@ -668,9 +669,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/storage/ndb/src/ndbapi/NdbTransaction.cpp b/storage/ndb/src/ndbapi/NdbTransaction.cpp index 0cbd67a38f6..0c59746c1e9 100644 --- a/storage/ndb/src/ndbapi/NdbTransaction.cpp +++ b/storage/ndb/src/ndbapi/NdbTransaction.cpp @@ -533,8 +533,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 @@ -1010,7 +1010,7 @@ 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", (ulong) this, (ulong) cursorOp)); releaseScanOperation(&m_firstExecutedScanOp, 0, cursorOp); diff --git a/storage/ndb/src/ndbapi/Ndbif.cpp b/storage/ndb/src/ndbapi/Ndbif.cpp index 5683ebe2e6f..599a38b287d 100644 --- a/storage/ndb/src/ndbapi/Ndbif.cpp +++ b/storage/ndb/src/ndbapi/Ndbif.cpp @@ -199,11 +199,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/storage/ndb/src/ndbapi/Ndbinit.cpp b/storage/ndb/src/ndbapi/Ndbinit.cpp index a8bfa143200..3b53c9484d4 100644 --- a/storage/ndb/src/ndbapi/Ndbinit.cpp +++ b/storage/ndb/src/ndbapi/Ndbinit.cpp @@ -43,7 +43,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; } @@ -132,7 +132,7 @@ void Ndb::setup(Ndb_cluster_connection *ndb_cluster_connection, Ndb::~Ndb() { DBUG_ENTER("Ndb::~Ndb()"); - DBUG_PRINT("enter",("this=0x%x",this)); + DBUG_PRINT("enter",("this: 0x%lx", (long) this)); if (m_sys_tab_0) getDictionary()->removeTableGlobal(*m_sys_tab_0, 0); @@ -146,12 +146,13 @@ Ndb::~Ndb() } doDisconnect(); - delete theEventBuffer; - + /* Disconnect from transporter to stop signals from coming in */ if (theImpl->m_transporter_facade != NULL && theNdbBlockNumber > 0){ theImpl->m_transporter_facade->close(theNdbBlockNumber, theFirstTransId); } - + + delete theEventBuffer; + releaseTransactionArrays(); delete []theConnectionArray; diff --git a/storage/ndb/src/ndbapi/Ndblist.cpp b/storage/ndb/src/ndbapi/Ndblist.cpp index f82348fc91d..a0d22466db4 100644 --- a/storage/ndb/src/ndbapi/Ndblist.cpp +++ b/storage/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", (ulong) aScanOperation)); #ifdef ndb_release_check_dup { NdbIndexScanOperation* tOp = theScanOpIdleList; while (tOp != NULL) { diff --git a/storage/ndb/src/ndbapi/ObjectMap.hpp b/storage/ndb/src/ndbapi/ObjectMap.hpp index e3db479f677..b211e2956dd 100644 --- a/storage/ndb/src/ndbapi/ObjectMap.hpp +++ b/storage/ndb/src/ndbapi/ObjectMap.hpp @@ -84,7 +84,7 @@ NdbObjectIdMap::map(void * object){ // unlock(); - DBUG_PRINT("info",("NdbObjectIdMap::map(0x%x) %u", object, ff<<2)); + DBUG_PRINT("info",("NdbObjectIdMap::map(0x%lx) %u", (long) object, ff<<2)); return ff<<2; } @@ -102,14 +102,16 @@ NdbObjectIdMap::unmap(Uint32 id, void *object){ m_map[i].m_next = m_firstFree; m_firstFree = i; } else { - ndbout_c("Error: NdbObjectIdMap::::unmap(%u, 0x%x) obj=0x%x", id, object, obj); - DBUG_PRINT("error",("NdbObjectIdMap::unmap(%u, 0x%x) obj=0x%x", id, object, obj)); + ndbout_c("Error: NdbObjectIdMap::::unmap(%u, 0x%lx) obj=0x%lx", + id, (long) object, (long) obj); + DBUG_PRINT("error",("NdbObjectIdMap::unmap(%u, 0x%lx) obj=0x%lx", + id, (long) object, (long) obj)); return 0; } // unlock(); - DBUG_PRINT("info",("NdbObjectIdMap::unmap(%u) obj=0x%x", id, obj)); + DBUG_PRINT("info",("NdbObjectIdMap::unmap(%u) obj=0x%lx", id, (long) obj)); return obj; } diff --git a/storage/ndb/src/ndbapi/ndb_cluster_connection.cpp b/storage/ndb/src/ndbapi/ndb_cluster_connection.cpp index 3ded8281b27..cae01877322 100644 --- a/storage/ndb/src/ndbapi/ndb_cluster_connection.cpp +++ b/storage/ndb/src/ndbapi/ndb_cluster_connection.cpp @@ -271,7 +271,7 @@ Ndb_cluster_connection_impl::Ndb_cluster_connection_impl(const char * m_latest_trans_gci(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)); if (!m_event_add_drop_mutex) m_event_add_drop_mutex= NdbMutex_Create(); diff --git a/storage/ndb/tools/desc.cpp b/storage/ndb/tools/desc.cpp index c042f745d9d..2a91d3215f5 100644 --- a/storage/ndb/tools/desc.cpp +++ b/storage/ndb/tools/desc.cpp @@ -131,7 +131,7 @@ int desc_logfilegroup(Ndb *myndb, char* name) assert(dict); NdbDictionary::LogfileGroup lfg= dict->getLogfileGroup(name); NdbError err= dict->getNdbError(); - if(err.classification!=ndberror_cl_none) + if( (int) err.classification != (int) ndberror_cl_none) return 0; ndbout << "Type: LogfileGroup" << endl; @@ -153,7 +153,7 @@ int desc_tablespace(Ndb *myndb, char* name) assert(dict); NdbDictionary::Tablespace ts= dict->getTablespace(name); NdbError err= dict->getNdbError(); - if(err.classification!=ndberror_cl_none) + if ((int) err.classification != (int) ndberror_cl_none) return 0; ndbout << "Type: Tablespace" << endl; @@ -175,11 +175,11 @@ int desc_undofile(Ndb_cluster_connection &con, Ndb *myndb, char* name) con.init_get_next_node(iter); - while(id= con.get_next_node(iter)) + while ((id= con.get_next_node(iter))) { NdbDictionary::Undofile uf= dict->getUndofile(0, name); NdbError err= dict->getNdbError(); - if(err.classification!=ndberror_cl_none) + if ((int) err.classification != (int) ndberror_cl_none) return 0; ndbout << "Type: Undofile" << endl; @@ -211,11 +211,11 @@ int desc_datafile(Ndb_cluster_connection &con, Ndb *myndb, char* name) con.init_get_next_node(iter); - while(id= con.get_next_node(iter)) + while ((id= con.get_next_node(iter))) { NdbDictionary::Datafile df= dict->getDatafile(id, name); NdbError err= dict->getNdbError(); - if(err.classification!=ndberror_cl_none) + if ((int) err.classification != (int) ndberror_cl_none) return 0; ndbout << "Type: Datafile" << endl; diff --git a/storage/ndb/tools/drop_index.cpp b/storage/ndb/tools/drop_index.cpp index aa207212dbe..c10211a9108 100644 --- a/storage/ndb/tools/drop_index.cpp +++ b/storage/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/storage/ndb/tools/drop_tab.cpp b/storage/ndb/tools/drop_tab.cpp index d14c60a2c6d..61df4ee9b34 100644 --- a/storage/ndb/tools/drop_tab.cpp +++ b/storage/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/storage/ndb/tools/ndb_condig.cpp b/storage/ndb/tools/ndb_condig.cpp index 8b862391c8e..049e4599447 100644 --- a/storage/ndb/tools/ndb_condig.cpp +++ b/storage/ndb/tools/ndb_condig.cpp @@ -114,6 +114,7 @@ struct Match int m_key; BaseString m_value; virtual int eval(const Iter&); + virtual ~Match() {} }; struct HostMatch : public Match @@ -127,6 +128,7 @@ struct Apply Apply(int val) { m_key = val;} int m_key; virtual int apply(const Iter&); + virtual ~Apply() {} }; struct NodeTypeApply : public Apply diff --git a/storage/ndb/tools/restore/Restore.cpp b/storage/ndb/tools/restore/Restore.cpp index ef535cf9e26..b51760266cb 100644 --- a/storage/ndb/tools/restore/Restore.cpp +++ b/storage/ndb/tools/restore/Restore.cpp @@ -300,7 +300,13 @@ RestoreMetaData::markSysTables() strcmp(tableName, "NDB$EVENTS_0") == 0 || strcmp(tableName, "sys/def/SYSTAB_0") == 0 || strcmp(tableName, "sys/def/NDB$EVENTS_0") == 0 || + /* + The following is for old MySQL versions, + before we changed the database name of the tables from + "cluster_replication" -> "cluster" -> "mysql" + */ strcmp(tableName, "cluster_replication/def/" NDB_APPLY_TABLE) == 0 || + strcmp(tableName, "cluster/def/" NDB_APPLY_TABLE) == 0 || strcmp(tableName, NDB_REP_DB "/def/" NDB_APPLY_TABLE) == 0 || strcmp(tableName, NDB_REP_DB "/def/" NDB_SCHEMA_TABLE)== 0 ) table->isSysTable = true; @@ -317,7 +323,7 @@ RestoreMetaData::markSysTables() Uint32 j; for (j = 0; j < getNoOfTables(); j++) { TableS* table = allTables[j]; - if (table->getTableId() == id1) { + if (table->getTableId() == (Uint32) id1) { if (table->isSysTable) blobTable->isSysTable = true; break; diff --git a/storage/ndb/tools/restore/consumer_restore.cpp b/storage/ndb/tools/restore/consumer_restore.cpp index 507058e2743..7524558a2d6 100644 --- a/storage/ndb/tools/restore/consumer_restore.cpp +++ b/storage/ndb/tools/restore/consumer_restore.cpp @@ -494,7 +494,7 @@ BackupRestore::object(Uint32 type, const void * ptr) NdbDictionary::Tablespace curr = dict->getTablespace(old.getName()); NdbError errobj = dict->getNdbError(); - if(errobj.classification == ndberror_cl_none) + if ((int) errobj.classification == (int) ndberror_cl_none) { NdbDictionary::Tablespace* currptr = new NdbDictionary::Tablespace(curr); NdbDictionary::Tablespace * null = 0; @@ -533,7 +533,7 @@ BackupRestore::object(Uint32 type, const void * ptr) NdbDictionary::LogfileGroup curr = dict->getLogfileGroup(old.getName()); NdbError errobj = dict->getNdbError(); - if(errobj.classification == ndberror_cl_none) + if ((int) errobj.classification == (int) ndberror_cl_none) { NdbDictionary::LogfileGroup* currptr = new NdbDictionary::LogfileGroup(curr); @@ -680,7 +680,7 @@ BackupRestore::table(const TableS & table){ return true; const NdbTableImpl & tmptab = NdbTableImpl::getImpl(* table.m_dictTable); - if(tmptab.m_indexType != NdbDictionary::Index::Undefined){ + if ((int) tmptab.m_indexType != (int) NdbDictionary::Index::Undefined){ m_indexes.push_back(table.m_dictTable); return true; } diff --git a/strings/ctype-bin.c b/strings/ctype-bin.c index 5758960ef6c..289b76c9e6e 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 c945164ac9c..c3848c64219 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 9b45d5a03b7..9d10ba82114 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))) diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c index df43eff3d73..5089db6bf48 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 6c3ceaf868b..8a4ed48bef5 100644 --- a/strings/ctype-utf8.c +++ b/strings/ctype-utf8.c @@ -2047,6 +2047,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) { @@ -2093,6 +2139,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) { @@ -2143,10 +2217,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); } @@ -2172,10 +2262,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); } @@ -4051,6 +4174,7 @@ static MY_CHARSET_HANDLER my_charset_filename_handler= my_strntoull_8bit, my_strntod_8bit, my_strtoll10_8bit, + my_strntoull10rnd_8bit, my_scan_8bit }; diff --git a/strings/decimal.c b/strings/decimal.c index 4ff2b5a693a..6070271c684 100644 --- a/strings/decimal.c +++ b/strings/decimal.c @@ -1042,7 +1042,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; } } @@ -1354,7 +1354,7 @@ int bin2decimal(char *from, decimal_t *to, int precision, int scale) } from+=i; *buf=x ^ mask; - if (((ulonglong)*buf) >= (ulonglong) 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 60548210b7d..a0e64d13b0c 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -193,6 +193,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 @@ -318,6 +320,7 @@ BuildMySQL "--enable-shared \ --with-example-storage-engine \ --with-blackhole-storage-engine \ --with-federated-storage-engine \ + --with-partition \ --with-big-tables \ --with-comment=\"MySQL Community Server - Debug (GPL)\"") @@ -328,7 +331,7 @@ then fi (cd mysql-debug-%{mysql_version}/mysql-test ; \ - ./mysql-test-run.pl --comment=debug --skip-rpl --skip-ndbcluster --force ; \ + ./mysql-test-run.pl --comment=debug --skip-rpl --skip-ndbcluster --force --report-features ; \ true) ############################################################################## @@ -348,6 +351,7 @@ BuildMySQL "--enable-shared \ --with-example-storage-engine \ --with-blackhole-storage-engine \ --with-federated-storage-engine \ + --with-partition \ --with-embedded-server \ --with-big-tables \ --with-comment=\"MySQL Community Server (GPL)\"") @@ -358,7 +362,7 @@ then fi cd mysql-release-%{mysql_version}/mysql-test -./mysql-test-run.pl --comment=normal --force --skip-ndbcluster --timer || true +./mysql-test-run.pl --comment=normal --force --skip-ndbcluster --timer --report-features || true ./mysql-test-run.pl --comment=ps --ps-protocol --force --skip-ndbcluster --timer || true ./mysql-test-run.pl --comment=normal+rowrepl --mysqld=--binlog-format=row --force --skip-ndbcluster --timer || true ./mysql-test-run.pl --comment=ps+rowrepl+NDB --ps-protocol --mysqld=--binlog-format=row --force --timer || true @@ -685,6 +689,18 @@ 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). + +* Mon Nov 13 2006 Joerg Bruehe <joerg@mysql.com> + +- Add "--with-partition" to all server builds. + +- Use "--report-features" in one test run per server build. + * Tue Aug 15 2006 Joerg Bruehe <joerg@mysql.com> - The "max" server is removed from packages, effective from 5.1.12-beta. diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index a44ada5dd72..d67ecb4c5e0 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -33,6 +33,7 @@ #include <errmsg.h> #include <my_getopt.h> #include <m_string.h> +#include <mysqld_error.h> #define VER "2.1" #define MAX_TEST_QUERY_LENGTH 300 /* MAX QUERY BUFFER LENGTH */ @@ -12017,13 +12018,21 @@ static void test_bug6081() rc= simple_command(mysql, COM_DROP_DB, current_db, (ulong)strlen(current_db), 0); - myquery(rc); + if (rc == 0 && mysql_errno(mysql) != ER_UNKNOWN_COM_ERROR) + { + myerror(NULL); /* purecov: inspected */ + die(__FILE__, __LINE__, "COM_DROP_DB failed"); /* purecov: inspected */ + } rc= simple_command(mysql, COM_DROP_DB, current_db, (ulong)strlen(current_db), 0); myquery_r(rc); rc= simple_command(mysql, COM_CREATE_DB, current_db, (ulong)strlen(current_db), 0); - myquery(rc); + if (rc == 0 && mysql_errno(mysql) != ER_UNKNOWN_COM_ERROR) + { + myerror(NULL); /* purecov: inspected */ + die(__FILE__, __LINE__, "COM_CREATE_DB failed"); /* purecov: inspected */ + } rc= simple_command(mysql, COM_CREATE_DB, current_db, (ulong)strlen(current_db), 0); myquery_r(rc); @@ -13686,7 +13695,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 +14838,8 @@ static void test_opt_reconnect() } +#ifndef EMBEDDED_LIBRARY + static void test_bug12744() { MYSQL_STMT *prep_stmt = NULL; @@ -14859,6 +14871,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() @@ -15471,6 +15485,24 @@ static void test_bug21206() } /* + Ensure we execute the status code while testing +*/ + +static void test_status() +{ + const char *status; + DBUG_ENTER("test_status"); + myheader("test_status"); + + if (!(status= mysql_stat(mysql))) + { + myerror("mysql_stat failed"); /* purecov: inspected */ + die(__FILE__, __LINE__, "mysql_stat failed"); /* purecov: inspected */ + } + DBUG_VOID_RETURN; +} + +/* Bug#21726: Incorrect result with multiple invocations of LAST_INSERT_ID @@ -15509,6 +15541,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 */ @@ -15786,6 +15963,9 @@ static struct my_tests_st my_tests[]= { { "test_bug19671", test_bug19671 }, { "test_bug21206", test_bug21206 }, { "test_bug21726", test_bug21726 }, + { "test_bug23383", test_bug23383 }, + { "test_bug21635", test_bug21635 }, + { "test_status", test_status}, { 0, 0 } }; diff --git a/tests/mysql_client_test.c.rej b/tests/mysql_client_test.c.rej new file mode 100644 index 00000000000..400ffee8a5e --- /dev/null +++ b/tests/mysql_client_test.c.rej @@ -0,0 +1,20 @@ +*************** +*** 15693,15700 **** + { "test_bug17667", test_bug17667 }, + { "test_bug15752", test_bug15752 }, + { "test_mysql_insert_id", test_mysql_insert_id }, +! { "test_bug19671", test_bug19671}, +! { "test_bug21206", test_bug21206}, + { 0, 0 } + }; + +--- 15776,15784 ---- + { "test_bug17667", test_bug17667 }, + { "test_bug15752", test_bug15752 }, + { "test_mysql_insert_id", test_mysql_insert_id }, +! { "test_bug19671", test_bug19671 }, +! { "test_bug21206", test_bug21206 }, +! { "test_bug21726", test_bug21726 }, + { 0, 0 } + }; + diff --git a/unittest/README.txt b/unittest/README.txt index e862a54e443..ea94a50595b 100644 --- a/unittest/README.txt +++ b/unittest/README.txt @@ -46,6 +46,8 @@ test won't be executed by 'make test' ! Documentation ------------- -There is Doxygen-generated documentation available at: +The generated documentation is temporarily placed at: - https://intranet.mysql.com/~mkindahl/mytap/html/ + http://www.kindahl.net/mytap/doc/ + +I will move it to a better place once I figure out where and how. diff --git a/unittest/mytap/Doxyfile b/unittest/mytap/Doxyfile index 8c23703e925..1b1c82b4c98 100644 --- a/unittest/mytap/Doxyfile +++ b/unittest/mytap/Doxyfile @@ -432,7 +432,7 @@ FILE_PATTERNS = # subdirectories should be searched for input files as well. Possible # values are YES and NO. If left blank NO is used. -RECURSIVE = YES +RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that # should excluded from the INPUT source files. This way you can easily @@ -457,14 +457,14 @@ EXCLUDE_PATTERNS = # directories that contain example code fragments that are included (see # the \include command). -EXAMPLE_PATH = +EXAMPLE_PATH = e # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. -EXAMPLE_PATTERNS = +EXAMPLE_PATTERNS = *.c # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude @@ -926,7 +926,7 @@ MACRO_EXPANSION = YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_PREDEFINED tags. -EXPAND_ONLY_PREDEF = NO +EXPAND_ONLY_PREDEF = YES # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. @@ -939,33 +939,34 @@ SEARCH_INCLUDES = YES INCLUDE_PATH = -# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard -# patterns (like *.h and *.hpp) to filter out the header-files in the -# directories. If left blank, the patterns specified with FILE_PATTERNS will -# be used. +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more +# wildcard patterns (like *.h and *.hpp) to filter out the +# header-files in the directories. If left blank, the patterns +# specified with FILE_PATTERNS will be used. INCLUDE_FILE_PATTERNS = -# The PREDEFINED tag can be used to specify one or more macro names that -# are defined before the preprocessor is started (similar to the -D option of -# gcc). The argument of the tag is a list of macros of the form: name -# or name=definition (no spaces). If the definition and the = are -# omitted =1 is assumed. +# The PREDEFINED tag can be used to specify one or more macro names +# that are defined before the preprocessor is started (similar to the +# -D option of gcc). The argument of the tag is a list of macros of +# the form: name or name=definition (no spaces). If the definition and +# the = are omitted =1 is assumed. PREDEFINED = -# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then -# this tag can be used to specify a list of macro names that should be expanded. -# The macro definition that is found in the sources will be used. -# Use the PREDEFINED tag if you want to use a different macro definition. +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES +# then this tag can be used to specify a list of macro names that +# should be expanded. The macro definition that is found in the +# sources will be used. Use the PREDEFINED tag if you want to use a +# different macro definition. -EXPAND_AS_DEFINED = +EXPAND_AS_DEFINED = __attribute__ -# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then -# doxygen's preprocessor will remove all function-like macros that are alone -# on a line, have an all uppercase name, and do not end with a semicolon. Such -# function macros are typically used for boiler-plate code, and will confuse the -# parser if not removed. +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are +# alone on a line, have an all uppercase name, and do not end with a +# semicolon. Such function macros are typically used for boiler-plate +# code, and will confuse the parser if not removed. SKIP_FUNCTION_MACROS = YES diff --git a/unittest/mytap/t/basic-t.c b/unittest/mytap/t/basic-t.c index bf4c1a9a664..16928509e8c 100644 --- a/unittest/mytap/t/basic-t.c +++ b/unittest/mytap/t/basic-t.c @@ -7,7 +7,7 @@ int main() { plan(5); ok(1 == 1, "testing basic functions"); - ok(2 == 2, ""); + ok(2 == 2, " "); ok(3 == 3, NULL); if (1 == 1) skip(2, "Sensa fragoli"); diff --git a/unittest/mytap/tap.c b/unittest/mytap/tap.c index 54292f3b828..e3a967ceb79 100644 --- a/unittest/mytap/tap.c +++ b/unittest/mytap/tap.c @@ -29,11 +29,17 @@ #include <signal.h> /** + @defgroup MyTAP_Internal MyTAP Internals + + Internal functions and data structures for the MyTAP implementation. +*/ + +/** Test data structure. Data structure containing all information about the test suite. - @ingroup MyTAP + @ingroup MyTAP_Internal */ static TEST_DATA g_test = { 0, 0, 0, "" }; @@ -41,6 +47,8 @@ static TEST_DATA g_test = { 0, 0, 0, "" }; Output stream for test report message. The macro is just a temporary solution. + + @ingroup MyTAP_Internal */ #define tapout stdout @@ -50,7 +58,7 @@ static TEST_DATA g_test = { 0, 0, 0, "" }; To emit the directive, use the emit_dir() function - @ingroup MyTAP + @ingroup MyTAP_Internal @see emit_dir @@ -59,7 +67,7 @@ static TEST_DATA g_test = { 0, 0, 0, "" }; @param ap Vararg list for the description string above. */ static void -emit_tap(int pass, char const *fmt, va_list ap) +vemit_tap(int pass, char const *fmt, va_list ap) { fprintf(tapout, "%sok %d%s", pass ? "" : "not ", @@ -80,18 +88,22 @@ emit_tap(int pass, char const *fmt, va_list ap) not ok 2 # todo some text explaining what remains @endcode + @ingroup MyTAP_Internal + @param dir Directive as a string - @param exp Explanation string + @param why Explanation string */ static void -emit_dir(const char *dir, const char *exp) +emit_dir(const char *dir, const char *why) { - fprintf(tapout, " # %s %s", dir, exp); + fprintf(tapout, " # %s %s", dir, why); } /** Emit a newline to the TAP output stream. + + @ingroup MyTAP_Internal */ static void emit_endl() @@ -198,7 +210,7 @@ ok(int const pass, char const *fmt, ...) if (!pass && *g_test.todo == '\0') ++g_test.failed; - emit_tap(pass, fmt, ap); + vemit_tap(pass, fmt, ap); va_end(ap); if (*g_test.todo != '\0') emit_dir("todo", g_test.todo); @@ -223,7 +235,8 @@ skip(int how_many, char const *const fmt, ...) while (how_many-- > 0) { va_list ap; - emit_tap(1, NULL, ap); + memset((char*) &ap, 0, sizeof(ap)); /* Keep compiler happy */ + vemit_tap(1, NULL, ap); emit_dir("skip", reason); emit_endl(); } @@ -316,7 +329,7 @@ int exit_status() { @section UnitTest Writing unit tests The purpose of writing unit tests is to use them to drive component - development towards a solution that the tests. This means that the + development towards a solution that passes the tests. This means that the unit tests has to be as complete as possible, testing at least: - Normal input @@ -325,29 +338,240 @@ int exit_status() { - Error handling - Bad environment - We will go over each case and explain it in more detail. + @subsection NormalSubSec Normal input + + This is to test that the component have the expected behaviour. + This is just plain simple: test that it works. For example, test + that you can unpack what you packed, adding gives the sum, pincing + the duck makes it quack. + + This is what everybody does when they write tests. + + + @subsection BorderlineTests Borderline cases + + If you have a size anywhere for your component, does it work for + size 1? Size 0? Sizes close to <code>UINT_MAX</code>? + + It might not be sensible to have a size 0, so in this case it is + not a borderline case, but rather a faulty input (see @ref + FaultyInputTests). + + + @subsection FaultyInputTests Faulty input + + Does your bitmap handle 0 bits size? Well, it might not be designed + for it, but is should <em>not</em> crash the application, but + rather produce an error. This is called defensive programming. - @subsection NormalSSec Normal input + Unfortunately, adding checks for values that should just not be + entered at all is not always practical: the checks cost cycles and + might cost more than it's worth. For example, some functions are + designed so that you may not give it a null pointer. In those + cases it's not sensible to pass it <code>NULL</code> just to see it + crash. - @subsection BorderlineSSec Borderline cases + Since every experienced programmer add an <code>assert()</code> to + ensure that you get a proper failure for the debug builds when a + null pointer passed (you add asserts too, right?), you will in this + case instead have a controlled (early) crash in the debug build. - @subsection FaultySSec Faulty input - @subsection ErrorSSec Error handling + @subsection ErrorHandlingTests Error handling - @subsection EnvironmentSSec Environment + This is testing that the errors your component is designed to give + actually are produced. For example, testing that trying to open a + non-existing file produces a sensible error code. + + + @subsection BadEnvironmentTests Environment Sometimes, modules has to behave well even when the environment - fails to work correctly. Typical examples are: out of dynamic - memory, disk is full, + fails to work correctly. Typical examples are when the computer is + out of dynamic memory or when the disk is full. You can emulate + this by replacing, e.g., <code>malloc()</code> with your own + version that will work for a while, but then fail. Some things are + worth to keep in mind here: + + - Make sure to make the function fail deterministically, so that + you really can repeat the test. + + - Make sure that it doesn't just fail immediately. The unit might + have checks for the first case, but might actually fail some time + in the near future. - @section UnitTestSec How to structure a unit test + + @section UnitTest How to structure a unit test In this section we will give some advice on how to structure the - unit tests to make the development run smoothly. + unit tests to make the development run smoothly. The basic + structure of a test is: + + - Plan + - Test + - Report + + + @subsection TestPlanning Plan the test + + Planning the test means telling how many tests there are. In the + event that one of the tests causes a crash, it is then possible to + see that there are fewer tests than expected, and print a proper + error message. + + To plan a test, use the @c plan() function in the following manner: + + @code + int main(int argc, char *argv[]) + { + plan(5); + . + . + . + } + @endcode + + If you don't call the @c plan() function, the number of tests + executed will be printed at the end. This is intended to be used + while developing the unit and you are constantly adding tests. It + is not indented to be used after the unit has been released. + - @subsection PieceSec Test each piece separately + @subsection TestRunning Execute the test + + To report the status of a test, the @c ok() function is used in the + following manner: + + @code + int main(int argc, char *argv[]) + { + plan(5); + ok(ducks == paddling_ducks, + "%d ducks did not paddle", ducks - paddling_ducks); + . + . + . + } + @endcode + + This will print a test result line on the standard output in TAP + format, which allows TAP handling frameworks (like Test::Harness) + to parse the status of the test. + + @subsection TestReport Report the result of the test + + At the end, a complete test report should be written, with some + statistics. If the test returns EXIT_SUCCESS, all tests were + successfull, otherwise at least one test failed. + + To get a TAP complient output and exit status, report the exit + status in the following manner: + + @code + int main(int argc, char *argv[]) + { + plan(5); + ok(ducks == paddling_ducks, + "%d ducks did not paddle", ducks - paddling_ducks); + . + . + . + return exit_status(); + } + @endcode + + @section DontDoThis Ways to not do unit testing + + In this section, we'll go through some quite common ways to write + tests that are <em>not</em> a good idea. + + @subsection BreadthFirstTests Doing breadth-first testing + + If you're writing a library with several functions, don't test all + functions using size 1, then all functions using size 2, etc. If a + test for size 42 fails, you have no easy way of tracking down why + it failed. + + It is better to concentrate on getting one function to work at a + time, which means that you test each function for all sizes that + you think is reasonable. Then you continue with the next function, + doing the same. This is usually also the way that a library is + developed (one function at a time) so stick to testing that is + appropriate for now the unit is developed. + + @subsection JustToBeSafeTest Writing unnecessarily large tests + + Don't write tests that use parameters in the range 1-1024 unless + you have a very good reason to belive that the component will + succeed for 562 but fail for 564 (the numbers picked are just + examples). + + It is very common to write extensive tests "just to be safe." + Having a test suite with a lot of values might give you a warm + fuzzy feeling, but it doesn't really help you find the bugs. Good + tests fail; seriously, if you write a test that you expect to + succeed, you don't need to write it. If you think that it + <em>might</em> fail, <em>then</em> you should write it. + + Don't take this as an excuse to avoid writing any tests at all + "since I make no mistakes" (when it comes to this, there are two + kinds of people: those who admit they make mistakes, and those who + don't); rather, this means that there is no reason to test that + using a buffer with size 100 works when you have a test for buffer + size 96. + + The drawback is that the test suite takes longer to run, for little + or no benefit. It is acceptable to do a exhaustive test if it + doesn't take too long to run and it is quite common to do an + exhaustive test of a function for a small set of values. + Use your judgment to decide what is excessive: your milage may + vary. +*/ + +/** + @example simple.t.c + + This is an simple example of how to write a test using the + library. The output of this program is: + + @code + 1..1 + # Testing basic functions + ok 1 - Testing gcs() + @endcode + + The basic structure is: plan the number of test points using the + plan() function, perform the test and write out the result of each + test point using the ok() function, print out a diagnostics message + using diag(), and report the result of the test by calling the + exit_status() function. Observe that this test does excessive + testing (see @ref JustToBeSafeTest), but the test point doesn't + take very long time. +*/ + +/** + @example todo.t.c + + This example demonstrates how to use the <code>todo_start()</code> + and <code>todo_end()</code> function to mark a sequence of tests to + be done. Observe that the tests are assumed to fail: if any test + succeeds, it is considered a "bonus". +*/ + +/** + @example skip.t.c + + This is an example of how the <code>SKIP_BLOCK_IF</code> can be + used to skip a predetermined number of tests. Observe that the + macro actually skips the following statement, but it's not sensible + to use anything than a block. +*/ + +/** + @example skip_all.t.c - Don't test all functions using size 1, then all functions using - size 2, etc. + Sometimes, you skip an entire test because it's testing a feature + that doesn't exist on the system that you're testing. To skip an + entire test, use the <code>skip_all()</code> function according to + this example. */ diff --git a/unittest/mytap/tap.h b/unittest/mytap/tap.h index 51b8c7df04d..a47060fa3cc 100644 --- a/unittest/mytap/tap.h +++ b/unittest/mytap/tap.h @@ -33,6 +33,8 @@ /** Data about test plan. + @ingroup MyTAP_Internal + @internal We are using the "typedef struct X { ... } X" idiom to create class/struct X both in C and C++. */ @@ -61,6 +63,14 @@ extern "C" { #endif /** + @defgroup MyTAP_API MyTAP API + + MySQL support for performing unit tests according to TAP. + + @{ +*/ + +/** Set number of tests that is planned to execute. The function also accepts the predefined constant @@ -101,11 +111,14 @@ void ok(int pass, char const *fmt, ...) /** Skip a determined number of tests. - Function to print that <em>how_many</em> tests have been - skipped. The reason is printed for each skipped test. Observe - that this function does not do the actual skipping for you, it just - prints information that tests have been skipped. It shall be used - in the following manner: + Function to print that <em>how_many</em> tests have been skipped. + The reason is printed for each skipped test. Observe that this + function does not do the actual skipping for you, it just prints + information that tests have been skipped. This function is not + usually used, but rather the macro @c SKIP_BLOCK_IF, which does the + skipping for you. + + It shall be used in the following manner: @code if (ducks == 0) { @@ -192,8 +205,8 @@ void BAIL_OUT(char const *fmt, ...) return exit_status(); @endcode - @returns EXIT_SUCCESS if all tests passed, EXIT_FAILURE if one or - more tests failed. + @returns @c EXIT_SUCCESS if all tests passed, @c EXIT_FAILURE if + one or more tests failed. */ int exit_status(void); @@ -242,6 +255,7 @@ void todo_start(char const *message, ...) void todo_end(); +/** @} */ #ifdef __cplusplus } diff --git a/vio/viossl.c b/vio/viossl.c index b5fd0e11c02..f436262a3ce 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 @@ -133,7 +133,7 @@ int vio_ssl_close(Vio *vio) 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 +151,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 +168,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 +226,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 +242,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 77eedab87e4..7bb2258532f 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 |