diff --git a/.bzrignore b/.bzrignore index 4af6fdbbe88..699cb75cc72 100644 --- a/.bzrignore +++ b/.bzrignore @@ -698,6 +698,8 @@ ndb/examples/ndbapi_example2/ndbapi_example2 ndb/examples/ndbapi_example3/ndbapi_example3 ndb/examples/ndbapi_example5/ndbapi_example5 ndb/examples/select_all/select_all +ndb/include/ndb_global.h +ndb/include/ndb_version.h ndb/lib/libMGM_API.so ndb/lib/libNDB_API.so ndb/lib/libNDB_ODBC.so diff --git a/BUILD/compile-dist b/BUILD/compile-dist new file mode 100755 index 00000000000..f27c218747c --- /dev/null +++ b/BUILD/compile-dist @@ -0,0 +1,47 @@ +#!/bin/sh +# +# This script's purpose is to update the automake/autoconf helper scripts and +# to run a plain "configure" without any special compile flags. Only features +# that affect the content of the source distribution are enabled. The resulting +# tree can then be picked up by "make dist" to create the "pristine source +# package" that is used as the basis for all other binary builds. +# +make distclean +aclocal +autoheader +libtoolize --automake --force --copy +automake --force --add-missing --copy +autoconf +(cd bdb/dist && sh s_all) +(cd innobase && aclocal && autoheader && aclocal && automake && autoconf) + +# Default to gcc for CC and CXX +if test -z "$CXX" ; then + export CXX=gcc +fi + +if test -z "$CC" ; then + export CC=gcc +fi + +# Use ccache, if available +if ccache -V > /dev/null 2>&1 +then + if ! (echo "$CC" | grep "ccache" > /dev/null) + then + export CC="ccache $CC" + fi + if ! (echo "$CXX" | grep "ccache" > /dev/null) + then + export CXX="ccache $CXX" + fi +fi + +# Make sure to enable all features that affect "make dist" +./configure \ + --with-embedded-server \ + --with-berkeley-db \ + --with-innodb \ + --enable-thread-safe-client \ + --with-ndbcluster +make diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index 2b3339e59d3..922020178ff 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -175,6 +175,7 @@ paul@frost.snake.net paul@ice.local paul@ice.snake.net paul@kite-hub.kitebird.com +paul@snake-hub.snake.net paul@teton.kitebird.com pekka@mysql.com pem@mysql.com diff --git a/Build-tools/Bootstrap b/Build-tools/Bootstrap index a7d347ba32f..10211dbb59c 100755 --- a/Build-tools/Bootstrap +++ b/Build-tools/Bootstrap @@ -26,7 +26,7 @@ else } # Some predefined settings -$build_command= "BUILD/compile-pentium-max"; +$build_command= "BUILD/compile-dist"; $PWD= cwd(); $opt_docdir= $PWD . "/mysqldoc"; $opt_archive_log= undef; @@ -70,7 +70,7 @@ GetOptions( "test|t", "verbose|v", "win-dist|w", - "quiet|q", + "quiet|q", ) || print_help(""); # @@ -122,18 +122,8 @@ if (($opt_directory ne $PWD) && (!-d $opt_directory && !$opt_dry_run)) # if ($opt_pull) { - &logger("Updating BK tree $REPO to latest ChangeSet first"); - chdir ($REPO) or &abort("Could not chdir to $REPO!"); - &run_command("bk pull", "Could not update $REPO!"); - chdir ($PWD) or &abort("Could not chdir to $PWD!"); - - unless ($opt_skip_manual) - { - &logger("Updating manual tree in $opt_docdir"); - chdir ($opt_docdir) or &abort("Could not chdir to $opt_docdir!"); - &run_command("bk pull", "Could not update $opt_docdir!"); - chdir ($PWD) or &abort("Could not chdir to $PWD!"); - } + &bk_pull("$REPO"); + &bk_pull("$opt_docdir") unless ($opt_skip_manual); } # @@ -262,7 +252,7 @@ if (defined $opt_changelog) $msg= "Adding $target_dir/ChangeLog"; $msg.= " (down to revision $opt_changelog)" if $opt_changelog ne ""; &logger($msg); - $command= "bk changes -mv"; + $command= "bk changes -v"; $command.= " -r" if ($opt_changelog ne "" || $opt_revision); $command.= $opt_changelog if $opt_changelog ne ""; $command.= ".." if ($opt_changelog ne "" && !$opt_revision); @@ -270,7 +260,7 @@ if (defined $opt_changelog) $command.= " " . $REPO . " > $target_dir/ChangeLog"; &logger($command); # We cannot use run_command here because of output redirection - if (!$opt_dry_run) + unless ($opt_dry_run) { system($command) == 0 or &abort("Could not create $target_dir/ChangeLog!"); } @@ -281,17 +271,17 @@ if (defined $opt_changelog) # unless ($opt_skip_manual) { - $msg= "Updating manual files"; - &logger($msg); + &logger("Updating manual files"); foreach $file qw/internals manual reservedwords/ { system ("bk cat $opt_docdir/Docs/$file.texi > $target_dir/Docs/$file.texi") == 0 or &abort("Could not update $file.texi in $target_dir/Docs/!"); } - system ("rm -f $target_dir/Docs/Images/Makefile*") == 0 - or &abort("Could not remove Makefiles in $target_dir/Docs/Images/!"); - system ("cp $opt_docdir/Docs/Images/*.* $target_dir/Docs/Images") == 0 - or &abort("Could not copy image files in $target_dir/Docs/Images/!"); + + &run_command("rm -f $target_dir/Docs/Images/Makefile*", + "Could not remove Makefiles in $target_dir/Docs/Images/!"); + &run_command("cp $opt_docdir/Docs/Images/*.* $target_dir/Docs/Images", + "Could not copy image files in $target_dir/Docs/Images/!"); } # @@ -377,6 +367,18 @@ if ($opt_archive_log) exit 0; +# +# Run a BK pull on the given BK tree +# +sub bk_pull +{ + my $bk_tree= $_[0]; + &logger("Updating BK tree $bk_tree to latest ChangeSet first"); + chdir ($bk_tree) or &abort("Could not chdir to $bk_tree!"); + &run_command("bk pull", "Could not update $bk_tree!"); + chdir ($PWD) or &abort("Could not chdir to $PWD!"); +} + # # Print the help text message (with an optional message on top) # diff --git a/Makefile.am b/Makefile.am index 56c52824071..ef7f8937d86 100644 --- a/Makefile.am +++ b/Makefile.am @@ -23,14 +23,14 @@ EXTRA_DIST = INSTALL-SOURCE README COPYING EXCEPTIONS-CLIENT SUBDIRS = . include @docs_dirs@ @zlib_dir@ \ @readline_topdir@ sql-common \ @thread_dirs@ pstack \ - @sql_server_dirs@ @sql_client_dirs@ scripts man tests \ + @sql_union_dirs@ scripts man tests \ netware @libmysqld_dirs@ \ @bench_dirs@ support-files @fs_dirs@ @tools_dirs@ DIST_SUBDIRS = . include @docs_dirs@ zlib \ @readline_topdir@ sql-common \ @thread_dirs@ pstack \ - @sql_server_dirs@ @sql_client_dirs@ scripts @man_dirs@ tests SSL\ + @sql_union_dirs@ scripts @man_dirs@ tests SSL\ BUILD netware os2 @libmysqld_dirs@ \ @bench_dirs@ support-files @fs_dirs@ @tools_dirs@ diff --git a/configure.in b/configure.in index 47ac06706b2..52906514c89 100644 --- a/configure.in +++ b/configure.in @@ -2450,7 +2450,7 @@ thread_dirs= dnl This probably should be cleaned up more - for now the threaded dnl client is just using plain-old libs. -sql_client_dirs="libmysql client" +sql_client_dirs="libmysql strings regex client" linked_client_targets="linked_libmysql_sources" CLIENT_LIBS=$NON_THREADED_CLIENT_LIBS if test "$THREAD_SAFE_CLIENT" != "no" @@ -2624,6 +2624,20 @@ AC_SUBST(sql_server_dirs) AC_SUBST(thread_dirs) AC_SUBST(server_scripts) +# Now that sql_client_dirs and sql_server_dirs are stable, determine the union. +# Start with the (longer) server list, add each client item not yet present. +sql_union_dirs=" $sql_server_dirs " +for DIR in $sql_client_dirs +do + if echo $sql_union_dirs | grep " $DIR " >/dev/null + then + : # already present, skip + else + sql_union_dirs="$sql_union_dirs $DIR " + fi +done +AC_SUBST(sql_union_dirs) + #if test "$with_posix_threads" = "no" -o "$with_mit_threads" = "yes" #then # MIT pthreads does now support connecting with unix sockets diff --git a/innobase/log/log0recv.c b/innobase/log/log0recv.c index 5eefd32c8a6..35dc9a06020 100644 --- a/innobase/log/log0recv.c +++ b/innobase/log/log0recv.c @@ -3040,8 +3040,7 @@ recv_reset_log_files_for_backup( memcpy(name + log_dir_len, logfilename, sizeof logfilename); buf = ut_malloc(LOG_FILE_HDR_SIZE + OS_FILE_LOG_BLOCK_SIZE); - memset(buf, LOG_FILE_HDR_SIZE + OS_FILE_LOG_BLOCK_SIZE, '\0'); - + memset(buf, '\0', LOG_FILE_HDR_SIZE + OS_FILE_LOG_BLOCK_SIZE); for (i = 0; i < n_log_files; i++) { diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index b791090346b..209dcf5756a 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -1864,13 +1864,14 @@ void set_stmt_errmsg(MYSQL_STMT * stmt, const char *err, int errcode, my_bool cli_read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt) { uchar *pos; - uint field_count, param_count; + uint field_count, param_count, packet_length; MYSQL_DATA *fields_data; DBUG_ENTER("read_prepare_result"); mysql= mysql->last_used_con; - if (net_safe_read(mysql) == packet_error) + if ((packet_length=net_safe_read(mysql)) == packet_error) DBUG_RETURN(1); + mysql->warning_count= 0; pos= (uchar*) mysql->net.read_pos; stmt->stmt_id= uint4korr(pos+1); pos+= 5; @@ -1878,6 +1879,8 @@ my_bool cli_read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt) field_count= uint2korr(pos); pos+= 2; /* Number of placeholders in the statement */ param_count= uint2korr(pos); pos+= 2; + if (packet_length >= 12) + mysql->warning_count= uint2korr(pos+1); if (param_count != 0) { @@ -1894,7 +1897,6 @@ my_bool cli_read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt) if (!(mysql->server_status & SERVER_STATUS_AUTOCOMMIT)) mysql->server_status|= SERVER_STATUS_IN_TRANS; - mysql->extra_info= net_field_length_ll(&pos); if (!(fields_data= (*mysql->methods->read_rows)(mysql,(MYSQL_FIELD*)0,7))) DBUG_RETURN(1); if (!(stmt->fields= unpack_fields(fields_data,&stmt->mem_root, @@ -1902,9 +1904,10 @@ my_bool cli_read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt) mysql->server_capabilities))) DBUG_RETURN(1); } - stmt->field_count= (uint) field_count; + stmt->field_count= field_count; stmt->param_count= (ulong) param_count; - mysql->warning_count= 0; + DBUG_PRINT("exit",("field_count: %u param_count: %u warning_count: %u", + field_count, param_count, (uint) mysql->warning_count)); DBUG_RETURN(0); } diff --git a/man/Makefile.am b/man/Makefile.am index 539c43dfed6..8d18165191a 100644 --- a/man/Makefile.am +++ b/man/Makefile.am @@ -17,11 +17,11 @@ ## Process this file with automake to create Makefile.in -man_MANS = mysql.1 isamchk.1 isamlog.1 mysql_zap.1 mysqlaccess.1 \ +man_MANS = mysql.1 mysql_zap.1 mysqlaccess.1 \ mysqladmin.1 mysqld.1 mysqld_multi.1 mysqldump.1 mysqlshow.1 \ perror.1 replace.1 mysqld_safe.1 mysql_fix_privilege_tables.1 -EXTRA_DIST = mysql.1.in isamchk.1.in isamlog.1.in mysql_zap.1.in \ +EXTRA_DIST = mysql.1.in mysql_zap.1.in \ mysqlaccess.1.in mysqladmin.1.in mysqld.1.in mysqld_multi.1.in \ mysqldump.1.in mysqlshow.1.in perror.1.in replace.1.in mysqlman.1.in \ mysqld_safe.1.in mysql_fix_privilege_tables.1.in diff --git a/man/isamchk.1.in b/man/isamchk.1.in deleted file mode 100644 index cad1303ee55..00000000000 --- a/man/isamchk.1.in +++ /dev/null @@ -1,145 +0,0 @@ -.TH isamchk 1 "19 December 2000" "MySQL @MYSQL_BASE_VERSION@" "MySQL database" -.SH NAME -.BR isamchk - \- Description, check and repair of ISAM tables. -Used without options all tables on the command will be checked for errors -.SH USAGE -isamchk [OPTIONS] tables[.ISM] -.SH SYNOPSIS -.B isamchk -.RB [ \-a | \-\-analyze ] -.RB [ \-# | \-\-debug=... ] -.RB [ \-\-character\-sets\-dir=...] -.RB [ \-C | \-\-default\-character\-set=...] -.RB [ \-d | \-\-description ] -.RB [ \-e | \-\-extend\-check ] -.RB [ \-f | \-\-force ] -.RB [ \-? | \-\-help ] -.RB [ \-i | \-\-information ] -.RB [ \-k | \-\-keys\-used=# ] -.RB [ \-l | \-\-no\-symlinks] -.RB [ \-q | \-\-quick ] -.RB [ \-r | \-\-recover ] -.RB [ \-o | \-\-safe\-recover ] -.RB [ \-O | "\-\-set\-variable var=option"] -.RB [ \-s | \-\-silent ] -.RB [ \-S | \-\-sort\-index ] -.RB [ \-R | \-\-sort\-records=#] -.RB [ \-u | \-\-unpack ] -.RB [ \-v | \-\-verbose ] -.RB [ \-V | \-\-version ] -.RB [ \-w | \-\-wait ] -.SH DESCRIPTION -.TP -.BR \-a | \-\-analyze -Analyze distribution of keys. Will make some joins in -MySQL faster. -.TP -.BR \-# | \-\-debug=... -Output debug log. Often this is 'd:t:o ,filename` -.TP -.BR \-\-character\-sets\-dir=... -Directory where character sets are -.TP -.BR \-C | \-\-default\-character\-set=... -Set the default character set -.TP -.BR \-d | \-\-description -Prints some information about table. -.TP -.BR \-e | \-\-extend\-check -Check the table VERY thoroughly. One need use this -only in extreme cases as isamchk should normally find -all errors even without this switch -.TP -.BR \-f | \-\-force -Overwrite old temporary files. -If one uses \-f when checking tables (running isamchk -without \-r), isamchk will automatically restart with -\-r on any wrong table. -.TP -.BR \-? | \-\-help -Display help and exit. -.TP -.BR \-i | \-\-information -Print statistics information about the table -.TP -.BR \-k | \-\-keys\-used=# -Used with '\-r'. Tell ISAM to update only the first -# keys. This can be used to get faster inserts! -.TP -.BR \-l | \-\-no\-symlinks -Do not follow symbolic links when repairing. Normally -isamchk repairs the table a symlink points at. -.TP -.BR \-q | \-\-quick -Used with \-r to get a faster repair. (The data file -isn't touched.) One can give a second '\-q' to force -isamchk to modify the original datafile. -.TP -.BR \-r | \-\-recover -Can fix almost anything except unique keys that aren't -unique. -.TP -.BR \-o | \-\-safe\-recover -Uses old recovery method; slower than '\-r' but can -handle a couple of cases that '\-r' cannot handle. -.TP -.BR \-O | " \-\-set\-variable var=option " -Change the value of a variable. -.TP -.BR \-s | \-\-silent -Only print errors. One can use two \-s to make isamchk -very silent -.TP -.BR \-S | \-\-sort\-index -Sort index blocks. This speeds up 'read\-next' in -applications -.TP -.BR \-R | \-\-sort\-records=# -Sort records according to an index. This makes your -data much more localized and may speed up things -(It may be VERY slow to do a sort the first time!) -.TP -.BR \-u | \-\-unpack -Unpack file packed with pack_isam. -.TP -.BR \-v | \-\-verbose -Print more information. This can be used with -\-d and \-e. Use many \-v for more verbosity! -.TP -.BR \-V | \-\-version -Print version and exit. -.TP -.BR \-w | \-\-wait -Wait if table is locked. -.SH "SEE ALSO" -isamlog(1), -mysql(1), -mysqlaccess(1), -mysqladmin(1), -mysqld(1), -mysqld_multi(1), -mysqld_safe(1), -mysqldump(1), -mysql_fix_privilege_tables(1), -mysqlshow(1), -mysql_zap(1), -perror(1), -replace(1) -.P -For more information please refer to the MySQL reference -manual, which may already be installed locally and which -is also available online at http://www.mysql.com/doc/en/ -.SH BUGS -Please refer to http://bugs.mysql.com/ to report bugs. -.SH AUTHOR -Ver 1.0, distribution @MYSQL_NO_DASH_VERSION@ -Michael (Monty) Widenius (monty@mysql.com), -MySQL AB (http://www.mysql.com/). -This software comes with no warranty. -Manual page by L. (Kill-9) Pedersen -(kill-9@kill\-9.dk), Mercurmedia Data Model Architect / -system developer (http://www.mercurmedia.com) - -.\" end of man page diff --git a/man/isamlog.1.in b/man/isamlog.1.in deleted file mode 100644 index 6040f6c4ad8..00000000000 --- a/man/isamlog.1.in +++ /dev/null @@ -1,107 +0,0 @@ -.TH isamlog 1 "19 December 2000" "MySQL @MYSQL_BASE_VERSION@" "MySQL database" -.SH NAME -isamlog - Write info about whats in a nisam log file. -.SH USAGE -isamlog [-?iruvIV] [-c #] [-f #] [-F filepath/] [-o #] [-R file recordpos] [-w write_file] [log-filename [table ...]] -.SH SYNOPSIS -.B isamlog -.RB [ -? | -I ] -.RB [ -V ] -.RB [ -c ] -.RB [ -f ] -.RB [ -F ] -.RB [ -i ] -.RB [ -o ] -.RB [ "-p #" ] -.RB [ -r ] -.RB [ -R ] -.RB [ -u ] -.RB [ -v ] -.RB [ -w ] -.SH DESCRIPTION -.TP -.BR isamlog -.TP -.BR -? | -I -info -.TP -.BR -V -version -.TP -.BR -c -do only # commands -.TP -.BR -f -max open files -.TP -.BR -F -file path -.TP -.BR -i -extra info -.TP -.BR -o -offset -.TP -.BR "-p #" -remove # components from path -.TP -.BR -r -recover -.TP -.BR -R -file recordposition -.TP -.BR -u -update -.TP -.BR -v -verbose -.TP -.BR -w -write file -.SH NOTE -If no file name is given isam.log is used -One can give a second and a third '-v' for more verbose. -Normaly one does a update (-u). -If a recover is done all writes and all possibly updates and deletes is done -and errors are only counted. -If one gives table names as arguments only these tables will be updated - - - -.SH "SEE ALSO" -isamchk(1), -mysql(1), -mysqlaccess(1), -mysqladmin(1), -mysqld(1), -mysqld_multi(1), -mysqld_safe(1), -mysqldump(1), -mysql_fix_privilege_tables(1), -mysqlshow(1), -mysql_zap(1), -perror(1), -replace(1) -.P -For more information please refer to the MySQL reference -manual, which may already be installed locally and which -is also available online at http://www.mysql.com/doc/en/ -.SH BUGS -Please refer to http://bugs.mysql.com/ to report bugs. - -.SH AUTHOR - -Ver 1.0, distribution @MYSQL_NO_DASH_VERSION@ -Michael (Monty) Widenius (monty@mysql.com), -MySQL AB (http://www.mysql.com/). -This software comes with no warranty. -Manual page by L. (Kill-9) Pedersen -(kill-9@kill-9.dk), Mercurmedia Data Model Architect / -system developer (http://www.mercurmedia.com) - - -.\" end of man page - - diff --git a/myisam/mi_check.c b/myisam/mi_check.c index dcf57e78fa4..dd8cc736741 100644 --- a/myisam/mi_check.c +++ b/myisam/mi_check.c @@ -1467,12 +1467,14 @@ static int writekeys(MI_CHECK *param, register MI_INFO *info, byte *buff, if (_mi_ft_add(info,i,(char*) key,buff,filepos)) goto err; } +#ifdef HAVE_SPATIAL else if (info->s->keyinfo[i].flag & HA_SPATIAL) { uint key_length=_mi_make_key(info,i,key,buff,filepos); if (rtree_insert(info, i, key, key_length)) goto err; } +#endif /*HAVE_SPATIAL*/ else { uint key_length=_mi_make_key(info,i,key,buff,filepos); diff --git a/mysql-test/lib/init_db.sql b/mysql-test/lib/init_db.sql new file mode 100644 index 00000000000..f42f7ca6b5f --- /dev/null +++ b/mysql-test/lib/init_db.sql @@ -0,0 +1,54 @@ +USE mysql; + +CREATE TABLE db (Host char(60) binary DEFAULT '' NOT NULL,Db char(64) binary DEFAULT '' NOT NULL,User char(16) binary DEFAULT '' NOT NULL,Select_priv enum('N','Y') DEFAULT 'N' NOT NULL,Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL,Update_priv enum('N','Y') DEFAULT 'N' NOT NULL,Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL,Create_priv enum('N','Y') DEFAULT 'N' NOT NULL,Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL,Grant_priv enum('N','Y') DEFAULT 'N' NOT NULL,References_priv enum('N','Y') DEFAULT 'N' NOT NULL,Index_priv enum('N','Y') DEFAULT 'N' NOT NULL,Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL,Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL,Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL,PRIMARY KEY Host (Host,Db,User),KEY User (User)) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Database privileges'; + +INSERT INTO db VALUES ('%','test','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y'); +INSERT INTO db VALUES ('%','test\_%','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y'); + + +CREATE TABLE host (Host char(60) binary DEFAULT '' NOT NULL,Db char(64) binary DEFAULT '' NOT NULL,Select_priv enum('N','Y') DEFAULT 'N' NOT NULL,Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL,Update_priv enum('N','Y') DEFAULT 'N' NOT NULL,Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL,Create_priv enum('N','Y') DEFAULT 'N' NOT NULL,Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL,Grant_priv enum('N','Y') DEFAULT 'N' NOT NULL,References_priv enum('N','Y') DEFAULT 'N' NOT NULL,Index_priv enum('N','Y') DEFAULT 'N' NOT NULL,Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL,Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL,Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL,PRIMARY KEY Host (Host,Db)) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Host privileges; Merged with database privileges'; + +CREATE TABLE user (Host char(60) binary DEFAULT '' NOT NULL,User char(16) binary DEFAULT '' NOT NULL,Password char(41) binary DEFAULT '' NOT NULL,Select_priv enum('N','Y') DEFAULT 'N' NOT NULL,Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL,Update_priv enum('N','Y') DEFAULT 'N' NOT NULL,Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL,Create_priv enum('N','Y') DEFAULT 'N' NOT NULL,Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL,Reload_priv enum('N','Y') DEFAULT 'N' NOT NULL,Shutdown_priv enum('N','Y') DEFAULT 'N' NOT NULL,Process_priv enum('N','Y') DEFAULT 'N' NOT NULL,File_priv enum('N','Y') DEFAULT 'N' NOT NULL,Grant_priv enum('N','Y') DEFAULT 'N' NOT NULL,References_priv enum('N','Y') DEFAULT 'N' NOT NULL,Index_priv enum('N','Y') DEFAULT 'N' NOT NULL,Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL,Show_db_priv enum('N','Y') DEFAULT 'N' NOT NULL,Super_priv enum('N','Y') DEFAULT 'N' NOT NULL,Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL,Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL,Execute_priv enum('N','Y') DEFAULT 'N' NOT NULL,Repl_slave_priv enum('N','Y') DEFAULT 'N' NOT NULL,Repl_client_priv enum('N','Y') DEFAULT 'N' NOT NULL,ssl_type enum('','ANY','X509', 'SPECIFIED') DEFAULT '' NOT NULL,ssl_cipher BLOB NOT NULL,x509_issuer BLOB NOT NULL,x509_subject BLOB NOT NULL,max_questions int(11) unsigned DEFAULT 0 NOT NULL,max_updates int(11) unsigned DEFAULT 0 NOT NULL,max_connections int(11) unsigned DEFAULT 0 NOT NULL,PRIMARY KEY Host (Host,User)) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Users and global privileges'; + +INSERT INTO user VALUES ('%','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); +INSERT INTO user VALUES ('localhost','','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); +INSERT INTO user VALUES ('%','','','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','','','','',0,0,0); + +CREATE TABLE func (name char(64) binary DEFAULT '' NOT NULL,ret tinyint(1) DEFAULT '0' NOT NULL,dl char(128) DEFAULT '' NOT NULL,type enum ('function','aggregate') NOT NULL,PRIMARY KEY (name)) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='User defined functions'; + +CREATE TABLE tables_priv (Host char(60) binary DEFAULT '' NOT NULL,Db char(64) binary DEFAULT '' NOT NULL,User char(16) binary DEFAULT '' NOT NULL,Table_name char(64) binary DEFAULT '' NOT NULL,Grantor char(77) DEFAULT '' NOT NULL,Timestamp timestamp(14),Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter') DEFAULT '' NOT NULL,Column_priv set('Select','Insert','Update','References') DEFAULT '' NOT NULL,PRIMARY KEY (Host,Db,User,Table_name),KEY Grantor (Grantor)) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Table privileges'; + +CREATE TABLE columns_priv (Host char(60) binary DEFAULT '' NOT NULL,Db char(64) binary DEFAULT '' NOT NULL,User char(16) binary DEFAULT '' NOT NULL,Table_name char(64) binary DEFAULT '' NOT NULL,Column_name char(64) binary DEFAULT '' NOT NULL,Timestamp timestamp(14),Column_priv set('Select','Insert','Update','References') DEFAULT '' NOT NULL,PRIMARY KEY (Host,Db,User,Table_name,Column_name)) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Column privileges'; + +CREATE TABLE help_topic (help_topic_id int unsigned not null,name varchar(64) not null,help_category_id smallint unsigned not null,description text not null,example text not null,url varchar(128) not null,primary key (help_topic_id),unique index (name)) engine=MyISAM CHARACTER SET utf8 comment='help topics'; + +CREATE TABLE help_category (help_category_id smallint unsigned not null,name varchar(64) not null,parent_category_id smallint unsigned null,url varchar(128) not null,primary key (help_category_id),unique index (name)) engine=MyISAM CHARACTER SET utf8 comment='help categories'; + +CREATE TABLE help_keyword (help_keyword_id int unsigned not null,name varchar(64) not null,primary key (help_keyword_id),unique index (name)) engine=MyISAM CHARACTER SET utf8 comment='help keywords'; + +CREATE TABLE help_relation (help_topic_id int unsigned not null references help_topic,help_keyword_id int unsigned not null references help_keyword,primary key (help_keyword_id, help_topic_id)) engine=MyISAM CHARACTER SET utf8 comment='keyword-topic relation'; + +CREATE TABLE time_zone_name (Name char(64) NOT NULL,Time_zone_id int unsigned NOT NULL,PRIMARY KEY Name (Name)) engine=MyISAM CHARACTER SET utf8 comment='Time zone names'; + +INSERT INTO time_zone_name (Name, Time_Zone_id) VALUES ('MET', 1), ('UTC', 2), ('Universal', 2), ('Europe/Moscow',3), ('leap/Europe/Moscow',4), ('Japan', 5); + + +CREATE TABLE time_zone (Time_zone_id int unsigned NOT NULL auto_increment,Use_leap_seconds enum('Y','N') DEFAULT 'N' NOT NULL,PRIMARY KEY TzId (Time_zone_id)) engine=MyISAM CHARACTER SET utf8 comment='Time zones'; + +INSERT INTO time_zone (Time_zone_id, Use_leap_seconds) VALUES (1,'N'), (2,'N'), (3,'N'), (4,'Y'), (5,'N'); + + +CREATE TABLE time_zone_transition (Time_zone_id int unsigned NOT NULL,Transition_time bigint signed NOT NULL,Transition_type_id int unsigned NOT NULL,PRIMARY KEY TzIdTranTime (Time_zone_id, Transition_time)) engine=MyISAM CHARACTER SET utf8 comment='Time zone transitions'; + +INSERT INTO time_zone_transition (Time_zone_id, Transition_time, Transition_type_id) VALUES (1, -1693706400, 0) ,(1, -1680483600, 1),(1, -1663455600, 2) ,(1, -1650150000, 3),(1, -1632006000, 2) ,(1, -1618700400, 3),(1, -938905200, 2) ,(1, -857257200, 3),(1, -844556400, 2) ,(1, -828226800, 3),(1, -812502000, 2) ,(1, -796777200, 3),(1, 228877200, 2) ,(1, 243997200, 3),(1, 260326800, 2) ,(1, 276051600, 3),(1, 291776400, 2) ,(1, 307501200, 3),(1, 323830800, 2) ,(1, 338950800, 3),(1, 354675600, 2) ,(1, 370400400, 3),(1, 386125200, 2) ,(1, 401850000, 3),(1, 417574800, 2) ,(1, 433299600, 3),(1, 449024400, 2) ,(1, 465354000, 3),(1, 481078800, 2) ,(1, 496803600, 3),(1, 512528400, 2) ,(1, 528253200, 3),(1, 543978000, 2) ,(1, 559702800, 3),(1, 575427600, 2) ,(1, 591152400, 3),(1, 606877200, 2) ,(1, 622602000, 3),(1, 638326800, 2) ,(1, 654656400, 3),(1, 670381200, 2) ,(1, 686106000, 3),(1, 701830800, 2) ,(1, 717555600, 3),(1, 733280400, 2) ,(1, 749005200, 3),(1, 764730000, 2) ,(1, 780454800, 3),(1, 796179600, 2) ,(1, 811904400, 3),(1, 828234000, 2) ,(1, 846378000, 3),(1, 859683600, 2) ,(1, 877827600, 3),(1, 891133200, 2) ,(1, 909277200, 3),(1, 922582800, 2) ,(1, 941331600, 3),(1, 954032400, 2) ,(1, 972781200, 3),(1, 985482000, 2) ,(1, 1004230800, 3),(1, 1017536400, 2) ,(1, 1035680400, 3),(1, 1048986000, 2) ,(1, 1067130000, 3),(1, 1080435600, 2) ,(1, 1099184400, 3),(1, 1111885200, 2) ,(1, 1130634000, 3),(1, 1143334800, 2) ,(1, 1162083600, 3),(1, 1174784400, 2) ,(1, 1193533200, 3),(1, 1206838800, 2) ,(1, 1224982800, 3),(1, 1238288400, 2) ,(1, 1256432400, 3),(1, 1269738000, 2) ,(1, 1288486800, 3),(1, 1301187600, 2) ,(1, 1319936400, 3),(1, 1332637200, 2) ,(1, 1351386000, 3),(1, 1364691600, 2) ,(1, 1382835600, 3),(1, 1396141200, 2) ,(1, 1414285200, 3),(1, 1427590800, 2) ,(1, 1445734800, 3),(1, 1459040400, 2) ,(1, 1477789200, 3),(1, 1490490000, 2) ,(1, 1509238800, 3),(1, 1521939600, 2) ,(1, 1540688400, 3),(1, 1553994000, 2) ,(1, 1572138000, 3),(1, 1585443600, 2) ,(1, 1603587600, 3),(1, 1616893200, 2) ,(1, 1635642000, 3),(1, 1648342800, 2) ,(1, 1667091600, 3),(1, 1679792400, 2) ,(1, 1698541200, 3),(1, 1711846800, 2) ,(1, 1729990800, 3),(1, 1743296400, 2) ,(1, 1761440400, 3),(1, 1774746000, 2) ,(1, 1792890000, 3),(1, 1806195600, 2) ,(1, 1824944400, 3),(1, 1837645200, 2) ,(1, 1856394000, 3),(1, 1869094800, 2) ,(1, 1887843600, 3),(1, 1901149200, 2) ,(1, 1919293200, 3),(1, 1932598800, 2) ,(1, 1950742800, 3),(1, 1964048400, 2) ,(1, 1982797200, 3),(1, 1995498000, 2) ,(1, 2014246800, 3),(1, 2026947600, 2) ,(1, 2045696400, 3),(1, 2058397200, 2) ,(1, 2077146000, 3),(1, 2090451600, 2) ,(1, 2108595600, 3),(1, 2121901200, 2) ,(1, 2140045200, 3),(3, -1688265000, 2) ,(3, -1656819048, 1),(3, -1641353448, 2) ,(3, -1627965048, 3),(3, -1618716648, 1) ,(3, -1596429048, 3),(3, -1593829848, 5) ,(3, -1589860800, 4),(3, -1542427200, 5) ,(3, -1539493200, 6),(3, -1525323600, 5) ,(3, -1522728000, 4),(3, -1491188400, 7) ,(3, -1247536800, 4),(3, 354920400, 5) ,(3, 370728000, 4),(3, 386456400, 5) ,(3, 402264000, 4),(3, 417992400, 5) ,(3, 433800000, 4),(3, 449614800, 5) ,(3, 465346800, 8),(3, 481071600, 9) ,(3, 496796400, 8),(3, 512521200, 9) ,(3, 528246000, 8),(3, 543970800, 9) ,(3, 559695600, 8),(3, 575420400, 9) ,(3, 591145200, 8),(3, 606870000, 9) ,(3, 622594800, 8),(3, 638319600, 9) ,(3, 654649200, 8),(3, 670374000, 10) ,(3, 686102400, 11),(3, 695779200, 8) ,(3, 701812800, 5),(3, 717534000, 4) ,(3, 733273200, 9),(3, 748998000, 8) ,(3, 764722800, 9),(3, 780447600, 8) ,(3, 796172400, 9),(3, 811897200, 8) ,(3, 828226800, 9),(3, 846370800, 8) ,(3, 859676400, 9),(3, 877820400, 8) ,(3, 891126000, 9),(3, 909270000, 8) ,(3, 922575600, 9),(3, 941324400, 8) ,(3, 954025200, 9),(3, 972774000, 8) ,(3, 985474800, 9),(3, 1004223600, 8) ,(3, 1017529200, 9),(3, 1035673200, 8) ,(3, 1048978800, 9),(3, 1067122800, 8) ,(3, 1080428400, 9),(3, 1099177200, 8) ,(3, 1111878000, 9),(3, 1130626800, 8) ,(3, 1143327600, 9),(3, 1162076400, 8) ,(3, 1174777200, 9),(3, 1193526000, 8) ,(3, 1206831600, 9),(3, 1224975600, 8) ,(3, 1238281200, 9),(3, 1256425200, 8) ,(3, 1269730800, 9),(3, 1288479600, 8) ,(3, 1301180400, 9),(3, 1319929200, 8) ,(3, 1332630000, 9),(3, 1351378800, 8) ,(3, 1364684400, 9),(3, 1382828400, 8) ,(3, 1396134000, 9),(3, 1414278000, 8) ,(3, 1427583600, 9),(3, 1445727600, 8) ,(3, 1459033200, 9),(3, 1477782000, 8) ,(3, 1490482800, 9),(3, 1509231600, 8) ,(3, 1521932400, 9),(3, 1540681200, 8) ,(3, 1553986800, 9),(3, 1572130800, 8) ,(3, 1585436400, 9),(3, 1603580400, 8) ,(3, 1616886000, 9),(3, 1635634800, 8) ,(3, 1648335600, 9),(3, 1667084400, 8) ,(3, 1679785200, 9),(3, 1698534000, 8) ,(3, 1711839600, 9),(3, 1729983600, 8) ,(3, 1743289200, 9),(3, 1761433200, 8) ,(3, 1774738800, 9),(3, 1792882800, 8) ,(3, 1806188400, 9),(3, 1824937200, 8) ,(3, 1837638000, 9),(3, 1856386800, 8) ,(3, 1869087600, 9),(3, 1887836400, 8) ,(3, 1901142000, 9),(3, 1919286000, 8) ,(3, 1932591600, 9),(3, 1950735600, 8) ,(3, 1964041200, 9),(3, 1982790000, 8) ,(3, 1995490800, 9),(3, 2014239600, 8) ,(3, 2026940400, 9),(3, 2045689200, 8) ,(3, 2058390000, 9),(3, 2077138800, 8) ,(3, 2090444400, 9),(3, 2108588400, 8) ,(3, 2121894000, 9),(3, 2140038000, 8),(4, -1688265000, 2) ,(4, -1656819048, 1),(4, -1641353448, 2) ,(4, -1627965048, 3),(4, -1618716648, 1) ,(4, -1596429048, 3),(4, -1593829848, 5) ,(4, -1589860800, 4),(4, -1542427200, 5) ,(4, -1539493200, 6),(4, -1525323600, 5) ,(4, -1522728000, 4),(4, -1491188400, 7) ,(4, -1247536800, 4),(4, 354920409, 5) ,(4, 370728010, 4),(4, 386456410, 5) ,(4, 402264011, 4),(4, 417992411, 5) ,(4, 433800012, 4),(4, 449614812, 5) ,(4, 465346812, 8),(4, 481071612, 9) ,(4, 496796413, 8),(4, 512521213, 9) ,(4, 528246013, 8),(4, 543970813, 9) ,(4, 559695613, 8),(4, 575420414, 9) ,(4, 591145214, 8),(4, 606870014, 9) ,(4, 622594814, 8),(4, 638319615, 9) ,(4, 654649215, 8),(4, 670374016, 10) ,(4, 686102416, 11),(4, 695779216, 8) ,(4, 701812816, 5),(4, 717534017, 4) ,(4, 733273217, 9),(4, 748998018, 8) ,(4, 764722818, 9),(4, 780447619, 8) ,(4, 796172419, 9),(4, 811897219, 8) ,(4, 828226820, 9),(4, 846370820, 8) ,(4, 859676420, 9),(4, 877820421, 8) ,(4, 891126021, 9),(4, 909270021, 8) ,(4, 922575622, 9),(4, 941324422, 8) ,(4, 954025222, 9),(4, 972774022, 8) ,(4, 985474822, 9),(4, 1004223622, 8) ,(4, 1017529222, 9),(4, 1035673222, 8) ,(4, 1048978822, 9),(4, 1067122822, 8) ,(4, 1080428422, 9),(4, 1099177222, 8) ,(4, 1111878022, 9),(4, 1130626822, 8) ,(4, 1143327622, 9),(4, 1162076422, 8) ,(4, 1174777222, 9),(4, 1193526022, 8) ,(4, 1206831622, 9),(4, 1224975622, 8) ,(4, 1238281222, 9),(4, 1256425222, 8) ,(4, 1269730822, 9),(4, 1288479622, 8) ,(4, 1301180422, 9),(4, 1319929222, 8) ,(4, 1332630022, 9),(4, 1351378822, 8) ,(4, 1364684422, 9),(4, 1382828422, 8) ,(4, 1396134022, 9),(4, 1414278022, 8) ,(4, 1427583622, 9),(4, 1445727622, 8) ,(4, 1459033222, 9),(4, 1477782022, 8) ,(4, 1490482822, 9),(4, 1509231622, 8) ,(4, 1521932422, 9),(4, 1540681222, 8) ,(4, 1553986822, 9),(4, 1572130822, 8) ,(4, 1585436422, 9),(4, 1603580422, 8) ,(4, 1616886022, 9),(4, 1635634822, 8) ,(4, 1648335622, 9),(4, 1667084422, 8) ,(4, 1679785222, 9),(4, 1698534022, 8) ,(4, 1711839622, 9),(4, 1729983622, 8) ,(4, 1743289222, 9),(4, 1761433222, 8) ,(4, 1774738822, 9),(4, 1792882822, 8) ,(4, 1806188422, 9),(4, 1824937222, 8) ,(4, 1837638022, 9),(4, 1856386822, 8) ,(4, 1869087622, 9),(4, 1887836422, 8) ,(4, 1901142022, 9),(4, 1919286022, 8) ,(4, 1932591622, 9),(4, 1950735622, 8) ,(4, 1964041222, 9),(4, 1982790022, 8) ,(4, 1995490822, 9),(4, 2014239622, 8) ,(4, 2026940422, 9),(4, 2045689222, 8) ,(4, 2058390022, 9),(4, 2077138822, 8) ,(4, 2090444422, 9),(4, 2108588422, 8) ,(4, 2121894022, 9),(4, 2140038022, 8); + + +CREATE TABLE time_zone_transition_type (Time_zone_id int unsigned NOT NULL,Transition_type_id int unsigned NOT NULL,Offset int signed DEFAULT 0 NOT NULL,Is_DST tinyint unsigned DEFAULT 0 NOT NULL,Abbreviation char(8) DEFAULT '' NOT NULL,PRIMARY KEY TzIdTrTId (Time_zone_id, Transition_type_id)) engine=MyISAM CHARACTER SET utf8 comment='Time zone transition types'; + +INSERT INTO time_zone_transition_type (Time_zone_id,Transition_type_id, Offset, Is_DST, Abbreviation) VALUES (1, 0, 7200, 1, 'MEST') ,(1, 1, 3600, 0, 'MET') ,(1, 2, 7200, 1, 'MEST') ,(1, 3, 3600, 0, 'MET') ,(2, 0, 0, 0, 'UTC') ,(3, 0, 9000, 0, 'MMT') ,(3, 1, 12648, 1, 'MST') ,(3, 2, 9048, 0, 'MMT') ,(3, 3, 16248, 1, 'MDST') ,(3, 4, 10800, 0, 'MSK') ,(3, 5, 14400, 1, 'MSD') ,(3, 6, 18000, 1, 'MSD') ,(3, 7, 7200, 0, 'EET') ,(3, 8, 10800, 0, 'MSK') ,(3, 9, 14400, 1, 'MSD') ,(3, 10, 10800, 1, 'EEST') ,(3, 11, 7200, 0, 'EET') ,(4, 0, 9000, 0, 'MMT') ,(4, 1, 12648, 1, 'MST') ,(4, 2, 9048, 0, 'MMT') ,(4, 3, 16248, 1, 'MDST') ,(4, 4, 10800, 0, 'MSK') ,(4, 5, 14400, 1, 'MSD') ,(4, 6, 18000, 1, 'MSD') ,(4, 7, 7200, 0, 'EET') ,(4, 8, 10800, 0, 'MSK') ,(4, 9, 14400, 1, 'MSD') ,(4, 10, 10800, 1, 'EEST') ,(4, 11, 7200, 0, 'EET') ,(5, 0, 32400, 0, 'CJT') ,(5, 1, 32400, 0, 'JST'); + +CREATE TABLE time_zone_leap_second (Transition_time bigint signed NOT NULL,Correction int signed NOT NULL,PRIMARY KEY TranTime (Transition_time)) engine=MyISAM CHARACTER SET utf8 comment='Leap seconds information for time zones'; + +INSERT INTO time_zone_leap_second (Transition_time, Correction) VALUES (78796800, 1) ,(94694401, 2) ,(126230402, 3) ,(157766403, 4) ,(189302404, 5) ,(220924805, 6) ,(252460806, 7) ,(283996807, 8) ,(315532808, 9) ,(362793609, 10) ,(394329610, 11) ,(425865611, 12) ,(489024012, 13) ,(567993613, 14) ,(631152014, 15) ,(662688015, 16) ,(709948816, 17) ,(741484817, 18) ,(773020818, 19) ,(820454419, 20) ,(867715220, 21) ,(915148821, 22); + + diff --git a/mysql-test/lib/mtr_gcov.pl b/mysql-test/lib/mtr_gcov.pl new file mode 100644 index 00000000000..07aac1d2017 --- /dev/null +++ b/mysql-test/lib/mtr_gcov.pl @@ -0,0 +1,44 @@ +# -*- cperl -*- + +# This is a library file used by the Perl version of mysql-test-run, +# and is part of the translation of the Bourne shell script with the +# same name. + +use strict; + +# These are not to be prefixed with "mtr_" + +sub gcov_prepare (); +sub gcov_collect (); + +############################################################################## +# +# +# +############################################################################## + +sub gcov_prepare () { + + `find $::glob_basedir -name \*.gcov \ + -or -name \*.da | xargs rm`; +} + +sub gcov_collect () { + + print "Collecting source coverage info...\n"; + -f $::opt_gcov_msg and unlink($::opt_gcov_msg); + -f $::opt_gcov_err and unlink($::opt_gcov_err); + foreach my $d ( @::mysqld_src_dirs ) + { + chdir("$::glob_basedir/$d"); + foreach my $f ( (glob("*.h"), glob("*.cc"), glob("*.c")) ) + { + `$::opt_gcov $f 2>>$::opt_gcov_err >>$::opt_gcov_msg`; + } + chdir($::glob_mysql_test_dir); + } + print "gcov info in $::opt_gcov_msg, errors in $::opt_gcov_err\n"; +} + + +1; diff --git a/mysql-test/lib/mtr_gprof.pl b/mysql-test/lib/mtr_gprof.pl new file mode 100644 index 00000000000..cc874eebfe5 --- /dev/null +++ b/mysql-test/lib/mtr_gprof.pl @@ -0,0 +1,50 @@ +# -*- cperl -*- + +# This is a library file used by the Perl version of mysql-test-run, +# and is part of the translation of the Bourne shell script with the +# same name. + +use strict; + +# These are not to be prefixed with "mtr_" + +sub gprof_prepare (); +sub gprof_collect (); + +############################################################################## +# +# +# +############################################################################## + +sub gprof_prepare () { + + rmtree($::opt_gprof_dir); + mkdir($::opt_gprof_dir); +} + +# FIXME what about master1 and slave1?! +sub gprof_collect () { + + if ( -f "$::master->[0]->{'path_myddir'}/gmon.out" ) + { + # FIXME check result code?! + mtr_run("gprof", + [$::exe_master_mysqld, + "$::master->[0]->{'path_myddir'}/gmon.out"], + $::opt_gprof_master, "", "", ""); + print "Master execution profile has been saved in $::opt_gprof_master\n"; + } + if ( -f "$::slave->[0]->{'path_myddir'}/gmon.out" ) + { + # FIXME check result code?! + mtr_run("gprof", + [$::exe_slave_mysqld, + "$::slave->[0]->{'path_myddir'}/gmon.out"], + $::opt_gprof_slave, "", "", ""); + print "Slave execution profile has been saved in $::opt_gprof_slave\n"; + } +} + + +1; diff --git a/mysql-test/lib/mtr_io.pl b/mysql-test/lib/mtr_io.pl new file mode 100644 index 00000000000..14ea37dbb75 --- /dev/null +++ b/mysql-test/lib/mtr_io.pl @@ -0,0 +1,71 @@ +# -*- cperl -*- + +# This is a library file used by the Perl version of mysql-test-run, +# and is part of the translation of the Bourne shell script with the +# same name. + +use strict; + +sub mtr_get_pid_from_file ($); +sub mtr_get_opts_from_file ($); +sub mtr_tofile ($@); +sub mtr_tonewfile($@); + +############################################################################## +# +# +# +############################################################################## + +sub mtr_get_pid_from_file ($) { + my $file= shift; + + open(FILE,"<",$file) or mtr_error("can't open file \"$file\": $!"); + my $pid= ; + chomp($pid); + close FILE; + return $pid; +} + +sub mtr_get_opts_from_file ($) { + my $file= shift; + + open(FILE,"<",$file) or mtr_error("can't open file \"$file\": $!"); + my @args; + while ( ) + { + chomp; + s/\$MYSQL_TEST_DIR/$::glob_mysql_test_dir/g; + push(@args, split(' ', $_)); + } + close FILE; + return \@args; +} + +sub mtr_fromfile ($) { + my $file= shift; + + open(FILE,"<",$file) or mtr_error("can't open file \"$file\": $!"); + my $text= join('', ); + close FILE; + return $text; +} + +sub mtr_tofile ($@) { + my $file= shift; + + open(FILE,">>",$file) or mtr_error("can't open file \"$file\": $!"); + print FILE join("", @_); + close FILE; +} + +sub mtr_tonewfile ($@) { + my $file= shift; + + open(FILE,">",$file) or mtr_error("can't open file \"$file\": $!"); + print FILE join("", @_); + close FILE; +} + + +1; diff --git a/mysql-test/lib/mtr_match.pl b/mysql-test/lib/mtr_match.pl new file mode 100644 index 00000000000..eb5de655520 --- /dev/null +++ b/mysql-test/lib/mtr_match.pl @@ -0,0 +1,67 @@ +# -*- cperl -*- + +# This is a library file used by the Perl version of mysql-test-run, +# and is part of the translation of the Bourne shell script with the +# same name. + +use strict; + +sub mtr_match_prefix ($$); +sub mtr_match_extension ($$); +sub mtr_match_any_exact ($$); + +############################################################################## +# +# +# +############################################################################## + +# Match a prefix and return what is after the prefix + +sub mtr_match_prefix ($$) { + my $string= shift; + my $prefix= shift; + + if ( $string =~ /^\Q$prefix\E(.*)$/ ) # strncmp + { + return $1; + } + else + { + return undef; # NULL + } +} + + +# Match extension and return the name without extension + +sub mtr_match_extension ($$) { + my $file= shift; + my $ext= shift; + + if ( $file =~ /^(.*)\.\Q$ext\E$/ ) # strchr+strcmp or something + { + return $1; + } + else + { + return undef; # NULL + } +} + + +sub mtr_match_any_exact ($$) { + my $string= shift; + my $mlist= shift; + + foreach my $m (@$mlist) + { + if ( $string eq $m ) + { + return 1; + } + } + return 0; +} + +1; diff --git a/mysql-test/lib/mtr_misc.pl b/mysql-test/lib/mtr_misc.pl new file mode 100644 index 00000000000..5f80864d1f7 --- /dev/null +++ b/mysql-test/lib/mtr_misc.pl @@ -0,0 +1,50 @@ +# -*- cperl -*- + +# This is a library file used by the Perl version of mysql-test-run, +# and is part of the translation of the Bourne shell script with the +# same name. + +use strict; + +sub mtr_full_hostname (); +sub mtr_init_args ($); +sub mtr_add_arg ($$); + +############################################################################## +# +# Misc +# +############################################################################## + +# We want the fully qualified host name and hostname() may have returned +# only the short name. So we use the resolver to find out. + +sub mtr_full_hostname () { + + my $hostname= hostname(); + if ( $hostname !~ /\./ ) + { + my $address= gethostbyname($hostname) + or die "Couldn't resolve $hostname : $!"; + my $fullname= gethostbyaddr($address, AF_INET); + $hostname= $fullname if $fullname; + } + return $hostname; +} + +# FIXME move to own lib + +sub mtr_init_args ($) { + my $args = shift; + $$args = []; # Empty list +} + +sub mtr_add_arg ($$) { + my $args= shift; + my $format= shift; + my @fargs = @_; + + push(@$args, sprintf($format, @fargs)); +} + +1; diff --git a/mysql-test/lib/mtr_process.pl b/mysql-test/lib/mtr_process.pl new file mode 100644 index 00000000000..8c584802b8e --- /dev/null +++ b/mysql-test/lib/mtr_process.pl @@ -0,0 +1,467 @@ +# -*- cperl -*- + +# This is a library file used by the Perl version of mysql-test-run, +# and is part of the translation of the Bourne shell script with the +# same name. + +use Carp qw(cluck); +use strict; + +use POSIX ":sys_wait_h"; + +sub mtr_run ($$$$$$); +sub mtr_spawn ($$$$$$); +sub mtr_stop_mysqld_servers ($$); +sub mtr_kill_leftovers (); + +# static in C +sub spawn_impl ($$$$$$$); + +############################################################################## +# +# Execute an external command +# +############################################################################## + +# This function try to mimic the C version used in "netware/mysql_test_run.c" +# FIXME learn it to handle append mode as well, a "new" flag or a "append" + +sub mtr_run ($$$$$$) { + my $path= shift; + my $arg_list_t= shift; + my $input= shift; + my $output= shift; + my $error= shift; + my $pid_file= shift; + + return spawn_impl($path,$arg_list_t,1,$input,$output,$error,$pid_file); +} + +sub mtr_spawn ($$$$$$) { + my $path= shift; + my $arg_list_t= shift; + my $input= shift; + my $output= shift; + my $error= shift; + my $pid_file= shift; + + return spawn_impl($path,$arg_list_t,0,$input,$output,$error,$pid_file); +} + + +############################################################################## +# +# If $join is set, we return the error code, else we return the PID +# +############################################################################## + +sub spawn_impl ($$$$$$$) { + my $path= shift; + my $arg_list_t= shift; + my $join= shift; + my $input= shift; + my $output= shift; + my $error= shift; + my $pid_file= shift; # FIXME + + # FIXME really needing a PATH??? + # $ENV{'PATH'}= "/bin:/usr/bin:/usr/local/bin:/usr/bsd:/usr/X11R6/bin:/usr/openwin/bin:/usr/bin/X11:$ENV{'PATH'}"; + + $ENV{'TZ'}= "GMT-3"; # for UNIX_TIMESTAMP tests to work + $ENV{'LC_COLLATE'}= "C"; + $ENV{'MYSQL_TEST_DIR'}= $::glob_mysql_test_dir; + $ENV{'MASTER_MYPORT'}= $::opt_master_myport; + $ENV{'SLAVE_MYPORT'}= $::opt_slave_myport; +# $ENV{'MYSQL_TCP_PORT'}= '@MYSQL_TCP_PORT@'; # FIXME + $ENV{'MYSQL_TCP_PORT'}= 3306; + $ENV{'MASTER_MYSOCK'}= $::master->[0]->{'path_mysock'}; + + if ( $::opt_script_debug ) + { + print STDERR "\n"; + print STDERR "#### ", "-" x 78, "\n"; + print STDERR "#### ", "STDIN $input\n" if $input; + print STDERR "#### ", "STDOUT $output\n" if $output; + print STDERR "#### ", "STDERR $error\n" if $error; + if ( $join ) + { + print STDERR "#### ", "run"; + } + else + { + print STDERR "#### ", "spawn"; + } + print STDERR "$path ", join(" ",@$arg_list_t), "\n"; + print STDERR "#### ", "-" x 78, "\n"; + } + + my $pid= fork(); + + if ( $pid ) + { + # Parent, i.e. the main script + if ( $join ) + { + # We run a command and wait for the result + # FIXME this need to be improved + waitpid($pid,0); + my $exit_value= $? >> 8; + my $signal_num= $? & 127; + my $dumped_core= $? & 128; + if ( $signal_num ) + { + mtr_error("spawn got signal $signal_num"); + } + if ( $dumped_core ) + { + mtr_error("spawn dumped core"); + } + return $exit_value; + } + else + { + # We spawned a process we don't wait for + return $pid; + } + } + else + { + # Child, redirect output and exec + # FIXME I tried POSIX::setsid() here to detach and, I hoped, + # avoid zombies. But everything went wild, somehow the parent + # became a deamon as well, and was hard to kill ;-) + # Need to catch SIGCHLD and do waitpid or something instead...... + + $SIG{INT}= 'DEFAULT'; # Parent do some stuff, we don't + + if ( $output ) + { + if ( ! open(STDOUT,">",$output) ) + { + mtr_error("can't redirect STDOUT to \"$output\": $!"); + } + } + if ( $error ) + { + if ( $output eq $error ) + { + if ( ! open(STDERR,">&STDOUT") ) + { + mtr_error("can't dup STDOUT: $!"); + } + } + else + { + if ( ! open(STDERR,">",$error) ) + { + mtr_error("can't redirect STDERR to \"$output\": $!"); + } + } + } + if ( $input ) + { + if ( ! open(STDIN,"<",$input) ) + { + mtr_error("can't redirect STDIN to \"$input\": $!"); + } + } + exec($path,@$arg_list_t); + } +} + +############################################################################## +# +# Kill processes left from previous runs +# +############################################################################## + +sub mtr_kill_leftovers () { + + # First, kill all masters and slaves that would conflict with + # this run. Make sure to remove the PID file, if any. + + my @args; + + for ( my $idx; $idx < 2; $idx++ ) + { + push(@args,{ + pid => 0, # We don't know the PID + pidfile => $::master->[$idx]->{'path_mypid'}, + sockfile => $::master->[$idx]->{'path_mysock'}, + port => $::master->[$idx]->{'path_myport'}, + }); + } + + for ( my $idx; $idx < 3; $idx++ ) + { + push(@args,{ + pid => 0, # We don't know the PID + pidfile => $::slave->[$idx]->{'path_mypid'}, + sockfile => $::slave->[$idx]->{'path_mysock'}, + port => $::slave->[$idx]->{'path_myport'}, + }); + } + + mtr_stop_mysqld_servers(\@args, 1); + + # We scan the "var/run/" directory for other process id's to kill + my $rundir= "$::glob_mysql_test_dir/var/run"; # FIXME $path_run_dir or something + + if ( -d $rundir ) + { + opendir(RUNDIR, $rundir) + or mtr_error("can't open directory \"$rundir\": $!"); + + my @pids; + + while ( my $elem= readdir(RUNDIR) ) + { + my $pidfile= "$rundir/$elem"; + + if ( -f $pidfile ) + { + my $pid= mtr_get_pid_from_file($pidfile); + if ( ! unlink($pidfile) ) + { + mtr_error("can't remove $pidfile"); + } + push(@pids, $pid); + } + } + closedir(RUNDIR); + + start_reap_all(); + + if ( $::glob_cygwin_perl ) + { + # We have no (easy) way of knowing the Cygwin controlling + # process, in the PID file we only have the Windows process id. + system("kill -f " . join(" ",@pids)); # Hope for the best.... + } + else + { + my $retries= 10; # 10 seconds + do + { + kill(9, @pids); + } while ( $retries-- and kill(0, @pids) ); + + if ( kill(0, @pids) ) + { + mtr_error("can't kill processes " . join(" ", @pids)); + } + } + + stop_reap_all(); + } +} + +############################################################################## +# +# Shut down mysqld servers +# +############################################################################## + +# To speed things we kill servers in parallel. +# The argument is a list of 'pidfiles' and 'socketfiles'. +# We use the pidfiles and socketfiles to try to terminate the servers. +# This is not perfect, there could still be other server processes +# left. + +# Force flag is to be set only for killing mysqld servers this script +# didn't create in this run, i.e. initial cleanup before we start working. +# If force flag is set, we try to kill all with mysqladmin, and +# give up if we have no PIDs. + +# FIXME On some operating systems, $srv->{'pid'} and $srv->{'pidfile'} +# will not be the same PID. We need to try to kill both I think. + +sub mtr_stop_mysqld_servers ($$) { + my $spec= shift; + my $force= shift; + + # ---------------------------------------------------------------------- + # If the process was not started from this file, we got no PID, + # we try to find it in the PID file. + # ---------------------------------------------------------------------- + + my $any_pid= 0; # If we have any PIDs + + foreach my $srv ( @$spec ) + { + if ( ! $srv->{'pid'} and -f $srv->{'pidfile'} ) + { + $srv->{'pid'}= mtr_get_pid_from_file($srv->{'pidfile'}); + } + if ( $srv->{'pid'} ) + { + $any_pid= 1; + } + } + + # If the processes where started from this script, and we know + # no PIDs, then we don't have to do anything. + + if ( ! $any_pid and ! $force ) + { + # cluck "This is how we got here!"; + return; + } + + # ---------------------------------------------------------------------- + # First try nice normal shutdown using 'mysqladmin' + # ---------------------------------------------------------------------- + + start_reap_all(); # Don't require waitpid() of children + + foreach my $srv ( @$spec ) + { + if ( -e $srv->{'sockfile'} or $srv->{'port'} ) + { + # FIXME wrong log..... + # FIXME, stderr..... + # Shutdown time must be high as slave may be in reconnect + my $args; + + mtr_init_args(\$args); + + mtr_add_arg($args, "--no-defaults"); + mtr_add_arg($args, "-uroot"); + if ( -e $srv->{'sockfile'} ) + { + mtr_add_arg($args, "--socket=%s", $srv->{'sockfile'}); + } + if ( $srv->{'port'} ) + { + mtr_add_arg($args, "--port=%s", $srv->{'port'}); + } + mtr_add_arg($args, "--connect_timeout=5"); + mtr_add_arg($args, "--shutdown_timeout=70"); + mtr_add_arg($args, "shutdown"); + # We don't wait for termination of mysqladmin + mtr_spawn($::exe_mysqladmin, $args, + "", $::path_manager_log, $::path_manager_log, ""); + } + } + + # Wait for them all to remove their pid and socket file + + PIDSOCKFILEREMOVED: + for (my $loop= $::opt_sleep_time_for_delete; $loop; $loop--) + { + my $pidsockfiles_left= 0; + foreach my $srv ( @$spec ) + { + if ( -e $srv->{'sockfile'} or -f $srv->{'pidfile'} ) + { + $pidsockfiles_left++; # Could be that pidfile is left + } + } + if ( ! $pidsockfiles_left ) + { + last PIDSOCKFILEREMOVED; + } + mtr_debug("Sleep for 1 second waiting for pid and socket file removal"); + sleep(1); # One second + } + + # ---------------------------------------------------------------------- + # If no known PIDs, we have nothing more to try + # ---------------------------------------------------------------------- + + if ( ! $any_pid ) + { + stop_reap_all(); + return; + } + + # ---------------------------------------------------------------------- + # We may have killed all that left a socket, but we are not sure we got + # them all killed. If we suspect it lives, try nice kill with SIG_TERM. + # Note that for true Win32 processes, kill(0,$pid) will not return 1. + # ---------------------------------------------------------------------- + + SIGNAL: + foreach my $sig (15,9) + { + my $process_left= 0; + foreach my $srv ( @$spec ) + { + if ( $srv->{'pid'} and + ( -f $srv->{'pidfile'} or kill(0,$srv->{'pid'}) ) ) + { + $process_left++; + mtr_warning("process $srv->{'pid'} not cooperating, " . + "will send signal $sig to process"); + kill($sig,$srv->{'pid'}); # SIG_TERM + } + if ( ! $process_left ) + { + last SIGNAL; + } + } + mtr_debug("Sleep for 5 seconds waiting for processes to die"); + sleep(5); # We wait longer than usual + } + + # ---------------------------------------------------------------------- + # Now, we check if all we can find using kill(0,$pid) are dead, + # and just assume the rest are. We cleanup socket and PID files. + # ---------------------------------------------------------------------- + + { + my $errors= 0; + foreach my $srv ( @$spec ) + { + if ( $srv->{'pid'} ) + { + if ( kill(0,$srv->{'pid'}) ) + { + # FIXME In Cygwin there seem to be some fast reuse + # of PIDs, so dying may not be the right thing to do. + $errors++; + mtr_warning("can't kill process $srv->{'pid'}"); + } + else + { + # We managed to kill it at last + # FIXME In Cygwin, we will get here even if the process lives. + + # Not needed as we know the process is dead, but to be safe + # we unlink and check success in two steps. We first unlink + # without checking the error code, and then check if the + # file still exists. + + foreach my $file ($srv->{'pidfile'}, $srv->{'sockfile'}) + { + unlink($file); + if ( -e $file ) + { + $errors++; + mtr_warning("couldn't delete $file"); + } + } + } + } + } + if ( $errors ) + { + # We are in trouble, just die.... + mtr_error("we could not kill or clean up all processes"); + } + } + + stop_reap_all(); + + # FIXME We just assume they are all dead, we don't know.... +} + +sub start_reap_all { + $SIG{CHLD}= 'IGNORE'; # FIXME is this enough? +} + +sub stop_reap_all { + $SIG{CHLD}= 'DEFAULT'; +} + +1; diff --git a/mysql-test/lib/mtr_report.pl b/mysql-test/lib/mtr_report.pl new file mode 100644 index 00000000000..0f75fc1341a --- /dev/null +++ b/mysql-test/lib/mtr_report.pl @@ -0,0 +1,262 @@ +# -*- cperl -*- + +# This is a library file used by the Perl version of mysql-test-run, +# and is part of the translation of the Bourne shell script with the +# same name. + +use strict; + +sub mtr_report_test_name($); +sub mtr_report_test_passed($); +sub mtr_report_test_failed($); +sub mtr_report_test_skipped($); + +sub mtr_show_failed_diff ($); +sub mtr_report_stats ($); +sub mtr_print_line (); +sub mtr_print_thick_line (); +sub mtr_print_header (); +sub mtr_report (@); +sub mtr_warning (@); +sub mtr_error (@); +sub mtr_debug (@); + + +############################################################################## +# +# +# +############################################################################## + +# We can't use diff -u or diff -a as these are not portable + +sub mtr_show_failed_diff ($) { + my $tname= shift; + + my $reject_file= "r/$tname.reject"; + my $result_file= "r/$tname.result"; + my $eval_file= "r/$tname.eval"; + + if ( -f $eval_file ) + { + $result_file= $eval_file; + } + elsif ( $::opt_result_ext and + ( $::opt_record or -f "$result_file$::opt_result_ext" )) + { + # If we have an special externsion for result files we use it if we are + # recording or a result file with that extension exists. + $result_file= "$result_file$::opt_result_ext"; + } + + if ( -f $reject_file ) + { + print "Below are the diffs between actual and expected results:\n"; + print "-------------------------------------------------------\n"; + # FIXME check result code?! + mtr_run("diff",["-c",$result_file,$reject_file], "", "", "", ""); + print "-------------------------------------------------------\n"; + print "Please follow the instructions outlined at\n"; + print "http://www.mysql.com/doc/en/Reporting_mysqltest_bugs.html\n"; + print "to find the reason to this problem and how to report this.\n\n"; + } +} + +sub mtr_report_test_name ($) { + my $tinfo= shift; + + printf "%-31s ", $tinfo->{'name'}; +} + +sub mtr_report_test_skipped ($) { + my $tinfo= shift; + + $tinfo->{'result'}= 'MTR_RES_SKIPPED'; + print "[ skipped ]\n"; +} + +sub mtr_report_test_passed ($) { + my $tinfo= shift; + + my $timer= ""; +# FIXME +# if ( $::opt_timer and -f "$::glob_mysql_test_dir/var/log/timer" ) +# { +# $timer= `cat var/log/timer`; +# $timer= sprintf "%13s", $timer; +# } + $tinfo->{'result'}= 'MTR_RES_PASSED'; + print "[ pass ] $timer\n"; +} + +sub mtr_report_test_failed ($) { + my $tinfo= shift; + + $tinfo->{'result'}= 'MTR_RES_FAILED'; + print "[ fail ]\n"; + + print "Errors are (from $::path_timefile) :\n"; + print mtr_fromfile($::path_timefile); # FIXME print_file() instead + print "\n(the last lines may be the most important ones)\n"; +} + +sub mtr_report_stats ($) { + my $tests= shift; + + # ---------------------------------------------------------------------- + # Find out how we where doing + # ---------------------------------------------------------------------- + + my $tot_skiped= 0; + my $tot_passed= 0; + my $tot_failed= 0; + my $tot_tests= 0; + + foreach my $tinfo (@$tests) + { + if ( $tinfo->{'result'} eq 'MTR_RES_SKIPPED' ) + { + $tot_skiped++; + } + elsif ( $tinfo->{'result'} eq 'MTR_RES_PASSED' ) + { + $tot_tests++; + $tot_passed++; + } + elsif ( $tinfo->{'result'} eq 'MTR_RES_FAILED' ) + { + $tot_tests++; + $tot_failed++; + } + } + + # ---------------------------------------------------------------------- + # Print out a summary report to screen + # ---------------------------------------------------------------------- + + if ( ! $tot_failed ) + { + print "All $tot_tests tests were successful.\n"; + } + else + { + my $ratio= $tot_passed * 100 / $tot_tests; + printf "Failed $tot_failed/$tot_tests tests, " . + "%.2f\% successful.\n\n", $ratio; + print + "The log files in var/log may give you some hint\n", + "of what when wrong.\n", + "If you want to report this error, please read first ", + "the documentation at\n", + "http://www.mysql.com/doc/en/MySQL_test_suite.html\n"; + } + + # ---------------------------------------------------------------------- + # ---------------------------------------------------------------------- + + if ( ! $::glob_use_running_server ) + { + + # Report if there was any fatal warnings/errors in the log files + # + unlink("$::glob_mysql_test_dir/var/log/warnings"); + unlink("$::glob_mysql_test_dir/var/log/warnings.tmp"); + # Remove some non fatal warnings from the log files + +# FIXME what is going on ????? ;-) +# sed -e 's!Warning: Table:.* on delete!!g' -e 's!Warning: Setting lower_case_table_names=2!!g' -e 's!Warning: One can only use the --user.*root!!g' \ +# var/log/*.err \ +# | sed -e 's!Warning: Table:.* on rename!!g' \ +# > var/log/warnings.tmp; +# +# found_error=0; +# # Find errors +# for i in "^Warning:" "^Error:" "^==.* at 0x" +# do +# if ( $GREP "$i" var/log/warnings.tmp >> var/log/warnings ) +# { +# found_error=1 +# } +# done +# unlink("$::glob_mysql_test_dir/var/log/warnings.tmp"); +# if ( $found_error= "1" ) +# { +# print "WARNING: Got errors/warnings while running tests. Please examine\n" +# print "$::glob_mysql_test_dir/var/log/warnings for details.\n" +# } +# } + } + + print "\n"; + + if ( $tot_failed != 0 ) + { + print "mysql-test-run: *** Failing the test(s):"; + + foreach my $tinfo (@$tests) + { + if ( $tinfo->{'result'} eq 'MTR_RES_FAILED' ) + { + print " $tinfo->{'name'}"; + } + } + print "\n"; + mtr_error("there where failing test cases"); + } +} + +############################################################################## +# +# Text formatting +# +############################################################################## + +sub mtr_print_line () { + print '-' x 55, "\n"; +} + +sub mtr_print_thick_line () { + print '=' x 55, "\n"; +} + +sub mtr_print_header () { + print "\n"; + if ( $::opt_timer ) + { + print "TEST RESULT TIME (ms)\n"; + } + else + { + print "TEST RESULT\n"; + } + mtr_print_line(); + print "\n"; +} + + +############################################################################## +# +# Misc +# +############################################################################## + +sub mtr_report (@) { + print join(" ", @_),"\n"; +} + +sub mtr_warning (@) { + print STDERR "mysql-test-run: WARNING: ",join(" ", @_),"\n"; +} + +sub mtr_error (@) { + die "mysql-test-run: *** ERROR: ",join(" ", @_),"\n"; +} + +sub mtr_debug (@) { + if ( $::opt_script_debug ) + { + print STDERR "####: ",join(" ", @_),"\n"; + } +} + +1; diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl new file mode 100755 index 00000000000..01729aa1018 --- /dev/null +++ b/mysql-test/mysql-test-run.pl @@ -0,0 +1,2182 @@ +#!/usr/bin/perl +# -*- cperl -*- + +# This is a transformation of the "mysql-test-run" Bourne shell script +# to Perl. This is just an intermediate step, the goal is to rewrite +# the Perl script to C. The complexity of the mysql-test-run script +# makes it a bit hard to write and debug it as a C program directly, +# so this is considered a prototype. +# +# Because of this the Perl coding style may in some cases look a bit +# funny. The rules used are +# +# - The coding style is as close as possible to the C/C++ MySQL +# coding standard. +# +# - Where NULL is to be returned, the undefined value is used. +# +# - Regexp comparisons are simple and can be translated to strcmp +# and other string functions. To ease this transformation matching +# is done in the lib "lib/mtr_match.pl", i.e. regular expressions +# should be avoided in the main program. +# +# - The "unless" construct is not to be used. It is the same as "if !". +# +# - opendir/readdir/closedir is used instead of glob()/<*>. +# +# - All lists of arguments to send to commands are Perl lists/arrays, +# not strings we append args to. Within reason, most string +# concatenation for arguments should be avoided. +# +# - sprintf() is to be used, within reason, for all string creation. +# This mtr_add_arg() function is also based on sprintf(), i.e. you +# use a format string and put the variable argument in the argument +# list. +# +# - Functions defined in the main program are not to be prefixed, +# functions in "library files" are to be prefixed with "mtr_" (for +# Mysql-Test-Run). There are some exceptions, code that fits best in +# the main program, but are put into separate files to avoid +# clutter, may be without prefix. +# +# - All stat/opendir/-f/ is to be kept in collect_test_cases(). It +# will create a struct that the rest of the program can use to get +# the information. This separates the "find information" from the +# "do the work" and makes the program more easy to maintain. +# +# - At the moment, there are tons of "global" variables that control +# this script, even accessed from the files in "lib/*.pl". This +# will change over time, for now global variables are used instead +# of using %opt, %path and %exe hashes, because I want more +# compile time checking, that hashes would not give me. Once this +# script is debugged, hashes will be used and passed as parameters +# to functions, to more closely mimic how it would be coded in C +# using structs. +# +# - The rule when it comes to the logic of this program is +# +# command_line_setup() - is to handle the logic between flags +# collect_test_cases() - is to do its best to select what tests +# to run, dig out options, if needs restart etc. +# run_testcase() - is to run a single testcase, and follow the +# logic set in both above. No, or rare file +# system operations. If a test seems complex, +# it should probably not be here. +# +# A nice way to trace the execution of this script while debugging +# is to use the Devel::Trace package found at +# "http://www.plover.com/~mjd/perl/Trace/" and run this script like +# "perl -d:Trace mysql-test-run.pl" +# +# FIXME Save a PID file from this code as well, to record the process +# id we think it has. In Cygwin, a fork creates one Cygwin process, +# and then the real Win32 process. Cygwin Perl can only kill Cygwin +# processes. And "mysqld --bootstrap ..." doesn't save a PID file. + +$Devel::Trace::TRACE= 0; # Don't trace boring init stuff + +#require 5.6.1; +use File::Path; +use File::Basename; +use Cwd; +use Getopt::Long; +use Sys::Hostname; +#use Carp; +use IO::Socket; +use IO::Socket::INET; +use Data::Dumper; +use strict; +#use diagnostics; + +require "lib/mtr_process.pl"; +require "lib/mtr_io.pl"; +require "lib/mtr_gcov.pl"; +require "lib/mtr_gprof.pl"; +require "lib/mtr_report.pl"; +require "lib/mtr_match.pl"; +require "lib/mtr_misc.pl"; + +$Devel::Trace::TRACE= 1; + +my @skip_if_embedded_server= + ( + "alter_table", + "bdb-deadlock", + "connect", + "flush_block_commit", + "grant2", + "grant_cache", + "grant", + "init_connect", + "innodb-deadlock", + "innodb-lock", + "mix_innodb_myisam_binlog", + "mysqlbinlog2", + "mysqlbinlog", + "mysqldump", + "mysql_protocols", + "ps_1general", + "rename", + "show_check", + "system_mysql_db_fix", + "user_var", + "variables", + ); + +# Used by gcov +our @mysqld_src_dirs= + ( + "strings", + "mysys", + "include", + "extra", + "regex", + "isam", + "merge", + "myisam", + "myisammrg", + "heap", + "sql", + ); + +############################################################################## +# +# Default settings +# +############################################################################## + +# 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 $glob_win32= 0; # OS and native Win32 executables +our $glob_win32_perl= 0; # ActiveState Win32 Perl +our $glob_cygwin_perl= 0; # Cygwin Perl +our $glob_mysql_test_dir= undef; +our $glob_mysql_bench_dir= undef; +our $glob_hostname= undef; +our $glob_scriptname= undef; +our $glob_use_running_server= 0; +our $glob_use_running_ndbcluster= 0; +our $glob_user= 'test'; +our $glob_use_embedded_server= 0; + +our $glob_basedir; +our $glob_do_test; + +# The total result + +our $path_charsetsdir; +our $path_client_bindir; +our $path_language; +our $path_tests_bindir; +our $path_timefile; +our $path_manager_log; # Used by mysqldadmin +our $path_slave_load_tmpdir; # What is this?! +our $path_my_basedir; +our $opt_tmpdir; # A path but set directly on cmd line + +our $opt_usage; +our $opt_suite; + +our $opt_netware; + +our $opt_script_debug= 0; # Script debugging, enable with --script-debug + +# Options FIXME not all.... + +our $exe_master_mysqld; +our $exe_mysql; +our $exe_mysqladmin; +our $exe_mysqlbinlog; +our $exe_mysqld; +our $exe_mysqldump; # Called from test case +our $exe_mysqltest; +our $exe_slave_mysqld; + +our $opt_bench= 0; +our $opt_small_bench= 0; +our $opt_big_test= 0; # Send --big-test to mysqltest + +our $opt_extra_mysqld_opt; # FIXME not handled + +our $opt_compress; +our $opt_current_test; +our $opt_ddd; +our $opt_debug; +our $opt_do_test; +our $opt_embedded_server; +our $opt_extern; +our $opt_fast; +our $opt_force; + +our $opt_gcov; +our $opt_gcov_err; +our $opt_gcov_msg; + +our $opt_gdb; +our $opt_client_gdb; +our $opt_manual_gdb; + +our $opt_gprof; +our $opt_gprof_dir; +our $opt_gprof_master; +our $opt_gprof_slave; + +our $opt_local; +our $opt_local_master; + +our $master; # Will be struct in C +our $slave; + +our $opt_ndbcluster_port; +our $opt_ndbconnectstring; + +our $opt_no_manager; # Does nothing now, we never use manager + +our $opt_old_master; + +our $opt_record; + +our $opt_result_ext; + +our $opt_skip; +our $opt_skip_rpl; +our $opt_skip_test; + +our $opt_sleep; + +our $opt_ps_protocol; + +# FIXME all of the sleep time handling needs cleanup +our $opt_sleep_time_after_restart= 1; +our $opt_sleep_time_for_delete= 10; +our $opt_sleep_time_for_first_master= 400; # enough time create innodb tables +our $opt_sleep_time_for_second_master= 400; +our $opt_sleep_time_for_first_slave= 400; +our $opt_sleep_time_for_second_slave= 30; + +our $opt_socket; + +our $opt_source_dist; + +our $opt_start_and_exit; +our $opt_start_from; + +our $opt_strace_client; + +our $opt_timer; + + +our $opt_user_test; + +our $opt_valgrind; +our $opt_valgrind_all; +our $opt_valgrind_options; + +our $opt_verbose; + +our $opt_wait_for_master; +our $opt_wait_for_slave; +our $opt_wait_timeout= 10; + +our $opt_warnings; + +our $opt_with_ndbcluster; +our $opt_with_openssl; + + +###################################################################### +# +# Function declarations +# +###################################################################### + +sub main (); +sub initial_setup (); +sub command_line_setup (); +sub executable_setup (); +sub kill_and_cleanup (); +sub collect_test_cases ($); +sub sleep_until_file_created ($$); +sub ndbcluster_start (); +sub ndbcluster_stop (); +sub run_benchmarks ($); +sub run_tests (); +sub mysql_install_db (); +sub install_db ($$); +sub run_testcase ($); +sub do_before_start_master ($$); +sub do_before_start_slave ($$); +sub mysqld_start ($$$$); +sub mysqld_arguments ($$$$$); +sub stop_masters_slaves (); +sub stop_masters (); +sub stop_slaves (); +sub run_mysqltest ($$); +sub usage ($); + +###################################################################### +# +# Main program +# +###################################################################### + +main(); + +sub main () { + + initial_setup(); + command_line_setup(); + executable_setup(); + signal_setup(); + + if ( $opt_gcov ) + { + gcov_prepare(); + } + + if ( $opt_gprof ) + { + gprof_prepare(); + } + + if ( ! $glob_use_running_server ) + { + kill_and_cleanup(); + mysql_install_db(); + + if ( $opt_with_ndbcluster and ! $glob_use_running_ndbcluster ) + { + ndbcluster_start(); # We start the cluster storage engine + } + +# mysql_loadstd(); FIXME copying from "std_data" .frm and +# .MGR but there are none?! + } + + if ( $opt_start_and_exit ) + { + mtr_report("Servers started, exiting"); + } + else + { + if ( $opt_bench ) + { + run_benchmarks(shift); # Shift what? Extra arguments?! + } + else + { + run_tests(); + } + } + + exit(0); +} + +############################################################################## +# +# Initial setup independent on command line arguments +# +############################################################################## + +sub initial_setup () { + + select(STDOUT); + $| = 1; # Make unbuffered + + $glob_scriptname= basename($0); + + $glob_win32_perl= ($^O eq "MSWin32"); + $glob_cygwin_perl= ($^O eq "cygwin"); + $glob_win32= ($glob_win32_perl or $glob_cygwin_perl); + + # 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_full_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); + $glob_mysql_bench_dir= "$glob_basedir/mysql-bench"; # FIXME make configurable + + $path_timefile= "$glob_mysql_test_dir/var/log/mysqltest-time"; + + # needs to be same length to test logging (FIXME what???) + $path_slave_load_tmpdir= "../../var/tmp"; + + $path_my_basedir= + $opt_source_dist ? $glob_mysql_test_dir : $glob_basedir; +} + + + +############################################################################## +# +# Default settings +# +############################################################################## + +sub command_line_setup () { + + # These are defaults for things that are set on the command line + + $opt_suite= "main"; # Special default suite + $opt_tmpdir= "$glob_mysql_test_dir/var/tmp"; + # FIXME maybe unneded? + $path_manager_log= "$glob_mysql_test_dir/var/log/manager.log"; + $opt_current_test= "$glob_mysql_test_dir/var/log/current_test"; + + my $opt_master_myport= 9306; + my $opt_slave_myport= 9308; + $opt_ndbcluster_port= 9350; + $opt_sleep_time_for_delete= 10; + + my $opt_user; + + # Read the command line + # Note: Keep list, and the order, in sync with usage at end of this file + + GetOptions( + # Control what engine/variation to run + 'embedded-server' => \$opt_embedded_server, + 'ps-protocol' => \$opt_ps_protocol, + 'bench' => \$opt_bench, + 'small-bench' => \$opt_small_bench, + 'no-manager' => \$opt_no_manager, + + # Control what test suites or cases to run + 'force' => \$opt_force, + 'with-ndbcluster' => \$opt_with_ndbcluster, + 'do-test=s' => \$opt_do_test, + 'suite=s' => \$opt_suite, + 'skip-rpl' => \$opt_skip_rpl, + 'skip-test=s' => \$opt_skip_test, + + # Specify ports + 'master_port=i' => \$opt_master_myport, + 'slave_port=i' => \$opt_slave_myport, + 'ndbcluster_port=i' => \$opt_ndbcluster_port, + + # Test case authoring + 'record' => \$opt_record, + + # ??? + 'mysqld=s' => \$opt_extra_mysqld_opt, + + # Run test on running server + 'extern' => \$opt_extern, + 'ndbconnectstring=s' => \$opt_ndbconnectstring, + + # Debugging + 'gdb' => \$opt_gdb, + 'manual-gdb' => \$opt_manual_gdb, + 'client-gdb' => \$opt_client_gdb, + 'ddd' => \$opt_ddd, + 'strace-client' => \$opt_strace_client, + 'master-binary=s' => \$exe_master_mysqld, + 'slave-binary=s' => \$exe_slave_mysqld, + + # Coverage, profiling etc + 'gcov' => \$opt_gcov, + 'gprof' => \$opt_gprof, + 'valgrind' => \$opt_valgrind, + 'valgrind-all' => \$opt_valgrind_all, + 'valgrind-options=s' => \$opt_valgrind_options, + + # Misc + 'big-test' => \$opt_big_test, + 'compress' => \$opt_compress, + 'debug' => \$opt_debug, + 'fast' => \$opt_fast, + 'local' => \$opt_local, + 'local-master' => \$opt_local_master, + 'netware' => \$opt_netware, + 'old-master' => \$opt_old_master, + 'script-debug' => \$opt_script_debug, + 'sleep=i' => \$opt_sleep, + 'socket=s' => \$opt_socket, + 'start-and-exit' => \$opt_start_and_exit, + 'start-from=s' => \$opt_start_from, + 'timer' => \$opt_timer, + 'tmpdir=s' => \$opt_tmpdir, + 'user-test=s' => \$opt_user_test, + 'user=s' => \$opt_user, + 'verbose' => \$opt_verbose, + 'wait-timeout=i' => \$opt_wait_timeout, + 'warnings|log-warnings' => \$opt_warnings, + 'with-openssl' => \$opt_with_openssl, + + 'help|h' => \$opt_usage, + ) or usage("Can't read options"); + + if ( $opt_usage ) + { + usage(""); + } + + # Put this into a hash, will be a C struct + + $master->[0]->{'path_myddir'}= "$glob_mysql_test_dir/var/master-data"; + $master->[0]->{'path_myerr'}= "$glob_mysql_test_dir/var/log/master.err"; + $master->[0]->{'path_mylog'}= "$glob_mysql_test_dir/var/log/master.log"; + $master->[0]->{'path_mypid'}= "$glob_mysql_test_dir/var/run/master.pid"; + $master->[0]->{'path_mysock'}= "$opt_tmpdir/master.sock"; + $master->[0]->{'path_myport'}= $opt_master_myport; + + $master->[1]->{'path_myddir'}= "$glob_mysql_test_dir/var/master1-data"; + $master->[1]->{'path_myerr'}= "$glob_mysql_test_dir/var/log/master1.err"; + $master->[1]->{'path_mylog'}= "$glob_mysql_test_dir/var/log/master1.log"; + $master->[1]->{'path_mypid'}= "$glob_mysql_test_dir/var/run/master1.pid"; + $master->[1]->{'path_mysock'}= "$opt_tmpdir/master1.sock"; + $master->[1]->{'path_myport'}= $opt_master_myport + 1; + + $slave->[0]->{'path_myddir'}= "$glob_mysql_test_dir/var/slave-data"; + $slave->[0]->{'path_myerr'}= "$glob_mysql_test_dir/var/log/slave.err"; + $slave->[0]->{'path_mylog'}= "$glob_mysql_test_dir/var/log/slave.log"; + $slave->[0]->{'path_mypid'}= "$glob_mysql_test_dir/var/run/slave.pid"; + $slave->[0]->{'path_mysock'}= "$opt_tmpdir/slave.sock"; + $slave->[0]->{'path_myport'}= $opt_slave_myport; + + $slave->[1]->{'path_myddir'}= "$glob_mysql_test_dir/var/slave1-data"; + $slave->[1]->{'path_myerr'}= "$glob_mysql_test_dir/var/log/slave1.err"; + $slave->[1]->{'path_mylog'}= "$glob_mysql_test_dir/var/log/slave1.log"; + $slave->[1]->{'path_mypid'}= "$glob_mysql_test_dir/var/run/slave1.pid"; + $slave->[1]->{'path_mysock'}= "$opt_tmpdir/slave1.sock"; + $slave->[1]->{'path_myport'}= $opt_slave_myport + 1; + + $slave->[2]->{'path_myddir'}= "$glob_mysql_test_dir/var/slave2-data"; + $slave->[2]->{'path_myerr'}= "$glob_mysql_test_dir/var/log/slave2.err"; + $slave->[2]->{'path_mylog'}= "$glob_mysql_test_dir/var/log/slave2.log"; + $slave->[2]->{'path_mypid'}= "$glob_mysql_test_dir/var/run/slave2.pid"; + $slave->[2]->{'path_mysock'}= "$opt_tmpdir/slave2.sock"; + $slave->[2]->{'path_myport'}= $opt_slave_myport + 2; + + # Do sanity checks of command line arguments + + if ( $opt_extern and $opt_local ) + { + mtr_error("Can't use --extern and --local at the same time"); + } + + if ( ! $opt_socket ) + { # FIXME set default before reading options? +# $opt_socket= '@MYSQL_UNIX_ADDR@'; + $opt_socket= "/tmp/mysql.sock"; # FIXME + } + + if ( $opt_extern ) + { + $glob_use_running_server= 1; + $opt_skip_rpl= 1; # We don't run rpl test cases + $master->[0]->{'path_mysock'}= $opt_socket; + } + + # -------------------------------------------------------------------------- + # Set LD_LIBRARY_PATH if we are using shared libraries + # -------------------------------------------------------------------------- + $ENV{'LD_LIBRARY_PATH'}= + "$glob_basedir/lib:$glob_basedir/libmysql/.libs" . + ($ENV{'LD_LIBRARY_PATH'} ? ":$ENV{'LD_LIBRARY_PATH'}" : ""); + $ENV{'DYLD_LIBRARY_PATH'}= + "$glob_basedir/lib:$glob_basedir/libmysql/.libs" . + ($ENV{'DYLD_LIBRARY_PATH'} ? ":$ENV{'DYLD_LIBRARY_PATH'}" : ""); + + # -------------------------------------------------------------------------- + # Look at the command line options and set script flags + # -------------------------------------------------------------------------- + + if ( $opt_record and ! @ARGV) + { + mtr_error("Will not run in record mode without a specific test case"); + } + + if ( $opt_embedded_server ) + { + $glob_use_embedded_server= 1; + $opt_skip_rpl= 1; # We never run replication with embedded + + if ( $opt_extern ) + { + mtr_error("Can't use --extern with --embedded-server"); + } + $opt_result_ext= ".es"; + } + + # FIXME don't understand what this is +# if ( $opt_local_master ) +# { +# $opt_master_myport= 3306; +# } + + if ( $opt_small_bench ) + { + $opt_bench= 1; + } + + if ( $opt_sleep ) + { + $opt_sleep_time_after_restart= $opt_sleep; + } + + if ( $opt_gcov and ! $opt_source_dist ) + { + mtr_error("Coverage test needs the source - please use source dist"); + } + + if ( $glob_use_embedded_server and ! $opt_source_dist ) + { + mtr_error("Embedded server needs source tree - please use source dist"); + } + + if ( $opt_gdb ) + { + $opt_wait_timeout= 300; + if ( $opt_extern ) + { + mtr_error("Can't use --extern with --gdb"); + } + } + + if ( $opt_manual_gdb ) + { + $opt_gdb= 1; + if ( $opt_extern ) + { + mtr_error("Can't use --extern with --manual-gdb"); + } + } + + if ( $opt_ddd ) + { + if ( $opt_extern ) + { + mtr_error("Can't use --extern with --ddd"); + } + } + + if ( $opt_ndbconnectstring ) + { + $glob_use_running_ndbcluster= 1; + $opt_with_ndbcluster= 1; + } + + # FIXME + + #if ( $opt_valgrind or $opt_valgrind_all ) + #{ + # VALGRIND=`which valgrind` # this will print an error if not found FIXME + # Give good warning to the user and stop + # if ( ! $VALGRIND ) + # { + # print "You need to have the 'valgrind' program in your PATH to run mysql-test-run with option --valgrind. Valgrind's home page is http://valgrind.kde.org.\n" + # exit 1 + # } + # >=2.1.2 requires the --tool option, some versions write to stdout, some to stderr + # valgrind --help 2>&1 | grep "\-\-tool" > /dev/null && VALGRIND="$VALGRIND --tool=memcheck" + # VALGRIND="$VALGRIND --alignment=8 --leak-check=yes --num-callers=16" + # $opt_extra_mysqld_opt.= " --skip-safemalloc --skip-bdb"; + # SLEEP_TIME_AFTER_RESTART=10 + # $opt_sleep_time_for_delete= 60 + # $glob_use_running_server= "" + # if ( "$1"= "--valgrind-all" ) + # { + # VALGRIND="$VALGRIND -v --show-reachable=yes" + # } + #} + + if ( $opt_user ) + { + $glob_user= $opt_user; + } + elsif ( $glob_use_running_server ) + { + $glob_user= "test"; + } + else + { + $glob_user= "root"; # We want to do FLUSH xxx commands + } + +} + + +############################################################################## +# +# Set paths to various executable programs +# +############################################################################## + +sub executable_setup () { + + if ( $opt_source_dist ) + { + if ( $glob_use_embedded_server ) + { + if ( -f "$glob_basedir/libmysqld/examples/mysqltest" ) + { + $exe_mysqltest= "$glob_basedir/libmysqld/examples/mysqltest"; + } + else + { + mtr_error("Cannot find embedded server 'mysqltest'"); + } + $path_tests_bindir= "$glob_basedir/libmysqld/examples"; + } + else + { + if ( -f "$glob_basedir/client/.libs/lt-mysqltest" ) + { + $exe_mysqltest= "$glob_basedir/client/.libs/lt-mysqltest"; + } + elsif ( -f "$glob_basedir/client/.libs/mysqltest" ) + { + $exe_mysqltest= "$glob_basedir/client/.libs/mysqltest"; + } + else + { + $exe_mysqltest= "$glob_basedir/client/mysqltest"; + } + $path_tests_bindir= "$glob_basedir/tests"; + } + if ( -f "$glob_basedir/client/.libs/mysqldump" ) + { + $exe_mysqldump= "$glob_basedir/client/.libs/mysqldump"; + } + else + { + $exe_mysqldump= "$glob_basedir/client/mysqldump"; + } + if ( -f "$glob_basedir/client/.libs/mysqlbinlog" ) + { + $exe_mysqlbinlog= "$glob_basedir/client/.libs/mysqlbinlog"; + } + else + { + $exe_mysqlbinlog= "$glob_basedir/client/mysqlbinlog"; + } + + $exe_mysqld= "$glob_basedir/sql/mysqld"; + $path_client_bindir= "$glob_basedir/client"; + $exe_mysqladmin= "$path_client_bindir/mysqladmin"; + $exe_mysql= "$path_client_bindir/mysql"; + $path_language= "$glob_basedir/sql/share/english/"; + $path_charsetsdir= "$glob_basedir/sql/share/charsets"; + } + else + { + $path_client_bindir= "$glob_basedir/bin"; + $path_tests_bindir= "$glob_basedir/tests"; + $exe_mysqltest= "$path_client_bindir/mysqltest"; + $exe_mysqldump= "$path_client_bindir/mysqldump"; + $exe_mysqlbinlog= "$path_client_bindir/mysqlbinlog"; + $exe_mysqladmin= "$path_client_bindir/mysqladmin"; + $exe_mysql= "$path_client_bindir/mysql"; + if ( -d "$glob_basedir/share/mysql/english" ) + { + $path_language ="$glob_basedir/share/mysql/english/"; + $path_charsetsdir ="$glob_basedir/share/mysql/charsets"; + } + else + { + $path_language ="$glob_basedir/share/english/"; + $path_charsetsdir ="$glob_basedir/share/charsets"; + } + + if ( -x "$glob_basedir/libexec/mysqld" ) + { + $exe_mysqld= "$glob_basedir/libexec/mysqld"; + } + else + { + $exe_mysqld= "$glob_basedir/bin/mysqld"; + } + + } + + # FIXME special $exe_master_mysqld and $exe_slave_mysqld + # are not used that much.... + + if ( ! $exe_master_mysqld ) + { + $exe_master_mysqld= $exe_mysqld; + } + + if ( ! $exe_slave_mysqld ) + { + $exe_slave_mysqld= $exe_mysqld; + } +} + + +############################################################################## +# +# If we get a ^C, we try to clean up before termination +# +############################################################################## +# FIXME check restrictions what to do in a signal handler + +sub signal_setup () { + $SIG{INT}= \&handle_int_signal; +} + +sub handle_int_signal () { + $SIG{INT}= 'DEFAULT'; # If we get a ^C again, we die... + mtr_warning("got INT signal, cleaning up....."); + stop_masters_slaves(); + mtr_error("We die from ^C signal from user"); +} + + +############################################################################## +# +# Collect information about test cases we are to run +# +############################################################################## + +sub collect_test_cases ($) { + my $suite= shift; # Test suite name + + my $testdir; + my $resdir; + + if ( $suite eq "main" ) + { + $testdir= "$glob_mysql_test_dir/t"; + $resdir= "$glob_mysql_test_dir/r"; + } + else + { + $testdir= "$glob_mysql_test_dir/suite/$suite/t"; + $resdir= "$glob_mysql_test_dir/suite/$suite/r"; + } + + my @tests; # Array of hash, will be array of C struct + + opendir(TESTDIR, $testdir) or mtr_error("Can't open dir \"$testdir\": $!"); + + foreach my $elem ( sort readdir(TESTDIR) ) { + my $tname= mtr_match_extension($elem,"test"); + next if ! defined $tname; + next if $opt_do_test and ! defined mtr_match_prefix($elem,$opt_do_test); + my $path= "$testdir/$elem"; + + # ---------------------------------------------------------------------- + # Skip some tests silently + # ---------------------------------------------------------------------- + + if ( $opt_start_from and $tname lt $opt_start_from ) + { + next; + } + + # ---------------------------------------------------------------------- + # Skip some tests but include in list, just mark them to skip + # ---------------------------------------------------------------------- + + my $tinfo= {}; + $tinfo->{'name'}= $tname; + $tinfo->{'result_file'}= "$resdir/$tname.result"; + push(@tests, $tinfo); + + if ( $opt_skip_test and defined mtr_match_prefix($tname,$opt_skip_test) ) + { + $tinfo->{'skip'}= 1; + next; + } + + # FIXME temporary solution, we have a hard coded list of test cases to + # skip if we are using the embedded server + + if ( $glob_use_embedded_server and + mtr_match_any_exact($tname,\@skip_if_embedded_server) ) + { + $tinfo->{'skip'}= 1; + next; + } + + # ---------------------------------------------------------------------- + # Collect information about test case + # ---------------------------------------------------------------------- + + $tinfo->{'path'}= $path; + + if ( defined mtr_match_prefix($tname,"rpl") ) + { + if ( $opt_skip_rpl ) + { + $tinfo->{'skip'}= 1; + next; + } + + # FIXME currently we always restart slaves + $tinfo->{'slave_restart'}= 1; + + if ( $tname eq 'rpl_failsafe' or $tname eq 'rpl_chain_temp_table' ) + { + $tinfo->{'slave_num'}= 3; + } + else + { + $tinfo->{'slave_num'}= 1; + } + } + + # FIXME what about embedded_server + ndbcluster, skip ?! + + my $master_opt_file= "$testdir/$tname-master.opt"; + my $slave_opt_file= "$testdir/$tname-slave.opt"; + my $slave_mi_file= "$testdir/$tname.slave-mi"; + my $master_sh= "$testdir/$tname-master.sh"; + my $slave_sh= "$testdir/$tname-slave.sh"; + + if ( -f $master_opt_file ) + { + $tinfo->{'master_restart'}= 1; # We think so for now + # This is a dirty hack from old mysql-test-run, we use the opt file + # to flag other things as well, it is not a opt list at all + my $extra_master_opt= mtr_get_opts_from_file($master_opt_file); + + foreach my $opt (@$extra_master_opt) + { + my $value; + + $value= mtr_match_prefix($opt, "--timezone="); + + if ( defined $value ) + { + $ENV{'TZ'}= $value; # FIXME pass this on somehow.... + $extra_master_opt= []; + $tinfo->{'master_restart'}= 0; + last; + } + + $value= mtr_match_prefix($opt, "--result-file="); + + if ( defined $value ) + { + $tinfo->{'result_file'}= "r/$value.result"; + if ( $opt_result_ext and $opt_record or + -f "$tinfo->{'result_file'}$opt_result_ext") + { + $tinfo->{'result_file'}.= $opt_result_ext; + } + $extra_master_opt= []; + $tinfo->{'master_restart'}= 0; + last; + } + } + + $tinfo->{'master_opt'}= $extra_master_opt; + } + + if ( -f $slave_opt_file ) + { + $tinfo->{'slave_opt'}= mtr_get_opts_from_file($slave_opt_file); + $tinfo->{'slave_restart'}= 1; + } + + if ( -f $slave_mi_file ) + { + $tinfo->{'slave_mi'}= mtr_get_opts_from_file($slave_mi_file); + $tinfo->{'slave_restart'}= 1; + } + + if ( -f $master_sh ) + { + if ( $glob_win32_perl ) + { + $tinfo->{'skip'}= 1; + } + else + { + $tinfo->{'master_sh'}= $master_sh; + $tinfo->{'master_restart'}= 1; + } + } + + if ( -f $slave_sh ) + { + if ( $glob_win32_perl ) + { + $tinfo->{'skip'}= 1; + } + else + { + $tinfo->{'slave_sh'}= $slave_sh; + $tinfo->{'slave_restart'}= 1; + } + } + + # We can't restart a running server that may be in use + + if ( $glob_use_running_server and + ( $tinfo->{'master_restart'} or $tinfo->{'slave_restart'} ) ) + { + $tinfo->{'skip'}= 1; + } + + } + + closedir TESTDIR; + + return \@tests; +} + + +############################################################################## +# +# Handle left overs from previous runs +# +############################################################################## + +sub kill_and_cleanup () { + + if ( $opt_fast or $glob_use_embedded_server ) + { + # FIXME is embedded server really using PID files?! + unlink($master->[0]->{'path_mypid'}); + unlink($master->[1]->{'path_mypid'}); + unlink($slave->[0]->{'path_mypid'}); + unlink($slave->[1]->{'path_mypid'}); + unlink($slave->[2]->{'path_mypid'}); + } + else + { + # Ensure that no old mysqld test servers are running + # This is different from terminating processes we have + # started from ths run of the script, this is terminating + # leftovers from previous runs. + + mtr_report("Killing Possible Leftover Processes"); + mtr_kill_leftovers(); + } + + if ( $opt_with_ndbcluster and ! $glob_use_running_ndbcluster ) + { + ndbcluster_stop(); + } + + mtr_report("Removing Stale Files"); + + rmtree("$glob_mysql_test_dir/var/log"); + rmtree("$glob_mysql_test_dir/var/ndbcluster"); + rmtree("$glob_mysql_test_dir/var/run"); + rmtree("$glob_mysql_test_dir/var/tmp"); + + mkpath("$glob_mysql_test_dir/var/log"); + mkpath("$glob_mysql_test_dir/var/ndbcluster"); + mkpath("$glob_mysql_test_dir/var/run"); + mkpath("$glob_mysql_test_dir/var/tmp"); + mkpath($opt_tmpdir); + + rmtree("$master->[0]->{'path_myddir'}"); + mkpath("$master->[0]->{'path_myddir'}/mysql"); # Need to create subdir?! + mkpath("$master->[0]->{'path_myddir'}/test"); + + rmtree("$master->[1]->{'path_myddir'}"); + mkpath("$master->[1]->{'path_myddir'}/mysql"); # Need to create subdir?! + mkpath("$master->[1]->{'path_myddir'}/test"); + + rmtree("$slave->[0]->{'path_myddir'}"); + mkpath("$slave->[0]->{'path_myddir'}/mysql"); # Need to create subdir?! + mkpath("$slave->[0]->{'path_myddir'}/test"); + + rmtree("$slave->[1]->{'path_myddir'}"); + mkpath("$slave->[1]->{'path_myddir'}/mysql"); # Need to create subdir?! + mkpath("$slave->[1]->{'path_myddir'}/test"); + + rmtree("$slave->[2]->{'path_myddir'}"); + mkpath("$slave->[2]->{'path_myddir'}/mysql"); # Need to create subdir?! + mkpath("$slave->[2]->{'path_myddir'}/test"); + + $opt_wait_for_master= $opt_sleep_time_for_first_master; + $opt_wait_for_slave= $opt_sleep_time_for_first_slave; +} + + +# FIXME + +sub sleep_until_file_created ($$) { + my $pidfile= shift; + my $timeout= shift; + + my $loop= $timeout * 2; + while ( $loop-- ) + { + if ( -r $pidfile ) + { + return; + } + mtr_debug("Sleep for 1 second waiting for creation of $pidfile"); + sleep(1); + } + + if ( ! -r $pidfile ) + { + mtr_error("No $pidfile was created"); + } +} + + +############################################################################## +# +# Start the ndb cluster +# +############################################################################## + +# FIXME why is there a different start below?! + +sub ndbcluster_start () { + + mtr_report("Starting ndbcluster"); + my $ndbcluster_opts= $opt_bench ? "" : "--small"; + # FIXME check result code?! + mtr_run("$glob_mysql_test_dir/ndb/ndbcluster", + ["--port-base=$opt_ndbcluster_port", + $ndbcluster_opts, + "--diskless", + "--initial", + "--data-dir=$glob_mysql_test_dir/var"], + "", "", "", ""); +} + +sub ndbcluster_stop () { + mtr_run("$glob_mysql_test_dir/ndb/ndbcluster", + ["--data-dir=$glob_mysql_test_dir/var", + "--port-base=$opt_ndbcluster_port", + "--stop"], + "", "", "", ""); +} + + +############################################################################## +# +# Run the benchmark suite +# +############################################################################## + +sub run_benchmarks ($) { + my $benchmark= shift; + + my $args; + + if ( ! $glob_use_embedded_server and ! $opt_local_master ) + { + $master->[0]->{'pid'}= mysqld_start('master',0,[],[]); + } + + mtr_init_args(\$args); + + mtr_add_arg($args, "--socket=%s", $master->[0]->{'path_mysock'}); + mtr_add_arg($args, "--user=root"); + + if ( $opt_small_bench ) + { + mtr_add_arg($args, "--small-test"); + mtr_add_arg($args, "--small-tables"); + } + + if ( $opt_with_ndbcluster ) + { + mtr_add_arg($args, "--create-options=TYPE=ndb"); + } + + my $benchdir= "$glob_basedir/sql-bench"; + chdir($benchdir); # FIXME check error + + # FIXME write shorter.... + + if ( ! $benchmark ) + { + mtr_add_arg($args, "--log"); + mtr_run("$glob_mysql_bench_dir/run-all-tests", $args, "", "", "", ""); + # FIXME check result code?! + } + elsif ( -x $benchmark ) + { + mtr_run("$glob_mysql_bench_dir/$benchmark", $args, "", "", "", ""); + # FIXME check result code?! + } + else + { + mtr_error("Benchmark $benchmark not found"); + } + + chdir($glob_mysql_test_dir); # Go back + + if ( ! $glob_use_embedded_server ) + { + stop_masters(); + } +} + + +############################################################################## +# +# Run the test suite +# +############################################################################## + +# FIXME how to specify several suites to run? Comma separated list? + +sub run_tests () { + run_suite($opt_suite); +} + +sub run_suite () { + my $suite= shift; + + mtr_print_thick_line(); + + mtr_report("Finding Tests in $suite suite"); + + my $tests= collect_test_cases($suite); + + mtr_report("Starting Tests in $suite suite"); + + mtr_print_header(); + + foreach my $tinfo ( @$tests ) + { + run_testcase($tinfo); + } + + mtr_print_line(); + + if ( ! $opt_gdb and ! $glob_use_running_server and + ! $opt_ddd and ! $glob_use_embedded_server ) + { + stop_masters_slaves(); + } + + if ( $opt_with_ndbcluster and ! $glob_use_running_ndbcluster ) + { + ndbcluster_stop(); + } + + if ( $opt_gcov ) + { + gcov_collect(); # collect coverage information + } + if ( $opt_gprof ) + { + gprof_collect(); # collect coverage information + } + + mtr_report_stats($tests); +} + + +############################################################################## +# +# Initiate the test databases +# +############################################################################## + +sub mysql_install_db () { + + mtr_report("Installing Test Databases"); + + install_db('master', $master->[0]->{'path_myddir'}); + install_db('slave', $slave->[0]->{'path_myddir'}); + + return 0; +} + + +sub install_db ($$) { + my $type= shift; + my $data_dir= shift; + + my $init_db_sql= "lib/init_db.sql"; # FIXME this is too simple maybe + my $args; + + mtr_report("Installing \u$type Databases"); + + mtr_init_args(\$args); + + mtr_add_arg($args, "--no-defaults"); + mtr_add_arg($args, "--bootstrap"); + mtr_add_arg($args, "--skip-grant-tables"); + mtr_add_arg($args, "--basedir=%s", $path_my_basedir); + mtr_add_arg($args, "--datadir=%s", $data_dir); + mtr_add_arg($args, "--skip-innodb"); + mtr_add_arg($args, "--skip-ndbcluster"); + mtr_add_arg($args, "--skip-bdb"); + + if ( ! $opt_netware ) + { + mtr_add_arg($args, "--language=%s", $path_language); + mtr_add_arg($args, "--character-sets-dir=%s", $path_charsetsdir); + } + + if ( mtr_run($exe_mysqld, $args, $init_db_sql, + $path_manager_log, $path_manager_log, "") != 0 ) + { + mtr_error("Error executing mysqld --bootstrap\n" . + "Could not install $type test DBs"); + } +} + + +############################################################################## +# +# Run a single test case +# +############################################################################## + +# When we get here, we have already filtered out test cases that doesn't +# apply to the current setup, for example if we use a running server, test +# cases that restart the server are dropped. So this function should mostly +# be about doing things, not a lot of logic. + +# We don't start and kill the servers for each testcase. But some +# testcases needs a restart, because they specify options to start +# mysqld with. After that testcase, we need to restart again, to set +# back the normal options. + +sub run_testcase ($) { + my $tinfo= shift; + + my $tname= $tinfo->{'name'}; + + mtr_tonewfile($opt_current_test,"$tname\n"); # Always tell where we are + + # ---------------------------------------------------------------------- + # If marked to skip, just print out and return. + # Note that a test case not marked as 'skip' can still be + # skipped later, because of the test case itself in cooperation + # with the mysqltest program tells us so. + # ---------------------------------------------------------------------- + + if ( $tinfo->{'skip'} ) + { + mtr_report_test_name($tinfo); + mtr_report_test_skipped($tinfo); + return; + } + + # ---------------------------------------------------------------------- + # If not using a running servers we may need to stop and restart. + # We restart in the case we have initiation scripts, server options + # etc to run. But we also restart again after the test first restart + # and test is run, to get back to normal server settings. + # + # To make the code a bit more clean, we actually only stop servers + # here, and mark this to be done. Then a generic "start" part will + # start up the needed servers again. + # ---------------------------------------------------------------------- + + if ( ! $glob_use_running_server and ! $glob_use_embedded_server ) + { + if ( $tinfo->{'master_restart'} or $master->[0]->{'uses_special_flags'} ) + { + stop_masters(); + $master->[0]->{'uses_special_flags'}= 0; # Forget about why we stopped + } + + # ---------------------------------------------------------------------- + # Always terminate all slaves, if any. Else we may have useless + # reconnection attempts and error messages in case the slave and + # master servers restart. + # ---------------------------------------------------------------------- + + stop_slaves(); + } + + # ---------------------------------------------------------------------- + # Prepare to start masters. Even if we use embedded, we want to run + # the preparation. + # ---------------------------------------------------------------------- + + mtr_report_test_name($tinfo); + + mtr_tofile($master->[0]->{'path_myerr'},"CURRENT_TEST: $tname\n"); + do_before_start_master($tname,$tinfo->{'master_sh'}); + + # ---------------------------------------------------------------------- + # Start masters + # ---------------------------------------------------------------------- + + if ( ! $glob_use_running_server and ! $glob_use_embedded_server ) + { + # FIXME give the args to the embedded server?! + # FIXME what does $opt_local_master mean?! + # FIXME split up start and check that started so that can do + # starts in parallel, masters and slaves at the same time. + + if ( ! $opt_local_master ) + { + if ( ! $master->[0]->{'pid'} ) + { + $master->[0]->{'pid'}= + mysqld_start('master',0,$tinfo->{'master_opt'},[]); + } + if ( $opt_with_ndbcluster and ! $master->[1]->{'pid'} ) + { + $master->[1]->{'pid'}= + mysqld_start('master',1,$tinfo->{'master_opt'},[]); + } + + if ( $tinfo->{'master_opt'} ) + { + $master->[0]->{'uses_special_flags'}= 1; + } + } + + # ---------------------------------------------------------------------- + # Start slaves - if needed + # ---------------------------------------------------------------------- + + if ( $tinfo->{'slave_num'} ) + { + mtr_tofile($slave->[0]->{'path_myerr'},"CURRENT_TEST: $tname\n"); + + do_before_start_slave($tname,$tinfo->{'slave_sh'}); + + for ( my $idx= 0; $idx < $tinfo->{'slave_num'}; $idx++ ) + { + if ( ! $slave->[$idx]->{'pid'} ) + { + $slave->[$idx]->{'pid'}= + mysqld_start('slave',$idx, + $tinfo->{'slave_opt'}, $tinfo->{'slave_mi'}); + } + } + } + } + + # ---------------------------------------------------------------------- + # Run the test case + # ---------------------------------------------------------------------- + + { + unlink("r/$tname.reject"); + unlink($path_timefile); + + my $res= run_mysqltest($tinfo, $tinfo->{'master_opt'}); + + if ( $res == 0 ) + { + mtr_report_test_passed($tinfo); + } + elsif ( $res == 2 ) + { + # Testcase itself tell us to skip this one + mtr_report_test_skipped($tinfo); + } + else + { + # Test case failed + if ( $res > 2 ) + { + mtr_tofile($path_timefile, + "mysqltest returned unexpected code $res, " . + "it has probably crashed"); + } + mtr_report_test_failed($tinfo); + mtr_show_failed_diff($tname); + print "\n"; + if ( ! $opt_force ) + { + print "Aborting: $tname failed. To continue, re-run with '--force'."; + print "\n"; + if ( ! $opt_gdb and ! $glob_use_running_server and + ! $opt_ddd and ! $glob_use_embedded_server ) + { + stop_masters_slaves(); + } + exit(1); + } + + # FIXME always terminate on failure?! + if ( ! $opt_gdb and ! $glob_use_running_server and + ! $opt_ddd and ! $glob_use_embedded_server ) + { + stop_masters_slaves(); + } + print "Resuming Tests\n\n"; + } + } +} + + +############################################################################## +# +# Start and stop servers +# +############################################################################## + +# The embedded server needs the cleanup so we do some of the start work +# but stop before actually running mysqld or anything. + +sub do_before_start_master ($$) { + my $tname= shift; + my $master_init_script= shift; + + # FIXME what about second master..... + + # Remove stale binary logs except for 2 tests which need them FIXME here???? + if ( $tname ne "rpl_crash_binlog_ib_1b" and + $tname ne "rpl_crash_binlog_ib_2b" and + $tname ne "rpl_crash_binlog_ib_3b") + { + # FIXME we really want separate dir for binlogs + `rm -fr $glob_mysql_test_dir/var/log/master-bin.*`; +# unlink("$glob_mysql_test_dir/var/log/master-bin.*"); + } + + # Remove old master.info and relay-log.info files + unlink("$glob_mysql_test_dir/var/master-data/master.info"); + unlink("$glob_mysql_test_dir/var/master-data/relay-log.info"); + unlink("$glob_mysql_test_dir/var/master1-data/master.info"); + unlink("$glob_mysql_test_dir/var/master1-data/relay-log.info"); + + #run master initialization shell script if one exists + + if ( $master_init_script and + mtr_run($master_init_script, [], "", "", "", "") != 0 ) + { + mtr_error("Can't run $master_init_script"); + } + # for gcov FIXME needed? If so we need more absolute paths +# chdir($glob_basedir); +} + +sub do_before_start_slave ($$) { + my $tname= shift; + my $slave_init_script= shift; + + # When testing fail-safe replication, we will have more than one slave + # in this case, we start secondary slaves with an argument + + # Remove stale binary logs and old master.info files + # except for too tests which need them + if ( $tname ne "rpl_crash_binlog_ib_1b" and + $tname ne "rpl_crash_binlog_ib_2b" and + $tname ne "rpl_crash_binlog_ib_3b" ) + { + # FIXME we really want separate dir for binlogs + `rm -fr $glob_mysql_test_dir/var/log/slave*-bin.*`; +# unlink("$glob_mysql_test_dir/var/log/slave*-bin.*"); # FIXME idx??? + # FIXME really master?! + unlink("$glob_mysql_test_dir/var/slave-data/master.info"); + unlink("$glob_mysql_test_dir/var/slave-data/relay-log.info"); + } + + #run slave initialization shell script if one exists + if ( $slave_init_script and + mtr_run($slave_init_script, [], "", "", "", "") != 0 ) + { + mtr_error("Can't run $slave_init_script"); + } + + unlink("$glob_mysql_test_dir/var/slave-data/log.*"); +} + +sub mysqld_arguments ($$$$$) { + my $args= shift; + my $type= shift; # master/slave/bootstrap + my $idx= shift; + my $extra_opt= shift; + my $slave_master_info= shift; + + my $sidx= ""; # Index as string, 0 is empty string + if ( $idx > 0 ) + { + $sidx= sprintf("%d", $idx); # sprintf not needed in Perl for this + } + + my $prefix= ""; # If mysqltest server arg + + if ( $glob_use_embedded_server ) + { + $prefix= "--server-arg="; + } else { + # We can't pass embedded server --no-defaults + mtr_add_arg($args, "%s--no-defaults", $prefix); + } + + mtr_add_arg($args, "%s--basedir=%s", $prefix, $path_my_basedir); + mtr_add_arg($args, "%s--character-sets-dir=%s", $prefix, $path_charsetsdir); + mtr_add_arg($args, "%s--core", $prefix); + mtr_add_arg($args, "%s--default-character-set=latin1", $prefix); + mtr_add_arg($args, "%s--language=%s", $prefix, $path_language); + mtr_add_arg($args, "%s--tmpdir=$opt_tmpdir", $prefix); + + if ( $opt_valgrind ) + { + mtr_add_arg($args, "%s--skip-safemalloc", $prefix); + mtr_add_arg($args, "%s--skip-bdb", $prefix); + } + + my $pidfile; + + if ( $type eq 'master' ) + { + mtr_add_arg($args, "%s--log-bin=%s/var/log/master-bin", $prefix, + $glob_mysql_test_dir); + mtr_add_arg($args, "%s--pid-file=%s", $prefix, + $master->[$idx]->{'path_mypid'}); + mtr_add_arg($args, "%s--port=%d", $prefix, + $master->[$idx]->{'path_myport'}); + mtr_add_arg($args, "%s--server-id=1", $prefix); + mtr_add_arg($args, "%s--socket=%s", $prefix, + $master->[$idx]->{'path_mysock'}); + mtr_add_arg($args, "%s--innodb_data_file_path=ibdata1:50M", $prefix); + mtr_add_arg($args, "%s--local-infile", $prefix); + mtr_add_arg($args, "%s--datadir=%s", $prefix, + $master->[$idx]->{'path_myddir'}); + } + + if ( $type eq 'slave' ) + { + my $slave_server_id= 2 + $idx; + my $slave_rpl_rank= $idx > 0 ? 2 : $slave_server_id; + + mtr_add_arg($args, "%s--datadir=%s", $prefix, + $slave->[$idx]->{'path_myddir'}); + mtr_add_arg($args, "%s--exit-info=256", $prefix); + mtr_add_arg($args, "%s--init-rpl-role=slave", $prefix); + mtr_add_arg($args, "%s--log-bin=%s/var/log/slave%s-bin", $prefix, + $glob_mysql_test_dir, $sidx); # FIXME use own dir for binlogs + mtr_add_arg($args, "%s--log-slave-updates", $prefix); + mtr_add_arg($args, "%s--log=%s", $prefix, + $slave->[$idx]->{'path_myerr'}); + mtr_add_arg($args, "%s--master-retry-count=10", $prefix); + mtr_add_arg($args, "%s--pid-file=%s", $prefix, + $slave->[$idx]->{'path_mypid'}); + mtr_add_arg($args, "%s--port=%d", $prefix, + $slave->[$idx]->{'path_myport'}); + mtr_add_arg($args, "%s--relay-log=%s/var/log/slave%s-relay-bin", $prefix, + $glob_mysql_test_dir, $sidx); + mtr_add_arg($args, "%s--report-host=127.0.0.1", $prefix); + mtr_add_arg($args, "%s--report-port=%d", $prefix, + $slave->[$idx]->{'path_myport'}); + mtr_add_arg($args, "%s--report-user=root", $prefix); + mtr_add_arg($args, "%s--skip-innodb", $prefix); + mtr_add_arg($args, "%s--skip-ndbcluster", $prefix); + mtr_add_arg($args, "%s--skip-slave-start", $prefix); + mtr_add_arg($args, "%s--slave-load-tmpdir=%s", $prefix, + $path_slave_load_tmpdir); + mtr_add_arg($args, "%s--socket=%s", $prefix, + $slave->[$idx]->{'path_mysock'}); + mtr_add_arg($args, "%s--set-variable=slave_net_timeout=10", $prefix); + + if ( @$slave_master_info ) + { + foreach my $arg ( @$slave_master_info ) + { + mtr_add_arg($args, "%s%s", $prefix, $arg); + } + } + else + { + mtr_add_arg($args, "%s--master-user=root", $prefix); + mtr_add_arg($args, "%s--master-connect-retry=1", $prefix); + mtr_add_arg($args, "%s--master-host=127.0.0.1", $prefix); + mtr_add_arg($args, "%s--master-password=", $prefix); + mtr_add_arg($args, "%s--master-port=%d", $prefix, + $master->[0]->{'path_myport'}); # First master + mtr_add_arg($args, "%s--server-id=%d", $prefix, $slave_server_id); + mtr_add_arg($args, "%s--rpl-recovery-rank=%d", $prefix, $slave_rpl_rank); + } + } # end slave + + if ( $opt_debug ) + { + if ( $type eq 'master' ) + { + mtr_add_arg($args, "--debug=d:t:i:A,%s/var/log/master%s.trace", + $prefix, $glob_mysql_test_dir, $sidx); + } + if ( $type eq 'slave' ) + { + mtr_add_arg($args, "--debug=d:t:i:A,%s/var/log/slave%s.trace", + $prefix, $glob_mysql_test_dir, $sidx); + } + } + + if ( $opt_with_ndbcluster ) + { + mtr_add_arg($args, "%s--ndbcluster", $prefix); + + if ( $glob_use_running_ndbcluster ) + { + mtr_add_arg($args,"--ndb-connectstring=%s", $prefix, + $opt_ndbconnectstring); + } + else + { + mtr_add_arg($args,"--ndb-connectstring=host=localhost:%d", + $prefix, $opt_ndbcluster_port); + } + } + + # FIXME always set nowdays??? SMALL_SERVER + mtr_add_arg($args, "%s--key_buffer_size=1M", $prefix); + mtr_add_arg($args, "%s--sort_buffer=256K", $prefix); + mtr_add_arg($args, "%s--max_heap_table_size=1M", $prefix); + + if ( $opt_with_openssl ) + { + mtr_add_arg($args, "%s--ssl-ca=%s/SSL/cacert.pem", $prefix, $glob_basedir); + mtr_add_arg($args, "%s--ssl-cert=%s/SSL/server-cert.pem", $prefix, + $glob_basedir); + mtr_add_arg($args, "%s--ssl-key=%s/SSL/server-key.pem", $prefix, + $glob_basedir); + } + + if ( $opt_warnings ) + { + mtr_add_arg($args, "%s--log-warnings", $prefix); + } + + if ( $opt_gdb or $opt_client_gdb or $opt_manual_gdb or $opt_ddd) + { + mtr_add_arg($args, "%s--gdb", $prefix); + } + + # If we should run all tests cases, we will use a local server for that + + if ( -w "/" ) + { + # We are running as root; We need to add the --root argument + mtr_add_arg($args, "%s--user=root", $prefix); + } + + if ( $type eq 'master' ) + { + + if ( ! $opt_old_master ) + { + mtr_add_arg($args, "%s--rpl-recovery-rank=1", $prefix); + mtr_add_arg($args, "%s--init-rpl-role=master", $prefix); + } + + # FIXME strange,..... + if ( $opt_local_master ) + { + mtr_add_arg($args, "%s--host=127.0.0.1", $prefix); + mtr_add_arg($args, "%s--port=%s", $prefix, $ENV{'MYSQL_MYPORT'}); + } + } + + foreach my $arg ( @$extra_opt ) + { + mtr_add_arg($args, "%s%s", $prefix, $arg); + } + + if ( $opt_bench ) + { + mtr_add_arg($args, "%s--rpl-recovery-rank=1", $prefix); + mtr_add_arg($args, "%s--init-rpl-role=master", $prefix); + } + else + { + mtr_add_arg($args, "%s--exit-info=256", $prefix); + mtr_add_arg($args, "%s--open-files-limit=1024", $prefix); + + if ( $type eq 'master' ) + { + mtr_add_arg($args, "%s--log=%s", $prefix, $master->[0]->{'path_mylog'}); + } + if ( $type eq 'slave' ) + { + mtr_add_arg($args, "%s--log=%s", $prefix, $slave->[0]->{'path_mylog'}); + } + } + + return $args; +} + +# FIXME +# if ( $type eq 'master' and $glob_use_embedded_server ) +# { +# # Add a -A to each argument to pass it to embedded server +# my @mysqltest_opt= map {("-A",$_)} @args; +# $opt_extra_mysqltest_opt= \@mysqltest_opt; +# return; +# } + +############################################################################## +# +# Start mysqld and return the PID +# +############################################################################## + +sub mysqld_start ($$$$) { + my $type= shift; # master/slave/bootstrap + my $idx= shift; + my $extra_opt= shift; + my $slave_master_info= shift; + + my $args; # Arg vector + my $exe; + my $pid; + + # FIXME code duplication, make up your mind.... + if ( $opt_source_dist ) + { + $exe= "$glob_basedir/sql/mysqld"; + } + else + { + $exe ="$glob_basedir/libexec/mysqld"; + if ( ! -x $exe ) + { + $exe ="$glob_basedir/bin/mysqld"; + } + } + + mtr_init_args(\$args); + + if ( $opt_valgrind ) + { + + mtr_add_arg($args, "--tool=memcheck"); + mtr_add_arg($args, "--alignment=8"); + mtr_add_arg($args, "--leak-check=yes"); + mtr_add_arg($args, "--num-callers=16"); + + if ( $opt_valgrind_all ) + { + mtr_add_arg($args, "-v"); + mtr_add_arg($args, "--show-reachable=yes"); + } + + if ( $opt_valgrind_options ) + { + # FIXME split earlier and put into @glob_valgrind_* + mtr_add_arg($args, split(' ', $opt_valgrind_options)); + } + + mtr_add_arg($args, $exe); + + $exe= $opt_valgrind; + } + + mysqld_arguments($args,$type,$idx,$extra_opt,$slave_master_info); + + if ( $type eq 'master' ) + { + if ( $pid= mtr_spawn($exe, $args, "", + $master->[$idx]->{'path_myerr'}, + $master->[$idx]->{'path_myerr'}, "") ) + { + sleep_until_file_created($master->[$idx]->{'path_mypid'}, + $opt_wait_for_master); + $opt_wait_for_master= $opt_sleep_time_for_second_master; + return $pid; + } + } + + if ( $type eq 'slave' ) + { + if ( $pid= mtr_spawn($exe, $args, "", + $slave->[$idx]->{'path_myerr'}, + $slave->[$idx]->{'path_myerr'}, "") ) + { + sleep_until_file_created($slave->[$idx]->{'path_mypid'}, + $opt_wait_for_slave); + $opt_wait_for_slave= $opt_sleep_time_for_second_slave; + return $pid; + } + } + + mtr_error("Can't start mysqld FIXME"); +} + +sub stop_masters_slaves () { + + print "Ending Tests\n"; + print "Shutting-down MySQL daemon\n\n"; + stop_masters(); + print "Master(s) shutdown finished\n"; + stop_slaves(); + print "Slave(s) shutdown finished\n"; +} + +sub stop_masters () { + + my @args; + + for ( my $idx; $idx < 2; $idx++ ) + { + # FIXME if we hit ^C before fully started, this test will prevent + # the mysqld process from being killed + if ( $master->[$idx]->{'pid'} ) + { + push(@args,{ + pid => $master->[$idx]->{'pid'}, + pidfile => $master->[$idx]->{'path_mypid'}, + sockfile => $master->[$idx]->{'path_mysock'}, + port => $master->[$idx]->{'path_myport'}, + }); + $master->[$idx]->{'pid'}= 0; # Assume we are done with it + } + } + + mtr_stop_mysqld_servers(\@args, 0); +} + +sub stop_slaves () { + my $force= shift; + + my @args; + + for ( my $idx; $idx < 3; $idx++ ) + { + if ( $slave->[$idx]->{'pid'} ) + { + push(@args,{ + pid => $slave->[$idx]->{'pid'}, + pidfile => $slave->[$idx]->{'path_mypid'}, + sockfile => $slave->[$idx]->{'path_mysock'}, + port => $slave->[$idx]->{'path_myport'}, + }); + $slave->[$idx]->{'pid'}= 0; # Assume we are done with it + } + } + + mtr_stop_mysqld_servers(\@args, 0); +} + + +sub run_mysqltest ($$) { + my $tinfo= shift; + my $master_opts= shift; + + # FIXME set where???? + my $cmdline_mysqldump= "$exe_mysqldump --no-defaults -uroot " . + "--socket=$master->[0]->{'path_mysock'} --password="; + if ( $opt_debug ) + { + $cmdline_mysqldump .= + " --debug=d:t:A,$glob_mysql_test_dir/var/log/mysqldump.trace"; + } + + my $cmdline_mysqlbinlog= + "$exe_mysqlbinlog --no-defaults --local-load=$opt_tmpdir"; + + if ( $opt_debug ) + { + $cmdline_mysqlbinlog .= + " --debug=d:t:A,$glob_mysql_test_dir/var/log/mysqlbinlog.trace"; + } + + my $cmdline_mysql= + "$exe_mysql --host=localhost --port=$master->[0]->{'path_myport'} " . + "--socket=$master->[0]->{'path_mysock'} --user=root --password="; + + $ENV{'MYSQL'}= $exe_mysql; + $ENV{'MYSQL_DUMP'}= $cmdline_mysqldump; + $ENV{'MYSQL_BINLOG'}= $exe_mysqlbinlog; + $ENV{'CLIENT_BINDIR'}= $path_client_bindir; + $ENV{'TESTS_BINDIR'}= $path_tests_bindir; + + my $exe= $exe_mysqltest; + my $args; + + mtr_init_args(\$args); + + mtr_add_arg($args, "--no-defaults"); + mtr_add_arg($args, "--socket=%s", $master->[0]->{'path_mysock'}); + mtr_add_arg($args, "--database=test"); + mtr_add_arg($args, "--user=%s", $glob_user); + mtr_add_arg($args, "--password="); + mtr_add_arg($args, "--silent"); + mtr_add_arg($args, "-v"); + mtr_add_arg($args, "--skip-safemalloc"); + mtr_add_arg($args, "--tmpdir=%s", $opt_tmpdir); + mtr_add_arg($args, "--port=%d", $master->[0]->{'path_myport'}); + + if ( $opt_ps_protocol ) + { + mtr_add_arg($args, "--ps-protocol"); + } + + if ( $opt_strace_client ) + { + $exe= "strace"; # FIXME there are ktrace, .... + mtr_add_arg($args, "-o"); + mtr_add_arg($args, "%s/var/log/mysqltest.strace", $glob_mysql_test_dir); + mtr_add_arg($args, "$exe_mysqltest"); + } + + if ( $opt_timer ) + { + mtr_add_arg($args, "--timer-file=var/log/timer"); + } + + if ( $opt_big_test ) + { + mtr_add_arg($args, "--big-test"); + } + + if ( $opt_record ) + { + mtr_add_arg($args, "--record"); + } + + if ( $opt_compress ) + { + mtr_add_arg($args, "--compress"); + } + + if ( $opt_sleep ) + { + mtr_add_arg($args, "--sleep=%d", $opt_sleep); + } + + if ( $opt_debug ) + { + mtr_add_arg($args, "--debug=d:t:A,%s/var/log/mysqltest.trace", + $glob_mysql_test_dir); + } + + if ( $opt_with_openssl ) + { + mtr_add_arg($args, "--ssl-ca=%s/SSL/cacert.pem", $glob_basedir); + mtr_add_arg($args, "--ssl-cert=%s/SSL/client-cert.pem", $glob_basedir); + mtr_add_arg($args, "--ssl-key=%s/SSL/client-key.pem", $glob_basedir); + } + + mtr_add_arg($args, "-R"); + mtr_add_arg($args, $tinfo->{'result_file'}); + + # ---------------------------------------------------------------------- + # If embedded server, we create server args to give mysqltest to pass on + # ---------------------------------------------------------------------- + + if ( $glob_use_embedded_server ) + { + mysqld_arguments($args,'master',0,$tinfo->{'master_opt'},[]); + } + + return mtr_run($exe_mysqltest,$args,$tinfo->{'path'},"",$path_timefile,""); +} + +############################################################################## +# +# Usage +# +############################################################################## + +sub usage ($) +{ + print STDERR < 0; +--enable_ps_protocol + # ANSI requires: 3 rows # MySQL returns: 0 rows - because of GROUP BY name resolution diff --git a/mysql-test/t/insert_select.test b/mysql-test/t/insert_select.test index e1459310bb9..15509b06679 100644 --- a/mysql-test/t/insert_select.test +++ b/mysql-test/t/insert_select.test @@ -136,9 +136,7 @@ insert into t2 values (2,"t2:2"), (3,"t2:3"); insert into t1 select * from t2; select * from t1; # REPLACE .. SELECT is not yet supported by PS ---disable_ps_protocol replace into t1 select * from t2; ---enable_ps_protocol select * from t1; drop table t1,t2; diff --git a/mysql-test/t/multi_update.test b/mysql-test/t/multi_update.test index de66218c4a6..f3b6216e3cf 100644 --- a/mysql-test/t/multi_update.test +++ b/mysql-test/t/multi_update.test @@ -6,9 +6,9 @@ drop table if exists t1,t2,t3; drop database if exists mysqltest; drop view if exists v1; ---error 0,1141 +--error 0,1141,1147 revoke all privileges on mysqltest.t1 from mysqltest_1@localhost; ---error 0,1141 +--error 0,1141,1147 revoke all privileges on mysqltest.* from mysqltest_1@localhost; delete from mysql.user where user=_binary'mysqltest_1'; --enable_warnings @@ -452,11 +452,8 @@ drop table t1, t2; # # Test for bug #1980. # -set @ttype_save=@@storage_engine; - --disable_warnings -set @@storage_engine=innodb; -create table t1 ( c char(8) not null ); +create table t1 ( c char(8) not null ) engine=innodb; --enable_warnings insert into t1 values ('0'),('1'),('2'),('3'),('4'),('5'),('6'),('7'),('8'),('9'); @@ -475,8 +472,7 @@ delete t1,t2 from t2,t1 where t1.a<'B' and t2.b=t1.b; drop table t1,t2; --disable_warnings -set @@storage_engine=bdb; -create table t1 ( c char(8) not null ); +create table t1 ( c char(8) not null ) engine=bdb; --enable_warnings insert into t1 values ('0'),('1'),('2'),('3'),('4'),('5'),('6'),('7'),('8'),('9'); @@ -492,7 +488,6 @@ insert into t2 select * from t1; delete t1,t2 from t2,t1 where t1.a<'B' and t2.b=t1.b; -set @@storage_engine=@ttype_save; drop table t1,t2; create table t1 (a int, b int); diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index 85a5f6d0ee1..47b115cf030 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -1789,7 +1789,10 @@ CREATE TABLE t1 (gvid int(10) unsigned default NULL, hmid int(10) unsigned defa INSERT INTO t1 VALUES (200001,2,1,1,100,1,1,1,0,0,0,1,0,1,20020425060057,'\\\\ARKIVIO-TESTPDC\\E$',''),(200002,2,2,1,101,1,1,1,0,0,0,1,0,1,20020425060057,'\\\\ARKIVIO-TESTPDC\\C$',''),(200003,1,3,2,NULL,NULL,NULL,NULL,NULL,NULL,NULL,1,0,1,20020425060427,'c:',NULL); CREATE TABLE t2 ( hmid int(10) unsigned default NULL, volid int(10) unsigned default NULL, sampletid smallint(5) unsigned default NULL, sampletime datetime default NULL, samplevalue bigint(20) unsigned default NULL, KEY idx1 (hmid,volid,sampletid,sampletime)) ENGINE=MyISAM; INSERT INTO t2 VALUES (1,3,10,'2002-06-01 08:00:00',35),(1,3,1010,'2002-06-01 12:00:01',35); +# Disable PS becasue we get more warnings from PS than from normal execution +--disable_ps_protocol SELECT a.gvid, (SUM(CASE b.sampletid WHEN 140 THEN b.samplevalue ELSE 0 END)) as the_success,(SUM(CASE b.sampletid WHEN 141 THEN b.samplevalue ELSE 0 END)) as the_fail,(SUM(CASE b.sampletid WHEN 142 THEN b.samplevalue ELSE 0 END)) as the_size,(SUM(CASE b.sampletid WHEN 143 THEN b.samplevalue ELSE 0 END)) as the_time FROM t1 a, t2 b WHERE a.hmid = b.hmid AND a.volid = b.volid AND b.sampletime >= 'wrong-date-value' AND b.sampletime < 'wrong-date-value' AND b.sampletid IN (140, 141, 142, 143) GROUP BY a.gvid; +--enable_ps_protocol # Testing the same select with NULL's instead of invalid datetime values SELECT a.gvid, (SUM(CASE b.sampletid WHEN 140 THEN b.samplevalue ELSE 0 END)) as the_success,(SUM(CASE b.sampletid WHEN 141 THEN b.samplevalue ELSE 0 END)) as the_fail,(SUM(CASE b.sampletid WHEN 142 THEN b.samplevalue ELSE 0 END)) as the_size,(SUM(CASE b.sampletid WHEN 143 THEN b.samplevalue ELSE 0 END)) as the_time FROM t1 a, t2 b WHERE a.hmid = b.hmid AND a.volid = b.volid AND b.sampletime >= NULL AND b.sampletime < NULL AND b.sampletid IN (140, 141, 142, 143) GROUP BY a.gvid; DROP TABLE t1,t2; diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 5f912622101..4f556e34d51 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -944,7 +944,7 @@ select fun(2.3, 3, 5)| insert into t2 values (append("xxx", "yyy"), mul(4,3), e())| insert into t2 values (append("a", "b"), mul(2,mul(3,4)), fun(1.7, 4, 6))| -# These don't work yet. +# Disable PS because double's give a bit different values --disable_ps_protocol select * from t2 where s = append("a", "b")| select * from t2 where i = mul(4,3) or i = mul(mul(3,4),2)| diff --git a/mysql-test/t/system_mysql_db_fix.test b/mysql-test/t/system_mysql_db_fix.test index 56f291ae69d..2cefa167466 100644 --- a/mysql-test/t/system_mysql_db_fix.test +++ b/mysql-test/t/system_mysql_db_fix.test @@ -1,6 +1,14 @@ # # This is the test for mysql_fix_privilege_tables # +# Note: If this test fails, don't be confused about the errors reported +# by mysql-test-run; This shows warnings from generated by +# mysql_fix_system_tables which should be ignored. +# Instead, concentrate on the errors in r/system_mysql_db.reject + +--disable_warnings +drop table if exists t1,t1aa,t2aa; +--enable_warnings -- disable_result_log -- disable_query_log diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test index 3900e59c2ee..bf75f09d553 100644 --- a/mysql-test/t/trigger.test +++ b/mysql-test/t/trigger.test @@ -53,6 +53,7 @@ select @a; drop trigger t1.trg; drop table t1; +# PS doesn't work with multi-row statements --disable_ps_protocol # Before update trigger # (In future we will achieve this via proper error handling in triggers) diff --git a/mysql-test/t/type_blob.test b/mysql-test/t/type_blob.test index 085cad8cffa..20a501bb5ed 100644 --- a/mysql-test/t/type_blob.test +++ b/mysql-test/t/type_blob.test @@ -17,10 +17,8 @@ drop table if exists t1,t2,t3,t4,t5,t6,t7; CREATE TABLE t1 (a blob, b text, c blob(250), d text(70000), e text(70000000)); show columns from t1; # PS doesn't give errors on prepare yet ---disable_ps_protocol CREATE TABLE t2 (a char(255), b varbinary(70000), c varchar(70000000)); CREATE TABLE t4 (c varchar(65530) character set utf8 not null); ---enable_ps_protocol show columns from t2; create table t3 (a long, b long byte); show create TABLE t3; diff --git a/mysql-test/t/type_datetime.test b/mysql-test/t/type_datetime.test index 04e4a73554a..a7eb78cb292 100644 --- a/mysql-test/t/type_datetime.test +++ b/mysql-test/t/type_datetime.test @@ -89,3 +89,15 @@ delete from t1; insert into t1 values ("0000-00-00 00:00:00 some trailer"),("2003-01-01 00:00:00 some trailer"); select * from t1; drop table t1; + +# +# Test for bug #7297 "Two digit year should be interpreted correctly even +# with zero month and day" +# +create table t1 (dt datetime); +# These dates should be treated as dates in 21st century +insert into t1 values ("12-00-00"), ("00-00-00 01:00:00"); +# Zero dates are still special :/ +insert into t1 values ("00-00-00"), ("00-00-00 00:00:00"); +select * from t1; +drop table t1; diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test index 468a88b83db..58e4c22e168 100644 --- a/mysql-test/t/union.test +++ b/mysql-test/t/union.test @@ -5,9 +5,6 @@ --disable_warnings drop table if exists t1,t2,t3,t4,t5,t6; --enable_warnings -# PS doesn't work correctly with found_rows: to be fixed ---disable_ps_protocol - CREATE TABLE t1 (a int not null, b char (10) not null); insert into t1 values(1,'a'),(2,'b'),(3,'c'),(3,'c'); @@ -30,9 +27,12 @@ select 't1',b,count(*) from t1 group by b UNION select 't2',b,count(*) from t2 g (select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1) order by t1.b; explain extended (select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1) order by b desc; (select sql_calc_found_rows a,b from t1 limit 2) union all (select a,b from t2 order by a) limit 2; +# PS doesn't work correctly with found_rows: to be fixed +--disable_ps_protocol select found_rows(); select sql_calc_found_rows a,b from t1 union all select a,b from t2 limit 2; select found_rows(); +--enable_ps_protocol # # Test some error conditions with UNION @@ -210,15 +210,27 @@ insert into t2 values (3),(4),(5); # Test global limits (SELECT SQL_CALC_FOUND_ROWS * FROM t1) UNION all (SELECT * FROM t2) LIMIT 1; +# PS doesn't work correctly with found_rows: to be fixed +--disable_ps_protocol select found_rows(); +--enable_ps_protocol (SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1) UNION all (SELECT * FROM t2) LIMIT 2; +# PS doesn't work correctly with found_rows: to be fixed +--disable_ps_protocol select found_rows(); +--enable_ps_protocol # Test cases where found_rows() should return number of returned rows (SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1) UNION all (SELECT * FROM t2); +# PS doesn't work correctly with found_rows: to be fixed +--disable_ps_protocol select found_rows(); +--enable_ps_protocol (SELECT SQL_CALC_FOUND_ROWS * FROM t1) UNION all (SELECT * FROM t2 LIMIT 1); +# PS doesn't work correctly with found_rows: to be fixed +--disable_ps_protocol select found_rows(); +--enable_ps_protocol # This used to work in 4.0 but not anymore in 4.1 --error 1064 (SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1) UNION SELECT * FROM t2 LIMIT 1; @@ -226,9 +238,15 @@ select found_rows(); # In these case found_rows() should work SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1 UNION all SELECT * FROM t2 LIMIT 2; +# PS doesn't work correctly with found_rows: to be fixed +--disable_ps_protocol select found_rows(); +--disable_ps_protocol SELECT SQL_CALC_FOUND_ROWS * FROM t1 UNION all SELECT * FROM t2 LIMIT 2; +# PS doesn't work correctly with found_rows: to be fixed +--disable_ps_protocol select found_rows(); +--disable_ps_protocol # The following examples will not be exact SELECT SQL_CALC_FOUND_ROWS * FROM t1 UNION SELECT * FROM t2 LIMIT 2; diff --git a/mysql-test/t/user_limits.test b/mysql-test/t/user_limits.test index 8c6d5453789..50c16e5e114 100644 --- a/mysql-test/t/user_limits.test +++ b/mysql-test/t/user_limits.test @@ -14,6 +14,9 @@ delete from mysql.tables_priv where user like 'mysqltest\_%'; delete from mysql.columns_priv where user like 'mysqltest\_%'; flush privileges; +# Limits doesn't work with prepared statements (yet) +--disable_ps_protocol + # Test of MAX_QUERIES_PER_HOUR limit grant usage on *.* to mysqltest_1@localhost with max_queries_per_hour 2; connect (mqph, localhost, mysqltest_1,,); @@ -149,6 +152,7 @@ disconnect muca2; disconnect muca3; set global max_user_connections= 0; drop user mysqltest_1@localhost; +--enable_ps_protocol # Final cleanup drop table t1; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 6dc49b28426..2aabbe20657 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -1394,7 +1394,6 @@ create view v1 as select * from t1 where a < 2 with check option; insert into v1 values (1) on duplicate key update a=2; -- error 1369 insert into v1 values (1) on duplicate key update a=2; --- error 1369 insert ignore into v1 values (1) on duplicate key update a=2; select * from t1; drop view v1; diff --git a/mysql-test/t/warnings.test b/mysql-test/t/warnings.test index 4bd659606f6..67162e7f84b 100644 --- a/mysql-test/t/warnings.test +++ b/mysql-test/t/warnings.test @@ -26,9 +26,8 @@ show warnings limit 1; drop database if exists not_exists_db; show count(*) warnings; create table t1(id int); -# PS doesn't give warnings on prepare ---disable_ps_protocol create table if not exists t1(id int); +--disable_ps_protocol select @@warning_count; --enable_ps_protocol drop table t1; @@ -96,12 +95,9 @@ drop table t1; # Test for deprecated TYPE= syntax # -# PS doesn't give warnings on prepare ---disable_ps_protocol create table t1 (id int) type=heap; alter table t1 type=myisam; drop table t1; ---enable_ps_protocol # # Test for deprecated table_type variable diff --git a/ndb/include/Makefile.am b/ndb/include/Makefile.am index aa03ef37e3c..1b298a09e26 100644 --- a/ndb/include/Makefile.am +++ b/ndb/include/Makefile.am @@ -44,3 +44,6 @@ dist-hook: -rm -rf `find $(distdir) -type d -name SCCS` windoze-dsp: + +# Don't update the files from bitkeeper +%::SCCS/s.% diff --git a/sql-common/my_time.c b/sql-common/my_time.c index 45adb657f73..1078259f15d 100644 --- a/sql-common/my_time.c +++ b/sql-common/my_time.c @@ -382,8 +382,7 @@ str_to_datetime(const char *str, uint length, MYSQL_TIME *l_time, } l_time->neg= 0; - if (year_length == 2 && i >= format_position[1] && i >=format_position[2] && - (l_time->month || l_time->day)) + if (year_length == 2 && not_zero_date) l_time->year+= (l_time->year < YY_PART_YEAR ? 2000 : 1900); if (!not_zero_date && (flags & TIME_NO_ZERO_DATE)) @@ -911,14 +910,14 @@ longlong number_to_datetime(longlong nr, MYSQL_TIME *time_res, goto err; if (nr <= (YY_PART_YEAR-1)*10000L+1231L) { - nr= (nr+20000000L)*1000000L; // YYMMDD, year: 2000-2069 + nr= (nr+20000000L)*1000000L; /* YYMMDD, year: 2000-2069 */ goto ok; } if (nr < (YY_PART_YEAR)*10000L+101L) goto err; if (nr <= 991231L) { - nr= (nr+19000000L)*1000000L; // YYMMDD, year: 1970-1999 + nr= (nr+19000000L)*1000000L; /* YYMMDD, year: 1970-1999 */ goto ok; } if (nr < 10000101L) @@ -932,13 +931,13 @@ longlong number_to_datetime(longlong nr, MYSQL_TIME *time_res, goto err; if (nr <= (YY_PART_YEAR-1)*LL(10000000000)+LL(1231235959)) { - nr= nr+LL(20000000000000); // YYMMDDHHMMSS, 2000-2069 + nr= nr+LL(20000000000000); /* YYMMDDHHMMSS, 2000-2069 */ goto ok; } if (nr < YY_PART_YEAR*LL(10000000000)+ LL(101000000)) goto err; if (nr <= LL(991231235959)) - nr= nr+LL(19000000000000); // YYMMDDHHMMSS, 1970-1999 + nr= nr+LL(19000000000000); /* YYMMDDHHMMSS, 1970-1999 */ ok: part1=(long) (nr/LL(1000000)); diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 37b3e6cfa00..1526d94a9a6 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -2375,6 +2375,7 @@ void ha_ndbcluster::print_results() break; } case NdbDictionary::Column::Undefined: + case NdbDictionary::Column::Bit: my_snprintf(buf, sizeof(buf), "Unknown type: %d", col->getType()); break; } @@ -2782,7 +2783,7 @@ void ha_ndbcluster::info(uint flag) if ((my_errno= check_ndb_connection())) DBUG_VOID_RETURN; Ndb *ndb= get_ndb(); - Uint64 rows; + Uint64 rows= 100; if (current_thd->variables.ndb_use_exact_count) ndb_get_table_statistics(ndb, m_tabname, &rows, 0); records= rows; diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 27c000138d8..2d0e5d7632f 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -1603,6 +1603,7 @@ void Item_func_from_unixtime::fix_length_and_dec() collation.set(&my_charset_bin); decimals=0; max_length=MAX_DATETIME_WIDTH*MY_CHARSET_BIN_MB_MAXLEN; + maybe_null= 1; thd->time_zone_used= 1; } @@ -1642,11 +1643,12 @@ longlong Item_func_from_unixtime::val_int() bool Item_func_from_unixtime::get_date(TIME *ltime, uint fuzzy_date __attribute__((unused))) { - longlong tmp= args[0]->val_int(); - - if ((null_value= (args[0]->null_value || - tmp < TIMESTAMP_MIN_VALUE || - tmp > TIMESTAMP_MAX_VALUE))) + ulonglong tmp= (ulonglong)(args[0]->val_int()); + /* + "tmp > TIMESTAMP_MAX_VALUE" check also covers case of negative + from_unixtime() argument since tmp is unsigned. + */ + if ((null_value= (args[0]->null_value || tmp > TIMESTAMP_MAX_VALUE))) return 1; thd->variables.time_zone->gmt_sec_to_TIME(ltime, (my_time_t)tmp); @@ -2202,6 +2204,12 @@ String *Item_datetime_typecast::val_str(String *str) bool Item_time_typecast::get_time(TIME *ltime) { bool res= get_arg0_time(ltime); + /* + For MYSQL_TIMESTAMP_TIME value we can have non-zero day part, + which we should not lose. + */ + if (ltime->time_type == MYSQL_TIMESTAMP_DATETIME) + ltime->year= ltime->month= ltime->day= 0; ltime->time_type= MYSQL_TIMESTAMP_TIME; return res; } @@ -2225,6 +2233,7 @@ String *Item_time_typecast::val_str(String *str) bool Item_date_typecast::get_date(TIME *ltime, uint fuzzy_date) { bool res= get_arg0_date(ltime, TIME_FUZZY_DATE); + ltime->hour= ltime->minute= ltime->second= ltime->second_part= 0; ltime->time_type= MYSQL_TIMESTAMP_DATE; return res; } diff --git a/sql/log_event.cc b/sql/log_event.cc index 581d3ef0d21..adebf446a82 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -2128,7 +2128,7 @@ Load_log_event::Load_log_event(THD *thd_arg, sql_exchange *ex, const char *db_arg, const char *table_name_arg, List &fields_arg, enum enum_duplicates handle_dup, - bool using_trans) + bool ignore, bool using_trans) :Log_event(thd_arg, !thd_arg->tmp_table_used ? 0 : LOG_EVENT_THREAD_SPECIFIC_F, using_trans), thread_id(thd_arg->thread_id), @@ -2166,9 +2166,6 @@ Load_log_event::Load_log_event(THD *thd_arg, sql_exchange *ex, sql_ex.empty_flags= 0; switch (handle_dup) { - case DUP_IGNORE: - sql_ex.opt_flags|= IGNORE_FLAG; - break; case DUP_REPLACE: sql_ex.opt_flags|= REPLACE_FLAG; break; @@ -2176,6 +2173,8 @@ Load_log_event::Load_log_event(THD *thd_arg, sql_exchange *ex, case DUP_ERROR: break; } + if (ignore) + sql_ex.opt_flags|= IGNORE_FLAG; if (!ex->field_term->length()) sql_ex.empty_flags |= FIELD_TERM_EMPTY; @@ -2511,6 +2510,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, { char llbuff[22]; enum enum_duplicates handle_dup; + bool ignore= 0; /* Make a simplified LOAD DATA INFILE query, for the information of the user in SHOW PROCESSLIST. Note that db is known in the 'db' column. @@ -2527,21 +2527,24 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, if (sql_ex.opt_flags & REPLACE_FLAG) handle_dup= DUP_REPLACE; else if (sql_ex.opt_flags & IGNORE_FLAG) - handle_dup= DUP_IGNORE; + { + ignore= 1; + handle_dup= DUP_ERROR; + } else { /* When replication is running fine, if it was DUP_ERROR on the - master then we could choose DUP_IGNORE here, because if DUP_ERROR + master then we could choose IGNORE here, because if DUP_ERROR suceeded on master, and data is identical on the master and slave, - then there should be no uniqueness errors on slave, so DUP_IGNORE is + then there should be no uniqueness errors on slave, so IGNORE is the same as DUP_ERROR. But in the unlikely case of uniqueness errors (because the data on the master and slave happen to be different (user error or bug), we want LOAD DATA to print an error message on the slave to discover the problem. If reading from net (a 3.23 master), mysql_load() will change this - to DUP_IGNORE. + to IGNORE. */ handle_dup= DUP_ERROR; } @@ -2575,8 +2578,8 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, */ thd->net.pkt_nr = net->pkt_nr; } - if (mysql_load(thd, &ex, &tables, field_list, handle_dup, net != 0, - TL_WRITE, 0)) + if (mysql_load(thd, &ex, &tables, field_list, handle_dup, ignore, + net != 0, TL_WRITE)) thd->query_error = 1; if (thd->cuted_fields) { @@ -3495,8 +3498,9 @@ Create_file_log_event:: Create_file_log_event(THD* thd_arg, sql_exchange* ex, const char* db_arg, const char* table_name_arg, List& fields_arg, enum enum_duplicates handle_dup, + bool ignore, char* block_arg, uint block_len_arg, bool using_trans) - :Load_log_event(thd_arg,ex,db_arg,table_name_arg,fields_arg,handle_dup, + :Load_log_event(thd_arg,ex,db_arg,table_name_arg,fields_arg,handle_dup, ignore, using_trans), fake_base(0), block(block_arg), event_buf(0), block_len(block_len_arg), file_id(thd_arg->file_id = mysql_bin_log.next_file_id()) diff --git a/sql/log_event.h b/sql/log_event.h index 390a8c8070d..64bb9d502e9 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -783,7 +783,7 @@ public: Load_log_event(THD* thd, sql_exchange* ex, const char* db_arg, const char* table_name_arg, - List& fields_arg, enum enum_duplicates handle_dup, + List& fields_arg, enum enum_duplicates handle_dup, bool ignore, bool using_trans); void set_fields(const char* db, List &fields_arg); const char* get_db() { return db; } @@ -1170,7 +1170,7 @@ public: Create_file_log_event(THD* thd, sql_exchange* ex, const char* db_arg, const char* table_name_arg, List& fields_arg, - enum enum_duplicates handle_dup, + enum enum_duplicates handle_dup, bool ignore, char* block_arg, uint block_len_arg, bool using_trans); #ifdef HAVE_REPLICATION diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index c5568bf52a4..01e2510328d 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -613,6 +613,7 @@ bool mysql_alter_table(THD *thd, char *new_db, char *new_name, List &keys, uint order_num, ORDER *order, enum enum_duplicates handle_duplicates, + bool ignore, ALTER_INFO *alter_info, bool do_send_ok=1); bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list, bool do_send_ok); bool mysql_create_like_table(THD *thd, TABLE_LIST *table, @@ -631,11 +632,11 @@ bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list, int mysql_update(THD *thd,TABLE_LIST *tables,List &fields, List &values,COND *conds, uint order_num, ORDER *order, ha_rows limit, - enum enum_duplicates handle_duplicates); + enum enum_duplicates handle_duplicates, bool ignore); bool mysql_multi_update(THD *thd, TABLE_LIST *table_list, List *fields, List *values, COND *conds, ulong options, - enum enum_duplicates handle_duplicates, + enum enum_duplicates handle_duplicates, bool ignore, SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex); bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, TABLE *table, List &fields, List_item *values, @@ -644,7 +645,8 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, TABLE *table, COND **where, bool select_insert); bool mysql_insert(THD *thd,TABLE_LIST *table,List &fields, List &values, List &update_fields, - List &update_values, enum_duplicates flag); + List &update_values, enum_duplicates flag, + bool ignore); int check_that_all_fields_are_given_values(THD *thd, TABLE *entry); bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds); bool mysql_delete(THD *thd, TABLE_LIST *table, COND *conds, SQL_LIST *order, @@ -882,8 +884,7 @@ bool eval_const_cond(COND *cond); /* sql_load.cc */ bool mysql_load(THD *thd, sql_exchange *ex, TABLE_LIST *table_list, List &fields, enum enum_duplicates handle_duplicates, - bool local_file, thr_lock_type lock_type, - bool ignore_check_option_errors); + bool ignore, bool local_file, thr_lock_type lock_type); int write_record(THD *thd, TABLE *table, COPY_INFO *info); /* sql_manager.cc */ diff --git a/sql/set_var.cc b/sql/set_var.cc index fbbe209eea4..d710be2bb2e 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -3054,7 +3054,7 @@ bool sys_var_thd_storage_engine::check(THD *thd, set_var *var) enum db_type db_type; if (!(res=var->value->val_str(&str)) || !(var->save_result.ulong_value= - (ulong) db_type= ha_resolve_by_name(res->ptr(), res->length())) || + (ulong) (db_type= ha_resolve_by_name(res->ptr(), res->length()))) || ha_checktype(db_type) != db_type) { value= res ? res->c_ptr() : "NULL"; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index ba00c1d3fa7..25f26938e84 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -3317,7 +3317,7 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, { GRANT_TABLE *grant_table; if (!(~table->grant.privilege & want_access) || - table->derived || table->schema_table) + table->derived || table->schema_table || table->belong_to_view) { /* It is subquery in the FROM clause. VIEW set table->derived after diff --git a/sql/sql_base.cc b/sql/sql_base.cc index b6510e53679..87e4f5df1cc 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2089,7 +2089,12 @@ find_field_in_table(THD *thd, TABLE_LIST *table_list, DBUG_RETURN(WRONG_GRANT); #endif if (thd->lex->current_select->no_wrap_view_item) - *ref= trans[i].item; + { + if (register_tree_change) + thd->change_item_tree(ref, trans[i].item); + else + *ref= trans[i].item; + } else { Item_ref *item_ref= new Item_ref(&trans[i].item, @@ -2098,6 +2103,8 @@ find_field_in_table(THD *thd, TABLE_LIST *table_list, /* as far as Item_ref have defined reference it do not need tables */ if (register_tree_change && item_ref) thd->change_item_tree(ref, item_ref); + else if (item_ref) + *ref= item_ref; } DBUG_RETURN((Field*) view_ref_found); } @@ -2247,12 +2254,12 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, if (item->cached_table) { /* - This shortcut is used by prepared statements. We assuming that - TABLE_LIST *tables is not changed during query execution (which - is true for all queries except RENAME but luckily RENAME doesn't + This shortcut is used by prepared statements. We assuming that + TABLE_LIST *tables is not changed during query execution (which + is true for all queries except RENAME but luckily RENAME doesn't use fields...) so we can rely on reusing pointer to its member. With this optimization we also miss case when addition of one more - field makes some prepared query ambiguous and so erroneous, but we + field makes some prepared query ambiguous and so erroneous, but we accept this trade off. */ if (item->cached_table->table) @@ -2268,7 +2275,7 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, else { TABLE_LIST *table= item->cached_table; - Field *find= find_field_in_table(thd, table, name, item->name, length, + found= find_field_in_table(thd, table, name, item->name, length, ref, (table->table && test(table->table->grant. @@ -2391,9 +2398,7 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, { if (field == WRONG_GRANT) return (Field*) 0; - item->cached_table= tables; - if (!tables->cacheable_table) - item->cached_table= 0; + item->cached_table= (!tables->cacheable_table || found) ? 0 : tables; if (found) { if (!thd->where) // Returns first found @@ -2946,6 +2951,7 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name, TABLE_LIST *last; TABLE_LIST *embedding; TABLE *table= tables->table; + bool alias_used= 0; if (!table_name || (!my_strcasecmp(table_alias_charset, table_name, tables->alias) && @@ -3018,6 +3024,8 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name, { iterator= &view_iter; view= 1; + alias_used= my_strcasecmp(table_alias_charset, + tables->real_name, tables->alias); } else { @@ -3039,15 +3047,15 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name, ¬_used_field_index, TRUE)) { Item *item= iterator->item(thd); - if (!found++) - (void) it->replace(item); // Replace '*' - else - it->after(item); if (view && !thd->lex->current_select->no_wrap_view_item) { item= new Item_ref(it->ref(), tables->view_name.str, field_name); } + if (!found++) + (void) it->replace(item); // Replace '*' + else + it->after(item); #ifndef NO_EMBEDDED_ACCESS_CHECKS if (any_privileges) { @@ -3101,9 +3109,15 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name, else if (allocate_view_names && thd->lex->current_select->first_execution) { - Item_field *item= new Item_field(thd->strdup(tables->view_db.str), - thd->strdup(tables->view_name.str), - thd->strdup(field_name)); + Item_field *item; + if (alias_used) + item= new Item_field(0, + thd->strdup(tables->alias), + thd->strdup(field_name)); + else + item= new Item_field(thd->strdup(tables->view_db.str), + thd->strdup(tables->view_name.str), + thd->strdup(field_name)); /* during cleunup() this item will be put in list to replace expression from VIEW diff --git a/sql/sql_class.h b/sql/sql_class.h index 2a0e0aac8b4..976c6789d9f 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -32,7 +32,7 @@ class sp_cache; enum enum_enable_or_disable { LEAVE_AS_IS, ENABLE, DISABLE }; enum enum_ha_read_modes { RFIRST, RNEXT, RPREV, RLAST, RKEY, RNEXT_SAME }; -enum enum_duplicates { DUP_ERROR, DUP_REPLACE, DUP_IGNORE, DUP_UPDATE }; +enum enum_duplicates { DUP_ERROR, DUP_REPLACE, DUP_UPDATE }; enum enum_log_type { LOG_CLOSED, LOG_TO_BE_OPENED, LOG_NORMAL, LOG_NEW, LOG_BIN}; enum enum_delay_key_write { DELAY_KEY_WRITE_NONE, DELAY_KEY_WRITE_ON, DELAY_KEY_WRITE_ALL }; @@ -225,12 +225,12 @@ typedef struct st_copy_info { ha_rows error_count; enum enum_duplicates handle_duplicates; int escape_char, last_errno; -/* for INSERT ... UPDATE */ + bool ignore; + /* for INSERT ... UPDATE */ List *update_fields; List *update_values; -/* for VIEW ... WITH CHECK OPTION */ + /* for VIEW ... WITH CHECK OPTION */ TABLE_LIST *view; - bool ignore; } COPY_INFO; @@ -1375,8 +1375,7 @@ class select_insert :public select_result_interceptor { select_insert(TABLE_LIST *table_list_par, TABLE *table_par, List *fields_par, List *update_fields, List *update_values, - enum_duplicates duplic, - bool ignore_check_option_errors); + enum_duplicates duplic, bool ignore); ~select_insert(); int prepare(List &list, SELECT_LEX_UNIT *u); bool send_data(List &items); @@ -1401,8 +1400,8 @@ public: HA_CREATE_INFO *create_info_par, List &fields_par, List &keys_par, - List &select_fields,enum_duplicates duplic) - :select_insert (NULL, NULL, &select_fields, 0, 0, duplic, 0), create_table(table), + List &select_fields,enum_duplicates duplic, bool ignore) + :select_insert (NULL, NULL, &select_fields, 0, 0, duplic, ignore), create_table(table), extra_fields(&fields_par),keys(&keys_par), create_info(create_info_par), lock(0) {} @@ -1673,12 +1672,12 @@ class multi_update :public select_result_interceptor uint table_count; Copy_field *copy_field; enum enum_duplicates handle_duplicates; - bool do_update, trans_safe, transactional_tables, log_delayed; + bool do_update, trans_safe, transactional_tables, log_delayed, ignore; public: multi_update(THD *thd_arg, TABLE_LIST *ut, TABLE_LIST *leaves_list, List *fields, List *values, - enum_duplicates handle_duplicates); + enum_duplicates handle_duplicates, bool ignore); ~multi_update(); int prepare(List &list, SELECT_LEX_UNIT *u); bool send_data(List &items); diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index f4c5b0f8b59..8edfc08fa82 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -68,8 +68,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, DBUG_RETURN(TRUE); } - if (thd->lex->duplicates == DUP_IGNORE) - select_lex->no_error= 1; + select_lex->no_error= thd->lex->ignore; /* Test if the user wants to delete all rows and deletion doesn't have diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 701ffe60cb3..dc80081bbc8 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -25,7 +25,7 @@ static int check_null_fields(THD *thd,TABLE *entry); #ifndef EMBEDDED_LIBRARY static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list); -static int write_delayed(THD *thd,TABLE *table, enum_duplicates dup, +static int write_delayed(THD *thd,TABLE *table, enum_duplicates dup, bool ignore, char *query, uint query_length, bool log_on); static void end_delayed_insert(THD *thd); extern "C" pthread_handler_decl(handle_delayed_insert,arg); @@ -138,7 +138,7 @@ check_insert_fields(THD *thd, TABLE_LIST *table_list, List &fields, } // For the values we need select_priv #ifndef NO_EMBEDDED_ACCESS_CHECKS - table->grant.want_privilege=(SELECT_ACL & ~table->grant.privilege); + table->grant.want_privilege= (SELECT_ACL & ~table->grant.privilege); #endif if (check_key_in_view(thd, table_list) || @@ -158,7 +158,8 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, List &values_list, List &update_fields, List &update_values, - enum_duplicates duplic) + enum_duplicates duplic, + bool ignore) { int error, res; /* @@ -168,7 +169,6 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, */ bool log_on= (thd->options & OPTION_BIN_LOG) || (!(thd->master_access & SUPER_ACL)); bool transactional_table, log_delayed; - bool ignore_err= (thd->lex->duplicates == DUP_IGNORE); uint value_count; ulong counter = 1; ulonglong id; @@ -271,18 +271,19 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, */ info.records= info.deleted= info.copied= info.updated= 0; + info.ignore= ignore; info.handle_duplicates=duplic; - info.update_fields=&update_fields; - info.update_values=&update_values; + info.update_fields= &update_fields; + info.update_values= &update_values; info.view= (table_list->view ? table_list : 0); - info.ignore= ignore_err; + /* Count warnings for all inserts. For single line insert, generate an error if try to set a NOT NULL field to NULL. */ thd->count_cuted_fields= ((values_list.elements == 1 && - duplic != DUP_IGNORE) ? + !ignore) ? CHECK_FIELD_ERROR_FOR_NULL : CHECK_FIELD_WARN); thd->cuted_fields = 0L; @@ -305,7 +306,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, table->file->start_bulk_insert(values_list.elements); thd->no_trans_update= 0; - thd->abort_on_warning= (duplic != DUP_IGNORE && + thd->abort_on_warning= (!ignore && (thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES))); @@ -366,7 +367,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, if ((res= table_list->view_check_option(thd, (values_list.elements == 1 ? 0 : - ignore_err))) == + ignore))) == VIEW_CHECK_SKIP) continue; else if (res == VIEW_CHECK_ERROR) @@ -377,7 +378,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, #ifndef EMBEDDED_LIBRARY if (lock_type == TL_WRITE_DELAYED) { - error=write_delayed(thd,table,duplic,query, thd->query_length, log_on); + error=write_delayed(thd, table, duplic, ignore, query, thd->query_length, log_on); query=0; } else @@ -490,7 +491,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, else { char buff[160]; - if (duplic == DUP_IGNORE) + if (ignore) sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records, (lock_type == TL_WRITE_DELAYED) ? (ulong) 0 : (ulong) (info.records - info.copied), (ulong) thd->cuted_fields); @@ -851,7 +852,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) } else if ((error=table->file->write_row(table->record[0]))) { - if (info->handle_duplicates != DUP_IGNORE || + if (!info->ignore || (error != HA_ERR_FOUND_DUPP_KEY && error != HA_ERR_FOUND_DUPP_UNIQUE)) goto err; table->file->restore_auto_increment(); @@ -906,13 +907,13 @@ public: char *record,*query; enum_duplicates dup; time_t start_time; - bool query_start_used,last_insert_id_used,insert_id_used, log_query; + bool query_start_used,last_insert_id_used,insert_id_used, ignore, log_query; ulonglong last_insert_id; timestamp_auto_set_type timestamp_field_type; uint query_length; - delayed_row(enum_duplicates dup_arg, bool log_query_arg) - :record(0),query(0),dup(dup_arg),log_query(log_query_arg) {} + delayed_row(enum_duplicates dup_arg, bool ignore_arg, bool log_query_arg) + :record(0), query(0), dup(dup_arg), ignore(ignore_arg), log_query(log_query_arg) {} ~delayed_row() { x_free(record); @@ -1224,7 +1225,7 @@ TABLE *delayed_insert::get_local_table(THD* client_thd) /* Put a question in queue */ -static int write_delayed(THD *thd,TABLE *table,enum_duplicates duplic, +static int write_delayed(THD *thd,TABLE *table,enum_duplicates duplic, bool ignore, char *query, uint query_length, bool log_on) { delayed_row *row=0; @@ -1237,7 +1238,7 @@ static int write_delayed(THD *thd,TABLE *table,enum_duplicates duplic, pthread_cond_wait(&di->cond_client,&di->mutex); thd->proc_info="storing row into queue"; - if (thd->killed || !(row= new delayed_row(duplic, log_on))) + if (thd->killed || !(row= new delayed_row(duplic, ignore, log_on))) goto err; if (!query) @@ -1600,8 +1601,9 @@ bool delayed_insert::handle_inserts(void) thd.insert_id_used=row->insert_id_used; table->timestamp_field_type= row->timestamp_field_type; + info.ignore= row->ignore; info.handle_duplicates= row->dup; - if (info.handle_duplicates == DUP_IGNORE || + if (info.ignore || info.handle_duplicates == DUP_REPLACE) { table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); @@ -1718,8 +1720,6 @@ bool delayed_insert::handle_inserts(void) bool mysql_insert_select_prepare(THD *thd) { LEX *lex= thd->lex; - TABLE_LIST *first_select_table= - (TABLE_LIST*) lex->select_lex.table_list.first; TABLE_LIST *first_select_leaf_table; int res; DBUG_ENTER("mysql_insert_select_prepare"); @@ -1756,7 +1756,8 @@ bool mysql_insert_select_prepare(THD *thd) select_insert::select_insert(TABLE_LIST *table_list_par, TABLE *table_par, List *fields_par, - List *update_fields, List *update_values, + List *update_fields, + List *update_values, enum_duplicates duplic, bool ignore_check_option_errors) :table_list(table_list_par), table(table_par), fields(fields_par), @@ -1803,12 +1804,11 @@ select_insert::prepare(List &values, SELECT_LEX_UNIT *u) restore_record(table,default_values); // Get empty record table->next_number_field=table->found_next_number_field; thd->cuted_fields=0; - if (info.handle_duplicates == DUP_IGNORE || - info.handle_duplicates == DUP_REPLACE) + if (info.ignore || info.handle_duplicates == DUP_REPLACE) table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); table->file->start_bulk_insert((ha_rows) 0); thd->no_trans_update= 0; - thd->abort_on_warning= (info.handle_duplicates != DUP_IGNORE && + thd->abort_on_warning= (!info.ignore && (thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES))); @@ -1854,9 +1854,7 @@ bool select_insert::send_data(List &values) DBUG_RETURN(1); if (table_list) // Not CREATE ... SELECT { - switch (table_list->view_check_option(thd, - thd->lex->duplicates == - DUP_IGNORE)) { + switch (table_list->view_check_option(thd, info.ignore)) { case VIEW_CHECK_SKIP: DBUG_RETURN(0); case VIEW_CHECK_ERROR: @@ -1965,7 +1963,7 @@ bool select_insert::send_eof() DBUG_RETURN(1); } char buff[160]; - if (info.handle_duplicates == DUP_IGNORE) + if (info.ignore) sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records, (ulong) (info.records - info.copied), (ulong) thd->cuted_fields); else @@ -2008,12 +2006,11 @@ select_create::prepare(List &values, SELECT_LEX_UNIT *u) restore_record(table,default_values); // Get empty record thd->cuted_fields=0; - if (info.handle_duplicates == DUP_IGNORE || - info.handle_duplicates == DUP_REPLACE) + if (info.ignore || info.handle_duplicates == DUP_REPLACE) table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); table->file->start_bulk_insert((ha_rows) 0); thd->no_trans_update= 0; - thd->abort_on_warning= (info.handle_duplicates != DUP_IGNORE && + thd->abort_on_warning= (!info.ignore && (thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES))); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 1081246c9e3..5929ad5c14b 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -166,6 +166,7 @@ void lex_start(THD *thd, uchar *buf,uint length) lex->ignore_space=test(thd->variables.sql_mode & MODE_IGNORE_SPACE); lex->sql_command=SQLCOM_END; lex->duplicates= DUP_ERROR; + lex->ignore= 0; lex->sphead= NULL; lex->spcont= NULL; lex->proc_list.first= 0; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 007a4601338..6ed5fb247dc 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -721,7 +721,7 @@ typedef struct st_lex /* special JOIN::prepare mode: changing of query is prohibited */ bool view_prepare_mode; bool safe_to_cache_query; - bool subqueries; + bool subqueries, ignore; bool variables_used; ALTER_INFO alter_info; /* Prepared statements SQL syntax:*/ diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 21dd2318504..6c29a0184fa 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -82,8 +82,8 @@ static int read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, List &fields, enum enum_duplicates handle_duplicates, - bool read_file_from_client,thr_lock_type lock_type, - bool ignore_check_option_errors) + bool ignore, + bool read_file_from_client,thr_lock_type lock_type) { char name[FN_REFLEN]; File file; @@ -186,7 +186,7 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, /* We can't give an error in the middle when using LOCAL files */ if (read_file_from_client && handle_duplicates == DUP_ERROR) - handle_duplicates=DUP_IGNORE; + ignore= 1; #ifndef EMBEDDED_LIBRARY if (read_file_from_client) @@ -237,6 +237,7 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, COPY_INFO info; bzero((char*) &info,sizeof(info)); + info.ignore= ignore; info.handle_duplicates=handle_duplicates; info.escape_char=escaped->length() ? (*escaped)[0] : INT_MAX; @@ -258,6 +259,7 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, lf_info.db = db; lf_info.table_name = table_list->real_name; lf_info.fields = &fields; + lf_info.ignore= ignore; lf_info.handle_dup = handle_duplicates; lf_info.wrote_create_file = 0; lf_info.last_pos_in_file = HA_POS_ERROR; @@ -288,7 +290,7 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET; table->next_number_field=table->found_next_number_field; - if (handle_duplicates == DUP_IGNORE || + if (ignore || handle_duplicates == DUP_REPLACE) table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); ha_enable_transaction(thd, FALSE); @@ -296,18 +298,18 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, table->copy_blobs=1; thd->no_trans_update= 0; - thd->abort_on_warning= (handle_duplicates != DUP_IGNORE && + thd->abort_on_warning= (!ignore && (thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES))); if (!field_term->length() && !enclosed->length()) error= read_fixed_length(thd, info, table_list, fields,read_info, - skip_lines, ignore_check_option_errors); + skip_lines, ignore); else error= read_sep_field(thd, info, table_list, fields, read_info, *enclosed, skip_lines, - ignore_check_option_errors); + ignore); if (table->file->end_bulk_insert()) error=1; /* purecov: inspected */ ha_enable_transaction(thd, TRUE); @@ -485,9 +487,8 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, ER(ER_WARN_TOO_MANY_RECORDS), thd->row_count); } - switch(table_list->view_check_option(thd, - ignore_check_option_errors)) - { + switch (table_list->view_check_option(thd, + ignore_check_option_errors)) { case VIEW_CHECK_SKIP: read_info.next_line(); goto continue_loop; @@ -607,9 +608,8 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, } } - switch(table_list->view_check_option(thd, - ignore_check_option_errors)) - { + switch (table_list->view_check_option(thd, + ignore_check_option_errors)) { case VIEW_CHECK_SKIP: read_info.next_line(); goto continue_loop; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 9ebeb9fe06d..60caa3ff421 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2628,7 +2628,8 @@ mysql_execute_command(THD *thd) lex->create_list, lex->key_list, select_lex->item_list, - lex->duplicates))) + lex->duplicates, + lex->ignore))) { /* CREATE from SELECT give its SELECT_LEX for SELECT, @@ -2768,7 +2769,7 @@ create_error: lex->key_list, select_lex->order_list.elements, (ORDER *) select_lex->order_list.first, - lex->duplicates, &lex->alter_info); + lex->duplicates, lex->ignore, &lex->alter_info); } break; } @@ -2933,7 +2934,7 @@ create_error: select_lex->order_list.elements, (ORDER *) select_lex->order_list.first, select_lex->select_limit, - lex->duplicates)); + lex->duplicates, lex->ignore)); /* mysql_update return 2 if we need to switch to multi-update */ if (result != 2) break; @@ -2954,7 +2955,7 @@ create_error: &lex->value_list, select_lex->where, select_lex->options, - lex->duplicates, unit, select_lex); + lex->duplicates, lex->ignore, unit, select_lex); break; } case SQLCOM_REPLACE: @@ -2965,8 +2966,7 @@ create_error: break; res= mysql_insert(thd, all_tables, lex->field_list, lex->many_values, lex->update_list, lex->value_list, - (lex->value_list.elements ? - DUP_UPDATE : lex->duplicates)); + lex->duplicates, lex->ignore); if (first_table->view && !first_table->contain_auto_increment) thd->last_insert_id= 0; // do not show last insert ID if VIEW have not it break; @@ -2997,8 +2997,7 @@ create_error: if (!res && (result= new select_insert(first_table, first_table->table, &lex->field_list, &lex->update_list, &lex->value_list, - lex->duplicates, - lex->duplicates == DUP_IGNORE))) + lex->duplicates, lex->ignore))) { /* insert/replace from SELECT give its SELECT_LEX for SELECT, @@ -3194,8 +3193,8 @@ create_error: goto error; } res= mysql_load(thd, lex->exchange, first_table, lex->field_list, - lex->duplicates, (bool) lex->local_file, - lex->lock_option, lex->duplicates == DUP_IGNORE); + lex->duplicates, lex->ignore, (bool) lex->local_file, + lex->lock_option); break; } @@ -4331,7 +4330,7 @@ check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables, TABLE_LIST *org_tables=tables; for (; tables; tables= tables->next_global) { - if (tables->derived || tables->schema_table || + if (tables->derived || tables->schema_table || tables->belong_to_view || (tables->table && (int)tables->table->tmp_table) || my_tz_check_n_skip_implicit_tables(&tables, thd->lex->time_zone_tables_used)) @@ -6043,7 +6042,7 @@ bool mysql_create_index(THD *thd, TABLE_LIST *table_list, List &keys) DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name, &create_info, table_list, fields, keys, 0, (ORDER*)0, - DUP_ERROR, &alter_info)); + DUP_ERROR, 0, &alter_info)); } @@ -6061,7 +6060,7 @@ bool mysql_drop_index(THD *thd, TABLE_LIST *table_list, ALTER_INFO *alter_info) DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name, &create_info, table_list, fields, keys, 0, (ORDER*)0, - DUP_ERROR, alter_info)); + DUP_ERROR, 0, alter_info)); } diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 4b6f1bd79fe..b65d0e137ce 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -150,13 +150,18 @@ find_prepared_statement(THD *thd, ulong id, const char *where) static bool send_prep_stmt(Prepared_statement *stmt, uint columns) { NET *net= &stmt->thd->net; - char buff[9]; + char buff[12]; + uint tmp; DBUG_ENTER("send_prep_stmt"); buff[0]= 0; /* OK packet indicator */ int4store(buff+1, stmt->id); int2store(buff+5, columns); int2store(buff+7, stmt->param_count); + buff[9]= 0; // Guard against a 4.1 client + tmp= min(stmt->thd->total_warn_count, 65535); + int2store(buff+10, tmp); + /* Send types and names of placeholders to the client XXX: fix this nasty upcast from List to List @@ -963,6 +968,9 @@ static int mysql_test_update(Prepared_statement *stmt, THD *thd= stmt->thd; uint table_count= 0; SELECT_LEX *select= &stmt->lex->select_lex; +#ifndef NO_EMBEDDED_ACCESS_CHECKS + uint want_privilege; +#endif DBUG_ENTER("mysql_test_update"); if (update_precheck(thd, table_list)) @@ -985,17 +993,29 @@ static int mysql_test_update(Prepared_statement *stmt, return 2; } + /* + thd->fill_derived_tables() is false here for sure (because it is + preparation of PS, so we even do not check it + */ if (lock_tables(thd, table_list, table_count) || - mysql_handle_derived(thd->lex, &mysql_derived_prepare) || - (thd->fill_derived_tables() && - mysql_handle_derived(thd->lex, &mysql_derived_filling))) + mysql_handle_derived(thd->lex, &mysql_derived_prepare)) DBUG_RETURN(1); +#ifndef NO_EMBEDDED_ACCESS_CHECKS + /* TABLE_LIST contain right privilages request */ + want_privilege= table_list->grant.want_privilege; +#endif + if (!(res= mysql_prepare_update(thd, table_list, &select->where, select->order_list.elements, (ORDER *) select->order_list.first))) { +#ifndef NO_EMBEDDED_ACCESS_CHECKS + table_list->grant.want_privilege= + table_list->table->grant.want_privilege= + want_privilege; +#endif thd->lex->select_lex.no_wrap_view_item= 1; if (setup_fields(thd, 0, table_list, select->item_list, 1, 0, 0)) { @@ -1005,6 +1025,12 @@ static int mysql_test_update(Prepared_statement *stmt, else { thd->lex->select_lex.no_wrap_view_item= 0; +#ifndef NO_EMBEDDED_ACCESS_CHECKS + /* Check values */ + table_list->grant.want_privilege= + table_list->table->grant.want_privilege= + (SELECT_ACL & ~table_list->table->grant.privilege); +#endif if (setup_fields(thd, 0, table_list, stmt->lex->value_list, 0, 0, 0)) res= 1; @@ -1385,13 +1411,40 @@ static int mysql_test_multidelete(Prepared_statement *stmt, } +/* + Wrapper for mysql_insert_select_prepare, to make change of local tables + after open_and_lock_tables() call. + + SYNOPSIS + mysql_insert_select_prepare_tester() + thd thread handler + + NOTE: we need remove first local tables after open_and_lock_tables, + because mysql_handle_derived use local tables lists +*/ + +static bool mysql_insert_select_prepare_tester(THD *thd) +{ + SELECT_LEX *first_select= &thd->lex->select_lex; + /* Skip first table, which is the table we are inserting in */ + first_select->table_list.first= (byte*)((TABLE_LIST*)first_select-> + table_list.first)->next_local; + /* + insert/replace from SELECT give its SELECT_LEX for SELECT, + and item_list belong to SELECT + */ + first_select->resolve_mode= SELECT_LEX::SELECT_MODE; + mysql_insert_select_prepare(thd); +} + + /* Validate and prepare for execution INSERT ... SELECT statement SYNOPSIS mysql_test_insert_select() stmt prepared statemen handler - tables list of tables queries + tables list of tables of query RETURN VALUE 0 success @@ -1406,26 +1459,23 @@ static int mysql_test_insert_select(Prepared_statement *stmt, LEX *lex= stmt->lex; TABLE_LIST *first_local_table; - if ((res= insert_precheck(stmt->thd, tables))) - return res; - first_local_table= (TABLE_LIST *)lex->select_lex.table_list.first; - DBUG_ASSERT(first_local_table != 0); - /* Skip first table, which is the table we are inserting in */ - lex->select_lex.table_list.first= (byte*) first_local_table->next_local; if (tables->table) { // don't allocate insert_values tables->table->insert_values=(byte *)1; } - /* - insert/replace from SELECT give its SELECT_LEX for SELECT, - and item_list belong to SELECT - */ - lex->select_lex.resolve_mode= SELECT_LEX::SELECT_MODE; - res= select_like_statement_test(stmt, tables, &mysql_insert_select_prepare, + if ((res= insert_precheck(stmt->thd, tables))) + return res; + + /* store it, because mysql_insert_select_prepare_tester change it */ + first_local_table= (TABLE_LIST *)lex->select_lex.table_list.first; + DBUG_ASSERT(first_local_table != 0); + + res= select_like_statement_test(stmt, tables, + &mysql_insert_select_prepare_tester, OPTION_SETUP_TABLES_DONE); - /* revert changes*/ + /* revert changes made by mysql_insert_select_prepare_tester */ lex->select_lex.table_list.first= (byte*) first_local_table; lex->select_lex.resolve_mode= SELECT_LEX::INSERT_MODE; return res; diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 9f083e19146..8ba92015535 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -1510,7 +1510,7 @@ err: int log_loaded_block(IO_CACHE* file) { - LOAD_FILE_INFO* lf_info; + LOAD_FILE_INFO *lf_info; uint block_len ; /* file->request_pos contains position where we started last read */ @@ -1532,7 +1532,7 @@ int log_loaded_block(IO_CACHE* file) { Create_file_log_event c(lf_info->thd,lf_info->ex,lf_info->db, lf_info->table_name, *lf_info->fields, - lf_info->handle_dup, buffer, + lf_info->handle_dup, lf_info->ignore, buffer, block_len, lf_info->log_delayed); mysql_bin_log.write(&c); lf_info->wrote_create_file = 1; diff --git a/sql/sql_repl.h b/sql/sql_repl.h index 71b25548da4..e8497fee343 100644 --- a/sql/sql_repl.h +++ b/sql/sql_repl.h @@ -67,7 +67,7 @@ typedef struct st_load_file_info enum enum_duplicates handle_dup; char* db; char* table_name; - bool wrote_create_file, log_delayed; + bool wrote_create_file, log_delayed, ignore; } LOAD_FILE_INFO; int log_loaded_block(IO_CACHE* file); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 6d0504802db..dce7c754f03 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -529,7 +529,7 @@ JOIN::optimize() optimized= 1; // Ignore errors of execution if option IGNORE present - if (thd->lex->duplicates == DUP_IGNORE) + if (thd->lex->ignore) thd->lex->current_select->no_error= 1; #ifdef HAVE_REF_TO_FIELDS // Not done yet /* Add HAVING to WHERE if possible */ diff --git a/sql/sql_table.cc b/sql/sql_table.cc index e8655a2a304..757e968a582 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -36,6 +36,7 @@ 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, enum enum_duplicates handle_duplicates, + bool ignore, uint order_num, ORDER *order, ha_rows *copied,ha_rows *deleted); @@ -2806,7 +2807,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, TABLE_LIST *table_list, List &fields, List &keys, uint order_num, ORDER *order, - enum enum_duplicates handle_duplicates, + enum enum_duplicates handle_duplicates, bool ignore, ALTER_INFO *alter_info, bool do_send_ok) { TABLE *table,*new_table=0; @@ -3348,7 +3349,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET; new_table->next_number_field=new_table->found_next_number_field; error=copy_data_between_tables(table,new_table,create_list, - handle_duplicates, + handle_duplicates, ignore, order_num, order, &copied, &deleted); } thd->last_insert_id=next_insert_id; // Needed for correct log @@ -3567,6 +3568,7 @@ static int copy_data_between_tables(TABLE *from,TABLE *to, List &create, enum enum_duplicates handle_duplicates, + bool ignore, uint order_num, ORDER *order, ha_rows *copied, ha_rows *deleted) @@ -3660,7 +3662,7 @@ copy_data_between_tables(TABLE *from,TABLE *to, current query id */ from->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS); init_read_record(&info, thd, from, (SQL_SELECT *) 0, 1,1); - if (handle_duplicates == DUP_IGNORE || + if (ignore || handle_duplicates == DUP_REPLACE) to->file->extra(HA_EXTRA_IGNORE_DUP_KEY); thd->row_count= 0; @@ -3686,7 +3688,7 @@ copy_data_between_tables(TABLE *from,TABLE *to, } if ((error=to->file->write_row((byte*) to->record[0]))) { - if ((handle_duplicates != DUP_IGNORE && + if ((!ignore && handle_duplicates != DUP_REPLACE) || (error != HA_ERR_FOUND_DUPP_KEY && error != HA_ERR_FOUND_DUPP_UNIQUE)) @@ -3757,14 +3759,14 @@ bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list, lex->alter_info.reset(); bzero((char*) &create_info,sizeof(create_info)); create_info.db_type=DB_TYPE_DEFAULT; - create_info.row_type=ROW_TYPE_DEFAULT; + create_info.row_type=ROW_TYPE_NOT_USED; create_info.default_table_charset=default_charset_info; /* Force alter table to recreate table */ lex->alter_info.flags= ALTER_CHANGE_COLUMN; DBUG_RETURN(mysql_alter_table(thd, NullS, NullS, &create_info, table_list, lex->create_list, lex->key_list, 0, (ORDER *) 0, - DUP_ERROR, &lex->alter_info, do_send_ok)); + DUP_ERROR, 0, &lex->alter_info, do_send_ok)); } diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 012a26a6f4d..901cb0ba496 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -51,10 +51,10 @@ select_union::select_union(TABLE *table_par) { bzero((char*) &info,sizeof(info)); /* - We can always use DUP_IGNORE because the temporary table will only + We can always use IGNORE because the temporary table will only contain a unique key if we are using not using UNION ALL */ - info.handle_duplicates= DUP_IGNORE; + info.ignore= 1; } select_union::~select_union() diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 4d30ffbda9b..5e7bdf69dbb 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -113,12 +113,11 @@ int mysql_update(THD *thd, COND *conds, uint order_num, ORDER *order, ha_rows limit, - enum enum_duplicates handle_duplicates) + enum enum_duplicates handle_duplicates, bool ignore) { bool using_limit= limit != HA_POS_ERROR; bool safe_update= thd->options & OPTION_SAFE_UPDATES; bool used_key_is_modified, transactional_table, log_delayed; - bool ignore_err= (thd->lex->duplicates == DUP_IGNORE); int res; int error=0; uint used_index; @@ -171,10 +170,8 @@ int mysql_update(THD *thd, table->quick_keys.clear_all(); #ifndef NO_EMBEDDED_ACCESS_CHECKS - /* In case of view TABLE_LIST contain right privilages request */ - want_privilege= (table_list->view ? - table_list->grant.want_privilege : - table->grant.want_privilege); + /* TABLE_LIST contain right privilages request */ + want_privilege= table_list->grant.want_privilege; #endif if (mysql_prepare_update(thd, table_list, &conds, order_num, order)) DBUG_RETURN(1); @@ -222,7 +219,7 @@ int mysql_update(THD *thd, #ifndef NO_EMBEDDED_ACCESS_CHECKS /* Check values */ table_list->grant.want_privilege= table->grant.want_privilege= - (SELECT_ACL & ~table->grant.privilege); + (SELECT_ACL & ~~table->grant.privilege); #endif if (setup_fields(thd, 0, table_list, values, 1, 0, 0)) { @@ -380,7 +377,7 @@ int mysql_update(THD *thd, } } - if (handle_duplicates == DUP_IGNORE) + if (ignore) table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); if (select && select->quick && select->quick->reset()) @@ -395,7 +392,7 @@ int mysql_update(THD *thd, transactional_table= table->file->has_transactions(); thd->no_trans_update= 0; - thd->abort_on_warning= test(handle_duplicates != DUP_IGNORE && + thd->abort_on_warning= test(!ignore && (thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES))); @@ -415,7 +412,7 @@ int mysql_update(THD *thd, if (compare_record(table, query_id)) { - if ((res= table_list->view_check_option(thd, ignore_err)) != + if ((res= table_list->view_check_option(thd, ignore)) != VIEW_CHECK_OK) { found--; @@ -433,8 +430,7 @@ int mysql_update(THD *thd, updated++; thd->no_trans_update= !transactional_table; } - else if (handle_duplicates != DUP_IGNORE || - error != HA_ERR_FOUND_DUPP_KEY) + else if (!ignore || error != HA_ERR_FOUND_DUPP_KEY) { thd->fatal_error(); // Force error message table->file->print_error(error,MYF(0)); @@ -717,7 +713,7 @@ bool mysql_multi_update_prepare(THD *thd) } /* Check access privileges for table */ - if (!tl->derived) + if (!tl->derived && !tl->belong_to_view) { uint want_privilege= tl->updating ? UPDATE_ACL : SELECT_ACL; if (!using_lock_tables) @@ -812,7 +808,7 @@ bool mysql_multi_update(THD *thd, List *values, COND *conds, ulong options, - enum enum_duplicates handle_duplicates, + enum enum_duplicates handle_duplicates, bool ignore, SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex) { bool res= FALSE; @@ -825,7 +821,7 @@ bool mysql_multi_update(THD *thd, if (!(result= new multi_update(thd, table_list, thd->lex->select_lex.leaf_tables, fields, values, - handle_duplicates))) + handle_duplicates, ignore))) DBUG_RETURN(TRUE); thd->no_trans_update= 0; @@ -851,12 +847,13 @@ bool mysql_multi_update(THD *thd, multi_update::multi_update(THD *thd_arg, TABLE_LIST *table_list, TABLE_LIST *leaves_list, List *field_list, List *value_list, - enum enum_duplicates handle_duplicates_arg) + enum enum_duplicates handle_duplicates_arg, + bool ignore_arg) :all_tables(table_list), leaves(leaves_list), update_tables(0), thd(thd_arg), tmp_tables(0), updated(0), found(0), fields(field_list), values(value_list), table_count(0), copy_field(0), handle_duplicates(handle_duplicates_arg), do_update(1), trans_safe(0), - transactional_tables(1) + transactional_tables(1), ignore(ignore_arg) {} @@ -1144,7 +1141,6 @@ multi_update::~multi_update() bool multi_update::send_data(List ¬_used_values) { TABLE_LIST *cur_table; - bool ignore_err= (thd->lex->duplicates == DUP_IGNORE); DBUG_ENTER("multi_update::send_data"); for (cur_table= update_tables; cur_table; cur_table= cur_table->next_local) @@ -1179,7 +1175,7 @@ bool multi_update::send_data(List ¬_used_values) if (compare_record(table, thd->query_id)) { int error; - if ((error= cur_table->view_check_option(thd, ignore_err)) != + if ((error= cur_table->view_check_option(thd, ignore)) != VIEW_CHECK_OK) { found--; @@ -1201,8 +1197,7 @@ bool multi_update::send_data(List ¬_used_values) table->record[0]))) { updated--; - if (handle_duplicates != DUP_IGNORE || - error != HA_ERR_FOUND_DUPP_KEY) + if (!ignore || error != HA_ERR_FOUND_DUPP_KEY) { thd->fatal_error(); // Force error message table->file->print_error(error,MYF(0)); @@ -1336,8 +1331,7 @@ int multi_update::do_updates(bool from_send_error) if ((local_error=table->file->update_row(table->record[1], table->record[0]))) { - if (local_error != HA_ERR_FOUND_DUPP_KEY || - handle_duplicates != DUP_IGNORE) + if (!ignore || local_error != HA_ERR_FOUND_DUPP_KEY) goto err; } updated++; diff --git a/sql/sql_view.cc b/sql/sql_view.cc index bafb57c44b0..e982eb8e6be 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -679,18 +679,6 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table) if (lex->spfuns.array.buffer) hash_free(&lex->spfuns); - /* - mark to avoid temporary table using and put view reference and find - last view table - */ - for (tbl= view_tables; - tbl; - tbl= (view_tables_tail= tbl)->next_global) - { - tbl->skip_temporary= 1; - tbl->belong_to_view= top_view; - } - /* check rights to run commands (EXPLAIN SELECT & SHOW CREATE) which show underlying tables @@ -710,6 +698,18 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table) goto err; } + /* + mark to avoid temporary table using and put view reference and find + last view table + */ + for (tbl= view_tables; + tbl; + tbl= (view_tables_tail= tbl)->next_global) + { + tbl->skip_temporary= 1; + tbl->belong_to_view= top_view; + } + /* move SQL_NO_CACHE & Co to whole query */ old_lex->safe_to_cache_query= (old_lex->safe_to_cache_query && lex->safe_to_cache_query); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 2095a76d0c7..289b96dff51 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -3220,8 +3220,9 @@ alter: { THD *thd= YYTHD; LEX *lex= thd->lex; - lex->sql_command = SQLCOM_ALTER_TABLE; - lex->name=0; + lex->sql_command= SQLCOM_ALTER_TABLE; + lex->name= 0; + lex->duplicates= DUP_ERROR; if (!lex->select_lex.add_table_to_list(thd, $4, NULL, TL_OPTION_UPDATING)) YYABORT; @@ -3449,8 +3450,9 @@ opt_column: | COLUMN_SYM {}; opt_ignore: - /* empty */ { Lex->duplicates=DUP_ERROR; } - | IGNORE_SYM { Lex->duplicates=DUP_IGNORE; }; + /* empty */ { Lex->ignore= 0;} + | IGNORE_SYM { Lex->ignore= 1;} + ; opt_restrict: /* empty */ { Lex->drop_mode= DROP_DEFAULT; } @@ -5573,7 +5575,8 @@ insert: INSERT { LEX *lex= Lex; - lex->sql_command = SQLCOM_INSERT; + lex->sql_command= SQLCOM_INSERT; + lex->duplicates= DUP_ERROR; /* for subselects */ lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ; lex->select_lex.resolve_mode= SELECT_LEX::INSERT_MODE; @@ -5734,6 +5737,7 @@ update: mysql_init_select(lex); lex->sql_command= SQLCOM_UPDATE; lex->lock_option= TL_UNLOCK; /* Will be set later */ + lex->duplicates= DUP_ERROR; } opt_low_priority opt_ignore join_table_list SET update_list @@ -5793,6 +5797,7 @@ delete: LEX *lex= Lex; lex->sql_command= SQLCOM_DELETE; lex->lock_option= lex->thd->update_lock_default; + lex->ignore= 0; lex->select_lex.init_order(); } opt_delete_options single_multi {} @@ -5849,7 +5854,7 @@ opt_delete_options: opt_delete_option: QUICK { Select->options|= OPTION_QUICK; } | LOW_PRIORITY { Lex->lock_option= TL_WRITE_LOW_PRIORITY; } - | IGNORE_SYM { Lex->duplicates= DUP_IGNORE; }; + | IGNORE_SYM { Lex->ignore= 1; }; truncate: TRUNCATE_SYM opt_table_sym table_name @@ -6357,6 +6362,8 @@ load: LOAD DATA_SYM load_data_lock opt_local INFILE TEXT_STRING_sys lex->sql_command= SQLCOM_LOAD; lex->lock_option= $3; lex->local_file= $4; + lex->duplicates= DUP_ERROR; + lex->ignore= 0; if (!(lex->exchange= new sql_exchange($6.str,0))) YYABORT; lex->field_list.empty(); @@ -6394,7 +6401,7 @@ load_data_lock: opt_duplicate: /* empty */ { Lex->duplicates=DUP_ERROR; } | REPLACE { Lex->duplicates=DUP_REPLACE; } - | IGNORE_SYM { Lex->duplicates=DUP_IGNORE; }; + | IGNORE_SYM { Lex->ignore= 1; }; opt_field_term: /* empty */ diff --git a/sql/table.cc b/sql/table.cc index e9b89d6b124..12862d21ac0 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1726,6 +1726,9 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds, } if (where && !where->fixed && where->fix_fields(thd, ancestor, &where)) goto err; + if (check_option && !check_option->fixed && + check_option->fix_fields(thd, ancestor, &where)) + goto err; restore_want_privilege(); /* WHERE/ON resolved => we can rename fields */ @@ -1873,11 +1876,19 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds, /* full text function moving to current select */ if (view->select_lex.ftfunc_list->elements) { + Item_arena *arena= thd->current_arena, backup; + if (arena->is_conventional()) + arena= 0; // For easier test + else + thd->set_n_backup_item_arena(arena, &backup); + Item_func_match *ifm; List_iterator_fast li(*(view->select_lex.ftfunc_list)); while ((ifm= li++)) current_select_save->ftfunc_list->push_front(ifm); + if (arena) + thd->restore_backup_item_arena(arena, &backup); } ok: diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index e7f8a035a15..4a7f70b0b87 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -152,15 +152,22 @@ languages and applications need to dynamically load and use MySQL. %package Max Release: %{release} -Summary: MySQL - server with Berkeley DB, RAID and UDF support +Summary: MySQL - server with extended functionality Group: Applications/Databases Provides: mysql-Max Obsoletes: mysql-Max Requires: MySQL-server >= 4.0 %description Max -Optional MySQL server binary that supports additional features like -Berkeley DB, RAID and User Defined Functions (UDFs). +Optional MySQL server binary that supports additional features like: + + - Berkeley DB Storage Engine + - Archive Storage Engine + - CSV Storage Engine + - Example Storage Engine + - MyISAM RAID + - User Defined Functions (UDFs). + To activate this binary, just install this package in addition to the standard MySQL package. @@ -273,6 +280,9 @@ BuildMySQL "--enable-shared \ --with-berkeley-db \ --with-innodb \ --with-raid \ + --with-archive \ + --with-csv-storage-engine \ + --with-example-storage-engine \ --with-embedded-server \ --with-server-suffix='-Max'" @@ -468,8 +478,6 @@ fi %doc %attr(644, root, root) %{_infodir}/mysql.info* -%doc %attr(644, root, man) %{_mandir}/man1/isamchk.1* -%doc %attr(644, root, man) %{_mandir}/man1/isamlog.1* %doc %attr(644, root, man) %{_mandir}/man1/mysql_zap.1* %doc %attr(644, root, man) %{_mandir}/man1/mysqld.1* %doc %attr(644, root, man) %{_mandir}/man1/mysql_fix_privilege_tables.1* @@ -480,8 +488,6 @@ fi %ghost %config(noreplace,missingok) %{_sysconfdir}/my.cnf -%attr(755, root, root) %{_bindir}/isamchk -%attr(755, root, root) %{_bindir}/isamlog %attr(755, root, root) %{_bindir}/my_print_defaults %attr(755, root, root) %{_bindir}/myisamchk %attr(755, root, root) %{_bindir}/myisam_ftdump @@ -502,7 +508,6 @@ fi %attr(755, root, root) %{_bindir}/mysqld_safe %attr(755, root, root) %{_bindir}/mysqlhotcopy %attr(755, root, root) %{_bindir}/mysqltest -%attr(755, root, root) %{_bindir}/pack_isam %attr(755, root, root) %{_bindir}/perror %attr(755, root, root) %{_bindir}/replace %attr(755, root, root) %{_bindir}/resolve_stack_dump @@ -556,7 +561,6 @@ fi %{_includedir}/mysql/* %{_libdir}/mysql/libdbug.a %{_libdir}/mysql/libheap.a -%{_libdir}/mysql/libmerge.a %if %{have_libgcc} %{_libdir}/mysql/libmygcc.a %endif @@ -568,7 +572,6 @@ fi %{_libdir}/mysql/libmysqlclient_r.la %{_libdir}/mysql/libmystrings.a %{_libdir}/mysql/libmysys.a -%{_libdir}/mysql/libnisam.a %{_libdir}/mysql/libvio.a %files shared @@ -597,6 +600,17 @@ fi # itself - note that they must be ordered by date (important when # merging BK trees) %changelog +* Tue Jan 04 2005 Petr Chardin + +- ISAM and merge storage engines were purged. As well as appropriate + tools and manpages (isamchk and isamlog) + +* Thu Dec 31 2004 Lenz Grimmer + +- enabled the "Archive" storage engine for the max binary +- enabled the "CSV" storage engine for the max binary +- enabled the "Example" storage engine for the max binary + * Thu Aug 26 2004 Lenz Grimmer - MySQL-Max now requires MySQL-server instead of MySQL (BUG 3860)