diff options
109 files changed, 2680 insertions, 745 deletions
diff --git a/BitKeeper/etc/collapsed b/BitKeeper/etc/collapsed index 37c2793cc12..3b45bb4f30c 100644 --- a/BitKeeper/etc/collapsed +++ b/BitKeeper/etc/collapsed @@ -1,3 +1,5 @@ 452a92d0-31-8wSzSfZi165fcGcXPA 454a7ef8gdvE_ddMlJyghvOAkKPNOQ 454f8960jsVT_kMKJtZ9OCgXoba0xQ +4554a95d7txO1DuO9G3nAizI3SkFAA +4554b3722d71SbPiI2Gx-RhbZjmuIQ diff --git a/BitKeeper/triggers/post-commit b/BitKeeper/triggers/post-commit index a09da93adaf..229553cdccf 100755 --- a/BitKeeper/triggers/post-commit +++ b/BitKeeper/triggers/post-commit @@ -28,9 +28,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 685eaeef7d1..85a362133a1 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) @@ -39,23 +39,23 @@ CLEAN_FILES: $(TXT_FILES) GT = $(srcdir)/Support/generate-text-files.pl -../INSTALL-SOURCE: mysql.info $(GT) - perl -w $(GT) $< "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) $< "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) $< "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-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) $< "mac-os-x-installation" "netware-installation" > $@ +../support-files/MacOSX/ReadMe.txt: $(srcdir)/mysql.info $(GT) + perl -w $(GT) $(srcdir)/mysql.info "mac-os-x-installation" "netware-installation" > $@ # Don't update the files from bitkeeper %::SCCS/s.% diff --git a/Makefile.am b/Makefile.am index 8d0746e6a64..36175ce55e4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -91,6 +91,7 @@ bin-dist: all # Remove BK's "SCCS" subdirectories from source distribution dist-hook: rm -rf `find $(distdir) -type d -name SCCS -print` + rm -f `find $(distdir) -type l -print` tags: support-files/build-tags @@ -114,6 +115,12 @@ test-force: ./mysql-test-run --force && \ ./mysql-test-run --ps-protocol --force +test-force-mem: + cd mysql-test; \ + ./mysql-test-run --force --mem && \ + ./mysql-test-run --ps-protocol --force --mem + + # We are testing a new Perl version of the test script test-pl: cd mysql-test; \ @@ -125,7 +132,9 @@ test-force-pl: ./mysql-test-run.pl --force && \ ./mysql-test-run.pl --ps-protocol --force +#used by autopush.pl to run memory based tests test-force-pl-mem: cd mysql-test; \ ./mysql-test-run.pl --force --mem && \ ./mysql-test-run.pl --ps-protocol --force --mem + diff --git a/acinclude.m4 b/acinclude.m4 index 102f869e0d4..811e9c0b183 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -1448,20 +1448,20 @@ bdb_version_ok=yes ]) AC_DEFUN([MYSQL_TOP_BUILDDIR], [ + # Remove trailing "./" if any + [$1]=`echo $[$1] | sed -e 's,^\./,,'` case "$[$1]" in - /* ) ;; # don't do anything with an absolute path - "$srcdir"/* ) + "bdb" | "$srcdir/bdb" | "$top_srcdir/bdb" | "$abs_top_srcdir/bdb" ) # If BDB is under the source directory, we need to look under the # build directory for bdb/build_unix. - # NOTE: I'm being lazy, and assuming the user did not specify - # something like --with-berkeley-db=bdb (it would be missing "./"). - [$1]="\$(top_builddir)/"`echo "$[$1]" | sed -e "s,^$srcdir/,,"` + [$1]="\$(top_builddir)/bdb" ;; + /* ) ;; # Other absolute path is assume to be external BDB directory * ) AC_MSG_ERROR([The BDB directory must be directly under the MySQL source directory, or be specified using the full path. ('$srcdir'; '$[$1]')]) ;; esac - if test X"$[$1]" != "/" + if test X"$[$1]" != X"/" then [$1]=`echo $[$1] | sed -e 's,/$,,'` fi @@ -1493,7 +1493,7 @@ AC_DEFUN([MYSQL_CHECK_INNODB], [ AC_MSG_RESULT([Using Innodb]) AC_DEFINE([HAVE_INNOBASE_DB], [1], [Using Innobase DB]) have_innodb="yes" - innodb_includes="-I../innobase/include" + innodb_includes="-I\$(top_builddir)/innobase/include -I\$(top_srcdir)/innobase/include" innodb_system_libs="" dnl Some libs are listed several times, in order for gcc to sort out dnl circular references. @@ -1812,7 +1812,7 @@ AC_DEFUN([MYSQL_CHECK_NDBCLUSTER], [ AC_MSG_RESULT([Using NDB Cluster]) AC_DEFINE([HAVE_NDBCLUSTER_DB], [1], [Using Ndb Cluster DB]) have_ndbcluster="yes" - ndbcluster_includes="-I../ndb/include -I../ndb/include/ndbapi" + ndbcluster_includes="-I\$(top_builddir)/ndb/include -I\$(top_srcdir)/ndb/include -I\$(top_srcdir)/ndb/include/ndbapi" ndbcluster_libs="\$(top_builddir)/ndb/src/.libs/libndbclient.a" ndbcluster_system_libs="" ndb_mgmclient_libs="\$(top_builddir)/ndb/src/mgmclient/libndbmgmclient.la" @@ -1835,6 +1835,30 @@ dnl END OF MYSQL_CHECK_NDBCLUSTER SECTION dnl --------------------------------------------------------------------------- +dnl +dnl Macro to check time_t range: according to C standard +dnl array index myst be greater then 0 => if time_t is signed +dnl the code in the macros below won't compile. +dnl + +AC_DEFUN([MYSQL_CHECK_TIME_T],[ + AC_MSG_CHECKING(if time_t is unsigned) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM( + [[ +#include <time.h> + ]], + [[ + int array[(((time_t)-1) > 0) ? 1 : -1]; + ]] ) + ], [ + AC_DEFINE([TIME_T_UNSIGNED], 1, [Define to 1 if time_t is unsigned]) + AC_MSG_RESULT(yes) + ], + [AC_MSG_RESULT(no)] + ) +]) + + dnl By default, many hosts won't let programs access large files; dnl one must use special compiler options to get large-file access to work. dnl For more details about this brain damage please see: diff --git a/bdb/dist/gen_rec.awk b/bdb/dist/gen_rec.awk index 75f2e86ca9e..e1b75699027 100644 --- a/bdb/dist/gen_rec.awk +++ b/bdb/dist/gen_rec.awk @@ -180,7 +180,7 @@ BEGIN { t = types[i]; if (modes[i] == "POINTER") { ndx = index(t, "*"); - t = substr(types[i], 0, ndx - 2); + t = substr(types[i], 1, ndx - 2); } printf("\t%s\t%s;\n", t, vars[i]) >> HFILE } diff --git a/client/mysqltest.c b/client/mysqltest.c index 9ad2f3df5de..c6cbf6aabe0 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -29,9 +29,10 @@ Matt Wagner <matt@mysql.com> Monty Jani + Holyfoot */ -#define MTEST_VERSION "3.0" +#define MTEST_VERSION "3.1" #include <my_global.h> #include <mysql_embed.h> @@ -220,6 +221,14 @@ struct st_connection MYSQL* util_mysql; char *name; MYSQL_STMT* stmt; + +#ifdef EMBEDDED_LIBRARY + const char *cur_query; + int cur_query_len; + pthread_mutex_t mutex; + pthread_cond_t cond; + int query_done; +#endif /*EMBEDDED_LIBRARY*/ }; struct st_connection connections[128]; struct st_connection* cur_con, *next_con, *connections_end; @@ -264,6 +273,7 @@ enum enum_commands { Q_DISABLE_PARSING, Q_ENABLE_PARSING, Q_REPLACE_REGEX, Q_REMOVE_FILE, Q_FILE_EXIST, Q_WRITE_FILE, Q_COPY_FILE, Q_PERL, Q_DIE, Q_EXIT, + Q_CHMOD_FILE, Q_UNKNOWN, /* Unknown command. */ Q_COMMENT, /* Comments, ignored. */ @@ -346,6 +356,7 @@ const char *command_names[]= "die", /* Don't execute any more commands, compare result */ "exit", + "chmod", 0 }; @@ -458,7 +469,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,6 +480,56 @@ void handle_error(struct st_command*, 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_decl(send_one_query, 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) @@ -1754,6 +1814,46 @@ void do_copy_file(struct st_command *command) /* SYNOPSIS + do_chmod_file + command command handle + + DESCRIPTION + chmod <octal> <file> + Change file permission of <file> + +*/ + +void do_chmod_file(struct st_command *command) +{ + ulong mode= 0; + static DYNAMIC_STRING ds_mode; + static DYNAMIC_STRING ds_file; + const struct command_arg chmod_file_args[] = { + "mode", ARG_STRING, TRUE, &ds_mode, "Mode of file", + "file", ARG_STRING, TRUE, &ds_file, "Filename of file to modify" + }; + DBUG_ENTER("do_chmod_file"); + + check_command_args(command, command->first_argument, + chmod_file_args, + sizeof(chmod_file_args)/sizeof(struct command_arg), + ' '); + + /* Parse what mode to set */ + if (ds_mode.length != 4 || + str2int(ds_mode.str, 8, 0, INT_MAX, &mode) == NullS) + die("You must write a 4 digit octal number for mode"); + + DBUG_PRINT("info", ("chmod %o %s", (uint)mode, ds_file.str)); + handle_command_error(command, chmod(ds_file.str, mode)); + dynstr_free(&ds_mode); + dynstr_free(&ds_file); + DBUG_VOID_RETURN; +} + + +/* + SYNOPSIS do_file_exists command called command @@ -2861,10 +2961,12 @@ void safe_connect(MYSQL* mysql, const char *name, const char *host, Connect failed Only allow retry if this was an error indicating the server - could not be contacted + could not be contacted. Error code differs depending + on protocol/connection type */ - if (mysql_errno(mysql) == CR_CONNECTION_ERROR && + if ((mysql_errno(mysql) == CR_CONN_HOST_ERROR || + mysql_errno(mysql) == CR_CONNECTION_ERROR) && failed_attempts < opt_max_connect_retries) my_sleep(connection_retry_sleep); else @@ -4138,8 +4240,9 @@ void init_win_path_patterns() /* List of string patterns to match in order to find paths */ const char* paths[] = { "$MYSQL_TEST_DIR", "$MYSQL_TMP_DIR", - "./test/", 0 }; - int num_paths= 3; + "$MYSQLTEST_VARDIR", + "./test/" }; + int num_paths= sizeof(paths)/sizeof(char*); int i; char* p; @@ -4159,6 +4262,13 @@ void init_win_path_patterns() else p= my_strdup(paths[i], MYF(MY_FAE)); + /* Don't insert zero length strings in patterns array */ + if (strlen(p) == 0) + { + my_free(p, MYF(0)); + continue; + } + if (insert_dynamic(&patterns, (gptr) &p)) die(NullS); @@ -4208,7 +4318,7 @@ void fix_win_paths(const char *val, int len) { const char** pattern= dynamic_element(&patterns, i, const char**); DBUG_PRINT("info", ("pattern: %s", *pattern)); - if (strlen(*pattern) == 0) continue; + /* Search for the path in string */ while ((p= strstr(val, *pattern))) { @@ -4498,7 +4608,6 @@ int append_warnings(DYNAMIC_STRING *ds, MYSQL* mysql) } - /* Run query using MySQL C API @@ -4515,10 +4624,11 @@ 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 *mysql= &cn->mysql; MYSQL_RES *res= 0; int err= 0, counter= 0; DBUG_ENTER("run_query_normal"); @@ -4530,14 +4640,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; @@ -5028,8 +5150,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; @@ -5186,7 +5309,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) @@ -5616,6 +5739,7 @@ int main(int argc, char **argv) case Q_FILE_EXIST: do_file_exist(command); break; case Q_WRITE_FILE: do_write_file(command); break; case Q_COPY_FILE: do_copy_file(command); break; + case Q_CHMOD_FILE: do_chmod_file(command); break; case Q_PERL: do_perl(command); break; case Q_DELIMITER: do_delimiter(command); @@ -5651,7 +5775,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++; @@ -5682,7 +5806,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; @@ -5708,7 +5832,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; @@ -6448,7 +6572,7 @@ int reg_replace(char** buf_p, int* buf_len_p, char *pattern, { my_regex_t r; my_regmatch_t *subs; - char *buf_end, *replace_end; + char *replace_end; char *buf= *buf_p; int len; int buf_len, need_buf_len; @@ -6468,8 +6592,6 @@ int reg_replace(char** buf_p, int* buf_len_p, char *pattern, SECURE_REG_BUF - buf_end= buf + buf_len; - if (icase) cflags|= REG_ICASE; diff --git a/configure.in b/configure.in index 013676b0045..4ac0637e42c 100644 --- a/configure.in +++ b/configure.in @@ -46,12 +46,14 @@ do case $host_os in netware* | modesto*) echo "$i/errmsg.sys: $i/errmsg.txt - \$(top_builddir)/extra/comp_err.linux -C\$(srcdir)/charsets/ $i/errmsg.txt $i/errmsg.sys" \ + mkdir -p $i + \$(top_builddir)/extra/comp_err.linux -C\$(srcdir)/charsets/ \$(srcdir)/$i/errmsg.txt $i/errmsg.sys" \ >> $AVAILABLE_LANGUAGES_ERRORS_RULES ;; *) echo "$i/errmsg.sys: $i/errmsg.txt - \$(top_builddir)/extra/comp_err -C\$(srcdir)/charsets/ $i/errmsg.txt $i/errmsg.sys" \ + mkdir -p $i + \$(top_builddir)/extra/comp_err -C\$(srcdir)/charsets/ \$(srcdir)/$i/errmsg.txt $i/errmsg.sys" \ >> $AVAILABLE_LANGUAGES_ERRORS_RULES ;; esac @@ -1824,6 +1826,13 @@ then AC_MSG_ERROR("MySQL needs a off_t type.") fi +dnl +dnl check if time_t is unsigned +dnl + +MYSQL_CHECK_TIME_T + + # do we need #pragma interface/#pragma implementation ? # yes if it's gcc 2.x, and not icc pretending to be gcc, and not cygwin AC_MSG_CHECKING(the need for @%:@pragma interface/implementation) diff --git a/include/Makefile.am b/include/Makefile.am index a17ef377e78..3a3b319505c 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -69,6 +69,7 @@ abi_check: mysql.h mysql_version.h mysql_com.h mysql_time.h my_list.h \ if [ @ICHECK@ != no ] ; then \ @ICHECK@ --canonify --skip-from-re /usr/ -o $@.ic mysql.h; \ @ICHECK@ --compare mysql_h.ic $@.ic; \ + $(RM) -f $@.ic; \ fi; \ touch abi_check; diff --git a/include/my_time.h b/include/my_time.h index 11c653f70d0..2fc45c8f874 100644 --- a/include/my_time.h +++ b/include/my_time.h @@ -38,6 +38,14 @@ typedef long my_time_t; #define MY_TIME_T_MAX LONG_MAX #define MY_TIME_T_MIN LONG_MIN + +/* Time handling defaults */ +#define TIMESTAMP_MAX_YEAR 2038 +#define YY_PART_YEAR 70 +#define TIMESTAMP_MIN_YEAR (1900 + YY_PART_YEAR - 1) +#define TIMESTAMP_MAX_VALUE INT_MAX32 +#define TIMESTAMP_MIN_VALUE 1 + #define YY_PART_YEAR 70 /* Flags to str_to_datetime */ @@ -67,6 +75,30 @@ long calc_daynr(uint year,uint month,uint day); void init_time(void); + +/* + Function to check sanity of a TIMESTAMP value + + DESCRIPTION + Check if a given MYSQL_TIME value fits in TIMESTAMP range. + This function doesn't make precise check, but rather a rough + estimate. + + RETURN VALUES + FALSE The value seems sane + TRUE The MYSQL_TIME value is definitely out of range +*/ + +static inline bool validate_timestamp_range(const MYSQL_TIME *t) +{ + if ((t->year > TIMESTAMP_MAX_YEAR || t->year < TIMESTAMP_MIN_YEAR) || + (t->year == TIMESTAMP_MAX_YEAR && (t->month > 1 || t->day > 19)) || + (t->year == TIMESTAMP_MIN_YEAR && (t->month < 12 || t->day < 31))) + return FALSE; + + return TRUE; +} + my_time_t my_system_gmt_sec(const MYSQL_TIME *t, long *my_timezone, bool *in_dst_time_gap); diff --git a/include/mysql.h b/include/mysql.h index bc99b6f6ba1..55ef6ee6d10 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -281,12 +281,6 @@ typedef struct st_mysql from mysql_stmt_close if close had to cancel result set of this object. */ my_bool *unbuffered_fetch_owner; - /* - 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; } MYSQL; typedef struct st_mysql_res { diff --git a/include/mysql_h.ic b/include/mysql_h.ic index 30ef44a1ccb..44c36c84747 100644 --- a/include/mysql_h.ic +++ b/include/mysql_h.ic @@ -154,7 +154,6 @@ struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned struct st_mysql_methods const * methods; void * thd; my_bool * unbuffered_fetch_owner; - struct st_mysql_stmt * current_stmt; }; # 571 "mysql.h" struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned long int)))) st_mysql_bind diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 91c0b6b8864..e963c0e429c 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -2496,6 +2496,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_PRINT("enter",("packet: %s, length :%d",packet ? packet :" ", length)); @@ -2503,15 +2505,17 @@ static my_bool execute(MYSQL_STMT *stmt, char *packet, ulong length) int4store(buff, stmt->stmt_id); /* Send stmt id to server */ buff[4]= (char) 0; /* no flags */ int4store(buff+5, 1); /* iteration count */ - if (cli_advanced_command(mysql, COM_EXECUTE, buff, sizeof(buff), - packet, length, 1, NULL) || - (*mysql->methods->read_query_result)(mysql)) + + res= test(cli_advanced_command(mysql, COM_EXECUTE, buff, sizeof(buff), + packet, length, 1, NULL) || + (*mysql->methods->read_query_result)(mysql)); + stmt->affected_rows= mysql->affected_rows; + 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->insert_id= mysql->insert_id; DBUG_RETURN(0); } @@ -4395,13 +4399,6 @@ int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt) set_stmt_error(stmt, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate); 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 f7cf00321cb..31f6fdffd53 100644 --- a/libmysql_r/Makefile.am +++ b/libmysql_r/Makefile.am @@ -31,8 +31,6 @@ INCLUDES = @MT_INCLUDES@ \ ## automake barfs if you don't use $(srcdir) or $(top_srcdir) in include include $(top_srcdir)/libmysql/Makefile.shared -libmysql_dir = $(top_srcdir)/libmysql - libmysqlclient_r_la_SOURCES = $(target_sources) libmysqlclient_r_la_LIBADD = $(target_libadd) libmysqlclient_r_la_LDFLAGS = $(target_ldflags) @@ -40,7 +38,9 @@ libmysqlclient_r_la_LDFLAGS = $(target_ldflags) # This is called from the toplevel makefile link_sources: set -x; \ - for f in `cd $(libmysql_dir) && echo *.[ch]`; do \ - rm -f $$f; \ - @LN_CP_F@ $(libmysql_dir)/$$f $$f; \ + for d in $(top_srcdir)/libmysql $(top_builddir)/libmysql; do \ + for f in `cd $$d && echo *.[ch]`; do \ + rm -f $$f; \ + @LN_CP_F@ $$d/$$f $$f; \ + done; \ done diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am index e121e4b8d6e..9582084ba5d 100644 --- a/libmysqld/Makefile.am +++ b/libmysqld/Makefile.am @@ -25,9 +25,11 @@ DEFS = -DEMBEDDED_LIBRARY -DMYSQL_SERVER \ -DDEFAULT_MYSQL_HOME="\"$(MYSQLBASEdir)\"" \ -DDATADIR="\"$(MYSQLDATAdir)\"" \ -DSHAREDIR="\"$(MYSQLSHAREdir)\"" -INCLUDES= @MT_INCLUDES@ @bdb_includes@ \ +INCLUDES= @MT_INCLUDES@ @bdb_includes@ @innodb_includes@ @ndbcluster_includes@ \ -I$(top_builddir)/include -I$(top_srcdir)/include \ - -I$(top_srcdir)/sql -I$(top_srcdir)/sql/examples -I$(top_srcdir)/regex \ + -I$(top_builddir)/sql -I$(top_srcdir)/sql \ + -I$(top_srcdir)/sql/examples \ + -I$(top_srcdir)/regex \ $(openssl_includes) @ZLIB_INCLUDES@ noinst_LIBRARIES = libmysqld_int.a @@ -118,16 +120,28 @@ endif #libmysqld_la_LDFLAGS = -version-info @SHARED_LIB_VERSION@ #CLEANFILES = $(libmysqld_la_LIBADD) libmysqld.la -# This is called from the toplevel makefile +# This is called from the toplevel makefile. If we can link now +# to an existing file in source, we do that, else we assume it +# will show up in the build tree eventually (generated file). link_sources: set -x; \ for f in $(sqlsources); do \ rm -f $$f; \ - @LN_CP_F@ $(top_srcdir)/sql/$$f $$f; \ + if test -e $(top_srcdir)/sql/$$f ; \ + then \ + @LN_CP_F@ $(top_srcdir)/sql/$$f $$f; \ + else \ + @LN_CP_F@ $(top_builddir)/sql/$$f $$f; \ + fi ; \ done; \ for f in $(libmysqlsources); do \ rm -f $$f; \ - @LN_CP_F@ $(top_srcdir)/libmysql/$$f $$f; \ + if test -e $(top_srcdir)/libmysql/$$f ; \ + then \ + @LN_CP_F@ $(top_srcdir)/libmysql/$$f $$f; \ + else \ + @LN_CP_F@ $(top_builddir)/libmysql/$$f $$f; \ + fi ; \ done; \ for f in $(sqlexamplessources); do \ rm -f $$f; \ diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index 1a3e10f08a8..804c4e001d2 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -94,7 +94,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; - mysql->current_stmt= stmt; + thd->current_stmt= stmt; thd->store_globals(); // Fix if more than one connect /* @@ -224,20 +224,24 @@ static int emb_stmt_execute(MYSQL_STMT *stmt) { DBUG_ENTER("emb_stmt_execute"); char header[4]; + my_bool res; + int4store(header, stmt->stmt_id); THD *thd= (THD*)stmt->mysql->thd; thd->client_param_count= stmt->param_count; thd->client_params= stmt->params; - if (emb_advanced_command(stmt->mysql, COM_EXECUTE,0,0, - header, sizeof(header), 1, stmt) || - emb_mysql_read_query_result(stmt->mysql)) + + res= test(emb_advanced_command(stmt->mysql, COM_EXECUTE,0,0, + header, sizeof(header), 1, stmt) || + emb_mysql_read_query_result(stmt->mysql)); + stmt->affected_rows= stmt->mysql->affected_rows; + stmt->insert_id= stmt->mysql->insert_id; + 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; DBUG_RETURN(0); } @@ -644,8 +648,8 @@ bool Protocol::send_fields(List<Item> *list, uint flag) DBUG_RETURN(0); field_count= list->elements; - field_alloc= mysql->current_stmt ? &mysql->current_stmt->mem_root : - &mysql->field_alloc; + field_alloc= thd->current_stmt ? &thd->current_stmt->mem_root : + &mysql->field_alloc; if (!(client_field= mysql->fields= (MYSQL_FIELD *)alloc_root(field_alloc, sizeof(MYSQL_FIELD) * field_count))) @@ -751,8 +755,8 @@ bool Protocol_prep::write() { MYSQL *mysql= thd->mysql; - if (mysql->current_stmt) - data= &mysql->current_stmt->result; + if (thd->current_stmt) + data= &thd->current_stmt->result; else { if (!(data= (MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA), diff --git a/myisam/mi_key.c b/myisam/mi_key.c index eaa854b1a37..9d538d58817 100644 --- a/myisam/mi_key.c +++ b/myisam/mi_key.c @@ -42,7 +42,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; @@ -84,18 +84,17 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key, pos= (byte*) record+keyseg->start; 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); @@ -358,8 +357,10 @@ static int _mi_put_key_in_record(register MI_INFO *info, uint keynr, pos= record+keyseg->start; if (keyseg->type != (int) HA_KEYTYPE_NUM) { - memcpy(pos,key,(size_t) length); - bfill(pos+length,keyseg->length-length,' '); + memcpy(pos,key,(size_t) length); + keyseg->charset->cset->fill(keyseg->charset, + pos + length, keyseg->length - length, + ' '); } else { diff --git a/myisam/mi_open.c b/myisam/mi_open.c index 4f298397615..4efe6f42d5e 100644 --- a/myisam/mi_open.c +++ b/myisam/mi_open.c @@ -326,6 +326,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) { @@ -1233,13 +1235,30 @@ int mi_enable_indexes(MI_INFO *info) RETURN 0 indexes are not disabled 1 all indexes are disabled - [2 non-unique indexes are disabled - NOT YET IMPLEMENTED] + 2 non-unique indexes are disabled */ int mi_indexes_are_disabled(MI_INFO *info) { MYISAM_SHARE *share= info->s; - return (! share->state.key_map && share->base.keys); + /* + No keys or all are enabled. keys is the number of keys. Left shifted + gives us only one bit set. When decreased by one, gives us all all bits + up to this one set and it gets unset. + */ + if (!share->base.keys || + (share->state.key_map == (ULL(1) << share->base.keys) - ULL(1))) + return 0; + + /* All are disabled */ + if (!share->state.key_map) + return 1; + + /* + We have keys. Some enabled, some disabled. + Don't check for any non-unique disabled but return directly 2 + */ + return 2; } diff --git a/myisam/sort.c b/myisam/sort.c index c5686a8e22c..fe9459e572b 100644 --- a/myisam/sort.c +++ b/myisam/sort.c @@ -315,6 +315,7 @@ pthread_handler_decl(thr_find_all_keys,arg) uint memavl,old_memavl,keys,sort_length; uint idx, maxbuffer; uchar **sort_keys=0; + DBUG_ENTER("thr_find_all_keys"); /* FIXME why no matching DBUG_RETURN ? */ LINT_INIT(keys); @@ -322,8 +323,9 @@ pthread_handler_decl(thr_find_all_keys,arg) if (my_thread_init()) goto err; - DBUG_ENTER("thr_find_all_keys"); + DBUG_PRINT("enter", ("master: %d", sort_param->master)); + if (sort_param->sort_info->got_error) goto err; diff --git a/mysql-test/Makefile.am b/mysql-test/Makefile.am index 1e6eb12f7b2..f8bf5c490f0 100644 --- a/mysql-test/Makefile.am +++ b/mysql-test/Makefile.am @@ -32,20 +32,22 @@ endif benchdir_root= $(prefix) testdir = $(benchdir_root)/mysql-test -EXTRA_SCRIPTS = mysql-test-run.sh install_test_db.sh $(PRESCRIPTS) -EXTRA_DIST = $(EXTRA_SCRIPTS) -GENSCRIPTS = mysql-test-run install_test_db mtr +EXTRA_SCRIPTS = mysql-test-run-shell.sh install_test_db.sh \ + $(PRESCRIPTS) +EXTRA_DIST = $(EXTRA_SCRIPTS) +GENSCRIPTS = mysql-test-run-shell mysql-test-run install_test_db mtr PRESCRIPTS = mysql-test-run.pl test_SCRIPTS = $(GENSCRIPTS) $(PRESCRIPTS) -test_DATA = std_data/client-key.pem std_data/client-cert.pem std_data/cacert.pem \ - std_data/server-cert.pem std_data/server-key.pem +test_DATA = std_data/client-key.pem \ + std_data/client-cert.pem \ + std_data/cacert.pem \ + std_data/server-cert.pem \ + std_data/server-key.pem CLEANFILES = $(GENSCRIPTS) $(test_DATA) INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include -I.. -EXTRA_PROGRAMS = mysql_test_run_new -noinst_HEADERS = my_manage.h -mysql_test_run_new_SOURCES= mysql_test_run_new.c my_manage.c my_create_tables.c +noinst_HEADERS = my_manage.h dist-hook: mkdir -p $(distdir)/t $(distdir)/r $(distdir)/include \ @@ -55,6 +57,7 @@ dist-hook: -$(INSTALL_DATA) $(srcdir)/t/*.disabled $(distdir)/t $(INSTALL_DATA) $(srcdir)/t/*.opt $(srcdir)/t/*.sh $(srcdir)/t/*.slave-mi $(distdir)/t $(INSTALL_DATA) $(srcdir)/include/*.inc $(distdir)/include + $(INSTALL_DATA) $(srcdir)/include/*.test $(distdir)/include $(INSTALL_DATA) $(srcdir)/r/*.result $(srcdir)/r/*.require $(distdir)/r $(INSTALL_DATA) $(srcdir)/std_data/Moscow_leap $(distdir)/std_data $(INSTALL_DATA) $(srcdir)/std_data/*.dat $(srcdir)/std_data/*.000001 $(distdir)/std_data @@ -82,6 +85,7 @@ install-data-local: $(INSTALL_DATA) $(srcdir)/r/*.result $(DESTDIR)$(testdir)/r $(INSTALL_DATA) $(srcdir)/r/*.require $(DESTDIR)$(testdir)/r $(INSTALL_DATA) $(srcdir)/include/*.inc $(DESTDIR)$(testdir)/include + $(INSTALL_DATA) $(srcdir)/include/*.test $(DESTDIR)$(testdir)/include $(INSTALL_DATA) $(srcdir)/std_data/*.dat $(DESTDIR)$(testdir)/std_data $(INSTALL_DATA) $(srcdir)/std_data/*.*001 $(DESTDIR)$(testdir)/std_data $(INSTALL_DATA) $(srcdir)/std_data/*.cnf $(DESTDIR)$(testdir)/std_data @@ -110,6 +114,11 @@ mtr: $(RM) -f mtr $(LN_S) mysql-test-run.pl mtr +# mysql-test-run - a shortcut for executing mysql-test-run.pl +mysql-test-run: + $(RM) -f mysql-test-run + $(LN_S) mysql-test-run.pl mysql-test-run + SUFFIXES = .sh .sh: 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/install_test_db.sh b/mysql-test/install_test_db.sh index 4554b92857e..c30583503dc 100644 --- a/mysql-test/install_test_db.sh +++ b/mysql-test/install_test_db.sh @@ -1,5 +1,5 @@ #!/bin/sh -# Copyright (C) 1997-2002 MySQL AB +# Copyright (C) 1997-2006 MySQL AB # For a more info consult the file COPYRIGHT distributed with this file # This scripts creates the privilege tables db, host, user, tables_priv, @@ -7,19 +7,26 @@ if [ x$1 = x"--bin" ]; then shift 1 + BINARY_DIST=1 + + bindir=../bin + scriptdir=../bin + libexecdir=../libexec # Check if it's a binary distribution or a 'make install' if test -x ../libexec/mysqld then execdir=../libexec + elif test -x ../../sbin/mysqld # RPM installation + then + execdir=../../sbin + bindir=../../bin + scriptdir=../../bin + libexecdir=../../libexec else execdir=../bin fi - bindir=../bin - BINARY_DIST=1 fix_bin=mysql-test - scriptdir=../bin - libexecdir=../libexec else execdir=../sql bindir=../client diff --git a/mysql-test/lib/mtr_cases.pl b/mysql-test/lib/mtr_cases.pl index d270d72d526..9e943fec9ef 100644 --- a/mysql-test/lib/mtr_cases.pl +++ b/mysql-test/lib/mtr_cases.pl @@ -593,6 +593,10 @@ sub mtr_options_from_test_file($$) { while ( my $line= <$F> ) { + + # Skip line if it start's with # + next if ( $line =~ /^#/ ); + # Match this line against tag in "tags" array foreach my $tag (@tags) { diff --git a/mysql-test/lib/mtr_io.pl b/mysql-test/lib/mtr_io.pl index 984d834486c..09749bc74e3 100644 --- a/mysql-test/lib/mtr_io.pl +++ b/mysql-test/lib/mtr_io.pl @@ -13,6 +13,8 @@ sub mtr_tofile ($@); sub mtr_tonewfile($@); sub mtr_lastlinefromfile($); sub mtr_appendfile_to_file ($$); +sub mtr_grab_file($); + ############################################################################## # @@ -128,6 +130,7 @@ sub unspace { return "$quote$string$quote"; } +# Read a whole file, stripping leading and trailing whitespace. sub mtr_fromfile ($) { my $file= shift; @@ -181,5 +184,16 @@ sub mtr_appendfile_to_file ($$) { close TOFILE; } +# Read a whole file verbatim. +sub mtr_grab_file($) { + my $file= shift; + open(FILE, '<', $file) + or return undef; + local $/= undef; + my $data= scalar(<FILE>); + close FILE; + return $data; +} + 1; diff --git a/mysql-test/lib/mtr_misc.pl b/mysql-test/lib/mtr_misc.pl index 5ac89aee62c..c016f3dc34f 100644 --- a/mysql-test/lib/mtr_misc.pl +++ b/mysql-test/lib/mtr_misc.pl @@ -66,6 +66,9 @@ sub mtr_add_arg ($$@) { ############################################################################## +# Note - More specific paths should be given before less specific. For examle +# /client/debug should be listed before /client + sub mtr_path_exists (@) { foreach my $path ( @_ ) { @@ -81,6 +84,9 @@ sub mtr_path_exists (@) { } } +# Note - More specific paths should be given before less specific. For examle +# /client/debug should be listed before /client + sub mtr_script_exists (@) { foreach my $path ( @_ ) { @@ -103,6 +109,9 @@ sub mtr_script_exists (@) { } } +# Note - More specific paths should be given before less specific. For examle +# /client/debug should be listed before /client + sub mtr_file_exists (@) { foreach my $path ( @_ ) { @@ -111,6 +120,9 @@ sub mtr_file_exists (@) { return ""; } +# Note - More specific paths should be given before less specific. For examle +# /client/debug should be listed before /client + sub mtr_exe_maybe_exists (@) { my @path= @_; @@ -129,6 +141,9 @@ sub mtr_exe_maybe_exists (@) { return ""; } +# Note - More specific paths should be given before less specific. For examle +# /client/debug should be listed before /client + sub mtr_exe_exists (@) { my @path= @_; if (my $path= mtr_exe_maybe_exists(@path)) diff --git a/mysql-test/lib/mtr_process.pl b/mysql-test/lib/mtr_process.pl index 9d0c1f601ba..cf0dc0dc6f8 100644 --- a/mysql-test/lib/mtr_process.pl +++ b/mysql-test/lib/mtr_process.pl @@ -708,7 +708,7 @@ sub mtr_wait_blocking($) { } } -# Start "mysqladmin shutdown" for a specific mysqld +# Start "mysqladmin <command>" for a specific mysqld sub mtr_mysqladmin_start($$$) { my $srv= shift; my $command= shift; @@ -738,9 +738,8 @@ sub mtr_mysqladmin_start($$$) { # Shutdown time must be high as slave may be in reconnect mtr_add_arg($args, "--shutdown_timeout=$adm_shutdown_tmo"); mtr_add_arg($args, "$command"); - my $path_mysqladmin_log= "$::opt_vardir/log/mysqladmin.log"; my $pid= mtr_spawn($::exe_mysqladmin, $args, - "", $path_mysqladmin_log, $path_mysqladmin_log, "", + "", "", "", "", { append_log_file => 1 }); mtr_verbose("mtr_mysqladmin_start, pid: $pid"); return $pid; @@ -1053,7 +1052,7 @@ sub sleep_until_file_created ($$$) { # Print extra message every 60 seconds my $seconds= ($loop * $sleeptime) / 1000; - if ( $seconds > 1 and int($seconds) % 60 == 0 ) + if ( $seconds > 1 and int($seconds * 10) % 600 == 0 ) { my $left= $timeout - $seconds; mtr_warning("Waited $seconds seconds for $pidfile to be created, " . diff --git a/mysql-test/lib/mtr_report.pl b/mysql-test/lib/mtr_report.pl index 8d7de9d1a4b..a2c16e1941a 100644 --- a/mysql-test/lib/mtr_report.pl +++ b/mysql-test/lib/mtr_report.pl @@ -34,7 +34,12 @@ sub mtr_verbose (@); # We can't use diff -u or diff -a as these are not portable sub mtr_show_failed_diff ($) { - my $tname= shift; + my $result_file_name= shift; + + # The reject and log files have been dumped to + # to filenames based on the result_file's name + my $tname= basename($result_file_name); + $tname=~ s/\..*$//; my $reject_file= "r/$tname.reject"; my $result_file= "r/$tname.result"; @@ -89,10 +94,14 @@ sub mtr_report_test_skipped ($) { { print "[ disabled ] $tinfo->{'comment'}\n"; } - else + elsif ( $tinfo->{'comment'} ) { print "[ skipped ] $tinfo->{'comment'}\n"; } + else + { + print "[ skipped ]\n"; + } } sub mtr_report_tests_not_skipped_though_disabled ($) { diff --git a/mysql-test/lib/mtr_unique.pl b/mysql-test/lib/mtr_unique.pl new file mode 100644 index 00000000000..a8fb320c773 --- /dev/null +++ b/mysql-test/lib/mtr_unique.pl @@ -0,0 +1,156 @@ +# +# This file is used from mysql-test-run.pl when choosing +# port numbers and directories to use for running mysqld. +# + +use strict; +use Fcntl ':flock'; + +# +# Requested IDs are stored in a hash and released upon END. +# +my %mtr_unique_assigned_ids = (); +END { + while(my ($id,$file) = each(%mtr_unique_assigned_ids)) { + print "Autoreleasing $file:$id\n"; + mtr_release_unique_id($file, $id); + } +} + +# +# Require a unique, numerical ID, given a file name (where all +# requested IDs are stored), a minimum and a maximum value. +# +# We use flock to implement locking for the ID file and ignore +# possible problems arising from lack of support for it on +# some platforms (it should work on most, and the possible +# race condition would occur rarely). The proper solution for +# this is a daemon that manages IDs, of course. +# +# If no unique ID within the specified parameters can be +# obtained, return undef. +# +sub mtr_require_unique_id($$$) { + my $file = shift; + my $min = shift; + my $max = shift; + my $ret = undef; + my $changed = 0; + + my $can_use_ps = `ps -e | grep '^[ ]*$$ '`; + + if(eval("readlink '$file'") || eval("readlink '$file.sem'")) { + die 'lock file is a symbolic link'; + } + + chmod 0777, "$file.sem"; + open SEM, ">", "$file.sem" or die "can't write to $file.sem"; + flock SEM, LOCK_EX or die "can't lock $file.sem"; + if(! -e $file) { + open FILE, ">", $file or die "can't create $file"; + close FILE; + } + + if(eval("readlink '$file'") || eval("readlink '$file.sem'")) { + die 'lock file is a symbolic link'; + } + + chmod 0777, $file; + open FILE, "+<", $file or die "can't open $file"; + select undef,undef,undef,0.2; + seek FILE, 0, 0; + my %taken = (); + while(<FILE>) { + chomp; + my ($id, $pid) = split / /; + $taken{$id} = $pid; + if($can_use_ps) { + my $res = `ps -e | grep '^[ ]*$pid '`; + if(!$res) { + print "Ignoring slot $id used by missing process $pid.\n"; + delete $taken{$id}; + ++$changed; + } + } + } + for(my $i=$min; $i<=$max; ++$i) { + if(! exists $taken{$i}) { + $ret = $i; + $taken{$i} = $$; + ++$changed; + last; + } + } + if($changed) { + seek FILE, 0, 0; + truncate FILE, 0 or die "can't truncate $file"; + for my $k (keys %taken) { + print FILE $k . ' ' . $taken{$k} . "\n"; + } + } + close FILE; + flock SEM, LOCK_UN or warn "can't unlock $file.sem"; + close SEM; + $mtr_unique_assigned_ids{$ret} = $file if defined $ret; + return $ret; +} + +# +# Require a unique ID like above, but sleep if no ID can be +# obtained immediately. +# +sub mtr_require_unique_id_and_wait($$$) { + my $ret = mtr_require_unique_id($_[0],$_[1],$_[2]); + while(! defined $ret) { + sleep 30; + $ret = mtr_require_unique_id($_[0],$_[1],$_[2]); + print "Waiting for unique id to become available...\n" unless $ret; + } + return $ret; +} + +# +# Release a unique ID. +# +sub mtr_release_unique_id($$) { + my $file = shift; + my $myid = shift; + + if(eval("readlink '$file'") || eval("readlink '$file.sem'")) { + die 'lock file is a symbolic link'; + } + + open SEM, ">", "$file.sem" or die "can't write to $file.sem"; + flock SEM, LOCK_EX or die "can't lock $file.sem"; + + if(eval("readlink '$file'") || eval("readlink '$file.sem'")) { + die 'lock file is a symbolic link'; + } + + if(! -e $file) { + open FILE, ">", $file or die "can't create $file"; + close FILE; + } + open FILE, "+<", $file or die "can't open $file"; + select undef,undef,undef,0.2; + seek FILE, 0, 0; + my %taken = (); + while(<FILE>) { + chomp; + my ($id, $pid) = split / /; + $taken{$id} = $pid; + } + delete $taken{$myid}; + seek FILE, 0, 0; + truncate FILE, 0 or die "can't truncate $file"; + for my $k (keys %taken) { + print FILE $k . ' ' . $taken{$k} . "\n"; + } + close FILE; + flock SEM, LOCK_UN or warn "can't unlock $file.sem"; + close SEM; + delete $mtr_unique_assigned_ids{$myid}; +} + +1; + diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run-shell.sh index 141a725db2e..544721cf40d 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run-shell.sh @@ -158,18 +158,29 @@ 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 .. -BASEDIR=`pwd` -cd $CWD -MYSQL_TEST_DIR=$BASEDIR/mysql-test +# ... one level for tar.gz, two levels for a RPM installation +if [ -d ./bin ] ; then + # this is not perfect: we have + # /usr/share/mysql/ # mysql-test-run is here, so this is "$MYSQL_TEST_DIR" + # /usr/bin/ # with MySQL client programs + # so the existence of "/usr/share/bin/" would make this test fail. + BASEDIR=`pwd` +else + cd .. + BASEDIR=`pwd` +fi + +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 @@ -648,8 +659,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" @@ -1261,7 +1279,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; @@ -1377,7 +1395,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; @@ -1606,10 +1624,13 @@ run_testcase () --result-file=*) result_file=`$ECHO "$EXTRA_MASTER_OPT" | $SED -e "s;--result-file=;;"` result_file="r/$result_file.result" - # Note that this must be set to space, not "" for test-reset to -# work + # Note that this must be set to space, not "" for test-reset to work EXTRA_MASTER_OPT=" " ;; + --force-restart) + # Note that this must be set to space, not "" for test-reset to work + EXTRA_MASTER_OPT=" " + ;; esac stop_master stop_master 1 diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 9bf0f8df632..5002f778da5 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -63,10 +63,11 @@ 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 our $glob_win32_perl= ($^O eq "MSWin32"); # ActiveState Win32 Perl our $glob_cygwin_perl= ($^O eq "cygwin"); # Cygwin Perl @@ -85,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; @@ -94,11 +96,6 @@ $Devel::Trace::TRACE= 1; # ############################################################################## -# We are to use handle_options() in "mysys/my_getopt.c" for the C version -# -# In the C version we want to use structs and, in some cases, arrays of -# structs. We let each struct be a separate hash. - # Misc global variables our $mysql_version_id; our $glob_mysql_test_dir= undef; @@ -106,7 +103,6 @@ our $glob_mysql_bench_dir= undef; our $glob_hostname= undef; our $glob_scriptname= undef; our $glob_timers= undef; -our $glob_use_running_server= 0; our $glob_use_running_ndbcluster= 0; our $glob_use_running_ndbcluster_slave= 0; our $glob_use_embedded_server= 0; @@ -127,6 +123,12 @@ our $opt_vardir; # A path but set directly on cmd line our $path_vardir_trace; # unix formatted opt_vardir for trace files our $opt_tmpdir; # A path but set directly on cmd line +# Visual Studio produces executables in different sub-directories based on the +# configuration used to build them. To make life easier, an environment +# variable or command-line option may be specified to control which set of +# executables will be used by the test suite. +our $opt_vs_config = $ENV{'MTR_VS_CONFIG'}; + our $default_vardir; our $opt_usage; @@ -159,7 +161,7 @@ our $exe_libtool; our $opt_bench= 0; our $opt_small_bench= 0; -our $opt_big_test= 0; # Send --big-test to mysqltest +our $opt_big_test= 0; our @opt_extra_mysqld_opt; @@ -176,7 +178,10 @@ our $opt_debug; our $opt_do_test; our @opt_cases; # The test cases names in argv our $opt_embedded_server; -our $opt_extern; + +our $opt_extern= 0; +our $opt_socket; + our $opt_fast; our $opt_force; our $opt_reorder= 0; @@ -215,6 +220,7 @@ our $opt_ndbcluster_port_slave; our $opt_ndbconnectstring_slave; our $opt_record; +our $opt_report_features; our $opt_check_testcases; our $opt_skip; @@ -226,17 +232,11 @@ our $opt_skip_im; our $opt_sleep; -our $opt_sleep_time_after_restart= 1; -our $opt_sleep_time_for_delete= 10; our $opt_testcase_timeout; our $opt_suite_timeout; my $default_testcase_timeout= 15; # 15 min max my $default_suite_timeout= 180; # 3 hours max -our $opt_socket; - -our $opt_source_dist; - our $opt_start_and_exit; our $opt_start_dirty; our $opt_start_from; @@ -246,7 +246,6 @@ our $opt_strace_client; our $opt_timer= 1; our $opt_user; -our $opt_user_test; our $opt_valgrind= 0; our $opt_valgrind_mysqld= 0; @@ -268,7 +267,6 @@ our $opt_stress_test_file= ""; our $opt_wait_for_master; our $opt_wait_for_slave; -our $opt_wait_timeout= 10; our $opt_warnings; @@ -298,6 +296,8 @@ our $glob_tot_real_time= 0; our %mysqld_variables; +my $source_dist= 0; + ###################################################################### # @@ -308,11 +308,12 @@ our %mysqld_variables; sub main (); sub initial_setup (); sub command_line_setup (); -sub datadir_setup (); +sub datadir_list_setup (); sub executable_setup (); sub environment_setup (); sub kill_running_servers (); -sub cleanup_stale_files (); +sub remove_stale_vardir (); +sub setup_vardir (); sub check_ssl_support ($); sub check_running_as_root(); sub check_ndbcluster_support ($); @@ -351,7 +352,6 @@ main(); sub main () { - initial_setup(); command_line_setup(); check_ndbcluster_support(\%mysqld_variables); @@ -423,96 +423,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); } -############################################################################## -# -# Initial setup independent on command line arguments -# -############################################################################## - -sub initial_setup () { - - select(STDOUT); - $| = 1; # Make unbuffered - - $glob_scriptname= basename($0); - - # We require that we are in the "mysql-test" directory - # to run mysql-test-run - if (! -f $glob_scriptname) - { - mtr_error("Can't find the location for the mysql-test-run script\n" . - "Go to to the mysql-test directory and execute the script " . - "as follows:\n./$glob_scriptname"); - } - - if ( -d "../sql" ) - { - $opt_source_dist= 1; - } - - $glob_hostname= mtr_short_hostname(); - - # 'basedir' is always parent of "mysql-test" directory - $glob_mysql_test_dir= cwd(); - if ( $glob_cygwin_perl ) - { - # Windows programs like 'mysqld' needs Windows paths - $glob_mysql_test_dir= `cygpath -m "$glob_mysql_test_dir"`; - chomp($glob_mysql_test_dir); - } - $glob_basedir= dirname($glob_mysql_test_dir); - - # 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; - - $path_my_basedir= - $opt_source_dist ? $glob_mysql_test_dir : $glob_basedir; - - $glob_timers= mtr_init_timers(); - - # - # Find the mysqld executable to be able to find the mysqld version - # number as early as possible - # - - # Look for the path where to find the client binaries - $path_client_bindir= mtr_path_exists("$glob_basedir/client_release", - "$glob_basedir/client_debug", - "$glob_basedir/client/release", - "$glob_basedir/client/debug", - "$glob_basedir/client", - "$glob_basedir/bin"); - - # Look for the mysqld executable - $exe_mysqld= mtr_exe_exists ("$glob_basedir/sql/mysqld", - "$path_client_bindir/mysqld-max-nt", - "$path_client_bindir/mysqld-max", - "$path_client_bindir/mysqld-nt", - "$path_client_bindir/mysqld", - "$path_client_bindir/mysqld-debug", - "$path_client_bindir/mysqld-max", - "$glob_basedir/libexec/mysqld", - "$glob_basedir/bin/mysqld", - "$glob_basedir/sql/release/mysqld", - "$glob_basedir/sql/debug/mysqld"); - - # Use the mysqld found above to find out what features are available - collect_mysqld_features(); - -} - - ############################################################################## # @@ -549,6 +473,16 @@ sub command_line_setup () { # 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 so requested, we try to avail ourselves of a unique build thread number. + if ( $ENV{'MTR_BUILD_THREAD'} ) { + if ( lc($ENV{'MTR_BUILD_THREAD'}) eq 'auto' ) { + print "Requesting build thread... "; + $ENV{'MTR_BUILD_THREAD'} = mtr_require_unique_id_and_wait("/tmp/mysql-test-ports", 200, 299); + print "got ".$ENV{'MTR_BUILD_THREAD'}."\n"; + } + } + if ( $ENV{'MTR_BUILD_THREAD'} ) { # Up to two masters, up to three slaves @@ -590,6 +524,7 @@ sub command_line_setup () { 'bench' => \$opt_bench, 'small-bench' => \$opt_small_bench, 'with-ndbcluster' => \$opt_with_ndbcluster, + 'vs-config' => \$opt_vs_config, # Control what test suites or cases to run 'force' => \$opt_force, @@ -667,9 +602,10 @@ sub command_line_setup () { 'tmpdir=s' => \$opt_tmpdir, 'vardir=s' => \$opt_vardir, 'benchdir=s' => \$glob_mysql_bench_dir, - 'mem:s' => \$opt_mem, + 'mem' => \$opt_mem, # Misc + 'report-features' => \$opt_report_features, 'comment=s' => \$opt_comment, 'debug' => \$opt_debug, 'fast' => \$opt_fast, @@ -683,9 +619,7 @@ sub command_line_setup () { 'start-and-exit' => \$opt_start_and_exit, 'timer!' => \$opt_timer, 'unified-diff|udiff' => \$opt_udiff, - 'user-test=s' => \$opt_user_test, 'user=s' => \$opt_user, - 'wait-timeout=i' => \$opt_wait_timeout, 'testcase-timeout=i' => \$opt_testcase_timeout, 'suite-timeout=i' => \$opt_suite_timeout, 'warnings|log-warnings' => \$opt_warnings, @@ -695,6 +629,85 @@ sub command_line_setup () { usage("") if $opt_usage; + $glob_scriptname= basename($0); + + # We require that we are in the "mysql-test" directory + # to run mysql-test-run + if (! -f $glob_scriptname) + { + mtr_error("Can't find the location for the mysql-test-run script\n" . + "Go to to the mysql-test directory and execute the script " . + "as follows:\n./$glob_scriptname"); + } + + if ( -d "../sql" ) + { + $source_dist= 1; + } + + $glob_hostname= mtr_short_hostname(); + + # Find the absolute path to the test directory + $glob_mysql_test_dir= cwd(); + if ( $glob_cygwin_perl ) + { + # Windows programs like 'mysqld' needs Windows paths + $glob_mysql_test_dir= `cygpath -m "$glob_mysql_test_dir"`; + chomp($glob_mysql_test_dir); + } + + # In most cases, the base directory we find everything relative to, + # is the parent directory of the "mysql-test" directory. For source + # distributions, TAR binary distributions and some other packages. + $glob_basedir= dirname($glob_mysql_test_dir); + + # In the RPM case, binaries and libraries are installed in the + # default system locations, instead of having our own private base + # directory. And we install "/usr/share/mysql-test". Moving up one + # more directory relative to "mysql-test" gives us a usable base + # directory for RPM installs. + if ( ! $source_dist and ! -d "$glob_basedir/bin" ) + { + $glob_basedir= dirname($glob_basedir); + } + + # Expect mysql-bench to be located adjacent to the source tree, by default + $glob_mysql_bench_dir= "$glob_basedir/../mysql-bench" + unless defined $glob_mysql_bench_dir; + $glob_mysql_bench_dir= undef + unless -d $glob_mysql_bench_dir; + + $path_my_basedir= + $source_dist ? $glob_mysql_test_dir : $glob_basedir; + + $glob_timers= mtr_init_timers(); + + # + # Find the mysqld executable to be able to find the mysqld version + # number as early as possible + # + + # Look for the client binaries directory + $path_client_bindir= mtr_path_exists("$glob_basedir/client_release", + "$glob_basedir/client_debug", + vs_config_dirs('client', ''), + "$glob_basedir/client", + "$glob_basedir/bin/"); + + $exe_mysqld= mtr_exe_exists (vs_config_dirs('sql', 'mysqld'), + "$glob_basedir/sql/mysqld", + "$path_client_bindir/mysqld-max-nt", + "$path_client_bindir/mysqld-max", + "$path_client_bindir/mysqld-nt", + "$path_client_bindir/mysqld", + "$path_client_bindir/mysqld-debug", + "$path_client_bindir/mysqld-max", + "$glob_basedir/libexec/mysqld", + "$glob_basedir/bin/mysqld"); + + # Use the mysqld found above to find out what features are available + collect_mysqld_features(); + if ( $opt_comment ) { print "\n"; @@ -814,14 +827,6 @@ sub command_line_setup () { $opt_tmpdir =~ s,/+$,,; # Remove ending slash if any # -------------------------------------------------------------------------- - # Set socket - # -------------------------------------------------------------------------- - if (!$opt_socket) - { - $opt_socket= $mysqld_variables{'socket'}; - } - - # -------------------------------------------------------------------------- # Check im suport # -------------------------------------------------------------------------- if ( $mysql_version_id < 50000 ) @@ -918,17 +923,17 @@ sub command_line_setup () { } # -------------------------------------------------------------------------- - # Sleep flag + # Big test flags # -------------------------------------------------------------------------- - if ( $opt_sleep ) - { - $opt_sleep_time_after_restart= $opt_sleep; - } + if ( $opt_big_test ) + { + $ENV{'BIG_TEST'}= 1; + } # -------------------------------------------------------------------------- # Gcov flag # -------------------------------------------------------------------------- - if ( $opt_gcov and ! $opt_source_dist ) + if ( $opt_gcov and ! $source_dist ) { mtr_error("Coverage test needs the source - please use source dist"); } @@ -942,8 +947,6 @@ sub command_line_setup () { { # Indicate that we are using debugger $glob_debugger= 1; - # Increase timeouts - $opt_wait_timeout= 300; if ( $opt_extern ) { mtr_error("Can't use --extern when using debugger"); @@ -1009,16 +1012,9 @@ sub command_line_setup () { $opt_suite_timeout*= 6 if $opt_valgrind; } - # Increase times to wait for executables to start if using valgrind - if ( $opt_valgrind ) - { - $opt_sleep_time_after_restart= 10; - $opt_sleep_time_for_delete= 60; - } - if ( ! $opt_user ) { - if ( $glob_use_running_server ) + if ( $opt_extern ) { $opt_user= "test"; } @@ -1200,9 +1196,17 @@ sub command_line_setup () { if ( $opt_extern ) { - $glob_use_running_server= 1; - $opt_skip_rpl= 1; # We don't run rpl test cases - $master->[0]->{'path_sock'}= $opt_socket; + # Turn off features not supported when running with extern server + $opt_skip_rpl= 1; + + # Setup master->[0] with the settings for the extern server + $master->[0]->{'path_sock'}= $opt_socket if $opt_socket; + mtr_report("Using extern server at '$master->[0]->{path_sock}'"); + } + else + { + mtr_error("--socket can only be used in combination with --extern") + if $opt_socket; } $path_timefile= "$opt_vardir/log/mysqltest-time"; @@ -1213,7 +1217,7 @@ sub command_line_setup () { $path_snapshot= "$opt_tmpdir/snapshot_$opt_master_myport/"; } -sub datadir_setup () { +sub datadir_list_setup () { # Make a list of all data_dirs @data_dir_lst = ( @@ -1243,26 +1247,15 @@ sub datadir_setup () { sub collect_mysqld_features () { - # - # Execute "mysqld --no-defaults --help --verbose", that will - # print out version and a list of all features and settings - # my $found_variable_list_start= 0; - my $spec_file= "$glob_mysql_test_dir/mysqld.spec.$$"; - if ( mtr_run($exe_mysqld, - ["--no-defaults", - "--verbose", - "--help"], - "", "$spec_file", "$spec_file", "") != 0 ) - { - mtr_error("Failed to get version and list of features from %s", - $exe_mysqld); - } - my $F= IO::File->new($spec_file) or - mtr_error("can't open file \"$spec_file\": $!"); + # + # Execute "mysqld --no-defaults --help --verbose" to get a + # of all features and settings + # + my $list= `$exe_mysqld --no-defaults --verbose --help`; - while ( my $line= <$F> ) + foreach my $line (split('\n', $list)) { # First look for version if ( !$mysql_version_id ) @@ -1315,7 +1308,7 @@ sub collect_mysqld_features () { } } } - unlink($spec_file); + mtr_error("Could not find version of MySQL") unless $mysql_version_id; mtr_error("Could not find variabes list") unless $found_variable_list_start; @@ -1328,7 +1321,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 ""); } @@ -1397,16 +1392,14 @@ sub executable_setup () { # Look for my_print_defaults $exe_my_print_defaults= - mtr_exe_exists("$path_client_bindir/my_print_defaults", - "$glob_basedir/extra/my_print_defaults", - "$glob_basedir/extra/release/my_print_defaults", - "$glob_basedir/extra/debug/my_print_defaults"); + mtr_exe_exists(vs_config_dirs('extra', 'my_print_defaults'), + "$path_client_bindir/my_print_defaults", + "$glob_basedir/extra/my_print_defaults"); # Look for perror - $exe_perror= mtr_exe_exists("$glob_basedir/extra/perror", - "$path_client_bindir/perror", - "$glob_basedir/extra/release/perror", - "$glob_basedir/extra/debug/perror"); + $exe_perror= mtr_exe_exists(vs_config_dirs('extra', 'perror'), + "$glob_basedir/extra/perror", + "$path_client_bindir/perror"); # Look for the client binaries $exe_mysqlcheck= mtr_exe_exists("$path_client_bindir/mysqlcheck"); @@ -1452,22 +1445,20 @@ sub executable_setup () { # Look for the udf_example library $lib_udf_example= - mtr_file_exists("$glob_basedir/sql/.libs/udf_example.so", - "$glob_basedir/sql/release/udf_example.dll", - "$glob_basedir/sql/debug/udf_example.dll"); + mtr_file_exists(vs_config_dirs('sql', 'udf_example.dll'), + "$glob_basedir/sql/.libs/udf_example.so",); # Look for mysqltest executable if ( $glob_use_embedded_server ) { $exe_mysqltest= - mtr_exe_exists("$glob_basedir/libmysqld/examples/mysqltest_embedded", - "$path_client_bindir/mysqltest_embedded"); + mtr_exe_exists(vs_config_dirs('libmysqld/examples', 'mysqltest_embedded'), + "$glob_basedir/libmysqld/examples/mysqltest_embedded", + "$path_client_bindir/mysqltest_embedded"); } else { $exe_mysqltest= mtr_exe_exists("$path_client_bindir/mysqltest"); - - } # Look for mysql_client_test executable which may _not_ exist in @@ -1476,15 +1467,15 @@ sub executable_setup () { { $exe_mysql_client_test= mtr_exe_maybe_exists( + vs_config_dirs('libmysqld/examples', 'mysql_client_test_embedded'), "$glob_basedir/libmysqld/examples/mysql_client_test_embedded"); } else { $exe_mysql_client_test= - mtr_exe_maybe_exists("$glob_basedir/tests/mysql_client_test", - "$glob_basedir/tests/release/mysql_client_test", - "$glob_basedir/tests/debug/mysql_client_test", - "$glob_basedir/bin"); + mtr_exe_maybe_exists(vs_config_dirs('tests', 'mysql_client_test'), + "$glob_basedir/tests/mysql_client_test", + "$glob_basedir/bin/mysql_client_test"); } } @@ -1558,7 +1549,7 @@ sub environment_setup () { # Setup LD_LIBRARY_PATH so the libraries from this distro/clone # are used in favor of the system installed ones # -------------------------------------------------------------------------- - if ( $opt_source_dist ) + if ( $source_dist ) { push(@ld_library_paths, "$glob_basedir/libmysql/.libs/", "$glob_basedir/libmysql_r/.libs/"); @@ -1589,9 +1580,17 @@ sub environment_setup () { # impossible to add correct supressions, that means if "/usr/lib/debug" # is available, it should be added to # LD_LIBRARY_PATH + # + # But pthread is broken in libc6-dbg on Debian <= 3.1 (see Debian + # bug 399035, http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=399035), + # so don't change LD_LIBRARY_PATH on that platform. # -------------------------------------------------------------------------- my $debug_libraries_path= "/usr/lib/debug"; - if ( $opt_valgrind and -d $debug_libraries_path ) + my $deb_version; + if ( $opt_valgrind and -d $debug_libraries_path and + (! -e '/etc/debian_version' or + ($deb_version= mtr_grab_file('/etc/debian_version')) == 0 or + $deb_version > 3.1 ) ) { push(@ld_library_paths, $debug_libraries_path); } @@ -1615,7 +1614,7 @@ sub environment_setup () { $ENV{'UMASK'}= "0660"; # The octal *string* $ENV{'UMASK_DIR'}= "0770"; # The octal *string* $ENV{'LC_COLLATE'}= "C"; - $ENV{'USE_RUNNING_SERVER'}= $glob_use_running_server; + $ENV{'USE_RUNNING_SERVER'}= $opt_extern; $ENV{'MYSQL_TEST_DIR'}= $glob_mysql_test_dir; $ENV{'MYSQLTEST_VARDIR'}= $opt_vardir; $ENV{'MYSQL_TMP_DIR'}= $opt_tmpdir; @@ -1818,6 +1817,10 @@ sub environment_setup () { # ---------------------------------------------------- $ENV{'MYSQL_MY_PRINT_DEFAULTS'}= $exe_my_print_defaults; + # ---------------------------------------------------- + # Setup env so childs can execute mysqladmin + # ---------------------------------------------------- + $ENV{'MYSQLADMIN'}= $exe_mysqladmin; # ---------------------------------------------------- # Setup env so childs can execute perror @@ -1912,29 +1915,23 @@ sub kill_running_servers () { # This is different from terminating processes we have # started from this run of the script, this is terminating # leftovers from previous runs. - - if ( ! -d $opt_vardir ) - { - if ( -l $opt_vardir and ! -d readlink($opt_vardir) ) - { - mtr_report("Removing $opt_vardir symlink without destination"); - unlink($opt_vardir); - } - # The "var" dir does not exist already - # the processes that mtr_kill_leftovers start will write - # their log files to var/log so it should be created - mkpath("$opt_vardir/log"); - } mtr_kill_leftovers(); } } -sub cleanup_stale_files () { - - my $created_by_mem_file= "$glob_mysql_test_dir/var/created_by_mem"; +# +# Remove var and any directories in var/ created by previous +# tests +# +sub remove_stale_vardir () { mtr_report("Removing Stale Files"); + # Safety! + mtr_error("No, don't remove the vardir when running with --extern") + if $opt_extern; + + mtr_verbose("opt_vardir: $opt_vardir"); if ( $opt_vardir eq $default_vardir ) { # @@ -1943,29 +1940,47 @@ sub cleanup_stale_files () { if ( -l $opt_vardir) { # var is a symlink - if (-f $created_by_mem_file) + + if ( $opt_mem and readlink($opt_vardir) eq $opt_mem ) { # Remove the directory which the link points at + mtr_verbose("Removing " . readlink($opt_vardir)); rmtree(readlink($opt_vardir)); - # Remove the entire "var" dir - rmtree("$opt_vardir/"); + # Remove the "var" symlink + mtr_verbose("unlink($opt_vardir)"); + unlink($opt_vardir); + } + elsif ( $opt_mem ) + { + # Just remove the "var" symlink + mtr_report("WARNING: Removing '$opt_vardir' symlink it's wrong"); + + mtr_verbose("unlink($opt_vardir)"); unlink($opt_vardir); } else { # Some users creates a soft link in mysql-test/var to another area - # - allow it + # - allow it, but remove all files in it + mtr_report("WARNING: Using the 'mysql-test/var' symlink"); - rmtree("$opt_vardir/log"); - rmtree("$opt_vardir/ndbcluster-$opt_ndbcluster_port"); - rmtree("$opt_vardir/run"); - rmtree("$opt_vardir/tmp"); + + # Make sure the directory where it points exist + mtr_error("The destination for symlink $opt_vardir does not exist") + if ! -d readlink($opt_vardir); + + foreach my $bin ( glob("$opt_vardir/*") ) + { + mtr_verbose("Removing bin $bin"); + rmtree($bin); + } } } else { # Remove the entire "var" dir + mtr_verbose("Removing $opt_vardir/"); rmtree("$opt_vardir/"); } } @@ -1977,21 +1992,56 @@ sub cleanup_stale_files () { # Remove the var/ dir in mysql-test dir if any # this could be an old symlink that shouldn't be there + mtr_verbose("Removing $default_vardir"); rmtree($default_vardir); # Remove the "var" dir + mtr_verbose("Removing $opt_vardir/"); rmtree("$opt_vardir/"); } +} + +# +# Create var and the directories needed in var +# +sub setup_vardir() { + mtr_report("Creating Directories"); + + if ( $opt_vardir eq $default_vardir ) + { + # + # Running with "var" in mysql-test dir + # + if ( -l $opt_vardir ) + { + # it's a symlink + + # Make sure the directory where it points exist + mtr_error("The destination for symlink $opt_vardir does not exist") + if ! -d readlink($opt_vardir); + } + elsif ( $opt_mem ) + { + # Runinng with "var" as a link to some "memory" location, normally tmpfs + mtr_verbose("Creating $opt_mem"); + mkpath($opt_mem); + + mtr_report("Symlinking 'var' to '$opt_mem'"); + symlink($opt_mem, $opt_vardir); + } + } - if ( $opt_mem ) + if ( ! -d $opt_vardir ) { - # Runinng with var as a link to some "memory" location, normally tmpfs - rmtree($opt_mem); - mkpath($opt_mem); - mtr_report("Creating symlink from $opt_vardir to $opt_mem"); - symlink($opt_mem, $opt_vardir); - # Put a small file to recognize this dir was created by --mem - mtr_tofile($created_by_mem_file, $opt_mem); + mtr_verbose("Creating $opt_vardir"); + mkpath($opt_vardir); + } + + # Ensure a proper error message if vardir couldn't be created + unless ( -d $opt_vardir and -w $opt_vardir ) + { + mtr_error("Writable 'var' directory is needed, use the " . + "'--vardir=<path>' option"); } mkpath("$opt_vardir/log"); @@ -1999,10 +2049,9 @@ sub cleanup_stale_files () { mkpath("$opt_vardir/tmp"); mkpath($opt_tmpdir) if $opt_tmpdir ne "$opt_vardir/tmp"; - # Remove old and create new data dirs + # Create new data dirs foreach my $data_dir (@data_dir_lst) { - rmtree("$data_dir"); mkpath("$data_dir/mysql"); mkpath("$data_dir/test"); } @@ -2102,6 +2151,31 @@ sub check_debug_support ($) { ############################################################################## # +# Helper function to handle configuration-based subdirectories which Visual +# Studio uses for storing binaries. If opt_vs_config is set, this returns +# a path based on that setting; if not, it returns paths for the default +# /release/ and /debug/ subdirectories. +# +# $exe can be undefined, if the directory itself will be used +# +############################################################################### + +sub vs_config_dirs ($$) { + my ($path_part, $exe) = @_; + + $exe = "" if not defined $exe; + + if ($opt_vs_config) + { + return ("$glob_basedir/$path_part/$opt_vs_config/$exe"); + } + + return ("$glob_basedir/$path_part/release/$exe", + "$glob_basedir/$path_part/debug/$exe"); +} + +############################################################################## +# # Start the ndb cluster # ############################################################################## @@ -2485,7 +2559,7 @@ sub run_suite () { mtr_print_line(); if ( ! $glob_debugger and - ! $glob_use_running_server and + ! $opt_extern and ! $glob_use_embedded_server ) { stop_all_servers(); @@ -2514,23 +2588,41 @@ sub run_suite () { sub initialize_servers () { - datadir_setup(); + datadir_list_setup(); - if ( ! $glob_use_running_server ) + if ( $opt_extern ) + { + # Running against an already started server, if the specified + # vardir does not already exist it should be created + if ( ! -d $opt_vardir ) + { + mtr_report("Creating '$opt_vardir'"); + setup_vardir(); + } + else + { + mtr_report("No need to create '$opt_vardir' it already exists"); + } + } + else { kill_running_servers(); if ( ! $opt_start_dirty ) { - cleanup_stale_files(); + remove_stale_vardir(); + setup_vardir(); + mysql_install_db(); if ( $opt_force ) { + # Save a snapshot of the freshly installed db + # to make it possible to restore to a known point in time save_installed_db(); } } - check_running_as_root(); } + check_running_as_root(); } sub mysql_install_db () { @@ -2897,26 +2989,15 @@ sub do_before_run_mysqltest($) unlink("$result_dir/$tname.log"); unlink("$result_dir/$tname.warnings"); - mtr_tonewfile($path_current_test_log,"$tname\n"); # Always tell where we are - - # output current test to ndbcluster log file to enable diagnostics - mtr_tofile($path_ndb_testrun_log,"CURRENT TEST $tname\n"); - - mtr_tofile($master->[0]->{'path_myerr'},"CURRENT_TEST: $tname\n"); - if ( $master->[1]->{'pid'} ) - { - mtr_tofile($master->[1]->{'path_myerr'},"CURRENT_TEST: $tname\n"); - } - if ( $mysql_version_id < 50000 ) { - # Set envirnoment variable NDB_STATUS_OK to 1 + # Set environment variable NDB_STATUS_OK to 1 # if script decided to run mysqltest cluster _is_ installed ok $ENV{'NDB_STATUS_OK'} = "1"; } elsif ( $mysql_version_id < 50100 ) { - # Set envirnoment variable NDB_STATUS_OK to YES + # Set environment variable NDB_STATUS_OK to YES # if script decided to run mysqltest cluster _is_ installed ok $ENV{'NDB_STATUS_OK'} = "YES"; } @@ -2927,9 +3008,9 @@ sub do_after_run_mysqltest($) my $tinfo= shift; my $tname= $tinfo->{'name'}; - mtr_tofile($path_mysqltest_log,"CURRENT TEST $tname\n"); - # Save info from this testcase run to mysqltest.log + mtr_appendfile_to_file($path_current_test_log, $path_mysqltest_log) + if -f $path_current_test_log; mtr_appendfile_to_file($path_timefile, $path_mysqltest_log) if -f $path_timefile; @@ -2939,6 +3020,26 @@ sub do_after_run_mysqltest($) } +sub run_testcase_mark_logs($) +{ + my ($log_msg)= @_; + + # Write a marker to all log files + + # The file indicating current test name + mtr_tonewfile($path_current_test_log, $log_msg); + + # each mysqld's .err file + foreach my $mysqld (@{$master}, @{$slave}) + { + mtr_tofile($mysqld->{path_myerr}, $log_msg); + } + + # ndbcluster log file + mtr_tofile($path_ndb_testrun_log, $log_msg); + +} + sub find_testcase_skipped_reason($) { my ($tinfo)= @_; @@ -3040,7 +3141,7 @@ sub run_testcase ($) { # ------------------------------------------------------- $ENV{'TZ'}= $tinfo->{'timezone'}; - mtr_verbose("Starting server with timezone: $tinfo->{'timezone'}"); + mtr_verbose("Setting timezone: $tinfo->{'timezone'}"); my $master_restart= run_testcase_need_master_restart($tinfo); my $slave_restart= run_testcase_need_slave_restart($tinfo); @@ -3048,7 +3149,7 @@ sub run_testcase ($) { if ($master_restart or $slave_restart) { # Can't restart a running server that may be in use - if ( $glob_use_running_server ) + if ( $opt_extern ) { mtr_report_test_name($tinfo); $tinfo->{comment}= "Can't restart a running server"; @@ -3058,6 +3159,10 @@ sub run_testcase ($) { run_testcase_stop_servers($tinfo, $master_restart, $slave_restart); } + + # Write to all log files to indicate start of testcase + run_testcase_mark_logs("CURRENT_TEST: $tinfo->{name}\n"); + my $died= mtr_record_dead_children(); if ($died or $master_restart or $slave_restart) { @@ -3210,7 +3315,7 @@ sub report_failure_and_restart ($) { my $tinfo= shift; mtr_report_test_failed($tinfo); - mtr_show_failed_diff($tinfo->{'name'}); + mtr_show_failed_diff($tinfo->{'result_file'}); print "\n"; if ( $opt_force ) { @@ -3227,7 +3332,7 @@ sub report_failure_and_restart ($) { print "Aborting: $tinfo->{'name'} failed in $test_mode mode. "; print "To continue, re-run with '--force'.\n"; if ( ! $glob_debugger and - ! $glob_use_running_server and + ! $opt_extern and ! $glob_use_embedded_server ) { stop_all_servers(); @@ -3399,6 +3504,17 @@ sub mysqld_arguments ($$$$$) { mtr_add_arg($args, "%s--ndb-extra-logging", $prefix); } } + + if ( $mysql_version_id <= 50106 ) + { + # Force mysqld to use log files up until 5.1.6 + mtr_add_arg($args, "%s--log=%s", $prefix, $master->[0]->{'path_mylog'}); + } + else + { + # Turn on logging, will be sent to tables + mtr_add_arg($args, "%s--log=", $prefix); + } } if ( $type eq 'slave' ) @@ -3416,8 +3532,6 @@ sub mysqld_arguments ($$$$$) { mtr_add_arg($args, "%s--log-slave-updates", $prefix); } - mtr_add_arg($args, "%s--log=%s", $prefix, - $slave->[$idx]->{'path_mylog'}); mtr_add_arg($args, "%s--master-retry-count=10", $prefix); mtr_add_arg($args, "%s--pid-file=%s", $prefix, $slave->[$idx]->{'path_pid'}); @@ -3478,6 +3592,18 @@ sub mysqld_arguments ($$$$$) { mtr_add_arg($args, "%s--ndb-extra-logging", $prefix); } } + + if ( $mysql_version_id <= 50106 ) + { + # Force mysqld to use log files up until 5.1.6 + mtr_add_arg($args, "%s--log=%s", $prefix, $master->[0]->{'path_mylog'}); + } + else + { + # Turn on logging, will be sent to tables + mtr_add_arg($args, "%s--log=", $prefix); + } + } # end slave if ( $opt_debug ) @@ -3554,7 +3680,6 @@ sub mysqld_arguments ($$$$$) { elsif ( $type eq 'master' ) { mtr_add_arg($args, "%s--open-files-limit=1024", $prefix); - mtr_add_arg($args, "%s--log=%s", $prefix, $master->[0]->{'path_mylog'}); } return $args; @@ -3803,10 +3928,17 @@ sub run_testcase_need_master_restart($) } elsif( ! $master->[0]->{'pid'} ) { - $do_restart= 1; - mtr_verbose("Restart master: master is not started"); + if ( $opt_extern ) + { + $do_restart= 0; + mtr_verbose("No restart: using extern master"); + } + else + { + $do_restart= 1; + mtr_verbose("Restart master: master is not started"); + } } - return $do_restart; } @@ -4052,8 +4184,6 @@ sub run_testcase_start_servers($) { return 1; } } - mtr_tofile($master->[1]->{'path_myerr'},"CURRENT_TEST: $tname\n"); - mysqld_start($master->[1],$tinfo->{'master_opt'},[]); } @@ -4081,8 +4211,6 @@ sub run_testcase_start_servers($) { # ---------------------------------------------------------------------- if ( $tinfo->{'slave_num'} ) { - mtr_tofile($slave->[0]->{'path_myerr'},"CURRENT_TEST: $tname\n"); - restore_slave_databases($tinfo->{'slave_num'}); do_before_start_slave($tinfo); @@ -4196,6 +4324,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 ($) { @@ -4260,11 +4425,6 @@ sub run_mysqltest ($) { mtr_add_arg($args, "--timer-file=%s/log/timer", $opt_vardir); } - if ( $opt_big_test ) - { - mtr_add_arg($args, "--big-test"); - } - if ( $opt_compress ) { mtr_add_arg($args, "--compress"); @@ -4333,8 +4493,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 ) { @@ -4622,6 +4784,8 @@ Options to control what engine/variation to run bench Run the benchmark suite small-bench Run the benchmarks with --small-tests --small-tables with-ndbcluster Use cluster as default table type for benchmark + vs-config Visual Studio configuration used to create executables + (default: MTR_VS_CONFIG environment variable) Options to control directories to use benchdir=DIR The directory where the benchmark suite is stored @@ -4631,9 +4795,9 @@ 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[=DIR] Run testsuite in "memory" using tmpfs or ramdisk - Attempts to use DIR first if specified else - uses as builtin list of standard locations + mem Run testsuite in "memory" using tmpfs or ramdisk + Attempts to find a suitable location + using a builtin list of standard locations for tmpfs (/dev/shm) The option can also be set using environment variable MTR_MEM=[DIR] @@ -4651,9 +4815,8 @@ Options to control what test suites or cases to run skip-rpl Skip the replication test cases. skip-im Don't start IM, and skip the IM test cases skip-test=PREFIX Skip test cases which name are prefixed with PREFIX - big-test Pass "--big-test" to mysqltest which will set the - environment variable BIG_TEST, which can be checked - from test cases. + big-test Set the environment variable BIG_TEST, which can be + checked from test cases. Options that specify ports @@ -4673,10 +4836,11 @@ Options that pass on options Options to run test on running server - extern Use running server for tests FIXME DANGEROUS + extern Use running server for tests ndb-connectstring=STR Use running cluster, and connect using STR ndb-connectstring-slave=STR Use running slave cluster, and connect using STR - user=USER User for connect to server + user=USER User for connection to extern server + socket=PATH Socket for connection to extern server Options for debugging the product @@ -4725,24 +4889,17 @@ Misc options unified-diff | udiff When presenting differences, use unified diff testcase-timeout=MINUTES Max test case run time (default $default_testcase_timeout) - suite-timeout=MINUTES Max test suite run time (default $default_suite_timeout) + suite-timeout=MINUTES Max test suite run time (default $default_suite_timeout) + warnings | log-warnings Pass --log-warnings to mysqld + sleep=SECONDS Passed to mysqltest, will be used as fixed sleep time Deprecated options with-openssl Deprecated option for ssl -Options not yet described, or that I want to look into more - local - netware - sleep=SECONDS - socket=PATH - user-test=s - wait-timeout=SECONDS - warnings - log-warnings - HERE mtr_exit(1); } + diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result index e9c9c873750..6c670af88a2 100644 --- a/mysql-test/r/alter_table.result +++ b/mysql-test/r/alter_table.result @@ -528,6 +528,127 @@ create table t1 ( a timestamp ); alter table t1 add unique ( a(1) ); ERROR HY000: Incorrect sub part key; the used key part isn't a string, the used length is longer than the key part, or the storage engine doesn't support unique sub keys drop table t1; +drop table if exists t1; +create table t1 (a int, key(a)); +show indexes from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 1 a 1 a A NULL NULL NULL YES BTREE +"this used not to disable the index" +alter table t1 modify a int, disable keys; +show indexes from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 1 a 1 a A NULL NULL NULL YES BTREE disabled +alter table t1 enable keys; +show indexes from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 1 a 1 a A NULL NULL NULL YES BTREE +alter table t1 modify a bigint, disable keys; +show indexes from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 1 a 1 a A NULL NULL NULL YES BTREE disabled +alter table t1 enable keys; +show indexes from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 1 a 1 a A NULL NULL NULL YES BTREE +alter table t1 add b char(10), disable keys; +show indexes from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 1 a 1 a A NULL NULL NULL YES BTREE disabled +alter table t1 add c decimal(10,2), enable keys; +show indexes from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 1 a 1 a A NULL NULL NULL YES BTREE +"this however did" +alter table t1 disable keys; +show indexes from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 1 a 1 a A NULL NULL NULL YES BTREE disabled +desc t1; +Field Type Null Key Default Extra +a bigint(20) YES MUL NULL +b char(10) YES NULL +c decimal(10,2) YES NULL +alter table t1 add d decimal(15,5); +"The key should still be disabled" +show indexes from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 1 a 1 a A NULL NULL NULL YES BTREE disabled +drop table t1; +"Now will test with one unique index" +create table t1(a int, b char(10), unique(a)); +show indexes from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 0 a 1 a A NULL NULL NULL YES BTREE +alter table t1 disable keys; +show indexes from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 0 a 1 a A NULL NULL NULL YES BTREE +alter table t1 enable keys; +"If no copy on noop change, this won't touch the data file" +"Unique index, no change" +alter table t1 modify a int, disable keys; +show indexes from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 0 a 1 a A NULL NULL NULL YES BTREE +"Change the type implying data copy" +"Unique index, no change" +alter table t1 modify a bigint, disable keys; +show indexes from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 0 a 1 a A NULL NULL NULL YES BTREE +alter table t1 modify a bigint; +show indexes from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 0 a 1 a A NULL NULL NULL YES BTREE +alter table t1 modify a int; +show indexes from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 0 a 1 a A NULL NULL NULL YES BTREE +drop table t1; +"Now will test with one unique and one non-unique index" +create table t1(a int, b char(10), unique(a), key(b)); +show indexes from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 0 a 1 a A NULL NULL NULL YES BTREE +t1 1 b 1 b A NULL NULL NULL YES BTREE +alter table t1 disable keys; +show indexes from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 0 a 1 a A NULL NULL NULL YES BTREE +t1 1 b 1 b A NULL NULL NULL YES BTREE disabled +alter table t1 enable keys; +"If no copy on noop change, this won't touch the data file" +"The non-unique index will be disabled" +alter table t1 modify a int, disable keys; +show indexes from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 0 a 1 a A NULL NULL NULL YES BTREE +t1 1 b 1 b A NULL NULL NULL YES BTREE disabled +alter table t1 enable keys; +show indexes from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 0 a 1 a A NULL NULL NULL YES BTREE +t1 1 b 1 b A NULL NULL NULL YES BTREE +"Change the type implying data copy" +"The non-unique index will be disabled" +alter table t1 modify a bigint, disable keys; +show indexes from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 0 a 1 a A NULL NULL NULL YES BTREE +t1 1 b 1 b A NULL NULL NULL YES BTREE disabled +"Change again the type, but leave the indexes as_is" +alter table t1 modify a int; +show indexes from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 0 a 1 a A NULL NULL NULL YES BTREE +t1 1 b 1 b A NULL NULL NULL YES BTREE disabled +"Try the same. When data is no copied on similar tables, this is noop" +alter table t1 modify a int; +show indexes from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 0 a 1 a A NULL NULL NULL YES BTREE +t1 1 b 1 b A NULL NULL NULL YES BTREE disabled +drop table t1; create database mysqltest1; create table t1 (c1 int); alter table t1 rename mysqltest1.t1; @@ -543,3 +664,14 @@ ERROR 3D000: No database selected alter table test.t1 rename test.t1; use test; drop table t1; +DROP TABLE IF EXISTS bug24219; +DROP TABLE IF EXISTS bug24219_2; +CREATE TABLE bug24219 (a INT, INDEX(a)); +SHOW INDEX FROM bug24219; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +bug24219 1 a 1 a A NULL NULL NULL YES BTREE +ALTER TABLE bug24219 RENAME TO bug24219_2, DISABLE KEYS; +SHOW INDEX FROM bug24219_2; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +bug24219_2 1 a 1 a A NULL NULL NULL YES BTREE disabled +DROP TABLE bug24219_2; diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result index 642a0fc13b5..bf827209795 100644 --- a/mysql-test/r/ctype_ucs.result +++ b/mysql-test/r/ctype_ucs.result @@ -715,6 +715,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/date_formats.result b/mysql-test/r/date_formats.result index 035d98d2b74..d4f9a4f0c56 100644 --- a/mysql-test/r/date_formats.result +++ b/mysql-test/r/date_formats.result @@ -181,12 +181,12 @@ date format datetime 2003-01-02 02:11:12.12345AM %Y-%m-%d %h:%i:%S.%f %p 2003-01-02 02:11:12.123450 2003-01-02 12:11:12.12345 am %Y-%m-%d %h:%i:%S.%f%p 2003-01-02 00:11:12.123450 2003-01-02 11:11:12Pm %Y-%m-%d %h:%i:%S%p 2003-01-02 23:11:12 -10:20:10 %H:%i:%s 0000-00-00 10:20:10 -10:20:10 %h:%i:%s.%f 0000-00-00 10:20:10 -10:20:10 %T 0000-00-00 10:20:10 -10:20:10AM %h:%i:%s%p 0000-00-00 10:20:10 -10:20:10AM %r 0000-00-00 10:20:10 -10:20:10.44AM %h:%i:%s.%f%p 0000-00-00 10:20:10.440000 +10:20:10 %H:%i:%s 0000-00-00 00:00:00 +10:20:10 %h:%i:%s.%f 0000-00-00 00:00:00 +10:20:10 %T 0000-00-00 00:00:00 +10:20:10AM %h:%i:%s%p 0000-00-00 00:00:00 +10:20:10AM %r 0000-00-00 00:00:00 +10:20:10.44AM %h:%i:%s.%f%p 0000-00-00 00:00:00 15-01-2001 12:59:58 %d-%m-%Y %H:%i:%S 2001-01-15 12:59:58 15 September 2001 %d %M %Y 2001-09-15 00:00:00 15 SEPTEMB 2001 %d %M %Y 2001-09-15 00:00:00 @@ -203,6 +203,13 @@ Tuesday 52 2001 %W %V %X 2002-01-01 00:00:00 15-01-2001 %d-%m-%Y %H:%i:%S 2001-01-15 00:00:00 15-01-20 %d-%m-%y 2020-01-15 00:00:00 15-2001-1 %d-%Y-%c 2001-01-15 00:00:00 +Warnings: +Warning 1292 Truncated incorrect datetime value: '0000-00-00 10:20:10' +Warning 1292 Truncated incorrect datetime value: '0000-00-00 10:20:10' +Warning 1292 Truncated incorrect datetime value: '0000-00-00 10:20:10' +Warning 1292 Truncated incorrect datetime value: '0000-00-00 10:20:10' +Warning 1292 Truncated incorrect datetime value: '0000-00-00 10:20:10' +Warning 1292 Truncated incorrect datetime value: '0000-00-00 10:20:10.440000' select date,format,DATE(str_to_date(date, format)) as date2 from t1; date format date2 2003-01-02 10:11:12 %Y-%m-%d %H:%i:%S 2003-01-02 @@ -243,12 +250,12 @@ date format time 2003-01-02 02:11:12.12345AM %Y-%m-%d %h:%i:%S.%f %p 02:11:12.123450 2003-01-02 12:11:12.12345 am %Y-%m-%d %h:%i:%S.%f%p 00:11:12.123450 2003-01-02 11:11:12Pm %Y-%m-%d %h:%i:%S%p 23:11:12 -10:20:10 %H:%i:%s 10:20:10 -10:20:10 %h:%i:%s.%f 10:20:10 -10:20:10 %T 10:20:10 -10:20:10AM %h:%i:%s%p 10:20:10 -10:20:10AM %r 10:20:10 -10:20:10.44AM %h:%i:%s.%f%p 10:20:10.440000 +10:20:10 %H:%i:%s NULL +10:20:10 %h:%i:%s.%f NULL +10:20:10 %T NULL +10:20:10AM %h:%i:%s%p NULL +10:20:10AM %r NULL +10:20:10.44AM %h:%i:%s.%f%p NULL 15-01-2001 12:59:58 %d-%m-%Y %H:%i:%S 12:59:58 15 September 2001 %d %M %Y 00:00:00 15 SEPTEMB 2001 %d %M %Y 00:00:00 @@ -265,6 +272,13 @@ Tuesday 52 2001 %W %V %X 00:00:00 15-01-2001 %d-%m-%Y %H:%i:%S 00:00:00 15-01-20 %d-%m-%y 00:00:00 15-2001-1 %d-%Y-%c 00:00:00 +Warnings: +Warning 1292 Truncated incorrect time value: '0000-00-00 10:20:10' +Warning 1292 Truncated incorrect time value: '0000-00-00 10:20:10' +Warning 1292 Truncated incorrect time value: '0000-00-00 10:20:10' +Warning 1292 Truncated incorrect time value: '0000-00-00 10:20:10' +Warning 1292 Truncated incorrect time value: '0000-00-00 10:20:10' +Warning 1292 Truncated incorrect time value: '0000-00-00 10:20:10.440000' select date,format,concat(TIME(str_to_date(date, format))) as time2 from t1; date format time2 2003-01-02 10:11:12 %Y-%m-%d %H:%i:%S 10:11:12 @@ -274,12 +288,12 @@ date format time2 2003-01-02 02:11:12.12345AM %Y-%m-%d %h:%i:%S.%f %p 02:11:12.123450 2003-01-02 12:11:12.12345 am %Y-%m-%d %h:%i:%S.%f%p 00:11:12.123450 2003-01-02 11:11:12Pm %Y-%m-%d %h:%i:%S%p 23:11:12 -10:20:10 %H:%i:%s 10:20:10 -10:20:10 %h:%i:%s.%f 10:20:10 -10:20:10 %T 10:20:10 -10:20:10AM %h:%i:%s%p 10:20:10 -10:20:10AM %r 10:20:10 -10:20:10.44AM %h:%i:%s.%f%p 10:20:10.440000 +10:20:10 %H:%i:%s NULL +10:20:10 %h:%i:%s.%f NULL +10:20:10 %T NULL +10:20:10AM %h:%i:%s%p NULL +10:20:10AM %r NULL +10:20:10.44AM %h:%i:%s.%f%p NULL 15-01-2001 12:59:58 %d-%m-%Y %H:%i:%S 12:59:58 15 September 2001 %d %M %Y 00:00:00 15 SEPTEMB 2001 %d %M %Y 00:00:00 @@ -296,6 +310,13 @@ Tuesday 52 2001 %W %V %X 00:00:00 15-01-2001 %d-%m-%Y %H:%i:%S 00:00:00 15-01-20 %d-%m-%y 00:00:00 15-2001-1 %d-%Y-%c 00:00:00 +Warnings: +Warning 1292 Truncated incorrect time value: '0000-00-00 10:20:10' +Warning 1292 Truncated incorrect time value: '0000-00-00 10:20:10' +Warning 1292 Truncated incorrect time value: '0000-00-00 10:20:10' +Warning 1292 Truncated incorrect time value: '0000-00-00 10:20:10' +Warning 1292 Truncated incorrect time value: '0000-00-00 10:20:10' +Warning 1292 Truncated incorrect time value: '0000-00-00 10:20:10.440000' select concat('',str_to_date('8:11:2.123456 03-01-02','%H:%i:%S.%f %y-%m-%d')); concat('',str_to_date('8:11:2.123456 03-01-02','%H:%i:%S.%f %y-%m-%d')) 2003-01-02 08:11:02.123456 @@ -530,4 +551,13 @@ DATE_FORMAT('%Y-%m-%d %H:%i:%s', 1151414896) NULL Warnings: Warning 1292 Truncated incorrect datetime value: '%Y-%m-%d %H:%i:%s' +select str_to_date('04 /30/2004', '%m /%d/%Y'); +str_to_date('04 /30/2004', '%m /%d/%Y') +2004-04-30 +select str_to_date('04/30 /2004', '%m /%d /%Y'); +str_to_date('04/30 /2004', '%m /%d /%Y') +2004-04-30 +select str_to_date('04/30/2004 ', '%m/%d/%Y '); +str_to_date('04/30/2004 ', '%m/%d/%Y ') +2004-04-30 "End of 4.1 tests" diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result index d4a46bfd79f..fa8a1e2cf6d 100644 --- a/mysql-test/r/func_gconcat.result +++ b/mysql-test/r/func_gconcat.result @@ -599,12 +599,72 @@ count(distinct (f1+1)) 1 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 400 1 Y 128 0 63 +def group_concat(f1) 252 1024 1 Y 128 0 63 f2 group_concat(f1) aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 1 bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 2 diff --git a/mysql-test/r/func_in.result b/mysql-test/r/func_in.result index 3cf2afc83d1..f74c63f7260 100644 --- a/mysql-test/r/func_in.result +++ b/mysql-test/r/func_in.result @@ -202,3 +202,11 @@ 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 diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index 5b2deeada55..fdfb42c878d 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -485,12 +485,48 @@ unix_timestamp('1969-12-01 19:00:01') select from_unixtime(-1); from_unixtime(-1) NULL -select from_unixtime(2145916800); -from_unixtime(2145916800) +select from_unixtime(2147483647); +from_unixtime(2147483647) +2038-01-19 06:14:07 +select from_unixtime(2147483648); +from_unixtime(2147483648) NULL select from_unixtime(0); from_unixtime(0) 1970-01-01 03:00:00 +select unix_timestamp(from_unixtime(2147483647)); +unix_timestamp(from_unixtime(2147483647)) +2147483647 +select unix_timestamp(from_unixtime(2147483648)); +unix_timestamp(from_unixtime(2147483648)) +NULL +select unix_timestamp('2039-01-20 01:00:00'); +unix_timestamp('2039-01-20 01:00:00') +0 +select unix_timestamp('1968-01-20 01:00:00'); +unix_timestamp('1968-01-20 01:00:00') +0 +select unix_timestamp('2038-02-10 01:00:00'); +unix_timestamp('2038-02-10 01:00:00') +0 +select unix_timestamp('1969-11-20 01:00:00'); +unix_timestamp('1969-11-20 01:00:00') +0 +select unix_timestamp('2038-01-20 01:00:00'); +unix_timestamp('2038-01-20 01:00:00') +0 +select unix_timestamp('1969-12-30 01:00:00'); +unix_timestamp('1969-12-30 01:00:00') +0 +select unix_timestamp('2038-01-17 12:00:00'); +unix_timestamp('2038-01-17 12:00:00') +2147331600 +select unix_timestamp('1970-01-01 03:00:01'); +unix_timestamp('1970-01-01 03:00:01') +1 +select unix_timestamp('2038-01-19 07:14:07'); +unix_timestamp('2038-01-19 07:14:07') +0 CREATE TABLE t1 (datetime datetime, timestamp timestamp, date date, time time); INSERT INTO t1 values ("2001-01-02 03:04:05", "2002-01-02 03:04:05", "2003-01-02", "06:07:08"); SELECT * from t1; @@ -815,4 +851,7 @@ union (select time_format(timediff(now(), DATE_SUB(now(),INTERVAL 5 HOUR)),'%k') As H); H 5 +select last_day('0000-00-00'); +last_day('0000-00-00') +NULL End of 4.1 tests diff --git a/mysql-test/r/mysqladmin.result b/mysql-test/r/mysqladmin.result new file mode 100644 index 00000000000..57927f8aa67 --- /dev/null +++ b/mysql-test/r/mysqladmin.result @@ -0,0 +1,4 @@ +mysqld is alive +mysqladmin: unknown variable 'database=db1' +Warning: mysqladmin: unknown variable 'loose-database=db2' +mysqld is alive diff --git a/mysql-test/r/mysqltest.result b/mysql-test/r/mysqltest.result index a63863977b0..3ddb82d4a8d 100644 --- a/mysql-test/r/mysqltest.result +++ b/mysql-test/r/mysqltest.result @@ -512,6 +512,12 @@ mysqltest: At line 1: End of line junk detected: "write_file filename "; mysqltest: At line 1: Missing required argument 'filename' to command 'file_exists' mysqltest: At line 1: Missing required argument 'from_file' to command 'copy_file' mysqltest: At line 1: Missing required argument 'to_file' to command 'copy_file' +mysqltest: At line 1: Missing required argument 'mode' to command 'chmod' +mysqltest: At line 1: You must write a 4 digit octal number for mode +mysqltest: At line 1: You must write a 4 digit octal number for mode +mysqltest: At line 1: Missing required argument 'file' to command 'chmod' +mysqltest: At line 1: You must write a 4 digit octal number for mode +mysqltest: At line 1: You must write a 4 digit octal number for mode hello hello hello diff --git a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result index 8126e223f55..320bb89b62e 100644 --- a/mysql-test/r/order_by.result +++ b/mysql-test/r/order_by.result @@ -820,3 +820,30 @@ 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; diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 2bb5df6e6cf..94c51fdc18b 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -775,12 +775,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 @@ -799,67 +799,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 GLOBAL variable and should be set with SET GLOBAL -set @@prepared_stmt_count=0; -ERROR HY000: Variable 'prepared_stmt_count' is a GLOBAL variable and should be set with SET GLOBAL -set global prepared_stmt_count=1; -ERROR 42000: Incorrect argument type to variable 'prepared_stmt_count' 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 HY000: Unknown error -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 HY000: Unknown error -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 HY000: Unknown error 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 HY000: Unknown error -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"; @@ -867,13 +870,13 @@ prepare stmt2 from "select 4"; ERROR HY000: Unknown error prepare stmt2 from "select 4"; ERROR HY000: Unknown error -select @@max_prepared_stmt_count, @@prepared_stmt_count; -@@max_prepared_stmt_count @@prepared_stmt_count -3 3 +select @@max_prepared_stmt_count; +@@max_prepared_stmt_count +3 +show status like 'prepared_stmt_count'; +Variable_name Value +Prepared_stmt_count 3 deallocate prepare stmt; -select @@max_prepared_stmt_count, @@prepared_stmt_count; -@@max_prepared_stmt_count @@prepared_stmt_count -3 0 set global max_prepared_stmt_count= @old_max_prepared_stmt_count; drop table if exists t1; create temporary table if not exists t1 (a1 int); diff --git a/mysql-test/r/rename.result b/mysql-test/r/rename.result index 964babb1228..d7db297cf26 100644 --- a/mysql-test/r/rename.result +++ b/mysql-test/r/rename.result @@ -54,3 +54,4 @@ Tables_in_test t2 t4 drop table t2, t4; +End of 4.1 tests 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/subselect.result b/mysql-test/r/subselect.result index e16a605434e..89315342f5e 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -2981,3 +2981,35 @@ 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; diff --git a/mysql-test/r/timezone.result b/mysql-test/r/timezone.result index 10944c3706e..1223fff36c6 100644 --- a/mysql-test/r/timezone.result +++ b/mysql-test/r/timezone.result @@ -41,7 +41,7 @@ Warning 1299 Invalid TIMESTAMP value in column 'ts' at row 2 DROP TABLE t1; select unix_timestamp('1970-01-01 01:00:00'), unix_timestamp('1970-01-01 01:00:01'), -unix_timestamp('2038-01-01 00:59:59'), -unix_timestamp('2038-01-01 01:00:00'); -unix_timestamp('1970-01-01 01:00:00') unix_timestamp('1970-01-01 01:00:01') unix_timestamp('2038-01-01 00:59:59') unix_timestamp('2038-01-01 01:00:00') -0 1 2145916799 0 +unix_timestamp('2038-01-19 04:14:07'), +unix_timestamp('2038-01-19 04:14:08'); +unix_timestamp('1970-01-01 01:00:00') unix_timestamp('1970-01-01 01:00:01') unix_timestamp('2038-01-19 04:14:07') unix_timestamp('2038-01-19 04:14:08') +0 1 2147483647 0 diff --git a/mysql-test/r/timezone2.result b/mysql-test/r/timezone2.result index 199b48ef1aa..ad3ce40ebb1 100644 --- a/mysql-test/r/timezone2.result +++ b/mysql-test/r/timezone2.result @@ -106,7 +106,7 @@ create table t1 (ts timestamp); set time_zone='UTC'; insert into t1 values ('0000-00-00 00:00:00'),('1969-12-31 23:59:59'), ('1970-01-01 00:00:00'),('1970-01-01 00:00:01'), -('2037-12-31 23:59:59'),('2038-01-01 00:00:00'); +('2038-01-19 03:14:07'),('2038-01-19 03:14:08'); Warnings: Warning 1264 Data truncated; out of range for column 'ts' at row 2 Warning 1264 Data truncated; out of range for column 'ts' at row 3 @@ -117,13 +117,13 @@ ts 0000-00-00 00:00:00 0000-00-00 00:00:00 1970-01-01 00:00:01 -2037-12-31 23:59:59 +2038-01-19 03:14:07 0000-00-00 00:00:00 delete from t1; set time_zone='MET'; insert into t1 values ('0000-00-00 00:00:00'),('1970-01-01 00:30:00'), ('1970-01-01 01:00:00'),('1970-01-01 01:00:01'), -('2038-01-01 00:59:59'),('2038-01-01 01:00:00'); +('2038-01-19 04:14:07'),('2038-01-19 04:14:08'); Warnings: Warning 1264 Data truncated; out of range for column 'ts' at row 2 Warning 1264 Data truncated; out of range for column 'ts' at row 3 @@ -134,13 +134,13 @@ ts 0000-00-00 00:00:00 0000-00-00 00:00:00 1970-01-01 01:00:01 -2038-01-01 00:59:59 +2038-01-19 04:14:07 0000-00-00 00:00:00 delete from t1; set time_zone='+01:30'; insert into t1 values ('0000-00-00 00:00:00'),('1970-01-01 01:00:00'), ('1970-01-01 01:30:00'),('1970-01-01 01:30:01'), -('2038-01-01 01:29:59'),('2038-01-01 01:30:00'); +('2038-01-19 04:44:07'),('2038-01-19 04:44:08'); Warnings: Warning 1264 Data truncated; out of range for column 'ts' at row 2 Warning 1264 Data truncated; out of range for column 'ts' at row 3 @@ -151,7 +151,7 @@ ts 0000-00-00 00:00:00 0000-00-00 00:00:00 1970-01-01 01:30:01 -2038-01-01 01:29:59 +2038-01-19 04:44:07 0000-00-00 00:00:00 drop table t1; show variables like 'time_zone'; @@ -213,12 +213,12 @@ convert_tz('2003-10-26 02:59:59', 'MET', 'UTC') select convert_tz('2003-10-26 04:00:00', 'MET', 'UTC'); convert_tz('2003-10-26 04:00:00', 'MET', 'UTC') 2003-10-26 03:00:00 -select convert_tz('2038-01-01 00:59:59', 'MET', 'UTC'); -convert_tz('2038-01-01 00:59:59', 'MET', 'UTC') -2037-12-31 23:59:59 -select convert_tz('2038-01-01 01:00:00', 'MET', 'UTC'); -convert_tz('2038-01-01 01:00:00', 'MET', 'UTC') -2038-01-01 01:00:00 +select convert_tz('2038-01-19 04:14:07', 'MET', 'UTC'); +convert_tz('2038-01-19 04:14:07', 'MET', 'UTC') +2038-01-19 03:14:07 +select convert_tz('2038-01-19 04:14:08', 'MET', 'UTC'); +convert_tz('2038-01-19 04:14:08', 'MET', 'UTC') +2038-01-19 04:14:08 select convert_tz('2103-01-01 04:00:00', 'MET', 'UTC'); convert_tz('2103-01-01 04:00:00', 'MET', 'UTC') 2103-01-01 04:00:00 diff --git a/mysql-test/r/timezone4.result b/mysql-test/r/timezone4.result new file mode 100644 index 00000000000..28028bea657 --- /dev/null +++ b/mysql-test/r/timezone4.result @@ -0,0 +1,6 @@ +select from_unixtime(0); +from_unixtime(0) +1969-12-31 14:00:00 +select unix_timestamp('1969-12-31 14:00:01'); +unix_timestamp('1969-12-31 14:00:01') +1 diff --git a/mysql-test/r/type_float.result b/mysql-test/r/type_float.result index 95050163787..f157bbc602d 100644 --- a/mysql-test/r/type_float.result +++ b/mysql-test/r/type_float.result @@ -274,7 +274,7 @@ a double 0 drop table t1,t2,t3; select 1e-308, 1.00000001e-300, 100000000e-300; 1e-308 1.00000001e-300 100000000e-300 -0 1.00000001e-300 1e-292 +1e-308 1.00000001e-300 1e-292 select 10e307; 10e307 1e+308 diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test index 9bd34c2a610..f4624eda053 100644 --- a/mysql-test/t/alter_table.test +++ b/mysql-test/t/alter_table.test @@ -362,6 +362,103 @@ alter table t1 add unique ( a(1) ); drop table t1; # +# Bug #24395: ALTER TABLE DISABLE KEYS doesn't work when modifying the table +# +# This problem happens if the data change is compatible. +# Changing to the same type is compatible for example. +# +--disable_warnings +drop table if exists t1; +--enable_warnings +create table t1 (a int, key(a)); +show indexes from t1; +--echo "this used not to disable the index" +alter table t1 modify a int, disable keys; +show indexes from t1; + +alter table t1 enable keys; +show indexes from t1; + +alter table t1 modify a bigint, disable keys; +show indexes from t1; + +alter table t1 enable keys; +show indexes from t1; + +alter table t1 add b char(10), disable keys; +show indexes from t1; + +alter table t1 add c decimal(10,2), enable keys; +show indexes from t1; + +--echo "this however did" +alter table t1 disable keys; +show indexes from t1; + +desc t1; + +alter table t1 add d decimal(15,5); +--echo "The key should still be disabled" +show indexes from t1; + +drop table t1; + +--echo "Now will test with one unique index" +create table t1(a int, b char(10), unique(a)); +show indexes from t1; +alter table t1 disable keys; +show indexes from t1; +alter table t1 enable keys; + +--echo "If no copy on noop change, this won't touch the data file" +--echo "Unique index, no change" +alter table t1 modify a int, disable keys; +show indexes from t1; + +--echo "Change the type implying data copy" +--echo "Unique index, no change" +alter table t1 modify a bigint, disable keys; +show indexes from t1; + +alter table t1 modify a bigint; +show indexes from t1; + +alter table t1 modify a int; +show indexes from t1; + +drop table t1; + +--echo "Now will test with one unique and one non-unique index" +create table t1(a int, b char(10), unique(a), key(b)); +show indexes from t1; +alter table t1 disable keys; +show indexes from t1; +alter table t1 enable keys; + + +--echo "If no copy on noop change, this won't touch the data file" +--echo "The non-unique index will be disabled" +alter table t1 modify a int, disable keys; +show indexes from t1; +alter table t1 enable keys; +show indexes from t1; + +--echo "Change the type implying data copy" +--echo "The non-unique index will be disabled" +alter table t1 modify a bigint, disable keys; +show indexes from t1; + +--echo "Change again the type, but leave the indexes as_is" +alter table t1 modify a int; +show indexes from t1; +--echo "Try the same. When data is no copied on similar tables, this is noop" +alter table t1 modify a int; +show indexes from t1; + +drop table t1; + + +# # Bug#11493 - Alter table rename to default database does not work without # db name qualifying # @@ -392,4 +489,22 @@ alter table test.t1 rename test.t1; use test; drop table t1; +# +# Bug#24219 - ALTER TABLE ... RENAME TO ... , DISABLE KEYS leads to crash +# +--disable_warnings +DROP TABLE IF EXISTS bug24219; +DROP TABLE IF EXISTS bug24219_2; +--enable_warnings + +CREATE TABLE bug24219 (a INT, INDEX(a)); + +SHOW INDEX FROM bug24219; + +ALTER TABLE bug24219 RENAME TO bug24219_2, DISABLE KEYS; + +SHOW INDEX FROM bug24219_2; + +DROP TABLE bug24219_2; + # End of 4.1 tests diff --git a/mysql-test/t/bdb-deadlock.test b/mysql-test/t/bdb-deadlock.test index 88243cfc860..b48648e0fd0 100644 --- a/mysql-test/t/bdb-deadlock.test +++ b/mysql-test/t/bdb-deadlock.test @@ -1,11 +1,3 @@ -# This test doesn't work with the embedded version as this code -# assumes that one query is running while we are doing queries on -# a second connection. -# This would work if mysqltest run would be threaded and handle each -# connection in a separate thread. -# - --- source include/not_embedded.inc -- source include/have_bdb.inc connect (con1,localhost,root,,); diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test index 641080f48ab..10559d33eb3 100644 --- a/mysql-test/t/ctype_ucs.test +++ b/mysql-test/t/ctype_ucs.test @@ -453,6 +453,24 @@ 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/date_formats.test b/mysql-test/t/date_formats.test index 922d047eac8..7e74c128dee 100644 --- a/mysql-test/t/date_formats.test +++ b/mysql-test/t/date_formats.test @@ -317,4 +317,12 @@ SELECT TIME_FORMAT("25:00:00", '%l %p'); # SELECT DATE_FORMAT('%Y-%m-%d %H:%i:%s', 1151414896); +# +# Bug #22029: str_to_date returning NULL +# + +select str_to_date('04 /30/2004', '%m /%d/%Y'); +select str_to_date('04/30 /2004', '%m /%d /%Y'); +select str_to_date('04/30/2004 ', '%m/%d/%Y '); + --echo "End of 4.1 tests" diff --git a/mysql-test/t/flush.test b/mysql-test/t/flush.test index aedf8e85b65..8fe62ecac01 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 1e7ecd2548c..0c1d2b82df6 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 40179ae7f38..fb21822caa0 100644 --- a/mysql-test/t/func_gconcat.test +++ b/mysql-test/t/func_gconcat.test @@ -391,6 +391,30 @@ select count(distinct (f1+1)) from t1 group by f1 with rollup; 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)); diff --git a/mysql-test/t/func_in.test b/mysql-test/t/func_in.test index 2ffe5a2d5f7..ffed2aac2a0 100644 --- a/mysql-test/t/func_in.test +++ b/mysql-test/t/func_in.test @@ -109,4 +109,24 @@ 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 diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index 066a059483c..fa12c45db04 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -236,17 +236,57 @@ select unix_timestamp(@a); select unix_timestamp('1969-12-01 19:00:01'); # -# Test for bug #6439 "unix_timestamp() function returns wrong datetime -# values for too big argument" and bug #7515 "from_unixtime(0) now -# returns NULL instead of the epoch". unix_timestamp() should return error -# for too big or negative argument. It should return Epoch value for zero -# argument since it seems that many user's rely on this fact. +# Tests for bug #6439 "unix_timestamp() function returns wrong datetime +# values for too big argument", bug #7515 "from_unixtime(0) now +# returns NULL instead of the epoch" and bug #9191 +# "TIMESTAMP/from_unixtime() no longer accepts 2^31-1." +# unix_timestamp() should return error for too big or negative argument. +# It should return Epoch value for zero argument since it seems that many +# users rely on this fact, from_unixtime() should work with values +# up to INT_MAX32 because of the same reason. # select from_unixtime(-1); -select from_unixtime(2145916800); +# check for from_unixtime(2^31-1) and from_unixtime(2^31) +select from_unixtime(2147483647); +select from_unixtime(2147483648); select from_unixtime(0); # +# Some more tests for bug #9191 "TIMESTAMP/from_unixtime() no +# longer accepts 2^31-1". Here we test that from_unixtime and +# unix_timestamp are consistent, when working with boundary dates. +# +select unix_timestamp(from_unixtime(2147483647)); +select unix_timestamp(from_unixtime(2147483648)); + +# check for invalid dates + +# bad year +select unix_timestamp('2039-01-20 01:00:00'); +select unix_timestamp('1968-01-20 01:00:00'); +# bad month +select unix_timestamp('2038-02-10 01:00:00'); +select unix_timestamp('1969-11-20 01:00:00'); +# bad day +select unix_timestamp('2038-01-20 01:00:00'); +select unix_timestamp('1969-12-30 01:00:00'); + +# +# Check negative shift (we subtract several days for boundary dates during +# conversion). +select unix_timestamp('2038-01-17 12:00:00'); + +# +# Check positive shift. (it happens only on +# platfroms with unsigned time_t, such as QNX) +# +select unix_timestamp('1970-01-01 03:00:01'); + +# check bad date, close to the boundary (we cut them off in the very end) +select unix_timestamp('2038-01-19 07:14:07'); + + +# # Test types from + INTERVAL # @@ -446,4 +486,10 @@ union union (select time_format(timediff(now(), DATE_SUB(now(),INTERVAL 5 HOUR)),'%k') As H); +# +# Bug #23653: crash if last_day('0000-00-00') +# + +select last_day('0000-00-00'); + --echo End of 4.1 tests diff --git a/mysql-test/t/innodb-deadlock.test b/mysql-test/t/innodb-deadlock.test index 41741942963..81acfba5c93 100644 --- a/mysql-test/t/innodb-deadlock.test +++ b/mysql-test/t/innodb-deadlock.test @@ -1,6 +1,4 @@ -- source include/have_innodb.inc -# Can't test this with embedded server --- source include/not_embedded.inc connect (con1,localhost,root,,); connect (con2,localhost,root,,); diff --git a/mysql-test/t/innodb-lock.test b/mysql-test/t/innodb-lock.test index 55a712fef9b..eacf7e562be 100644 --- a/mysql-test/t/innodb-lock.test +++ b/mysql-test/t/innodb-lock.test @@ -1,6 +1,4 @@ -- source include/have_innodb.inc -# Can't test this with embedded server --- source include/not_embedded.inc # # Check and select innodb lock type diff --git a/mysql-test/t/lock_multi.test b/mysql-test/t/lock_multi.test index 2e40aeaccb7..32e7f4234c4 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/mysql_client.test b/mysql-test/t/mysql_client.test index 2a7f4a935bb..505ca5d4b21 100644 --- a/mysql-test/t/mysql_client.test +++ b/mysql-test/t/mysql_client.test @@ -35,6 +35,24 @@ --exec echo 'help ' | $MYSQL > $MYSQLTEST_VARDIR/tmp/bug20328.tmp # +# 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#17583: mysql drops connection when stdout is not writable # create table t17583 (a int); @@ -51,4 +69,21 @@ select count(*) from t17583; --exec echo "select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; " |$MYSQL test >&- drop table t17583; +# +# 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 --echo End of 4.1 tests. diff --git a/mysql-test/t/mysqladmin.test b/mysql-test/t/mysqladmin.test new file mode 100644 index 00000000000..7c016fd7416 --- /dev/null +++ b/mysql-test/t/mysqladmin.test @@ -0,0 +1,32 @@ +# +# Test "mysqladmin ping" +# + +--exec $MYSQLADMIN --no-defaults -S $MASTER_MYSOCK -P $MASTER_MYPORT -u root --password= ping 2>&1 + + +# +# Bug#10608 mysqladmin breaks on "database" variable in my.cnf +# + +# When mysqladmin finds database in .cnf file it shall fail +--write_file $MYSQLTEST_VARDIR/tmp/bug10608.cnf +[client] +database=db1 +EOF + +--replace_regex /\/.*mysqladmin/mysqladmin/ +--error 7 +--exec $MYSQLADMIN --defaults-file=$MYSQLTEST_VARDIR/tmp/bug10608.cnf -S $MASTER_MYSOCK -P $MASTER_MYPORT -u root --password= ping 2>&1 + + +# When mysqladmin finds "loose-database" in .cnf file it shall print +# a warning and continue +--write_file $MYSQLTEST_VARDIR/tmp/bug10608.cnf +[client] +loose-database=db2 +EOF + +--replace_regex /Warning: .*mysqladmin/Warning: mysqladmin/ +--exec $MYSQLADMIN --defaults-file=$MYSQLTEST_VARDIR/tmp/bug10608.cnf -S $MASTER_MYSOCK -P $MASTER_MYPORT -u root --password= ping 2>&1 + diff --git a/mysql-test/t/mysqltest.test b/mysql-test/t/mysqltest.test index 3c20b38722f..c06d51d9d49 100644 --- a/mysql-test/t/mysqltest.test +++ b/mysql-test/t/mysqltest.test @@ -1522,6 +1522,46 @@ remove_file $MYSQLTEST_VARDIR/tmp/file2.tmp; --exec echo "copy_file from_file;" | $MYSQL_TEST 2>&1 # ---------------------------------------------------------------------------- +# test for chmod +# ---------------------------------------------------------------------------- +--write_file $MYSQLTEST_VARDIR/tmp/file1.tmp +file1 +EOF + +chmod 0000 $MYSQLTEST_VARDIR/tmp/file1.tmp; +# The below write fails, but --error is not implemented +# for write_file +#--write_file $MYSQLTEST_VARDIR/tmp/file1.tmp +#test should fail +#EOF + +chmod 0777 $MYSQLTEST_VARDIR/tmp/file1.tmp; +--write_file $MYSQLTEST_VARDIR/tmp/file1.tmp +test2 +EOF + +remove_file $MYSQLTEST_VARDIR/tmp/file1.tmp; + +--error 1 +--exec echo "chmod ;" | $MYSQL_TEST 2>&1 + +--error 1 +--exec echo "chmod 0 from_file;" | $MYSQL_TEST 2>&1 + +--error 1 +--exec echo "chmod 08 from_file;" | $MYSQL_TEST 2>&1 + +--error 1 +--exec echo "chmod from_file;" | $MYSQL_TEST 2>&1 + +--error 1 +--exec echo "chmod ABZD from_file;" | $MYSQL_TEST 2>&1 + +--error 1 +--exec echo "chmod 06789 from_file;" | $MYSQL_TEST 2>&1 + + +# ---------------------------------------------------------------------------- # test for perl # ---------------------------------------------------------------------------- --perl diff --git a/mysql-test/t/order_by.test b/mysql-test/t/order_by.test index 1664afc70f9..a8024be7032 100644 --- a/mysql-test/t/order_by.test +++ b/mysql-test/t/order_by.test @@ -559,4 +559,20 @@ 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 diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index 5b488ae4393..fbeaaa494e0 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -811,6 +811,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; # @@ -820,17 +823,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; @@ -844,12 +847,6 @@ set @@max_prepared_stmt_count=1; set max_prepared_stmt_count=1; --error 1229 # ER_GLOBAL_VARIABLE set local max_prepared_stmt_count=1; ---error 1229 # ER_GLOBAL_VARIABLE -set local prepared_stmt_count=0; ---error 1229 # ER_GLOBAL_VARIABLE -set @@prepared_stmt_count=0; ---error 1232 # ER_WRONG_TYPE_FOR_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; @@ -857,47 +854,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 1105 # ER_UNKNOWN_ERROR 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 1105 # ER_UNKNOWN_ERROR 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 1105 # ER_UNKNOWN_ERROR prepare stmt from "select 1"; # Result: the old statement is deallocated, the new is not created. --error 1243 # ER_UNKNOWN_STMT_HANDLER execute stmt; -select @@prepared_stmt_count; +show status like 'prepared_stmt_count'; --error 1105 # ER_UNKNOWN_ERROR 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; @@ -908,18 +908,11 @@ prepare stmt2 from "select 4"; connection default; --error 1105 # ER_UNKNOWN_ERROR prepare stmt2 from "select 4"; -select @@max_prepared_stmt_count, @@prepared_stmt_count; +select @@max_prepared_stmt_count; +show status like 'prepared_stmt_count'; disconnect con1; connection default; -# Wait for the connection to die: deal with a possible race deallocate prepare stmt; -let $count= `select @@prepared_stmt_count`; -if ($count) -{ ---sleep 2 - let $count= `select @@prepared_stmt_count`; -} -select @@max_prepared_stmt_count, @@prepared_stmt_count; # # Restore the old value. # diff --git a/mysql-test/t/rename.test b/mysql-test/t/rename.test index b0fb60c0ee4..cd1cc1e66b8 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) @@ -70,4 +66,8 @@ show tables; drop table t2, t4; -# End of 4.1 tests +disconnect con2; +disconnect con1; +connection default; + +--echo End of 4.1 tests 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/show_check.test b/mysql-test/t/show_check.test index d70903adbc4..8be676d9a35 100644 --- a/mysql-test/t/show_check.test +++ b/mysql-test/t/show_check.test @@ -1,5 +1,4 @@ -# Requires use of multiple simultaneous connections, not supported with -# embedded server testing +# Uses GRANT commands that usually disabled in embedded server -- source include/not_embedded.inc # diff --git a/mysql-test/t/status.test b/mysql-test/t/status.test index 7fea51c9327..df8da26df57 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/subselect.test b/mysql-test/t/subselect.test index f3877b301d6..804cc2274c9 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -1948,4 +1948,37 @@ 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 diff --git a/mysql-test/t/timezone.test b/mysql-test/t/timezone.test index 34bbb365c70..157b18f57fa 100644 --- a/mysql-test/t/timezone.test +++ b/mysql-test/t/timezone.test @@ -52,11 +52,12 @@ INSERT INTO t1 (ts) VALUES ('2003-03-30 01:59:59'), DROP TABLE t1; # -# Test for fix for Bug#2523 +# Test for fix for Bug#2523 Check that boundary dates are processed +# correctly. # select unix_timestamp('1970-01-01 01:00:00'), unix_timestamp('1970-01-01 01:00:01'), - unix_timestamp('2038-01-01 00:59:59'), - unix_timestamp('2038-01-01 01:00:00'); + unix_timestamp('2038-01-19 04:14:07'), + unix_timestamp('2038-01-19 04:14:08'); # End of 4.1 tests diff --git a/mysql-test/t/timezone2.test b/mysql-test/t/timezone2.test index 523249a3a2c..43f9a944be1 100644 --- a/mysql-test/t/timezone2.test +++ b/mysql-test/t/timezone2.test @@ -107,21 +107,21 @@ create table t1 (ts timestamp); set time_zone='UTC'; insert into t1 values ('0000-00-00 00:00:00'),('1969-12-31 23:59:59'), ('1970-01-01 00:00:00'),('1970-01-01 00:00:01'), - ('2037-12-31 23:59:59'),('2038-01-01 00:00:00'); + ('2038-01-19 03:14:07'),('2038-01-19 03:14:08'); select * from t1; delete from t1; # MET time zone has range shifted by one hour set time_zone='MET'; insert into t1 values ('0000-00-00 00:00:00'),('1970-01-01 00:30:00'), ('1970-01-01 01:00:00'),('1970-01-01 01:00:01'), - ('2038-01-01 00:59:59'),('2038-01-01 01:00:00'); + ('2038-01-19 04:14:07'),('2038-01-19 04:14:08'); select * from t1; delete from t1; # same for +01:30 time zone set time_zone='+01:30'; insert into t1 values ('0000-00-00 00:00:00'),('1970-01-01 01:00:00'), ('1970-01-01 01:30:00'),('1970-01-01 01:30:01'), - ('2038-01-01 01:29:59'),('2038-01-01 01:30:00'); + ('2038-01-19 04:44:07'),('2038-01-19 04:44:08'); select * from t1; drop table t1; @@ -171,8 +171,8 @@ select convert_tz('2003-10-26 01:00:00', 'MET', 'UTC'); select convert_tz('2003-10-26 02:00:00', 'MET', 'UTC'); select convert_tz('2003-10-26 02:59:59', 'MET', 'UTC'); select convert_tz('2003-10-26 04:00:00', 'MET', 'UTC'); -select convert_tz('2038-01-01 00:59:59', 'MET', 'UTC'); -select convert_tz('2038-01-01 01:00:00', 'MET', 'UTC'); +select convert_tz('2038-01-19 04:14:07', 'MET', 'UTC'); +select convert_tz('2038-01-19 04:14:08', 'MET', 'UTC'); select convert_tz('2103-01-01 04:00:00', 'MET', 'UTC'); # Let us test variable time zone argument diff --git a/mysql-test/t/timezone4-master.opt b/mysql-test/t/timezone4-master.opt new file mode 100644 index 00000000000..d1ab6207933 --- /dev/null +++ b/mysql-test/t/timezone4-master.opt @@ -0,0 +1 @@ +--timezone=GMT+10 diff --git a/mysql-test/t/timezone4.test b/mysql-test/t/timezone4.test new file mode 100644 index 00000000000..d7372c75d5a --- /dev/null +++ b/mysql-test/t/timezone4.test @@ -0,0 +1,13 @@ +# +# Tests for time functions. The difference from func_time test is the +# timezone. In func_time it's GMT-3. In our case it's GMT+10 +# + +# +# Test for bug bug #9191 "TIMESTAMP/from_unixtime() no longer accepts 2^31-1" +# + +select from_unixtime(0); +# check 0 boundary +select unix_timestamp('1969-12-31 14:00:01'); + diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c index dfc3fb3d39c..3f87186ccc3 100644 --- a/mysys/my_getopt.c +++ b/mysys/my_getopt.c @@ -59,11 +59,15 @@ char *disabled_my_option= (char*) "0"; my_bool my_getopt_print_errors= 1; -static void default_reporter(enum loglevel level __attribute__((unused)), +static void default_reporter(enum loglevel level, const char *format, ...) { va_list args; va_start(args, format); + if (level == WARNING_LEVEL) + fprintf(stderr, "%s", "Warning: "); + else if (level == INFORMATION_LEVEL) + fprintf(stderr, "%s", "Info: "); vfprintf(stderr, format, args); va_end(args); } diff --git a/ndb/config/common.mk.am b/ndb/config/common.mk.am index 4df1b0e289a..d0b7e753285 100644 --- a/ndb/config/common.mk.am +++ b/ndb/config/common.mk.am @@ -7,6 +7,6 @@ ndbapiincludedir = "$(pkgincludedir)/ndb/ndbapi" mgmapiincludedir = "$(pkgincludedir)/ndb/mgmapi" INCLUDES = $(INCLUDES_LOC) -LDADD = $(LDADD_LOC) -L$(top_srcdir)/ndb/src/common/portlib -lmygcc +LDADD = $(LDADD_LOC) -L$(top_builddir)/ndb/src/common/portlib -lmygcc DEFS = @DEFS@ @NDB_DEFS@ $(DEFS_LOC) $(NDB_EXTRA_FLAGS) NDB_CXXFLAGS=@ndb_cxxflags_fix@ $(NDB_CXXFLAGS_LOC) diff --git a/ndb/config/type_kernel.mk.am b/ndb/config/type_kernel.mk.am index 703876ee2e9..ccb01709dfb 100644 --- a/ndb/config/type_kernel.mk.am +++ b/ndb/config/type_kernel.mk.am @@ -1,6 +1,9 @@ INCLUDES += \ - -I$(srcdir) -I$(top_srcdir)/include \ + -I$(srcdir) \ + -I$(top_builddir)/include \ + -I$(top_builddir)/ndb/include \ + -I$(top_srcdir)/include \ -I$(top_srcdir)/ndb/include \ -I$(top_srcdir)/ndb/src/kernel/vm \ -I$(top_srcdir)/ndb/src/kernel/error \ diff --git a/ndb/config/type_ndbapi.mk.am b/ndb/config/type_ndbapi.mk.am index ed648273aea..8b447bd693d 100644 --- a/ndb/config/type_ndbapi.mk.am +++ b/ndb/config/type_ndbapi.mk.am @@ -1,6 +1,10 @@ INCLUDES += \ - -I$(srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/ndb/include \ + -I$(srcdir) \ + -I$(top_builddir)/include \ + -I$(top_builddir)/ndb/include \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/ndb/include \ -I$(top_srcdir)/ndb/include/kernel \ -I$(top_srcdir)/ndb/include/transporter \ -I$(top_srcdir)/ndb/include/debugger \ diff --git a/ndb/config/type_ndbapitest.mk.am b/ndb/config/type_ndbapitest.mk.am index 392c4e9fc70..e9a383eaad7 100644 --- a/ndb/config/type_ndbapitest.mk.am +++ b/ndb/config/type_ndbapitest.mk.am @@ -5,7 +5,10 @@ LDADD += $(top_builddir)/ndb/test/src/libNDBT.a \ $(top_builddir)/mysys/libmysys.a \ $(top_builddir)/strings/libmystrings.a @NDB_SCI_LIBS@ -INCLUDES += -I$(top_srcdir) -I$(top_srcdir)/include \ +INCLUDES += -I$(top_srcdir) \ + -I$(top_builddir)/include \ + -I$(top_builddir)/ndb/include \ + -I$(top_srcdir)/include \ -I$(top_srcdir)/ndb/include \ -I$(top_srcdir)/ndb/include/ndbapi \ -I$(top_srcdir)/ndb/include/util \ diff --git a/ndb/config/type_ndbapitools.mk.am b/ndb/config/type_ndbapitools.mk.am index 679dac09f47..1f4d93af618 100644 --- a/ndb/config/type_ndbapitools.mk.am +++ b/ndb/config/type_ndbapitools.mk.am @@ -5,7 +5,10 @@ LDADD += \ $(top_builddir)/mysys/libmysys.a \ $(top_builddir)/strings/libmystrings.a @NDB_SCI_LIBS@ -lmygcc -INCLUDES += -I$(srcdir) -I$(top_srcdir)/include \ +INCLUDES += -I$(srcdir) \ + -I$(top_builddir)/include \ + -I$(top_builddir)/ndb/include \ + -I$(top_srcdir)/include \ -I$(top_srcdir)/ndb/include \ -I$(top_srcdir)/ndb/include/ndbapi \ -I$(top_srcdir)/ndb/include/util \ diff --git a/ndb/config/type_util.mk.am b/ndb/config/type_util.mk.am index 0dfa77b7a7c..b92501faee9 100644 --- a/ndb/config/type_util.mk.am +++ b/ndb/config/type_util.mk.am @@ -1,5 +1,8 @@ -INCLUDES += -I$(srcdir) -I$(top_srcdir)/include \ +INCLUDES += -I$(srcdir) \ + -I$(top_builddir)/include \ + -I$(top_builddir)/ndb/include \ + -I$(top_srcdir)/include \ -I$(top_srcdir)/ndb/include \ -I$(top_srcdir)/ndb/include/util \ -I$(top_srcdir)/ndb/include/portlib \ diff --git a/ndb/src/common/portlib/gcc.cpp b/ndb/src/common/portlib/gcc.cpp index 66aa4812dc6..557c1ac3717 100644 --- a/ndb/src/common/portlib/gcc.cpp +++ b/ndb/src/common/portlib/gcc.cpp @@ -4,4 +4,7 @@ */ #ifdef DEFINE_CXA_PURE_VIRTUAL extern "C" { int __cxa_pure_virtual() { return 0;} } +#else +/* Some compiler/linker combinations fail on files without exported symbols. */ +extern "C" { int dummy_export_symbol() { return 0;} } #endif diff --git a/ndb/src/kernel/Makefile.am b/ndb/src/kernel/Makefile.am index 5b55238c262..c9e590835db 100644 --- a/ndb/src/kernel/Makefile.am +++ b/ndb/src/kernel/Makefile.am @@ -9,21 +9,21 @@ ndbd_SOURCES = main.cpp SimBlockList.cpp include $(top_srcdir)/ndb/config/type_kernel.mk.am INCLUDES += \ - -Iblocks/cmvmi \ - -Iblocks/dbacc \ - -Iblocks/dbdict \ - -Iblocks/dbdih \ - -Iblocks/dblqh \ - -Iblocks/dbtc \ - -Iblocks/dbtup \ - -Iblocks/ndbfs \ - -Iblocks/ndbcntr \ - -Iblocks/qmgr \ - -Iblocks/trix \ - -Iblocks/backup \ - -Iblocks/dbutil \ - -Iblocks/suma \ - -Iblocks/dbtux + -I$(srcdir)/blocks/cmvmi \ + -I$(srcdir)/blocks/dbacc \ + -I$(srcdir)/blocks/dbdict \ + -I$(srcdir)/blocks/dbdih \ + -I$(srcdir)/blocks/dblqh \ + -I$(srcdir)/blocks/dbtc \ + -I$(srcdir)/blocks/dbtup \ + -I$(srcdir)/blocks/ndbfs \ + -I$(srcdir)/blocks/ndbcntr \ + -I$(srcdir)/blocks/qmgr \ + -I$(srcdir)/blocks/trix \ + -I$(srcdir)/blocks/backup \ + -I$(srcdir)/blocks/dbutil \ + -I$(srcdir)/blocks/suma \ + -I$(srcdir)/blocks/dbtux LDADD += \ blocks/cmvmi/libcmvmi.a \ diff --git a/scripts/make_binary_distribution.sh b/scripts/make_binary_distribution.sh index f37e667dd86..6359eb009ce 100644 --- a/scripts/make_binary_distribution.sh +++ b/scripts/make_binary_distribution.sh @@ -224,6 +224,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/std_data/*.dat mysql-test/std_data/*.*001 \ mysql-test/std_data/*.cnf \ $BASE/mysql-test/std_data diff --git a/scripts/mysql_fix_privilege_tables.sh b/scripts/mysql_fix_privilege_tables.sh index 56807a81d7c..361affae247 100644 --- a/scripts/mysql_fix_privilege_tables.sh +++ b/scripts/mysql_fix_privilege_tables.sh @@ -120,9 +120,6 @@ then fi cmd="$bindir/mysql --no-defaults --force --user=$user --host=$host" -if test ! -z "$password" ; then - cmd="$cmd --password=$password" -fi if test ! -z "$port"; then cmd="$cmd --port=$port" fi @@ -178,11 +175,22 @@ then s_echo "" fi +run_cmd() { + # Password argument is added here to allow for spaces in password. + + if test ! -z "$password" + then + cat $sql_file | $cmd --password="$password" + else + cat $sql_file | $cmd + fi +} + if test $verbose = 0 then - cat $sql_file | $cmd > /dev/null 2>&1 + run_cmd > /dev/null 2>&1 else - cat $sql_file | $cmd > /dev/null + run_cmd > /dev/null fi if test $? = 0 then diff --git a/sql-common/client.c b/sql-common/client.c index 3acd763c054..87e22624dd9 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -1173,6 +1173,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]); diff --git a/sql-common/my_time.c b/sql-common/my_time.c index baf9a3902d9..2d3d71e646c 100644 --- a/sql-common/my_time.c +++ b/sql-common/my_time.c @@ -350,7 +350,10 @@ str_to_datetime(const char *str, uint length, MYSQL_TIME *l_time, l_time->year > 9999 || l_time->month > 12 || l_time->day > 31 || l_time->hour > 23 || l_time->minute > 59 || l_time->second > 59 || - (!(flags & TIME_FUZZY_DATE) && (l_time->month == 0 || l_time->day == 0))) + (!(flags & TIME_FUZZY_DATE) && + (l_time->month == 0 || l_time->day == 0)) || + (l_time->year == 0 && l_time->month == 0 && l_time->day == 0 && + (l_time->hour != 0 || l_time->minute != 0 || l_time->second != 0))) { /* Only give warning for a zero date if there is some garbage after */ if (!not_zero_date) /* If zero date */ @@ -714,15 +717,28 @@ long calc_daynr(uint year,uint month,uint day) RETURN VALUE Time in UTC seconds since Unix Epoch representation. */ -my_time_t -my_system_gmt_sec(const MYSQL_TIME *t, long *my_timezone, bool *in_dst_time_gap) +my_time_t +my_system_gmt_sec(const MYSQL_TIME *t_src, long *my_timezone, + bool *in_dst_time_gap) { uint loop; - time_t tmp; + time_t tmp= 0; + int shift= 0; + MYSQL_TIME tmp_time; + MYSQL_TIME *t= &tmp_time; struct tm *l_time,tm_tmp; long diff, current_timezone; /* + Use temp variable to avoid trashing input data, which could happen in + case of shift required for boundary dates processing. + */ + memcpy(&tmp_time, t_src, sizeof(MYSQL_TIME)); + + if (!validate_timestamp_range(t)) + return 0; + + /* Calculate the gmt time based on current time and timezone The -1 on the end is to ensure that if have a date that exists twice (like 2002-10-27 02:00:0 MET), we will find the initial date. @@ -735,13 +751,89 @@ my_system_gmt_sec(const MYSQL_TIME *t, long *my_timezone, bool *in_dst_time_gap) Note: this code assumes that our time_t estimation is not too far away from real value (we assume that localtime_r(tmp) will return something within 24 hrs from t) which is probably true for all current time zones. + + Note2: For the dates, which have time_t representation close to + MAX_INT32 (efficient time_t limit for supported platforms), we should + do a small trick to avoid overflow. That is, convert the date, which is + two days earlier, and then add these days to the final value. + + The same trick is done for the values close to 0 in time_t + representation for platfroms with unsigned time_t (QNX). + + To be more verbose, here is a sample (extracted from the code below): + (calc_daynr(2038, 1, 19) - (long) days_at_timestart)*86400L + 4*3600L + would return -2147480896 because of the long type overflow. In result + we would get 1901 year in localtime_r(), which is an obvious error. + + Alike problem raises with the dates close to Epoch. E.g. + (calc_daynr(1969, 12, 31) - (long) days_at_timestart)*86400L + 23*3600L + will give -3600. + + On some platforms, (E.g. on QNX) time_t is unsigned and localtime(-3600) + wil give us a date around 2106 year. Which is no good. + + Theoreticaly, there could be problems with the latter conversion: + there are at least two timezones, which had time switches near 1 Jan + of 1970 (because of political reasons). These are America/Hermosillo and + America/Mazatlan time zones. They changed their offset on + 1970-01-01 08:00:00 UTC from UTC-8 to UTC-7. For these zones + the code below will give incorrect results for dates close to + 1970-01-01, in the case OS takes into account these historical switches. + Luckily, it seems that we support only one platform with unsigned + time_t. It's QNX. And QNX does not support historical timezone data at all. + E.g. there are no /usr/share/zoneinfo/ files or any other mean to supply + historical information for localtime_r() etc. That is, the problem is not + relevant to QNX. + + We are safe with shifts close to MAX_INT32, as there are no known + time switches on Jan 2038 yet :) */ - tmp=(time_t) (((calc_daynr((uint) t->year,(uint) t->month,(uint) t->day) - - (long) days_at_timestart)*86400L + (long) t->hour*3600L + - (long) (t->minute*60 + t->second)) + (time_t) my_time_zone - - 3600); - current_timezone= my_time_zone; + if ((t->year == TIMESTAMP_MAX_YEAR) && (t->month == 1) && (t->day > 4)) + { + /* + Below we will pass (uint) (t->day - shift) to calc_daynr. + As we don't want to get an overflow here, we will shift + only safe dates. That's why we have (t->day > 4) above. + */ + t->day-= 2; + shift= 2; + } +#ifdef TIME_T_UNSIGNED + else + { + /* + We can get 0 in time_t representaion only on 1969, 31 of Dec or on + 1970, 1 of Jan. For both dates we use shift, which is added + to t->day in order to step out a bit from the border. + This is required for platforms, where time_t is unsigned. + As far as I know, among the platforms we support it's only QNX. + Note: the order of below if-statements is significant. + */ + + if ((t->year == TIMESTAMP_MIN_YEAR + 1) && (t->month == 1) + && (t->day <= 10)) + { + t->day+= 2; + shift= -2; + } + if ((t->year == TIMESTAMP_MIN_YEAR) && (t->month == 12) + && (t->day == 31)) + { + t->year++; + t->month= 1; + t->day= 2; + shift= -2; + } + } +#endif + + tmp= (time_t) (((calc_daynr((uint) t->year, (uint) t->month, (uint) t->day) - + (long) days_at_timestart)*86400L + (long) t->hour*3600L + + (long) (t->minute*60 + t->second)) + (time_t) my_time_zone - + 3600); + + current_timezone= my_time_zone; localtime_r(&tmp,&tm_tmp); l_time=&tm_tmp; for (loop=0; @@ -793,7 +885,24 @@ my_system_gmt_sec(const MYSQL_TIME *t, long *my_timezone, bool *in_dst_time_gap) *in_dst_time_gap= 1; } *my_timezone= current_timezone; - + + + /* shift back, if we were dealing with boundary dates */ + tmp+= shift*86400L; + + /* + This is possible for dates, which slightly exceed boundaries. + Conversion will pass ok for them, but we don't allow them. + First check will pass for platforms with signed time_t. + instruction above (tmp+= shift*86400L) could exceed + MAX_INT32 (== TIMESTAMP_MAX_VALUE) and overflow will happen. + So, tmp < TIMESTAMP_MIN_VALUE will be triggered. On platfroms + with unsigned time_t tmp+= shift*86400L might result in a number, + larger then TIMESTAMP_MAX_VALUE, so another check will work. + */ + 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/item.cc b/sql/item.cc index 94f0a24fcc3..45d7856b2c1 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1761,10 +1761,37 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) 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(db_name,table_name,field_name); + if (!rf) + return 1; + thd->change_item_tree(ref, 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, tables, ref) || rf->check_cols(1); + } } } diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 6b6996160a1..859b4e0ecc1 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1998,7 +1998,6 @@ void Item_func_in::fix_length_and_dec() if (cmp_type == STRING_RESULT) in_item->cmp_charset= cmp_collation.collation; } - maybe_null= args[0]->maybe_null; max_length= 1; } diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index f3be0663af8..cd1f8f83821 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -391,6 +391,15 @@ enum Item_result Item_singlerow_subselect::result_type() const return engine->type(); } +/* + Don't rely on the result type to calculate field type. + Ask the engine instead. +*/ +enum_field_types Item_singlerow_subselect::field_type() const +{ + return engine->field_type(); +} + void Item_singlerow_subselect::fix_length_and_dec() { if ((max_columns= engine->cols()) == 1) @@ -610,6 +619,7 @@ double Item_in_subselect::val() */ DBUG_ASSERT(0); DBUG_ASSERT(fixed == 1); + null_value= 0; if (exec()) { reset(); @@ -625,6 +635,7 @@ double Item_in_subselect::val() longlong Item_in_subselect::val_int() { DBUG_ASSERT(fixed == 1); + null_value= 0; if (exec()) { reset(); @@ -645,6 +656,7 @@ String *Item_in_subselect::val_str(String *str) */ DBUG_ASSERT(0); DBUG_ASSERT(fixed == 1); + null_value= 0; if (exec()) { reset(); @@ -1354,31 +1366,35 @@ int subselect_uniquesubquery_engine::prepare() return 1; } -static Item_result set_row(List<Item> &item_list, Item *item, - Item_cache **row, bool *maybe_null) +/* + 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; - *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; @@ -1390,13 +1406,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; } } diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 93171ad64a1..7b064bfe92c 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -142,6 +142,7 @@ public: longlong val_int (); String *val_str (String *); enum Item_result result_type() const; + enum_field_types field_type() const; void fix_length_and_dec(); uint cols(); @@ -273,6 +274,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: @@ -282,6 +284,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 @@ -296,6 +299,7 @@ public: virtual uint cols()= 0; /* return number of columnss 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; @@ -303,6 +307,9 @@ public: virtual void print(String *str)= 0; virtual int change_item(Item_subselect *si, select_subselect *result)= 0; virtual bool no_tables()= 0; + +protected: + void set_row(List<Item> &item_list, Item_cache **row); }; diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 5fd65fecbfc..419efd07615 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -71,9 +71,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; } @@ -1673,6 +1677,7 @@ int dump_leaf_key(byte* key, uint32 count __attribute__((unused)), { char buff[MAX_FIELD_WIDTH]; String tmp((char *)&buff,sizeof(buff),default_charset_info), tmp2; + uint old_length= item->result.length(); if (item->no_appended) item->no_appended= FALSE; @@ -1711,8 +1716,22 @@ int dump_leaf_key(byte* key, uint32 count __attribute__((unused)), /* stop if length of result more than group_concat_max_len */ if (item->result.length() > item->group_concat_max_len) { + int well_formed_error; + CHARSET_INFO *cs= item->collation.collation; + const char *ptr= item->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->group_concat_max_len, + item->result.length(), + &well_formed_error); + item->result.length(old_length + add_length); item->count_cut_values++; - item->result.length(item->group_concat_max_len); item->warning_for_row= TRUE; return 1; } @@ -1902,8 +1921,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() <= group_concat_max_len && - !warning_for_row && + if (!warning_for_row && (!tree_mode || (el->count == 1 && distinct && !arg_count_order))) dump_leaf_key(table->record[0], 1, this); diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index c1bca7afc60..d6465406c68 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -289,15 +289,15 @@ static bool extract_date_time(DATE_TIME_FORMAT *format, for (; ptr != end && val != val_end; ptr++) { + /* Skip pre-space between each argument */ + while (val != val_end && my_isspace(cs, *val)) + val++; + if (*ptr == '%' && ptr+1 != end) { int val_len; char *tmp; - /* Skip pre-space between each argument */ - while (val != val_end && my_isspace(cs, *val)) - val++; - val_len= (uint) (val_end - val); switch (*++ptr) { /* Year */ @@ -1931,15 +1931,10 @@ bool Item_func_convert_tz::get_date(TIME *ltime, return 1; } - /* Check if we in range where we treat datetime values as non-UTC */ - if (ltime->year < TIMESTAMP_MAX_YEAR && ltime->year > TIMESTAMP_MIN_YEAR || - ltime->year==TIMESTAMP_MAX_YEAR && ltime->month==1 && ltime->day==1 || - ltime->year==TIMESTAMP_MIN_YEAR && ltime->month==12 && ltime->day==31) - { - my_time_tmp= from_tz->TIME_to_gmt_sec(ltime, ¬_used); - if (my_time_tmp >= TIMESTAMP_MIN_VALUE && my_time_tmp <= TIMESTAMP_MAX_VALUE) - to_tz->gmt_sec_to_TIME(ltime, my_time_tmp); - } + my_time_tmp= from_tz->TIME_to_gmt_sec(ltime, ¬_used); + /* my_time_tmp is guranteed to be in the allowed range */ + if (my_time_tmp) + to_tz->gmt_sec_to_TIME(ltime, my_time_tmp); null_value= 0; return 0; @@ -3058,7 +3053,8 @@ String *Item_func_str_to_date::val_str(String *str) bool Item_func_last_day::get_date(TIME *ltime, uint fuzzy_date) { - if (get_arg0_date(ltime, fuzzy_date & ~TIME_FUZZY_DATE)) + if (get_arg0_date(ltime, fuzzy_date & ~TIME_FUZZY_DATE) || + (ltime->month == 0)) return 1; uint month_idx= ltime->month-1; ltime->day= days_in_month[month_idx]; diff --git a/sql/log_event.h b/sql/log_event.h index 6c4e65f7460..ec2d8993bca 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -148,6 +148,14 @@ struct sql_ex_info #define DELETE_FILE_HEADER_LEN 4 /* + Max number of possible extra bytes in a replication event compared to a + packet (i.e. a query) sent from client to master. +*/ +#define MAX_LOG_EVENT_HEADER (LOG_EVENT_HEADER_LEN + /* write_header */ \ + QUERY_HEADER_LEN + /* write_data */ \ + NAME_LEN + 1) + +/* Event header offsets; these point to places inside the fixed header. */ diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index b1b0016c06b..8d6cdebe1f7 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -144,12 +144,6 @@ MY_LOCALE *my_locale_by_name(const char *name); /* Characters shown for the command in 'show processlist' */ #define PROCESS_LIST_WIDTH 100 -/* Time handling defaults */ -#define TIMESTAMP_MAX_YEAR 2038 -#define YY_PART_YEAR 70 -#define TIMESTAMP_MIN_YEAR (1900 + YY_PART_YEAR - 1) -#define TIMESTAMP_MAX_VALUE 2145916799 -#define TIMESTAMP_MIN_VALUE 1 #define PRECISION_FOR_DOUBLE 53 #define PRECISION_FOR_FLOAT 24 diff --git a/sql/mysqld.cc b/sql/mysqld.cc index dbb1838c3d7..cd0ddc00624 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -274,7 +274,7 @@ bool opt_disable_networking=0, opt_skip_show_db=0; bool opt_character_set_client_handshake= 1; bool lower_case_table_names_used= 0; bool server_id_supplied = 0; -bool opt_endinfo,using_udf_functions, locked_in_memory; +bool opt_endinfo, using_udf_functions, locked_in_memory; bool opt_using_transactions, using_update_log; bool volatile abort_loop, select_thread_in_use, signal_thread_in_use; bool volatile ready_to_exit, shutdown_in_progress, grant_option; @@ -2015,13 +2015,24 @@ later when used with nscd), disable LDAP in your nsswitch.conf, or use a\n\ mysqld that is not statically linked.\n"); #endif - if (test_flags & TEST_CORE_ON_SIGNAL) - { - fprintf(stderr, "Writing a core file\n"); - fflush(stderr); - write_core(sig); - } - exit(1); + if (locked_in_memory) + { + fprintf(stderr, "\n\ +The \"--memlock\" argument, which was enabled, uses system calls that are\n\ +unreliable and unstable on some operating systems and operating-system\n\ +versions (notably, some versions of Linux). This crash could be due to use\n\ +of those buggy OS calls. You should consider whether you really need the\n\ +\"--memlock\" parameter and/or consult the OS distributer about \"mlockall\"\n\ +bugs.\n"); + } + + if (test_flags & TEST_CORE_ON_SIGNAL) + { + fprintf(stderr, "Writing a core file\n"); + fflush(stderr); + write_core(sig); + } + exit(1); } #ifndef SA_RESETHAND @@ -5722,6 +5733,7 @@ struct show_var_st status_vars[]= { {"Open_streams", (char*) &my_stream_opened, SHOW_LONG_CONST}, {"Open_tables", (char*) 0, SHOW_OPENTABLES}, {"Opened_tables", (char*) &opened_tables, SHOW_LONG}, + {"Prepared_stmt_count", (char*) &prepared_stmt_count, SHOW_LONG_CONST}, #ifdef HAVE_QUERY_CACHE {"Qcache_free_blocks", (char*) &query_cache.free_memory_blocks, SHOW_LONG_CONST}, @@ -5892,6 +5904,7 @@ static void mysql_init_variables(void) binlog_cache_use= binlog_cache_disk_use= 0; max_used_connections= slow_launch_threads = 0; mysqld_user= mysqld_chroot= opt_init_file= opt_bin_logname = 0; + prepared_stmt_count= 0; errmesg= 0; mysqld_unix_port= opt_mysql_tmpdir= my_bind_addr_str= NullS; bzero((gptr) &mysql_tmpdir_list, sizeof(mysql_tmpdir_list)); diff --git a/sql/protocol.cc b/sql/protocol.cc index a2287740f1e..7c7dfaf7bef 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -43,7 +43,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; @@ -297,8 +297,8 @@ send_ok(THD *thd, ha_rows affected_rows, ulonglong id, const char *message) DBUG_VOID_RETURN; 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", @@ -416,7 +416,7 @@ bool send_old_password_request(THD *thd) 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) @@ -439,7 +439,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; } @@ -448,7 +448,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; } @@ -457,7 +457,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; } @@ -520,7 +520,7 @@ bool Protocol::send_fields(List<Item> *list, uint flag) if (flag & 1) { // 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)); } @@ -648,7 +648,7 @@ bool Protocol::send_records_num(List<Item> *list, ulonglong records) { char *pos; char buff[20]; - pos=net_store_length(buff, (uint) list->elements); + pos=net_store_length(buff, list->elements); pos=net_store_length(pos, records); return my_net_write(&thd->net, buff,(uint) (pos-buff)); } diff --git a/sql/protocol.h b/sql/protocol.h index 32d6acccddf..ce3adb41df5 100644 --- a/sql/protocol.h +++ b/sql/protocol.h @@ -177,7 +177,6 @@ void send_ok(THD *thd, ha_rows affected_rows=0L, ulonglong id=0L, const char *info=0); void send_eof(THD *thd, bool no_flush=0); 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/set_var.cc b/sql/set_var.cc index 4433b6bf7d8..71ca382f9d9 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -119,7 +119,6 @@ static KEY_CACHE *create_key_cache(const char *name, uint length); void fix_sql_mode_var(THD *thd, enum_var_type type); static byte *get_error_count(THD *thd); static byte *get_warning_count(THD *thd); -static byte *get_prepared_stmt_count(THD *thd); static byte *get_have_innodb(THD *thd); /* @@ -482,9 +481,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 @@ -604,7 +600,6 @@ sys_var *sys_variables[]= &sys_new_mode, &sys_old_passwords, &sys_preload_buff_size, - &sys_prepared_stmt_count, &sys_pseudo_thread_id, &sys_query_alloc_block_size, &sys_query_cache_size, @@ -860,7 +855,6 @@ struct show_var_st init_vars[]= { {"pid_file", (char*) pidfile_name, SHOW_CHAR}, {"port", (char*) &mysqld_port, SHOW_INT}, {sys_preload_buff_size.name, (char*) &sys_preload_buff_size, SHOW_SYS}, - {sys_prepared_stmt_count.name, (char*) &sys_prepared_stmt_count, SHOW_SYS}, {"protocol_version", (char*) &protocol_version, SHOW_INT}, {sys_query_alloc_block_size.name, (char*) &sys_query_alloc_block_size, SHOW_SYS}, @@ -2715,14 +2709,6 @@ static byte *get_have_innodb(THD *thd) } -static byte *get_prepared_stmt_count(THD *thd) -{ - pthread_mutex_lock(&LOCK_prepared_stmt_count); - thd->sys_var_tmp.ulong_value= prepared_stmt_count; - pthread_mutex_unlock(&LOCK_prepared_stmt_count); - return (byte*) &thd->sys_var_tmp.ulong_value; -} - /**************************************************************************** Main handling of variables: - Initialisation diff --git a/sql/slave.cc b/sql/slave.cc index e3bc2d75829..6785e92b9f9 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -2618,6 +2618,13 @@ static int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type) SYSTEM_THREAD_SLAVE_SQL : SYSTEM_THREAD_SLAVE_IO; thd->host_or_ip= ""; 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->master_access= ~(ulong)0; thd->priv_user = 0; @@ -3143,16 +3150,24 @@ slave_begin: sql_print_error("Slave I/O thread: error in mysql_init()"); goto err; } - + thd->proc_info = "Connecting to master"; // we can get killed during safe_connect if (!safe_connect(thd, mysql, mi)) + { sql_print_information("Slave I/O thread: connected to master '%s@%s:%d',\ replication started in log '%s' at position %s", mi->user, - mi->host, mi->port, - IO_RPL_LOG_NAME, - llstr(mi->master_log_pos,llbuff)); + mi->host, mi->port, + IO_RPL_LOG_NAME, + llstr(mi->master_log_pos,llbuff)); + /* + Adding MAX_LOG_EVENT_HEADER_LEN to the max_packet_size on the I/O + thread, since a replication event can become this much larger than + the corresponding packet (query) sent from client to master. + */ + mysql->net.max_packet_size= thd->net.max_packet_size+= MAX_LOG_EVENT_HEADER; + } else { sql_print_error("Slave I/O thread killed while connecting to master"); diff --git a/sql/sql_class.h b/sql/sql_class.h index b61403e4b0a..05105bfc86a 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -686,6 +686,12 @@ public: char *extra_data; ulong extra_length; String query_rest; + /* + 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 diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 2a7ab55b8c4..a20f2a6506c 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -420,6 +420,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; while (!net->error && net->vio != 0 && !thd->killed) { diff --git a/sql/sql_table.cc b/sql/sql_table.cc index da66b556b5e..f82dd627101 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -34,11 +34,12 @@ const char *primary_key_name="PRIMARY"; static bool check_if_keyname_exists(const char *name,KEY *start, KEY *end); static char *make_unique_key_name(const char *field_name,KEY *start,KEY *end); static int copy_data_between_tables(TABLE *from,TABLE *to, - List<create_field> &create, - enum enum_duplicates handle_duplicates, + List<create_field> &create, + enum enum_duplicates handle_duplicates, bool ignore, - uint order_num, ORDER *order, - ha_rows *copied,ha_rows *deleted); + uint order_num, ORDER *order, + ha_rows *copied, ha_rows *deleted, + enum enum_enable_or_disable keys_onoff); /* @@ -2837,6 +2838,54 @@ int mysql_drop_indexes(THD *thd, TABLE_LIST *table_list, /* + Manages enabling/disabling of indexes for ALTER TABLE + + SYNOPSIS + alter_table_manage_keys() + table Target table + indexes_were_disabled Whether the indexes of the from table + were disabled + keys_onoff ENABLE | DISABLE | LEAVE_AS_IS + + RETURN VALUES + FALSE OK + TRUE Error +*/ + +static +bool alter_table_manage_keys(TABLE *table, int indexes_were_disabled, + enum enum_enable_or_disable keys_onoff) +{ + int error= 0; + DBUG_ENTER("alter_table_manage_keys"); + DBUG_PRINT("enter", ("table=%p were_disabled=%d on_off=%d", + table, indexes_were_disabled, keys_onoff)); + + switch (keys_onoff) { + case ENABLE: + error= table->file->enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE); + break; + case LEAVE_AS_IS: + if (!indexes_were_disabled) + break; + /* fall-through: disabled indexes */ + case DISABLE: + error= table->file->disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE); + } + + if (error == HA_ERR_WRONG_COMMAND) + { + push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_NOTE, + ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA), table->table_name); + error= 0; + } else if (error) + table->file->print_error(error, MYF(0)); + + DBUG_RETURN(error); +} + + +/* Alter table */ @@ -2949,8 +2998,35 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, thd->proc_info="setup"; if (alter_info->is_simple && !table->tmp_table) { - error=0; - if (new_name != table_name || new_db != db) + switch (alter_info->keys_onoff) { + case LEAVE_AS_IS: + error= 0; + break; + case ENABLE: + VOID(pthread_mutex_lock(&LOCK_open)); + wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN); + VOID(pthread_mutex_unlock(&LOCK_open)); + error= table->file->enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE); + /* COND_refresh will be signaled in close_thread_tables() */ + break; + case DISABLE: + VOID(pthread_mutex_lock(&LOCK_open)); + wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN); + VOID(pthread_mutex_unlock(&LOCK_open)); + error= table->file->disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE); + /* COND_refresh will be signaled in close_thread_tables() */ + break; + } + + if (error == HA_ERR_WRONG_COMMAND) + { + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, + ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA), + table->table_name); + error= 0; + } + + if (!error && (new_name != table_name || new_db != db)) { thd->proc_info="rename"; VOID(pthread_mutex_lock(&LOCK_open)); @@ -2971,27 +3047,6 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, VOID(pthread_mutex_unlock(&LOCK_open)); } - if (!error) - { - switch (alter_info->keys_onoff) { - case LEAVE_AS_IS: - break; - case ENABLE: - VOID(pthread_mutex_lock(&LOCK_open)); - wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN); - VOID(pthread_mutex_unlock(&LOCK_open)); - error= table->file->enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE); - /* COND_refresh will be signaled in close_thread_tables() */ - break; - case DISABLE: - VOID(pthread_mutex_lock(&LOCK_open)); - wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN); - VOID(pthread_mutex_unlock(&LOCK_open)); - error=table->file->disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE); - /* COND_refresh will be signaled in close_thread_tables() */ - break; - } - } if (error == HA_ERR_WRONG_COMMAND) { push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, @@ -2999,6 +3054,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, table->table_name); error=0; } + if (!error) { mysql_update_log.write(thd, thd->query, thd->query_length); @@ -3368,7 +3424,14 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, if (!new_table->is_view) error=copy_data_between_tables(table,new_table,create_list, handle_duplicates, ignore, - order_num, order, &copied, &deleted); + order_num, order, &copied, &deleted, + alter_info->keys_onoff); + /* + No need to have call to alter_table_manage_keys() in the else because + in 4.1 we always copy data, except for views. In 5.0 it could happen + that no data is copied and only frm is modified. Then we have to handle + alter_info->keys_onoff outside of copy_data_between_tables + */ thd->last_insert_id=next_insert_id; // Needed for correct log thd->count_cuted_fields= CHECK_FIELD_IGNORE; @@ -3591,7 +3654,8 @@ copy_data_between_tables(TABLE *from,TABLE *to, bool ignore, uint order_num, ORDER *order, ha_rows *copied, - ha_rows *deleted) + ha_rows *deleted, + enum enum_enable_or_disable keys_onoff) { int error; Copy_field *copy,*copy_end; @@ -3623,6 +3687,10 @@ copy_data_between_tables(TABLE *from,TABLE *to, if (to->file->external_lock(thd, F_WRLCK)) DBUG_RETURN(-1); + + /* We need external lock before we can disable/enable keys */ + alter_table_manage_keys(to, from->file->indexes_are_disabled(), keys_onoff); + from->file->info(HA_STATUS_VARIABLE); to->file->start_bulk_insert(from->file->records); diff --git a/sql/time.cc b/sql/time.cc index ddc5e6435be..a1a27619e4b 100644 --- a/sql/time.cc +++ b/sql/time.cc @@ -230,14 +230,11 @@ my_time_t TIME_to_timestamp(THD *thd, const TIME *t, bool *in_dst_time_gap) *in_dst_time_gap= 0; - if (t->year < TIMESTAMP_MAX_YEAR && t->year > TIMESTAMP_MIN_YEAR || - t->year == TIMESTAMP_MAX_YEAR && t->month == 1 && t->day == 1 || - t->year == TIMESTAMP_MIN_YEAR && t->month == 12 && t->day == 31) + timestamp= thd->variables.time_zone->TIME_to_gmt_sec(t, in_dst_time_gap); + if (timestamp) { thd->time_zone_used= 1; - timestamp= thd->variables.time_zone->TIME_to_gmt_sec(t, in_dst_time_gap); - if (timestamp >= TIMESTAMP_MIN_VALUE && timestamp <= TIMESTAMP_MAX_VALUE) - return timestamp; + return timestamp; } /* If we are here we have range error. */ diff --git a/sql/tztime.cc b/sql/tztime.cc index b0a32748998..9af33526c98 100644 --- a/sql/tztime.cc +++ b/sql/tztime.cc @@ -885,9 +885,14 @@ TIME_to_gmt_sec(const TIME *t, const TIME_ZONE_INFO *sp, bool *in_dst_time_gap) my_time_t local_t; uint saved_seconds; uint i; + int shift= 0; DBUG_ENTER("TIME_to_gmt_sec"); + if (!validate_timestamp_range(t)) + DBUG_RETURN(0); + + /* We need this for correct leap seconds handling */ if (t->second < SECS_PER_MIN) saved_seconds= 0; @@ -895,11 +900,29 @@ TIME_to_gmt_sec(const TIME *t, const TIME_ZONE_INFO *sp, bool *in_dst_time_gap) saved_seconds= t->second; /* - NOTE If we want to convert full my_time_t range without MySQL - restrictions we should catch overflow here somehow. + NOTE: to convert full my_time_t range we do a shift of the + boundary dates here to avoid overflow of my_time_t. + We use alike approach in my_system_gmt_sec(). + + However in that function we also have to take into account + overflow near 0 on some platforms. That's because my_system_gmt_sec + uses localtime_r(), which doesn't work with negative values correctly + on platforms with unsigned time_t (QNX). Here we don't use localtime() + => we negative values of local_t are ok. */ - local_t= sec_since_epoch(t->year, t->month, t->day, + if ((t->year == TIMESTAMP_MAX_YEAR) && (t->month == 1) && t->day > 4) + { + /* + We will pass (t->day - shift) to sec_since_epoch(), and + want this value to be a positive number, so we shift + only dates > 4.01.2038 (to avoid owerflow). + */ + shift= 2; + } + + + local_t= sec_since_epoch(t->year, t->month, (t->day - shift), t->hour, t->minute, saved_seconds ? 0 : t->second); @@ -918,6 +941,22 @@ TIME_to_gmt_sec(const TIME *t, const TIME_ZONE_INFO *sp, bool *in_dst_time_gap) /* binary search for our range */ i= find_time_range(local_t, sp->revts, sp->revcnt); + /* + As there are no offset switches at the end of TIMESTAMP range, + we could simply check for overflow here (and don't need to bother + about DST gaps etc) + */ + if (shift) + { + if (local_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; + } + if (sp->revtis[i].rt_type) { /* @@ -927,10 +966,16 @@ TIME_to_gmt_sec(const TIME *t, const TIME_ZONE_INFO *sp, bool *in_dst_time_gap) beginning of the gap. */ *in_dst_time_gap= 1; - DBUG_RETURN(sp->revts[i] - sp->revtis[i].rt_offset + saved_seconds); + local_t= sp->revts[i] - sp->revtis[i].rt_offset + saved_seconds; } else - DBUG_RETURN(local_t - sp->revtis[i].rt_offset + saved_seconds); + local_t= local_t - sp->revtis[i].rt_offset + saved_seconds; + + /* check for TIMESTAMP_MAX_VALUE was already done above */ + if (local_t < TIMESTAMP_MIN_VALUE) + local_t= 0; + + DBUG_RETURN(local_t); } @@ -1294,9 +1339,24 @@ Time_zone_offset::Time_zone_offset(long tz_offset_arg): my_time_t Time_zone_offset::TIME_to_gmt_sec(const TIME *t, bool *in_dst_time_gap) const { - return sec_since_epoch(t->year, t->month, t->day, - t->hour, t->minute, t->second) - - offset; + my_time_t local_t; + + /* + Check timestamp range.we have to do this as calling function relies on + us to make all validation checks here. + */ + if (!validate_timestamp_range(t)) + return 0; + + local_t= sec_since_epoch(t->year, t->month, t->day, + t->hour, t->minute, t->second) - + offset; + + if (local_t >= TIMESTAMP_MIN_VALUE && local_t <= TIMESTAMP_MAX_VALUE) + return local_t; + + /* range error*/ + return 0; } diff --git a/strings/strtod.c b/strings/strtod.c index f298e265d7f..79ba458c009 100644 --- a/strings/strtod.c +++ b/strings/strtod.c @@ -31,7 +31,6 @@ #define MAX_DBL_EXP 308 #define MAX_RESULT_FOR_MAX_EXP 1.7976931348623157 -#define MIN_RESULT_FOR_MIN_EXP 2.225073858507202 static double scaler10[] = { 1.0, 1e10, 1e20, 1e30, 1e40, 1e50, 1e60, 1e70, 1e80, 1e90 }; @@ -161,26 +160,15 @@ double my_strtod(const char *str, char **end_ptr, int *error) order= exp + (neg_exp ? -1 : 1) * (ndigits - 1); if (order < 0) order= -order; - if (order >= MAX_DBL_EXP && result) + if (order >= MAX_DBL_EXP && !neg_exp && result) { double c; /* Compute modulus of C (see comment above) */ c= result / scaler * 10.0; - if (neg_exp) + if (order > MAX_DBL_EXP || c > MAX_RESULT_FOR_MAX_EXP) { - if (order > MAX_DBL_EXP || c < MIN_RESULT_FOR_MIN_EXP) - { - result= 0.0; - goto done; - } - } - else - { - if (order > MAX_DBL_EXP || c > MAX_RESULT_FOR_MAX_EXP) - { - overflow= 1; - goto done; - } + overflow= 1; + goto done; } } diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index 1daac2d0e95..b14ffd24894 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -170,6 +170,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 @@ -317,7 +319,10 @@ then cp -fp config.log "$MYSQL_MAXCONFLOG_DEST" fi -make -i test-force || true +( cd mysql-test + perl ./mysql-test-run.pl --force --report-features + perl ./mysql-test-run.pl --force --ps-protocol + true ) # Save mysqld-max ./libtool --mode=execute cp sql/mysqld sql/mysqld-max @@ -380,7 +385,10 @@ then cp -fp config.log "$MYSQL_CONFLOG_DEST" fi -make -i test-force || true +( cd mysql-test + perl ./mysql-test-run.pl --force --report-features + perl ./mysql-test-run.pl --force --ps-protocol + true ) %install RBR=$RPM_BUILD_ROOT @@ -716,6 +724,17 @@ fi # itself - note that they must be ordered by date (important when # merging BK trees) %changelog +* Thu Nov 16 2006 Joerg Bruehe <joerg@mysql.com> + +- Explicitly note that the "MySQL-shared" RPMs (as built by MySQL AB) + replace "mysql-shared" (as distributed by SuSE) to allow easy upgrading + (bug#22081). + +* Wed Nov 15 2006 Joerg Bruehe <joerg@mysql.com> + +- Switch from "make test*" to explicit calls of the test suite, + so that "report features" can be used. + * Tue Jun 27 2006 Joerg Bruehe <joerg@mysql.com> - move "mysqldumpslow" from the client RPM to the server RPM (bug#20216) diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index b1ee144e517..98d7182d46f 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -11950,6 +11950,150 @@ 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_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 */ @@ -12176,6 +12320,8 @@ static struct my_tests_st my_tests[]= { { "test_bug15613", test_bug15613 }, { "test_bug20152", test_bug20152 }, { "test_bug21726", test_bug21726 }, + { "test_bug23383", test_bug23383 }, + { "test_bug21635", test_bug21635 }, { 0, 0 } }; |