diff options
author | Michael Widenius <monty@askmonty.org> | 2010-08-25 01:44:50 +0300 |
---|---|---|
committer | Michael Widenius <monty@askmonty.org> | 2010-08-25 01:44:50 +0300 |
commit | 58a75bb18b2a4080c8fae77024afed37f1be1314 (patch) | |
tree | 4d9d65f5747636d6dea9295e79464108df24a9a2 | |
parent | 99b79db5dca6909456a40d859298ba3992b145da (diff) | |
parent | a82671178919afba86ddfdf2b64321eb9afff8e5 (diff) | |
download | mariadb-git-58a75bb18b2a4080c8fae77024afed37f1be1314.tar.gz |
Automerge with 5.1
167 files changed, 1626 insertions, 926 deletions
diff --git a/.bzrignore b/.bzrignore index 9907f5b4e12..dd569894167 100644 --- a/.bzrignore +++ b/.bzrignore @@ -1936,3 +1936,5 @@ sql/client_plugin.c *.dgcov libmysqld/create_options.cc storage/pbxt/bin/xtstat +mysql-test/mtr_command +scripts/convert-debug-for-diff diff --git a/BUILD/SETUP.sh b/BUILD/SETUP.sh index 0ad5351f545..33830fd9987 100755 --- a/BUILD/SETUP.sh +++ b/BUILD/SETUP.sh @@ -91,8 +91,8 @@ path=`dirname $0` get_make_parallel_flag # SSL library to use.--with-ssl will select our bundled yaSSL -# implementation of SSL. To use openSSl you will nee too point out -# the location of openSSL headers and lbs on your system. +# implementation of SSL. To use OpenSSL you will need to specify +# the location of OpenSSL headers and libs on your system. # Ex --with-ssl=/usr SSL_LIBRARY=--with-ssl @@ -182,8 +182,7 @@ max_no_embedded_configs="$SSL_LIBRARY --with-plugins=max" max_no_qc_configs="$SSL_LIBRARY --with-plugins=max --without-query-cache" max_no_ndb_configs="$SSL_LIBRARY --with-plugins=max-no-ndb --with-embedded-server --with-libevent" max_configs="$SSL_LIBRARY --with-plugins=max --with-embedded-server --with-libevent" -# Disable NDB in maria max builds -max_configs=$max_no_ndb_configs +all_configs="$SSL_LIBRARY --with-plugins=max --with-plugin-ndbcluster --with-embedded-server --with-libevent" # # CPU and platform specific compilation flags. diff --git a/BUILD/compile-amd64-debug-all b/BUILD/compile-amd64-debug-all new file mode 100755 index 00000000000..b8b2ed05402 --- /dev/null +++ b/BUILD/compile-amd64-debug-all @@ -0,0 +1,7 @@ +#! /bin/sh +path=`dirname $0` +. "$path/SETUP.sh" +extra_flags="$amd64_cflags $debug_cflags" +extra_configs="$amd64_configs $debug_configs $all_configs" + +. "$path/FINISH.sh" diff --git a/BUILD/compile-pentium-debug-all b/BUILD/compile-pentium-debug-all new file mode 100755 index 00000000000..710ce8af63c --- /dev/null +++ b/BUILD/compile-pentium-debug-all @@ -0,0 +1,10 @@ +#! /bin/sh + +path=`dirname $0` +set -- "$@" --with-debug=full +. "$path/SETUP.sh" + +extra_flags="$pentium_cflags $debug_cflags" +extra_configs="$pentium_configs $debug_configs $all_configs $error_inject --with-experimental-collations" + +. "$path/FINISH.sh" diff --git a/BUILD/compile-pentium64-debug-all b/BUILD/compile-pentium64-debug-all new file mode 100755 index 00000000000..7824f7ad47f --- /dev/null +++ b/BUILD/compile-pentium64-debug-all @@ -0,0 +1,12 @@ +#! /bin/sh + +path=`dirname $0` +set -- "$@" --with-debug=full +. "$path/SETUP.sh" + +extra_flags="$pentium64_cflags $debug_cflags" +extra_configs="$pentium_configs $debug_configs $all_configs" + +extra_configs="$extra_configs " +CC="$CC --pipe" +. "$path/FINISH.sh" diff --git a/client/mysql.cc b/client/mysql.cc index 71a9e44fa23..5d6018fd910 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -156,6 +156,7 @@ static my_bool ignore_errors=0,wait_flag=0,quick=0, static my_bool debug_info_flag, debug_check_flag, batch_abort_on_error; static my_bool column_types_flag; static my_bool preserve_comments= 0; +static my_bool in_com_source, aborted= 0; static ulong opt_max_allowed_packet, opt_net_buffer_length; static uint verbose=0,opt_silent=0,opt_mysql_port=0, opt_local_infile=0; static uint my_end_arg; @@ -1088,6 +1089,7 @@ int main(int argc,char *argv[]) "\\N [\\d]> ",MYF(MY_WME)); current_prompt = my_strdup(default_prompt,MYF(MY_WME)); prompt_counter=0; + aborted= 0; outfile[0]=0; // no (default) outfile strmov(pager, "stdout"); // the default, if --pager wasn't given @@ -1282,8 +1284,10 @@ sig_handler mysql_end(int sig) /* This function handles sigint calls If query is in process, kill query + If 'source' is executed, abort source command no query in process, terminate like previous behavior */ + sig_handler handle_sigint(int sig) { char kill_buffer[40]; @@ -1322,7 +1326,8 @@ sig_handler handle_sigint(int sig) mysql_close(kill_mysql); tee_fprintf(stdout, "Ctrl-C -- query killed. Continuing normally.\n"); interrupted_query= 0; - + if (in_com_source) + aborted= 1; // Abort source command return; err: @@ -1886,7 +1891,7 @@ static int read_and_execute(bool interactive) String buffer; #endif - char *line; + char *line= 0; char in_string=0; ulong line_number=0; bool ml_comment= 0; @@ -1894,7 +1899,7 @@ static int read_and_execute(bool interactive) bool truncated= 0; status.exit_status=1; - for (;;) + while (!aborted) { if (!interactive) { @@ -4074,17 +4079,19 @@ static int com_source(String *buffer, char *line) status.file_name=source_name; glob_buffer.length(0); // Empty command buffer ignore_errors= !batch_abort_on_error; + in_com_source= 1; error= read_and_execute(false); ignore_errors= save_ignore_errors; status=old_status; // Continue as before + in_com_source= aborted= 0; my_fclose(sql_file,MYF(0)); batch_readline_end(line_buff); /* If we got an error during source operation, don't abort the client if ignore_errors is set */ - if (error && batch_abort_on_error && ignore_errors) - error= -1; + if (error && !batch_abort_on_error && ignore_errors) + error= -1; // Ignore error return error; } diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c index fd067e8a8ad..62eab5bf6e4 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -71,8 +71,8 @@ static struct my_option my_long_options[] = &opt_auto_repair, &opt_auto_repair, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"character-sets-dir", OPT_CHARSETS_DIR, - "Directory for character set files.", &charsets_dir, - &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + "Directory for character set files.", (char**) &charsets_dir, + (char**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"check", 'c', "Check table for errors.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"check-only-changed", 'C', diff --git a/client/mysqldump.c b/client/mysqldump.c index 0045faa2229..bb09af4a3c2 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -211,8 +211,8 @@ static struct my_option my_long_options[] = 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif {"character-sets-dir", OPT_CHARSETS_DIR, - "Directory for character set files.", &charsets_dir, - &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + "Directory for character set files.", (char**) &charsets_dir, + (char**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"comments", 'i', "Write additional information.", &opt_comments, &opt_comments, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, @@ -242,8 +242,8 @@ static struct my_option my_long_options[] = {"debug", '#', "This is a non-debug version. Catch this and exit.", 0,0, 0, GET_DISABLED, OPT_ARG, 0, 0, 0, 0, 0, 0}, #else - {"debug", '#', "Output debug log.", &default_dbug_option, - &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, + {"debug", '#', "Output debug log.", (char**) &default_dbug_option, + (char**) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, #endif {"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.", &debug_check_flag, &debug_check_flag, 0, diff --git a/client/mysqlimport.c b/client/mysqlimport.c index 404106560c1..43994a4f514 100644 --- a/client/mysqlimport.c +++ b/client/mysqlimport.c @@ -73,8 +73,8 @@ static struct my_option my_long_options[] = 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif {"character-sets-dir", OPT_CHARSETS_DIR, - "Directory for character set files.", &charsets_dir, - &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + "Directory for character set files.", (char**) &charsets_dir, + (char**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"default-character-set", OPT_DEFAULT_CHARSET, "Set the default character set.", &default_charset, &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, diff --git a/extra/my_print_defaults.c b/extra/my_print_defaults.c index da7061471fa..847738951dd 100644 --- a/extra/my_print_defaults.c +++ b/extra/my_print_defaults.c @@ -55,8 +55,8 @@ static struct my_option my_long_options[] = {"debug", '#', "This is a non-debug version. Catch this and exit", 0,0, 0, GET_DISABLED, OPT_ARG, 0, 0, 0, 0, 0, 0}, #else - {"debug", '#', "Output debug log", &default_dbug_option, - &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, + {"debug", '#', "Output debug log", (char**) &default_dbug_option, + (char**) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, #endif {"defaults-file", 'c', "Like --config-file, except: if first option, " "then read this file only, do not read global or per-user config " diff --git a/include/my_global.h b/include/my_global.h index 6add808ed55..13802804f91 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -807,10 +807,10 @@ typedef SOCKET_SIZE_TYPE size_socket; #endif /* get memory in huncs */ #define ONCE_ALLOC_INIT (uint) (4096-MALLOC_OVERHEAD) - /* Typical record cash */ -#define RECORD_CACHE_SIZE (uint) (64*1024-MALLOC_OVERHEAD) - /* Typical key cash */ -#define KEY_CACHE_SIZE (uint) (8*1024*1024-MALLOC_OVERHEAD) + /* Typical record cache */ +#define RECORD_CACHE_SIZE (uint) (128*1024-MALLOC_OVERHEAD) + /* Typical key cache */ +#define KEY_CACHE_SIZE (uint) (128L*1024L*1024L-MALLOC_OVERHEAD) /* Default size of a key cache block */ #define KEY_CACHE_BLOCK_SIZE (uint) 1024 diff --git a/mysql-test/Makefile.am b/mysql-test/Makefile.am index 991c8116f1b..c74a042cab0 100644 --- a/mysql-test/Makefile.am +++ b/mysql-test/Makefile.am @@ -63,13 +63,14 @@ nobase_test_DATA = \ lib/My/SafeProcess.pm \ lib/My/File/Path.pm \ lib/My/SysInfo.pm \ + lib/My/Suite.pm \ lib/My/CoreDump.pm \ lib/My/SafeProcess/Base.pm \ lib/My/SafeProcess/safe_process.pl SUBDIRS = lib/My/SafeProcess -EXTRA_DIST = README \ +EXTRA_DIST = README README.suites \ $(test_SCRIPTS) \ $(nobase_test_DATA) @@ -101,7 +102,7 @@ TEST_DIRS = t r include std_data std_data/parts collections \ suite/ndb suite/ndb/t suite/ndb/r \ suite/rpl_ndb suite/rpl_ndb/t suite/rpl_ndb/r \ suite/parts suite/parts/t suite/parts/r suite/parts/inc \ - suite/pbxt/t suite/pbxt/r \ + suite/pbxt/t suite/pbxt/r suite/pbxt \ suite/innodb suite/innodb/t suite/innodb/r suite/innodb/include \ suite/vcol suite/vcol/t suite/vcol/r suite/vcol/inc \ suite/oqgraph suite/oqgraph/t suite/oqgraph/r suite/oqgraph/include \ diff --git a/mysql-test/README b/mysql-test/README index 77b398ebf39..3c8303ca070 100644 --- a/mysql-test/README +++ b/mysql-test/README @@ -18,7 +18,7 @@ the test suite expects you to provide the names of the tests to run. For example, here is the command to run the "alias" and "analyze" tests with an external server: -mysql-test-run --extern alias analyze +mysql-test-run --extern socket=/tmp/mysql.sock alias analyze To match your setup, you might also need to provide --socket, --user, and other relevant options. diff --git a/mysql-test/README.suites b/mysql-test/README.suites new file mode 100644 index 00000000000..99155f37485 --- /dev/null +++ b/mysql-test/README.suites @@ -0,0 +1,138 @@ +These are the assorted notes that will be turned into a manual eventually. + +========================== +Tests are organized in suites. +A "suite" is a subdirectory inside, one of, + + <basedir>/mysql-test/suite + <basedir>/mysql-test + <basedir>/share/mysql-test/suite + <basedir>/share/mysql-test + <basedir>/share/mysql/mysql-test/suite + <basedir>/share/mysql/mysql-test + <basedir>/storage/*/mysql-test-suites + +This is supposed to cover running mtr from a source directory and installed. + +========================== +A suite contains *.test and *.result files. They can be in the t/ and r/ +subdirectories under the suitedir or directly in the suitedir +(that is suitedir/t/*.test or suitedir/*.test, same for *.result)) + +========================== +A suite can contain a suite.opt file - at the same location where .test +files are. As usual, the .opt file can use $-substitutions for the +environment variables. + +Usually, using my.cnf template (see below) is preferrable. +========================== +A suite can have suite.pm file in the suitedir. It must declare a +package that inherits from My::Suite. + +The suite.pm needs to have @ISA=qw(My::Suite) and it must end +with bless {}; - that is it must return an object of that class. +It can also return a string - in this case all tests in the suite +will be skipped, with this string being printed as a reason. + +A suite class can define config_files() and servers() methods. + +A config_files method returns a list of additional config files (besides +my.cnf), that this suite needs to be created. For every file it specifies +a function that will create it, when given a My::Config object. For example: + + sub config_files { ( 'config.ini' => \&write_ini, + 'new.conf' => \&do_new_conf ) } + +A servers method returns a list of processes that needs to be started for +this suite. A process is specified as a pair (regex, hash). A regex must +match a section in the my.cnf template (for example, qr/mysqld\./ corresponds +to all mysqld processes), a hash contains these options: + + SORT => a number, processes are started in the order of increasing SORT + values (and stopped in the reverse order). mysqld has number 300. + START => a function to start a process. It takes two arguments, + My::Config::Group and My::Test. If START is undefined the process + will not be started. + WAIT => a function waits for the process to be started. It takes + My::Config::Group as an argument. Internallys mtr first invokes + START for all processes, then WAIT for all started processes. + +example: sub servers { ( qr/^foo$/ => { SORT => 200, + START => \&start_foo, + WAIT => \&wait_foo } ) } + +See sphinx suite for an example. + +========================== +A suite can have my.cnf template file in the suitedir. +A my.cnf template uses a normal my.cnf syntax - groups, options, +and values - with templating extensions. They are + +* There can be groups with non-standard names, not used by mysqld. + These groups may be used by the suite.pm file somehow. + For example, they can be written to the additional config files. + See sphinx suite for an example. + +* There can be ENV group. It sets values for the environment variables. + +* Values can refer to each other - they will be expanded as needed. + A reference to a value of an option looks like @groupname.optionname. + For example + + [mysqld.2] + master-port= @mysqld.1.port + + it sets the master-port in the mysqld.2 group to the value of + port in the mysqld.1 group. + +* An option name may start from '#'. In the resulting my.cnf it will look + like a comment, but it still can be referred to. For example: + + [example] + #foo = localhost:@mysqld.1.port + bar = http://@example.#foo/index.html + +* There are two special - in this regard - groups. + + Via the ENV group one can refer to any environment variable, not only + to values in the [ENV] group of my.cnf file. + + Via the OPT group one can refer to special values: + @OPT.vardir - a path to vardir + @OPT.port - a new port number is reserved out of the pool. It will not + match any other port number used by this test run. + See sphinx suite for an example. + +Most probably a suite my.cnf will need to start from + + !include include/default_my.cnf + +and then modify the configuration as necessary. +========================== + +A suite can have combinations file in the suitedir. It uses my.cnf syntax +but it cannot use @-substitutions. Instead, it can use $-substitutions for +the environment variables. Because the combination options will not be +merged to a my.cnf, but will be added to the command line. Example: + + [conf1] + opt1=val1 + + [conf2] + opt1=val2 + opt2=$HAVE_SOMETHING + +Such a file will cause every test from the suite to be run twice - once +with mysqld using --opt1=val1 and the other one with mysqld using +--opt1=val2 --opt2=$HAVE_SOMETHING + +One can limit mtr run to a subset of combinations by setting environment +variable SUITENAME_COMBINATIONS to the ':'-separated set of combination +names. E.g. + + RPL_COMBINATIONS=mix:row ./mtr --suite rpl + +See innodb_plugin suite for an example of how suite.pm may set this variable +to exclude unsupported configurations. +========================== + diff --git a/mysql-test/include/default_my.cnf b/mysql-test/include/default_my.cnf index d77fee0e200..17a418ff7b5 100644 --- a/mysql-test/include/default_my.cnf +++ b/mysql-test/include/default_my.cnf @@ -6,9 +6,6 @@ # Run the master.sh script before starting this process #!run-master-sh -log-bin= master-bin - - [mysqlbinlog] disable-force-if-open diff --git a/mysql-test/include/default_mysqld.cnf b/mysql-test/include/default_mysqld.cnf index c93762f6c25..e46c3bc3c17 100644 --- a/mysql-test/include/default_mysqld.cnf +++ b/mysql-test/include/default_mysqld.cnf @@ -13,9 +13,10 @@ key_buffer_size= 1M sort_buffer= 256K max_heap_table_size= 1M +loose-skip-innodb +loose-skip-pbxt + loose-innodb_data_file_path= ibdata1:10M:autoextend slave-net-timeout=120 -log-bin=mysqld-bin - diff --git a/mysql-test/include/have_binlog_format_mixed.opt b/mysql-test/include/have_binlog_format_mixed.opt new file mode 100644 index 00000000000..01cf3e0520f --- /dev/null +++ b/mysql-test/include/have_binlog_format_mixed.opt @@ -0,0 +1 @@ +--binlog-format=mixed diff --git a/mysql-test/include/have_binlog_format_row.opt b/mysql-test/include/have_binlog_format_row.opt new file mode 100644 index 00000000000..83ed8522e72 --- /dev/null +++ b/mysql-test/include/have_binlog_format_row.opt @@ -0,0 +1 @@ +--binlog-format=row diff --git a/mysql-test/include/have_binlog_format_statement.opt b/mysql-test/include/have_binlog_format_statement.opt new file mode 100644 index 00000000000..0dac5e9fb9c --- /dev/null +++ b/mysql-test/include/have_binlog_format_statement.opt @@ -0,0 +1,2 @@ +--binlog-format=statement + diff --git a/mysql-test/include/have_exampledb.inc b/mysql-test/include/have_exampledb.inc deleted file mode 100644 index db3985e3c7c..00000000000 --- a/mysql-test/include/have_exampledb.inc +++ /dev/null @@ -1,4 +0,0 @@ -disable_query_log; ---require r/true.require -select (support = 'YES' or support = 'DEFAULT') as `TRUE` from information_schema.engines where engine = 'example'; -enable_query_log; diff --git a/mysql-test/include/have_innodb.inc b/mysql-test/include/have_innodb.inc index 8944cc46f3e..c3c8b5cc4f2 100644 --- a/mysql-test/include/have_innodb.inc +++ b/mysql-test/include/have_innodb.inc @@ -1,4 +1,5 @@ -disable_query_log; ---require r/true.require -select (support = 'YES' or support = 'DEFAULT' or support = 'ENABLED') as `TRUE` from information_schema.engines where engine = 'innodb'; -enable_query_log; +if (!`SELECT count(*) FROM information_schema.engines WHERE + (support = 'YES' OR support = 'DEFAULT') AND + engine = 'innodb'`){ + skip Needs innodb engine; +} diff --git a/mysql-test/include/have_innodb.opt b/mysql-test/include/have_innodb.opt new file mode 100644 index 00000000000..48457b17309 --- /dev/null +++ b/mysql-test/include/have_innodb.opt @@ -0,0 +1 @@ +--loose-innodb diff --git a/mysql-test/include/have_innodb_plugin.inc b/mysql-test/include/have_innodb_plugin.inc index 6b5fc29d459..5f67fb1f97d 100644 --- a/mysql-test/include/have_innodb_plugin.inc +++ b/mysql-test/include/have_innodb_plugin.inc @@ -1,4 +1,5 @@ -disable_query_log; ---require r/true.require -SELECT (plugin_library LIKE 'ha_innodb_plugin%' OR plugin_description LIKE '%xtradb%') AS `TRUE` FROM information_schema.plugins WHERE LOWER(plugin_name) = 'innodb' AND LOWER(plugin_status) = 'active'; -enable_query_log; +if (!`SELECT COUNT(*) FROM INFORMATION_SCHEMA.PLUGINS + WHERE PLUGIN_NAME = 'innodb' AND PLUGIN_STATUS = 'active' AND + (PLUGIN_LIBRARY LIKE 'ha_innodb_plugin%' OR PLUGIN_DESCRIPTION LIKE '%xtradb%')`) { + skip Need InnoDB plugin or XtraDB; +} diff --git a/mysql-test/include/have_log_bin-master.opt b/mysql-test/include/have_log_bin-master.opt new file mode 100644 index 00000000000..9ce5d80d7e8 --- /dev/null +++ b/mysql-test/include/have_log_bin-master.opt @@ -0,0 +1 @@ +--log-bin=master-bin diff --git a/mysql-test/include/have_log_bin-slave.opt b/mysql-test/include/have_log_bin-slave.opt new file mode 100644 index 00000000000..92012982830 --- /dev/null +++ b/mysql-test/include/have_log_bin-slave.opt @@ -0,0 +1 @@ +--log-bin=slave-bin diff --git a/mysql-test/include/have_log_bin.inc b/mysql-test/include/have_log_bin.inc index 369af9b8e1d..e51205d25ad 100644 --- a/mysql-test/include/have_log_bin.inc +++ b/mysql-test/include/have_log_bin.inc @@ -6,6 +6,8 @@ # # source include/have_log_bin.inc; +source include/not_embedded.inc; + -- require r/have_log_bin.require disable_query_log; show variables like 'log_bin'; diff --git a/mysql-test/include/have_pbxt.opt b/mysql-test/include/have_pbxt.opt new file mode 100644 index 00000000000..54ba9495053 --- /dev/null +++ b/mysql-test/include/have_pbxt.opt @@ -0,0 +1 @@ +--loose-pbxt diff --git a/mysql-test/lib/My/Config.pm b/mysql-test/lib/My/Config.pm index f8416e3df3a..0955c1bb190 100644 --- a/mysql-test/lib/My/Config.pm +++ b/mysql-test/lib/My/Config.pm @@ -6,7 +6,6 @@ use strict; use warnings; use Carp; - sub new { my ($class, $option_name, $option_value)= @_; my $self= bless { name => $option_name, @@ -61,7 +60,7 @@ sub insert { $option->{value}= $value; } else { - my $option= My::Config::Option->new($option_name, $value); + $option= My::Config::Option->new($option_name, $value); # Insert option in list push(@{$self->{options}}, $option); # Insert option in hash @@ -163,6 +162,62 @@ sub if_exist { return $option->value(); } +package My::Config::Group::ENV; +our @ISA=qw(My::Config::Group); + +use strict; +use warnings; +use Carp; + +sub new { + my ($class, $group_name)= @_; + bless My::Config::Group->new($group_name), $class; +} + +# +# Return value for an option in the group, fail if it does not exist +# +sub value { + my ($self, $option_name)= @_; + my $option= $self->option($option_name); + + if (! defined($option) and defined $ENV{$option_name}) { + my $value= $ENV{$option_name}; + $option= My::Config::Option->new($option_name, $value); + } + + croak "No option named '$option_name' in group '$self->{name}'" + if ! defined($option); + + return $option->value(); +} + +package My::Config::Group::OPT; +our @ISA=qw(My::Config::Group); + +use strict; +use warnings; +use Carp; + +sub new { + my ($class, $group_name)= @_; + bless My::Config::Group->new($group_name), $class; +} + +sub options { + my ($self)= @_; + () +} + +sub value { + my ($self, $option_name)= @_; + my $option= $self->option($option_name); + + croak "No option named '$option_name' in group '$self->{name}'" + if ! defined($option); + + return $option->value()->(); +} package My::Config; @@ -182,7 +237,10 @@ sub new { my ($class, $path)= @_; my $group_name= undef; - my $self= bless { groups => [] }, $class; + my $self= bless { groups => [ + My::Config::Group::ENV->new('ENV'), + My::Config::Group::OPT->new('OPT'), + ] }, $class; my $F= IO::File->new($path, "<") or croak "Could not open '$path': $!"; @@ -199,19 +257,13 @@ sub new { } # Magic #! comments - elsif ( $line =~ /^#\!/) { - my $magic= $line; + elsif ( $line =~ /^(#\!\S+)(?:\s*(.*?)\s*)?$/) { + my ($magic, $arg)= ($1, $2); croak "Found magic comment '$magic' outside of group" unless $group_name; #print "$magic\n"; - $self->insert($group_name, $magic, undef); - } - - # Comments - elsif ( $line =~ /^#/ || $line =~ /^;/) { - # Skip comment - next; + $self->insert($group_name, $magic, $arg); } # Empty lines @@ -236,7 +288,7 @@ sub new { } # <option> - elsif ( $line =~ /^([\@\w-]+)\s*$/ ) { + elsif ( $line =~ /^(#?[\w-]+)\s*$/ ) { my $option= $1; croak "Found option '$option' outside of group" @@ -247,7 +299,7 @@ sub new { } # <option>=<value> - elsif ( $line =~ /^([\@\w-]+)\s*=\s*(.*?)\s*$/ ) { + elsif ( $line =~ /^(#?[\w-]+)\s*=\s*(.*?)\s*$/ ) { my $option= $1; my $value= $2; @@ -256,10 +308,17 @@ sub new { #print "$option=$value\n"; $self->insert($group_name, $option, $value); - } else { - croak "Unexpected line '$line' found in '$path'"; } + # Comments + elsif ( $line =~ /^#/ || $line =~ /^;/) { + # Skip comment + next; + } + + else { + croak "Unexpected line '$line' found in '$path'"; + } } undef $F; # Close the file @@ -437,44 +496,4 @@ sub exists { return defined($option); } - -# Overload "to string"-operator with 'stringify' -use overload - '""' => \&stringify; - -# -# Return the config as a string in my.cnf file format -# -sub stringify { - my ($self)= @_; - my $res; - - foreach my $group ($self->groups()) { - $res .= "[$group->{name}]\n"; - - foreach my $option ($group->options()) { - $res .= $option->name(); - my $value= $option->value(); - if (defined $value) { - $res .= "=$value"; - } - $res .= "\n"; - } - $res .= "\n"; - } - return $res; -} - - -# -# Save the config to named file -# -sub save { - my ($self, $path)= @_; - my $F= IO::File->new($path, ">") - or croak "Could not open '$path': $!"; - print $F $self; - undef $F; # Close the file -} - 1; diff --git a/mysql-test/lib/My/ConfigFactory.pm b/mysql-test/lib/My/ConfigFactory.pm index c70831ab4b9..d5414713262 100644 --- a/mysql-test/lib/My/ConfigFactory.pm +++ b/mysql-test/lib/My/ConfigFactory.pm @@ -57,16 +57,12 @@ sub fix_pidfile { sub fix_port { my ($self, $config, $group_name, $group)= @_; - my $hostname= $group->value('#host'); - return $self->{HOSTS}->{$hostname}++; + return $self->{PORT}++; } sub fix_host { my ($self)= @_; - # Get next host from HOSTS array - my @hosts= keys(%{$self->{HOSTS}});; - my $host_no= $self->{NEXT_HOST}++ % @hosts; - return $hosts[$host_no]; + 'localhost' } sub is_unique { @@ -229,7 +225,7 @@ if (IS_WINDOWS) sub fix_ndb_mgmd_port { my ($self, $config, $group_name, $group)= @_; my $hostname= $group->value('HostName'); - return $self->{HOSTS}->{$hostname}++; + return $self->{PORT}++; } @@ -428,20 +424,24 @@ sub post_check_embedded_group { sub resolve_at_variable { my ($self, $config, $group, $option)= @_; + local $_ = $option->value(); + my ($res, $after); - # Split the options value on last . - my @parts= split(/\./, $option->value()); - my $option_name= pop(@parts); - my $group_name= join('.', @parts); + while (m/(.*?)\@((?:\w+\.)+)(#?[-\w]+)/g) { + my ($before, $group_name, $option_name)= ($1, $2, $3); + $after = $'; + chop($group_name); - $group_name =~ s/^\@//; # Remove at + my $from_group= $config->group($group_name) + or croak "There is no group named '$group_name' that ", + "can be used to resolve '$option_name'"; - my $from_group= $config->group($group_name) - or croak "There is no group named '$group_name' that ", - "can be used to resolve '$option_name'"; + my $value= $from_group->value($option_name); + $res .= $before.$value; + } + $res .= $after; - my $from= $from_group->value($option_name); - $config->insert($group->name(), $option->name(), $from) + $config->insert($group->name(), $option->name(), $res) } @@ -453,7 +453,7 @@ sub post_fix_resolve_at_variables { next unless defined $option->value(); $self->resolve_at_variable($config, $group, $option) - if ($option->value() =~ /^\@/); + if ($option->value() =~ /\@/); } } } @@ -595,28 +595,18 @@ sub new_config { croak "you must pass '$required'" unless defined $args->{$required}; } - # Fill in hosts/port hash - my $hosts= {}; - my $baseport= $args->{baseport}; - $args->{hosts}= [ 'localhost' ] unless exists($args->{hosts}); - foreach my $host ( @{$args->{hosts}} ) { - $hosts->{$host}= $baseport; - } - # Open the config template my $config= My::Config->new($args->{'template_path'}); - my $extra_template_path= $args->{'extra_template_path'}; - if ($extra_template_path){ - $config->append(My::Config->new($extra_template_path)); - } my $self= bless { CONFIG => $config, ARGS => $args, - HOSTS => $hosts, - NEXT_HOST => 0, + PORT => $args->{baseport}, SERVER_ID => 1, }, $class; + # add auto-options + $config->insert('OPT', 'port' => sub { fix_port($self, $config) }); + $config->insert('OPT', 'vardir' => sub { shift->{ARGS}->{vardir} }); { # Run pre rules diff --git a/mysql-test/lib/My/Handles.pm b/mysql-test/lib/My/Handles.pm index 66ee22b403f..66ee22b403f 100755..100644 --- a/mysql-test/lib/My/Handles.pm +++ b/mysql-test/lib/My/Handles.pm diff --git a/mysql-test/lib/My/SafeProcess.pm b/mysql-test/lib/My/SafeProcess.pm index b3409020f21..084ef408d5b 100644 --- a/mysql-test/lib/My/SafeProcess.pm +++ b/mysql-test/lib/My/SafeProcess.pm @@ -120,7 +120,7 @@ sub new { my $input = delete($opts{'input'}); my $output = delete($opts{'output'}); my $error = delete($opts{'error'}); - my $verbose = delete($opts{'verbose'}); + my $verbose = delete($opts{'verbose'}) || $::opt_verbose; my $nocore = delete($opts{'nocore'}); my $host = delete($opts{'host'}); my $shutdown = delete($opts{'shutdown'}); diff --git a/mysql-test/lib/My/Suite.pm b/mysql-test/lib/My/Suite.pm new file mode 100644 index 00000000000..69609e1c4f5 --- /dev/null +++ b/mysql-test/lib/My/Suite.pm @@ -0,0 +1,10 @@ +# A default suite class that is used for all suites without their owns suite.pm +# see README.suites for a description + +package My::Suite; + +sub config_files { () } +sub servers { () } + +bless { }; + diff --git a/mysql-test/lib/My/Test.pm b/mysql-test/lib/My/Test.pm index 21dd33336f6..c8bfbd34521 100644 --- a/mysql-test/lib/My/Test.pm +++ b/mysql-test/lib/My/Test.pm @@ -20,6 +20,12 @@ sub new { return $self; } +sub fullname { + my ($self)= @_; + $self->{name} . (defined $self->{combination} + ? " '$self->{combination}'" + : "") +} # # Return a unique key that can be used to diff --git a/mysql-test/lib/mtr_cases.pm b/mysql-test/lib/mtr_cases.pm index 7bdb0e37604..88e078baa7f 100644 --- a/mysql-test/lib/mtr_cases.pm +++ b/mysql-test/lib/mtr_cases.pm @@ -39,7 +39,6 @@ our $enable_disabled; our $default_storage_engine; our $opt_with_ndbcluster_only; our $defaults_file; -our $defaults_extra_file; our $quick_collect; sub collect_option { @@ -68,21 +67,10 @@ require "mtr_misc.pl"; my $do_test_reg; my $skip_test_reg; -# Related to adding InnoDB plugin combinations -my $lib_innodb_plugin; - # If "Quick collect", set to 1 once a test to run has been found. my $some_test_found; -sub find_innodb_plugin { - $lib_innodb_plugin= - my_find_file($::basedir, - ["storage/innodb_plugin", "storage/innodb_plugin/.libs", - "lib/mysql/plugin", "lib/plugin"], - ["ha_innodb_plugin.dll", "ha_innodb_plugin.so", - "ha_innodb_plugin.sl"], - NOT_REQUIRED); -} +my $default_suite_object = do 'My/Suite.pm'; sub init_pattern { my ($from, $what)= @_; @@ -116,8 +104,6 @@ sub collect_test_cases ($$$) { $do_test_reg= init_pattern($do_test, "--do-test"); $skip_test_reg= init_pattern($skip_test, "--skip-test"); - &find_innodb_plugin; - # If not reordering, we also shouldn't group by suites, unless # no test cases were named. # This also effects some logic in the loop following this. @@ -188,17 +174,17 @@ sub collect_test_cases ($$$) { my $opts= $tinfo->{'master_opt'} ? $tinfo->{'master_opt'} : []; push(@criteria, join("!", sort @{$opts}) . "~"); - $sort_criteria{$tinfo->{name}} = join(" ", @criteria); + $sort_criteria{$tinfo->fullname()} = join(" ", @criteria); } @$cases = sort { - $sort_criteria{$a->{'name'}} . $a->{'name'} cmp - $sort_criteria{$b->{'name'}} . $b->{'name'}; } @$cases; + $sort_criteria{$a->fullname()} . $a->fullname() cmp + $sort_criteria{$b->fullname()} . $b->fullname() } @$cases; # For debugging the sort-order # foreach my $tinfo (@$cases) # { - # print("$sort_criteria{$tinfo->{'name'}} -> \t$tinfo->{'name'}\n"); + # print $sort_criteria{$tinfo->fullname()}," -> \t",$tinfo->fullname(),"\n"; # } } @@ -310,6 +296,17 @@ sub collect_one_suite mtr_verbose("testdir: $testdir"); mtr_verbose("resdir: $resdir"); + # + # Load the Suite object + # + unless ($::suites{$suite}) { + if (-f "$suitedir/suite.pm") { + $::suites{$suite} = do "$suitedir/suite.pm"; + } else { + $::suites{$suite} = $default_suite_object; + } + } + # ---------------------------------------------------------------------- # Build a hash of disabled testcases for this suite # ---------------------------------------------------------------------- @@ -438,14 +435,16 @@ sub collect_one_suite { # Read combinations file in my.cnf format mtr_verbose("Read combinations file"); + my %env_filter = map { $_ => 1 } split /:/, $ENV{"\U${suite}_COMBINATIONS"}; my $config= My::Config->new($combination_file); foreach my $group ($config->groups()) { my $comb= {}; $comb->{name}= $group->name(); + next if %env_filter and not $env_filter{$comb->{name}}; foreach my $option ( $group->options() ) { push(@{$comb->{comb_opt}}, $option->option()); } - push(@combinations, $comb); + push(@combinations, $comb) if $comb->{comb_opt}; } } @@ -539,28 +538,7 @@ sub optimize_cases { # support it # ======================================================= #print "binlog_format: $binlog_format\n"; - if (defined $binlog_format ) - { - # ======================================================= - # Fixed --binlog-format=x specified on command line - # ======================================================= - if ( defined $tinfo->{'binlog_formats'} ) - { - #print "binlog_formats: ". join(", ", @{$tinfo->{binlog_formats}})."\n"; - - # The test supports different binlog formats - # check if the selected one is ok - my $supported= - grep { $_ eq $binlog_format } @{$tinfo->{'binlog_formats'}}; - if ( !$supported ) - { - $tinfo->{'skip'}= 1; - $tinfo->{'comment'}= - "Doesn't support --binlog-format='$binlog_format'"; - } - } - } - else + if (not defined $binlog_format ) { # ======================================================= # Use dynamic switching of binlog format @@ -623,10 +601,6 @@ sub optimize_cases { $tinfo->{'ndb_test'}= 1 if ( $default_engine =~ /^ndb/i ); - $tinfo->{'innodb_test'}= 1 - if ( $default_engine =~ /^innodb/i ); - $tinfo->{'pbxt_test'}= 1 - if ( $default_engine =~ /^pbxt/i ); } } @@ -758,7 +732,7 @@ sub collect_one_test_case { name => "$suitename.$tname", shortname => $tname, path => "$testdir/$filename", - + suite => $suitename, ); my $result_file= "$resdir/$tname.result"; @@ -880,7 +854,7 @@ sub collect_one_test_case { if ( -f "$testdir/$tname.slave-mi"); - tags_from_test_file($tinfo,"$testdir/${tname}.test"); + my @source_files = tags_from_test_file($tinfo,"$testdir/${tname}.test"); # Get default storage engine from suite.opt file @@ -897,12 +871,6 @@ sub collect_one_test_case { $tinfo->{'ndb_test'}= 1 if ( $local_default_storage_engine =~ /^ndb/i ); - $tinfo->{'innodb_test'}= 1 - if ( $local_default_storage_engine =~ /^innodb/i ); - - $tinfo->{'pbxt_test'}= 1 - if ( $local_default_storage_engine =~ /^pbxt/i ); - } if ( $tinfo->{'big_test'} and ! $::opt_big_test ) @@ -949,72 +917,6 @@ sub collect_one_test_case { } } - if ($tinfo->{'federated_test'}) - { - # This is a test that needs federated, enable it - push(@{$tinfo->{'master_opt'}}, "--loose-federated"); - push(@{$tinfo->{'slave_opt'}}, "--loose-federated"); - } - - if ( $tinfo->{'innodb_test'} ) - { - # This is a test that needs innodb - if ( $::mysqld_variables{'innodb'} eq "OFF" || - ! exists $::mysqld_variables{'innodb'} ) - { - # innodb is not supported, skip it - $tinfo->{'skip'}= 1; - $tinfo->{'comment'}= "No innodb support"; - return $tinfo; - } - } - elsif ( $tinfo->{'innodb_plugin_test'} ) - { - # This is a test that needs the innodb plugin - if (&find_innodb_plugin) - { - my $sep= (IS_WINDOWS) ? ';' : ':'; - my $plugin_filename= basename($lib_innodb_plugin); - my $plugin_list= - "innodb=$plugin_filename$sep" . - "innodb_trx=$plugin_filename$sep" . - "innodb_locks=$plugin_filename$sep" . - "innodb_lock_waits=$plugin_filename$sep" . - "innodb_cmp=$plugin_filename$sep" . - "innodb_cmp_reset=$plugin_filename$sep" . - "innodb_cmpmem=$plugin_filename$sep" . - "innodb_cmpmem_reset=$plugin_filename"; - - foreach my $k ('master_opt', 'slave_opt') { - push(@{$tinfo->{$k}}, '--ignore-builtin-innodb'); - push(@{$tinfo->{$k}}, '--plugin-dir=' . dirname($lib_innodb_plugin)); - push(@{$tinfo->{$k}}, "--plugin-load=$plugin_list"); - } - } - } - else - { - push(@{$tinfo->{'master_opt'}}, "--loose-skip-innodb"); - push(@{$tinfo->{'slave_opt'}}, "--loose-skip-innodb"); - } - - if ( $tinfo->{'need_binlog'} ) - { - if (grep(/^--skip-log-bin/, @::opt_extra_mysqld_opt) ) - { - $tinfo->{'skip'}= 1; - $tinfo->{'comment'}= "Test needs binlog"; - return $tinfo; - } - } - else - { - # Test does not need binlog, add --skip-binlog to - # the options used when starting - push(@{$tinfo->{'master_opt'}}, "--loose-skip-log-bin"); - push(@{$tinfo->{'slave_opt'}}, "--loose-skip-log-bin"); - } - if ( $tinfo->{'rpl_test'} ) { if ( $skip_rpl ) @@ -1085,28 +987,6 @@ sub collect_one_test_case { $tinfo->{template_path}= $config; } - if ( $tinfo->{'pbxt_test'} ) - { - # This is a test that needs pbxt - if ( $::mysqld_variables{'pbxt'} eq "OFF" || - ! exists $::mysqld_variables{'pbxt'} ) - { - # Engine is not supported, skip it - $tinfo->{'skip'}= 1; - return $tinfo; - } - } - else - { - # Only disable engine if it's on by default (to avoid warnings about - # not existing loose options - if ( $::mysqld_variables{'pbxt'} eq "ON") - { - push(@{$tinfo->{'master_opt'}}, "--loose-skip-pbxt"); - push(@{$tinfo->{'slave_opt'}}, "--loose-skip-pbxt"); - } - } - if ( $tinfo->{'example_plugin_test'} ) { if ( !$ENV{'HA_EXAMPLE_SO'} ) @@ -1127,27 +1007,27 @@ sub collect_one_test_case { } } - - # Set extra config file to use - if (defined $defaults_extra_file) { - $tinfo->{extra_template_path}= $defaults_extra_file; + if (not ref $::suites{$tinfo->{suite}}) + { + $tinfo->{'skip'}= 1; + $tinfo->{'comment'}= $::suites{$tinfo->{suite}}; + return $tinfo; } # ---------------------------------------------------------------------- - # Append mysqld extra options to both master and slave + # Append mysqld extra options to master and slave, as appropriate # ---------------------------------------------------------------------- + for (@source_files) { + s/\.\w+$//; + process_opts_file($tinfo, "$_.opt", 'master_opt'); + process_opts_file($tinfo, "$_.opt", 'slave_opt'); + process_opts_file($tinfo, "$_-master.opt", 'master_opt'); + process_opts_file($tinfo, "$_-slave.opt", 'slave_opt'); + } + push(@{$tinfo->{'master_opt'}}, @::opt_extra_mysqld_opt); push(@{$tinfo->{'slave_opt'}}, @::opt_extra_mysqld_opt); - # ---------------------------------------------------------------------- - # Add master opts, extra options only for master - # ---------------------------------------------------------------------- - process_opts_file($tinfo, "$testdir/$tname-master.opt", 'master_opt'); - - # ---------------------------------------------------------------------- - # Add slave opts, list of extra option only for slave - # ---------------------------------------------------------------------- - process_opts_file($tinfo, "$testdir/$tname-slave.opt", 'slave_opt'); return $tinfo; } @@ -1157,24 +1037,6 @@ sub collect_one_test_case { # the specified value in "tinfo" my @tags= ( - ["include/have_binlog_format_row.inc", "binlog_formats", ["row"]], - ["include/have_binlog_format_statement.inc", "binlog_formats", ["statement"]], - ["include/have_binlog_format_mixed.inc", "binlog_formats", ["mixed"]], - ["include/have_binlog_format_mixed_or_row.inc", - "binlog_formats", ["mixed", "row"]], - ["include/have_binlog_format_mixed_or_statement.inc", - "binlog_formats", ["mixed", "statement"]], - ["include/have_binlog_format_row_or_statement.inc", - "binlog_formats", ["row", "statement"]], - - ["include/have_log_bin.inc", "need_binlog", 1], - - ["include/have_innodb.inc", "innodb_test", 1], - ["include/have_innodb_plugin.inc", "innodb_plugin_test", 1], - ["include/have_real.inc", "innodb_test", 1], - ["include/have_real_innodb_plugin.inc", "innodb_plugin_test", 1], - ["include/have_xtradb.inc", "innodb_test", 1], - ["include/have_pbxt.inc", "pbxt_test", 1], ["include/big_test.inc", "big_test", 1], ["include/have_debug.inc", "need_debug", 1], ["include/have_ndb.inc", "ndb_test", 1], @@ -1182,7 +1044,6 @@ my @tags= ["include/master-slave.inc", "rpl_test", 1], ["include/ndb_master-slave.inc", "rpl_test", 1], ["include/ndb_master-slave.inc", "ndb_test", 1], - ["federated.inc", "federated_test", 1], ["include/not_embedded.inc", "not_embedded", 1], ["include/not_valgrind.inc", "not_valgrind", 1], ["include/have_example_plugin.inc", "example_plugin_test", 1], @@ -1196,6 +1057,7 @@ sub tags_from_test_file { my $file= shift; #mtr_verbose("$file"); my $F= IO::File->new($file) or mtr_error("can't open file \"$file\": $!"); + my @all_files=($file); while ( my $line= <$F> ) { @@ -1231,13 +1093,13 @@ sub tags_from_test_file { # Only source the file if it exists, we may get # false positives in the regexes above if someone # writes "source nnnn;" in a test case(such as mysqltest.test) - tags_from_test_file($tinfo, $sourced_file); + unshift @all_files, tags_from_test_file($tinfo, $sourced_file); last; } } } - } + @all_files; } sub unspace { @@ -1250,6 +1112,7 @@ sub unspace { sub opts_from_file ($) { my $file= shift; + local $_; open(FILE,"<",$file) or mtr_error("can't open file \"$file\": $!"); my @args; diff --git a/mysql-test/lib/mtr_report.pm b/mysql-test/lib/mtr_report.pm index f6a6a2b63b5..c13e6a93319 100644 --- a/mysql-test/lib/mtr_report.pm +++ b/mysql-test/lib/mtr_report.pm @@ -61,14 +61,10 @@ sub _name { sub _mtr_report_test_name ($) { my $tinfo= shift; - my $tname= $tinfo->{name}; + my $tname= $tinfo->fullname(); return unless defined $verbose; - # Add combination name if any - $tname.= " '$tinfo->{combination}'" - if defined $tinfo->{combination}; - print _name(). _timestamp(); printf "%-40s ", $tname; my $worker = $tinfo->{worker}; diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 678f5ff23bf..0d673c87c4c 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -130,7 +130,7 @@ my $path_config_file; # The generated config file, var/my.cnf # executables will be used by the test suite. our $opt_vs_config = $ENV{'MTR_VS_CONFIG'}; -my $DEFAULT_SUITES= "main,binlog,federated,rpl,maria,parts,innodb,innodb_plugin,percona,vcol,oqgraph"; +my $DEFAULT_SUITES= "main,binlog,federated,rpl,maria,parts,innodb,innodb_plugin,percona,vcol,oqgraph,ndb"; my $opt_suites; our $opt_verbose= 0; # Verbose output, enable with --verbose @@ -257,6 +257,8 @@ our $debug_compiled_binaries; our %mysqld_variables; +our %suites; + my $source_dist= 0; my $opt_max_save_core= env_or_val(MTR_MAX_SAVE_CORE => 5); @@ -711,6 +713,8 @@ sub run_test_server ($$$) { $next= splice(@$tests, $second_best, 1); } + xterm_stat(scalar(@$tests)); + if ($next) { #$next->print_test(); $next->write_test($sock, 'TESTCASE'); @@ -807,7 +811,7 @@ sub run_worker ($) { # We need to gracefully shut down the servers to see any # Valgrind memory leak errors etc. since last server restart. if ($opt_warnings) { - stop_servers(all_servers()); + stop_servers(reverse all_servers()); if(check_warnings_post_shutdown($server)) { # Warnings appeared in log file(s) during final server shutdown. exit(1); @@ -1592,7 +1596,7 @@ sub collect_mysqld_features { my $cmd= join(" ", $exe_mysqld, @$args); my $list= `$cmd`; - print "cmd: $cmd\n"; + mtr_verbose("cmd: $cmd"); foreach my $line (split('\n', $list)) { @@ -2490,7 +2494,7 @@ sub check_ndbcluster_support ($) { } -sub ndbcluster_wait_started($$){ +sub ndbcluster_wait_started { my $cluster= shift; my $ndb_waiter_extra_opt= shift; my $path_waitlog= join('/', $opt_vardir, $cluster->name(), "ndb_waiter.log"); @@ -2658,7 +2662,7 @@ sub ndbd_start { sub ndbcluster_start ($) { - my $cluster= shift; + my ($cluster) = @_; mtr_verbose("ndbcluster_start '".$cluster->name()."'"); @@ -2678,6 +2682,109 @@ sub ndbcluster_start ($) { } +sub mysql_server_start($) { + my ($mysqld, $tinfo) = @_; + + if ( $mysqld->{proc} ) + { + # Already started + + # Write start of testcase to log file + mark_log($mysqld->value('#log-error'), $tinfo); + + return; + } + + my $datadir= $mysqld->value('datadir'); + if (not $opt_start_dirty) + { + + my @options= ('log-bin', 'relay-log'); + foreach my $option_name ( @options ) { + next unless $mysqld->option($option_name); + + my $file_name= $mysqld->value($option_name); + next unless + defined $file_name and + -e $file_name; + + mtr_debug(" -removing '$file_name'"); + unlink($file_name) or die ("unable to remove file '$file_name'"); + } + + if (-d $datadir ) { + preserve_error_log($mysqld); + mtr_verbose(" - removing '$datadir'"); + rmtree($datadir); + } + } + + my $mysqld_basedir= $mysqld->value('basedir'); + if ( $basedir eq $mysqld_basedir ) + { + if (! $opt_start_dirty) # If dirty, keep possibly grown system db + { + # Copy datadir from installed system db + for my $path ( "$opt_vardir", "$opt_vardir/..") { + my $install_db= "$path/install.db"; + copytree($install_db, $datadir) + if -d $install_db; + } + mtr_error("Failed to copy system db to '$datadir'") + unless -d $datadir; + } + } + else + { + mysql_install_db($mysqld); # For versional testing + + mtr_error("Failed to install system db to '$datadir'") + unless -d $datadir; + + } + restore_error_log($mysqld); + + # Create the servers tmpdir + my $tmpdir= $mysqld->value('tmpdir'); + mkpath($tmpdir) unless -d $tmpdir; + + # Write start of testcase to log file + mark_log($mysqld->value('#log-error'), $tinfo); + + # Run <tname>-master.sh + if ($mysqld->option('#!run-master-sh') and + run_sh_script($tinfo->{master_sh}) ) + { + $tinfo->{'comment'}= "Failed to execute '$tinfo->{master_sh}'"; + return 1; + } + + # Run <tname>-slave.sh + if ($mysqld->option('#!run-slave-sh') and + run_sh_script($tinfo->{slave_sh})) + { + $tinfo->{'comment'}= "Failed to execute '$tinfo->{slave_sh}'"; + return 1; + } + + if (!$opt_embedded_server) + { + my $extra_opts= get_extra_opts($mysqld, $tinfo); + mysqld_start($mysqld,$extra_opts); + + # Save this test case information, so next can examine it + $mysqld->{'started_tinfo'}= $tinfo; + } +} + +sub mysql_server_wait { + my ($mysqld) = @_; + + return not sleep_until_file_created($mysqld->value('pid-file'), + $opt_start_timeout, + $mysqld->{'proc'}); +} + sub create_config_file_for_extern { my %opts= ( @@ -3452,9 +3559,82 @@ sub restart_forced_by_test # Return timezone value of tinfo or default value sub timezone { my ($tinfo)= @_; - return $tinfo->{timezone} || "DEFAULT"; + local $_ = $tinfo->{timezone}; + return 'DEFAULT' unless defined $_; + s/\$\{(\w+)\}/envsubst($1)/ge; + s/\$(\w+)/envsubst($1)/ge; + $_; +} + +sub mycnf_create { + my ($config) = @_; + my $res; + + foreach my $group ($config->groups()) { + $res .= "[$group->{name}]\n"; + + foreach my $option ($group->options()) { + $res .= $option->name(); + my $value= $option->value(); + if (defined $value) { + $res .= "=$value"; + } + $res .= "\n"; + } + $res .= "\n"; + } + $res; +} + +sub config_files($) { + my ($tinfo) = @_; + ( + 'my.cnf' => \&mycnf_create, + $suites{$tinfo->{suite}}->config_files() + ); +} + +sub _like { return $config ? $config->like($_[0]) : (); } +sub mysqlds { return _like('mysqld\.'); } +sub ndbds { return _like('cluster_config\.ndbd\.');} +sub ndb_mgmds { return _like('cluster_config\.ndb_mgmd\.'); } + +sub fix_servers($) { + my ($tinfo) = @_; + return () unless $config; + my %servers = ( + qr/mysqld\./ => { + SORT => 300, + START => \&mysql_server_start, + WAIT => \&mysql_server_wait, + }, + qr/mysql_cluster\./ => { + SORT => 200, + START => \&ndbcluster_start, + WAIT => \&ndbcluster_wait_started, + }, + qr/cluster_config\.ndb_mgmd\./ => { + SORT => 210, + START => undef, + }, + qr/cluster_config\.ndbd\./ => { + SORT => 220, + START => undef, + }, + $suites{$tinfo->{suite}}->servers() + ); + for ($config->groups()) { + while (my ($re,$prop) = each %servers) { + @$_{keys %$prop} = values %$prop if $_->{name} =~ /^$re/; + } + } } +sub all_servers { + return unless $config; + ( sort { $a->{SORT} <=> $b->{SORT} } + grep { defined $_->{SORT} } $config->groups() ); +} # Storage for changed environment variables my %old_env; @@ -3497,7 +3677,7 @@ sub run_testcase ($$) { if ( @restart != 0) { # Remember that we restarted for this test case (count restarts) $tinfo->{'restarted'}= 1; - stop_servers(@restart ); + stop_servers(reverse @restart); if ($opt_warnings) { check_warnings_post_shutdown($server_socket); } @@ -3533,7 +3713,6 @@ sub run_testcase ($$) { vardir => $opt_vardir, tmpdir => $opt_tmpdir, baseport => $baseport, - #hosts => [ 'host1', 'host2' ], user => $opt_user, password => '', ssl => $opt_ssl_supported, @@ -3541,8 +3720,16 @@ sub run_testcase ($$) { } ); - # Write the new my.cnf - $config->save($path_config_file); + fix_servers($tinfo); + + # Write config files: + my %config_files = config_files($tinfo); + while (my ($file, $generate) = each %config_files) { + my ($path) = "$opt_vardir/$file"; + open (F, '>', $path) or die "Could not open '$path': $!"; + print F &$generate($config); + close F; + } # Remember current config so a restart can occur when a test need # to use a different one @@ -3685,7 +3872,7 @@ sub run_testcase ($$) { if ($opt_warnings) { # Checking error logs for warnings, so need to stop server # gracefully so that memory leaks etc. can be properly detected. - stop_servers(all_servers()); + stop_servers(reverse all_servers()); check_warnings_post_shutdown($server_socket); # Even if we got warnings here, we should not fail this # particular test, as the warnings may be caused by an earlier @@ -3843,7 +4030,8 @@ sub run_testcase ($$) { # valuable debugging information even if there is no test failure recorded. sub _preserve_error_log_names { my ($mysqld)= @_; - my $error_log_file= $mysqld->value('#log-error'); + my $error_log_file= $mysqld->if_exist('#log-error'); + return unless $error_log_file and -r $error_log_file; my $error_log_dir= dirname($error_log_file); my $save_name= $error_log_dir ."/../". $mysqld->name() .".error.log"; return ($error_log_file, $save_name); @@ -3852,14 +4040,14 @@ sub _preserve_error_log_names { sub preserve_error_log { my ($mysqld)= @_; my ($error_log_file, $save_name)= _preserve_error_log_names($mysqld); - my $res= rename($error_log_file, $save_name); + rename($error_log_file, $save_name) if $save_name; # Ignore any errors, as it's just a best-effort to keep the log if possible. } sub restore_error_log { my ($mysqld)= @_; my ($error_log_file, $save_name)= _preserve_error_log_names($mysqld); - my $res= rename($save_name, $error_log_file); + rename($save_name, $error_log_file) if $save_name; } # Keep track of last position in mysqld error log where we scanned for @@ -3903,6 +4091,8 @@ sub pre_write_errorlog { sub extract_server_log ($$) { my ($error_log, $tname) = @_; + + return unless $error_log; # Open the servers .err log file and read all lines # belonging to current test into @lines @@ -3945,9 +4135,9 @@ sub get_log_from_proc ($$) { my ($proc, $name)= @_; my $srv_log= ""; - foreach my $mysqld (mysqlds()) { + foreach my $mysqld (all_servers()) { if ($mysqld->{proc} eq $proc) { - my @srv_lines= extract_server_log($mysqld->value('#log-error'), $name); + my @srv_lines= extract_server_log($mysqld->if_exist('#log-error'), $name); $srv_log= "\nServer log from this test:\n" . join ("", @srv_lines); last; } @@ -4026,15 +4216,18 @@ sub extract_warning_lines ($) { my @antipatterns = ( qr/error .*connecting to master/, + qr/Plugin 'ndbcluster' will be forced to shutdown/, qr/InnoDB: Error: in ALTER TABLE `test`.`t[12]`/, qr/InnoDB: Error: table `test`.`t[12]` does not exist in the InnoDB internal/, qr/Slave: Unknown table 't1' Error_code: 1051/, qr/Slave SQL:.*(Error_code: [[:digit:]]+|Query:.*)/, qr/slave SQL thread aborted/, - qr/unknown option '--loose-/, - qr/unknown variable 'loose-/, + qr/unknown option '--loose[-_]/, + qr/unknown variable 'loose[-_]/, qr/Now setting lower_case_table_names to [02]/, qr/Setting lower_case_table_names=2/, + qr/You have forced lower_case_table_names to 0/, + qr/Plugin 'ndbcluster' will be forced to shutdow/, qr/deprecated/, qr/Slave SQL thread retried transaction/, qr/Slave \(additional info\)/, @@ -4343,29 +4536,18 @@ sub clean_dir { sub clean_datadir { - mtr_verbose("Cleaning datadirs..."); if (started(all_servers()) != 0){ mtr_error("Trying to clean datadir before all servers stopped"); } - foreach my $cluster ( clusters() ) + for (all_servers()) { - my $cluster_dir= "$opt_vardir/".$cluster->{name}; - mtr_verbose(" - removing '$cluster_dir'"); - rmtree($cluster_dir); - - } - - foreach my $mysqld ( mysqlds() ) - { - my $mysqld_dir= dirname($mysqld->value('datadir')); - preserve_error_log($mysqld); - if (-d $mysqld_dir ) { - mtr_verbose(" - removing '$mysqld_dir'"); - rmtree($mysqld_dir); - } + preserve_error_log($_); # or at least, try to + my $dir= "$opt_vardir/".$_->{name}; + mtr_verbose(" - removing '$dir'"); + rmtree($dir); } # Remove all files in tmp and var/tmp @@ -4388,17 +4570,6 @@ sub save_datadir_after_failure($$) { } -sub remove_ndbfs_from_ndbd_datadir { - my ($ndbd_datadir)= @_; - # Remove the ndb_*_fs directory from ndbd.X/ dir - foreach my $ndbfs_dir ( glob("$ndbd_datadir/ndb_*_fs") ) - { - next unless -d $ndbfs_dir; # Skip if not a directory - rmtree($ndbfs_dir); - } -} - - sub after_failure ($) { my ($tinfo)= @_; @@ -4415,31 +4586,18 @@ sub after_failure ($) { mkpath($save_dir) if ! -d $save_dir; - # Save the used my.cnf file - copy($path_config_file, $save_dir); + # Save the used config files + my %config_files = config_files($tinfo); + while (my ($file, $generate) = each %config_files) { + copy("$opt_vardir/$file", $save_dir); + } # Copy the tmp dir copytree("$opt_vardir/tmp/", "$save_dir/tmp/"); - if ( clusters() ) { - foreach my $cluster ( clusters() ) { - my $cluster_dir= "$opt_vardir/".$cluster->{name}; - - # Remove the fileystem of each ndbd - foreach my $ndbd ( in_cluster($cluster, ndbds()) ) - { - my $ndbd_datadir= $ndbd->value("DataDir"); - remove_ndbfs_from_ndbd_datadir($ndbd_datadir); - } - - save_datadir_after_failure($cluster_dir, $save_dir); - } - } - else { - foreach my $mysqld ( mysqlds() ) { - my $data_dir= $mysqld->value('datadir'); - save_datadir_after_failure(dirname($data_dir), $save_dir); - } + foreach (all_servers()) { + my $dir= "$opt_vardir/".$_->{name}; + save_datadir_after_failure($dir, $save_dir); } } @@ -4577,8 +4735,8 @@ sub mysqld_arguments ($$$) { mtr_add_arg($args, "%s--log-output=table,file"); } - # Check if "extra_opt" contains skip-log-bin - my $skip_binlog= grep(/^(--|--loose-)skip-log-bin/, @$extra_opts); + # Check if "extra_opt" contains --log-bin + my $skip_binlog= not grep /^--(loose-)?log-bin/, @$extra_opts; # Indicate to mysqld it will be debugged in debugger if ( $glob_debugger ) @@ -4834,8 +4992,7 @@ sub server_need_restart { return 1; } - my $is_mysqld= grep ($server eq $_, mysqlds()); - if ($is_mysqld) + if ($server->name() =~ /^mysqld\./) { # Check that running process was started with same options @@ -4887,17 +5044,9 @@ sub servers_need_restart($) { -# -# Return list of specific servers -# - there is no servers in an empty config -# -sub _like { return $config ? $config->like($_[0]) : (); } -sub mysqlds { return _like('mysqld.'); } -sub ndbds { return _like('cluster_config.ndbd.');} -sub ndb_mgmds { return _like('cluster_config.ndb_mgmd.'); } -sub clusters { return _like('mysql_cluster.'); } -sub all_servers { return ( mysqlds(), ndb_mgmds(), ndbds() ); } +############################################ +############################################ # # Filter a list of servers and return only those that are part @@ -4951,28 +5100,10 @@ sub get_extra_opts { sub stop_servers($$) { my (@servers)= @_; - if ( join('|', @servers) eq join('|', all_servers()) ) - { - # All servers are going down, use some kind of order to - # avoid too many warnings in the log files - - mtr_report("Restarting all servers"); - - # mysqld processes - My::SafeProcess::shutdown( $opt_shutdown_timeout, started(mysqlds()) ); - - # cluster processes - My::SafeProcess::shutdown( $opt_shutdown_timeout, - started(ndbds(), ndb_mgmds()) ); - } - else - { - mtr_report("Restarting ", started(@servers)); + mtr_report("Restarting ", started(@servers)); - # Stop only some servers - My::SafeProcess::shutdown( $opt_shutdown_timeout, - started(@servers) ); - } + My::SafeProcess::shutdown($opt_shutdown_timeout, + started(@servers)); foreach my $server (@servers) { @@ -4999,145 +5130,14 @@ sub stop_servers($$) { sub start_servers($) { my ($tinfo)= @_; - # Start clusters - foreach my $cluster ( clusters() ) - { - ndbcluster_start($cluster); - } - - # Start mysqlds - foreach my $mysqld ( mysqlds() ) - { - if ( $mysqld->{proc} ) - { - # Already started - - # Write start of testcase to log file - mark_log($mysqld->value('#log-error'), $tinfo); - - next; - } - - my $datadir= $mysqld->value('datadir'); - if ($opt_start_dirty) - { - # Don't delete anything if starting dirty - ; - } - else - { - - my @options= ('log-bin', 'relay-log'); - foreach my $option_name ( @options ) { - next unless $mysqld->option($option_name); - - my $file_name= $mysqld->value($option_name); - next unless - defined $file_name and - -e $file_name; - - mtr_debug(" -removing '$file_name'"); - unlink($file_name) or die ("unable to remove file '$file_name'"); - } - - if (-d $datadir ) { - preserve_error_log($mysqld); - mtr_verbose(" - removing '$datadir'"); - rmtree($datadir); - } - } - - my $mysqld_basedir= $mysqld->value('basedir'); - if ( $basedir eq $mysqld_basedir ) - { - if (! $opt_start_dirty) # If dirty, keep possibly grown system db - { - # Copy datadir from installed system db - for my $path ( "$opt_vardir", "$opt_vardir/..") { - my $install_db= "$path/install.db"; - copytree($install_db, $datadir) - if -d $install_db; - } - mtr_error("Failed to copy system db to '$datadir'") - unless -d $datadir; - } - } - else - { - mysql_install_db($mysqld); # For versional testing - - mtr_error("Failed to install system db to '$datadir'") - unless -d $datadir; - - } - restore_error_log($mysqld); - - # Create the servers tmpdir - my $tmpdir= $mysqld->value('tmpdir'); - mkpath($tmpdir) unless -d $tmpdir; - - # Write start of testcase to log file - mark_log($mysqld->value('#log-error'), $tinfo); - - # Run <tname>-master.sh - if ($mysqld->option('#!run-master-sh') and - run_sh_script($tinfo->{master_sh}) ) - { - $tinfo->{'comment'}= "Failed to execute '$tinfo->{master_sh}'"; - return 1; - } - - # Run <tname>-slave.sh - if ($mysqld->option('#!run-slave-sh') and - run_sh_script($tinfo->{slave_sh})) - { - $tinfo->{'comment'}= "Failed to execute '$tinfo->{slave_sh}'"; - return 1; - } - - if (!$opt_embedded_server) - { - my $extra_opts= get_extra_opts($mysqld, $tinfo); - mysqld_start($mysqld,$extra_opts); - - # Save this test case information, so next can examine it - $mysqld->{'started_tinfo'}= $tinfo; - } - - } - - # Wait for clusters to start - foreach my $cluster ( clusters() ) - { - if (ndbcluster_wait_started($cluster, "")) - { - # failed to start - $tinfo->{'comment'}= "Start of '".$cluster->name()."' cluster failed"; - return 1; - } + for (all_servers()) { + $_->{START}->($_, $tinfo) if $_->{START}; } - # Wait for mysqlds to start - foreach my $mysqld ( mysqlds() ) - { - next if !started($mysqld); - - if (sleep_until_file_created($mysqld->value('pid-file'), - $opt_start_timeout, - $mysqld->{'proc'}) == 0) { - $tinfo->{comment}= - "Failed to start ".$mysqld->name(); - - my $logfile= $mysqld->value('#log-error'); - if ( defined $logfile and -f $logfile ) - { - my @srv_lines= extract_server_log($logfile, $tinfo->{name}); - $tinfo->{logfile}= "Server log is:\n" . join ("", @srv_lines); - } - else - { - $tinfo->{logfile}= "Could not open server logfile: '$logfile'"; - } + for (all_servers()) { + next unless $_->{WAIT} and started($_); + if ($_->{WAIT}->($_)) { + $tinfo->{comment}= "Failed to start ".$_->name(); return 1; } } @@ -5835,3 +5835,25 @@ sub list_options ($) { exit(1); } + +sub time_format($) { + sprintf '%d:%02d:%02d', $_[0]/3600, ($_[0]/60)%60, $_[0]%60; +} + +my $num_tests; + +sub xterm_stat { + if (-t STDOUT and $ENV{TERM} =~ /xterm/) { + my ($left) = @_; + + # 2.5 -> best by test + $num_tests = $left + 2.5 unless $num_tests; + + my $done = $num_tests - $left; + my $spent = time - $^T; + + printf "\e];mtr: spent %s on %d tests. %s (%d tests) left\a", + time_format($spent), $done, + time_format($spent/$done * $left), $left; + } +} diff --git a/mysql-test/r/exampledb.result b/mysql-test/r/exampledb.result deleted file mode 100644 index 6eea24e2e1f..00000000000 --- a/mysql-test/r/exampledb.result +++ /dev/null @@ -1,8 +0,0 @@ -drop database if exists events_test; -drop database if exists events_test2; -drop table if exists t1; -CREATE TABLE t1 ( -Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, -Varor_period smallint(4) unsigned DEFAULT '0' NOT NULL -) ENGINE=example; -drop table t1; diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result index 645dd460735..deda00364aa 100644 --- a/mysql-test/r/group_by.result +++ b/mysql-test/r/group_by.result @@ -1809,5 +1809,22 @@ SELECT MAX(t2.a) FROM t2 LEFT JOIN t1 ON t2.a = t1.a; MAX(t2.a) 2 DROP TABLE t1, t2; +CREATE TABLE t1 (a int(11) NOT NULL); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 ( +key_col int(11) NOT NULL, +KEY (key_col) +); +INSERT INTO t2 VALUES (1),(2); +select min(t2.key_col) from t1,t2 where t1.a=1; +min(t2.key_col) +1 +select min(t2.key_col) from t1,t2 where t1.a > 1000; +min(t2.key_col) +NULL +select min(t2.key_col)+1 from t1,t2 where t1.a> 1000; +min(t2.key_col)+1 +NULL +drop table t1,t2; # # End of 5.1 tests diff --git a/mysql-test/r/subselect4.result b/mysql-test/r/subselect4.result index 482e0045840..153fbed9622 100644 --- a/mysql-test/r/subselect4.result +++ b/mysql-test/r/subselect4.result @@ -59,3 +59,26 @@ FROM t3 WHERE 1 = 0 GROUP BY 1; (SELECT 1 FROM t1,t2 WHERE t2.b > t3.b) DROP TABLE t1,t2,t3; End of 5.0 tests. +CREATE TABLE t1 (col_int_nokey int(11) NOT NULL, col_varchar_nokey varchar(1) NOT NULL) engine=myisam; +INSERT INTO t1 VALUES (2,'s'),(0,'v'),(2,'s'); +CREATE TABLE t2 ( +pk int(11) NOT NULL AUTO_INCREMENT, +`col_int_key` int(11) NOT NULL, +col_varchar_key varchar(1) NOT NULL, +PRIMARY KEY (pk), +KEY `col_int_key` (`col_int_key`), +KEY `col_varchar_key` (`col_varchar_key`) +) ENGINE=MyISAM; +INSERT INTO t2 VALUES (4,10,'g'), (5,20,'v'); +SELECT t1.col_int_nokey,(SELECT MIN( t2_a.col_int_key ) FROM t2 t2_a, t2 t2_b, t1 t1_a WHERE t1_a.col_varchar_nokey = t2_b.col_varchar_key and t1.col_int_nokey ) as sub FROM t1; +col_int_nokey sub +2 10 +0 NULL +2 10 +SELECT t1.col_int_nokey,(SELECT MIN( t2_a.col_int_key ) +1 FROM t2 t2_a, t2 t2_b, t1 t1_a WHERE t1_a.col_varchar_nokey = t2_b.col_varchar_key and t1.col_int_nokey ) as sub FROM t1; +col_int_nokey sub +2 11 +0 NULL +2 11 +DROP TABLE t1,t2; +End of 5.1 tests. diff --git a/mysql-test/r/warnings_engine_disabled.result b/mysql-test/r/warnings_engine_disabled.result index e5d35fdaa5f..2cc68eed653 100644 --- a/mysql-test/r/warnings_engine_disabled.result +++ b/mysql-test/r/warnings_engine_disabled.result @@ -1,15 +1,14 @@ -create table t1 (id int) engine=NDB; +create table t1 (id int) engine=InnoDB; Warnings: -Warning 1286 Unknown table engine 'NDB' +Warning 1286 Unknown table engine 'InnoDB' Warning 1266 Using storage engine MyISAM for table 't1' -alter table t1 engine=NDB; +alter table t1 engine=InnoDB; Warnings: -Warning 1286 Unknown table engine 'NDB' +Warning 1286 Unknown table engine 'InnoDB' drop table t1; -SELECT ENGINE, SUPPORT FROM INFORMATION_SCHEMA.ENGINES WHERE ENGINE='ndbcluster'; +SELECT ENGINE, SUPPORT FROM INFORMATION_SCHEMA.ENGINES WHERE ENGINE='InnoDB'; ENGINE SUPPORT -ndbcluster NO -SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE -PLUGIN_NAME='ndbcluster'; +InnoDB NO +SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME='InnoDB'; PLUGIN_NAME PLUGIN_STATUS -ndbcluster DISABLED +InnoDB DISABLED diff --git a/mysql-test/suite/binlog/t/binlog_base64_flag.test b/mysql-test/suite/binlog/t/binlog_base64_flag.test index 3f1e4e98bec..2964b493c5d 100644 --- a/mysql-test/suite/binlog/t/binlog_base64_flag.test +++ b/mysql-test/suite/binlog/t/binlog_base64_flag.test @@ -7,6 +7,7 @@ # BINLOG statement does not work in embedded mode. +source include/have_log_bin.inc; source include/not_embedded.inc; disable_warnings; diff --git a/mysql-test/suite/binlog/t/binlog_old_versions.test b/mysql-test/suite/binlog/t/binlog_old_versions.test index 0ccea406a82..32c27fe8f89 100644 --- a/mysql-test/suite/binlog/t/binlog_old_versions.test +++ b/mysql-test/suite/binlog/t/binlog_old_versions.test @@ -22,6 +22,7 @@ # Related bugs: BUG#27779, BUG#31581, BUG#31582, BUG#31583, BUG#32407 +source include/have_log_bin.inc; source include/not_embedded.inc; --disable_warnings diff --git a/mysql-test/suite/binlog/t/binlog_row_mix_innodb_myisam-master.opt b/mysql-test/suite/binlog/t/binlog_row_mix_innodb_myisam-master.opt index e76299453d3..cb48f1aaf60 100644 --- a/mysql-test/suite/binlog/t/binlog_row_mix_innodb_myisam-master.opt +++ b/mysql-test/suite/binlog/t/binlog_row_mix_innodb_myisam-master.opt @@ -1 +1 @@ ---innodb_lock_wait_timeout=2 +--loose-innodb_lock_wait_timeout=2 diff --git a/mysql-test/suite/binlog/t/binlog_stm_mix_innodb_myisam-master.opt b/mysql-test/suite/binlog/t/binlog_stm_mix_innodb_myisam-master.opt index e76299453d3..cb48f1aaf60 100644 --- a/mysql-test/suite/binlog/t/binlog_stm_mix_innodb_myisam-master.opt +++ b/mysql-test/suite/binlog/t/binlog_stm_mix_innodb_myisam-master.opt @@ -1 +1 @@ ---innodb_lock_wait_timeout=2 +--loose-innodb_lock_wait_timeout=2 diff --git a/mysql-test/suite/federated/federated_bug_32426.result b/mysql-test/suite/federated/federated_bug_32426.result new file mode 100644 index 00000000000..fbfa6dc3d52 --- /dev/null +++ b/mysql-test/suite/federated/federated_bug_32426.result @@ -0,0 +1,30 @@ +CREATE DATABASE federated; +CREATE DATABASE federated; +# +# Bug #32426: FEDERATED query returns corrupt results for ORDER BY +# on a TEXT column +# +CREATE TABLE federated.t1(a TEXT); +INSERT INTO federated.t1 VALUES('abc'), ('gh'), ('f'), ('ijk'), ('de'); +CREATE TABLE federated.t1(a TEXT) ENGINE=FEDERATED +CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1'; +SELECT * FROM federated.t1 ORDER BY A; +a +abc +de +f +gh +ijk +SELECT * FROM federated.t1 ORDER BY A DESC; +a +ijk +gh +f +de +abc +DROP TABLE federated.t1; +DROP TABLE federated.t1; +DROP TABLE IF EXISTS federated.t1; +DROP DATABASE IF EXISTS federated; +DROP TABLE IF EXISTS federated.t1; +DROP DATABASE IF EXISTS federated; diff --git a/mysql-test/suite/federated/federated_bug_32426.test b/mysql-test/suite/federated/federated_bug_32426.test new file mode 100644 index 00000000000..254dfaa610a --- /dev/null +++ b/mysql-test/suite/federated/federated_bug_32426.test @@ -0,0 +1,24 @@ +source federated.inc; + +--echo # +--echo # Bug #32426: FEDERATED query returns corrupt results for ORDER BY +--echo # on a TEXT column +--echo # +connection slave; +CREATE TABLE federated.t1(a TEXT); +INSERT INTO federated.t1 VALUES('abc'), ('gh'), ('f'), ('ijk'), ('de'); + +connection master; +--replace_result $SLAVE_MYPORT SLAVE_PORT +eval CREATE TABLE federated.t1(a TEXT) ENGINE=FEDERATED + CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1'; +SELECT * FROM federated.t1 ORDER BY A; +SELECT * FROM federated.t1 ORDER BY A DESC; +DROP TABLE federated.t1; + +connection slave; +DROP TABLE federated.t1; + +connection default; + +source federated_cleanup.inc; diff --git a/mysql-test/suite/federated/federated_innodb-slave.opt b/mysql-test/suite/federated/federated_innodb-slave.opt index 627becdbfb5..48457b17309 100644 --- a/mysql-test/suite/federated/federated_innodb-slave.opt +++ b/mysql-test/suite/federated/federated_innodb-slave.opt @@ -1 +1 @@ ---innodb +--loose-innodb diff --git a/mysql-test/suite/federated/federated_server.result b/mysql-test/suite/federated/federated_server.result index 753b9286287..05782c6ef81 100644 --- a/mysql-test/suite/federated/federated_server.result +++ b/mysql-test/suite/federated/federated_server.result @@ -213,7 +213,7 @@ id name alter server s1 options (database 'db_bogus'); flush tables; select * from federated.t1; -ERROR 42000: Got error: 1044 : Access denied for user 'test_fed'@'localhost' to database 'db_bogus' +ERROR 42000: Received error: 1044 : Access denied for user 'test_fed'@'localhost' to database 'db_bogus' drop server if exists 's1'; ERROR 42000: Access denied; you need the SUPER privilege for this operation create server 's1' foreign data wrapper 'mysql' options diff --git a/mysql-test/suite/federated/my.cnf b/mysql-test/suite/federated/my.cnf index 82600949712..7556abad300 100644 --- a/mysql-test/suite/federated/my.cnf +++ b/mysql-test/suite/federated/my.cnf @@ -3,9 +3,10 @@ [mysqld.1] log-bin= master-bin +loose-federated [mysqld.2] - +loose-federated [ENV] MASTER_MYPORT= @mysqld.1.port diff --git a/mysql-test/suite/funcs_1/t/is_columns_is.test b/mysql-test/suite/funcs_1/t/is_columns_is.test index 0ac687354a1..7e40eac0923 100644 --- a/mysql-test/suite/funcs_1/t/is_columns_is.test +++ b/mysql-test/suite/funcs_1/t/is_columns_is.test @@ -18,6 +18,7 @@ --source include/not_embedded.inc # This test depends on having the PBXT information_schema stuff. --source include/have_pbxt.inc +--source include/have_innodb.inc --source include/have_xtradb.inc let $my_where = WHERE table_schema = 'information_schema' diff --git a/mysql-test/suite/innodb/t/innodb-master.opt b/mysql-test/suite/innodb/t/innodb-master.opt index 4901efb416c..08a79432e47 100644 --- a/mysql-test/suite/innodb/t/innodb-master.opt +++ b/mysql-test/suite/innodb/t/innodb-master.opt @@ -1 +1 @@ ---binlog_cache_size=32768 --innodb_lock_wait_timeout=1 +--binlog_cache_size=32768 --loose-innodb_lock_wait_timeout=1 diff --git a/mysql-test/suite/innodb/t/innodb-semi-consistent-master.opt b/mysql-test/suite/innodb/t/innodb-semi-consistent-master.opt index e76299453d3..cb48f1aaf60 100644 --- a/mysql-test/suite/innodb/t/innodb-semi-consistent-master.opt +++ b/mysql-test/suite/innodb/t/innodb-semi-consistent-master.opt @@ -1 +1 @@ ---innodb_lock_wait_timeout=2 +--loose-innodb_lock_wait_timeout=2 diff --git a/mysql-test/suite/innodb/t/innodb_autoinc_lock_mode_zero-master.opt b/mysql-test/suite/innodb/t/innodb_autoinc_lock_mode_zero-master.opt index fad0da2ac2e..e27ee9b2c78 100644 --- a/mysql-test/suite/innodb/t/innodb_autoinc_lock_mode_zero-master.opt +++ b/mysql-test/suite/innodb/t/innodb_autoinc_lock_mode_zero-master.opt @@ -1 +1 @@ ---innodb-autoinc-lock-mode=0 +--loose-innodb-autoinc-lock-mode=0 diff --git a/mysql-test/suite/innodb/t/innodb_bug30919-master.opt b/mysql-test/suite/innodb/t/innodb_bug30919-master.opt index 8636d2d8734..58b254fe596 100644 --- a/mysql-test/suite/innodb/t/innodb_bug30919-master.opt +++ b/mysql-test/suite/innodb/t/innodb_bug30919-master.opt @@ -1 +1 @@ ---innodb --innodb_autoinc_lock_mode=0 +--loose-innodb --loose-innodb_autoinc_lock_mode=0 diff --git a/mysql-test/suite/innodb/t/innodb_bug39438-master.opt b/mysql-test/suite/innodb/t/innodb_bug39438-master.opt index 43fac202fd4..0746d13d1c0 100644 --- a/mysql-test/suite/innodb/t/innodb_bug39438-master.opt +++ b/mysql-test/suite/innodb/t/innodb_bug39438-master.opt @@ -1 +1 @@ ---innodb-file-per-table=1 +--loose-innodb-file-per-table=1 diff --git a/mysql-test/suite/innodb/t/innodb_bug52663-master.opt b/mysql-test/suite/innodb/t/innodb_bug52663-master.opt index 462f8fbe828..82dec8b25fd 100644 --- a/mysql-test/suite/innodb/t/innodb_bug52663-master.opt +++ b/mysql-test/suite/innodb/t/innodb_bug52663-master.opt @@ -1 +1 @@ ---innodb_lock_wait_timeout=1 +--loose-innodb_lock_wait_timeout=1 diff --git a/mysql-test/suite/innodb/t/innodb_bug53674-master.opt b/mysql-test/suite/innodb/t/innodb_bug53674-master.opt index f1cfd7ab6c7..1fe48c3a33a 100644 --- a/mysql-test/suite/innodb/t/innodb_bug53674-master.opt +++ b/mysql-test/suite/innodb/t/innodb_bug53674-master.opt @@ -1 +1 @@ ---log-bin --innodb-locks-unsafe-for-binlog --binlog-format=mixed +--loose-innodb-locks-unsafe-for-binlog --binlog-format=mixed diff --git a/mysql-test/suite/innodb/t/innodb_bug53674.test b/mysql-test/suite/innodb/t/innodb_bug53674.test index 47f67f109c3..c96c3403b36 100644 --- a/mysql-test/suite/innodb/t/innodb_bug53674.test +++ b/mysql-test/suite/innodb/t/innodb_bug53674.test @@ -1,4 +1,5 @@ -- source include/have_innodb.inc +-- source include/have_log_bin.inc create table bug53674(a int)engine=innodb; insert into bug53674 values (1),(2); diff --git a/mysql-test/suite/innodb/t/innodb_lock_wait_timeout_1-master.opt b/mysql-test/suite/innodb/t/innodb_lock_wait_timeout_1-master.opt index 462f8fbe828..82dec8b25fd 100644 --- a/mysql-test/suite/innodb/t/innodb_lock_wait_timeout_1-master.opt +++ b/mysql-test/suite/innodb/t/innodb_lock_wait_timeout_1-master.opt @@ -1 +1 @@ ---innodb_lock_wait_timeout=1 +--loose-innodb_lock_wait_timeout=1 diff --git a/mysql-test/suite/innodb/t/innodb_misc1-master.opt b/mysql-test/suite/innodb/t/innodb_misc1-master.opt index 4901efb416c..08a79432e47 100644 --- a/mysql-test/suite/innodb/t/innodb_misc1-master.opt +++ b/mysql-test/suite/innodb/t/innodb_misc1-master.opt @@ -1 +1 @@ ---binlog_cache_size=32768 --innodb_lock_wait_timeout=1 +--binlog_cache_size=32768 --loose-innodb_lock_wait_timeout=1 diff --git a/mysql-test/suite/innodb/t/innodb_mysql-master.opt b/mysql-test/suite/innodb/t/innodb_mysql-master.opt index 205c733455d..5b4331aa7a6 100644 --- a/mysql-test/suite/innodb/t/innodb_mysql-master.opt +++ b/mysql-test/suite/innodb/t/innodb_mysql-master.opt @@ -1 +1 @@ ---innodb-lock-wait-timeout=2 +--loose-innodb-lock-wait-timeout=2 diff --git a/mysql-test/suite/innodb/t/innodb_mysql_rbk-master.opt b/mysql-test/suite/innodb/t/innodb_mysql_rbk-master.opt index 0e400f9c36b..0de618855c3 100644 --- a/mysql-test/suite/innodb/t/innodb_mysql_rbk-master.opt +++ b/mysql-test/suite/innodb/t/innodb_mysql_rbk-master.opt @@ -1 +1 @@ ---innodb_lock_wait_timeout=1 --innodb_rollback_on_timeout=1 +--loose-innodb_lock_wait_timeout=1 --loose-innodb_rollback_on_timeout=1 diff --git a/mysql-test/suite/innodb/t/innodb_timeout_rollback-master.opt b/mysql-test/suite/innodb/t/innodb_timeout_rollback-master.opt index 50921bb4df0..a451be2eef0 100644 --- a/mysql-test/suite/innodb/t/innodb_timeout_rollback-master.opt +++ b/mysql-test/suite/innodb/t/innodb_timeout_rollback-master.opt @@ -1 +1 @@ ---innodb_lock_wait_timeout=2 --innodb_rollback_on_timeout +--loose-innodb_lock_wait_timeout=2 --loose-innodb_rollback_on_timeout diff --git a/mysql-test/suite/innodb_plugin/combinations b/mysql-test/suite/innodb_plugin/combinations new file mode 100644 index 00000000000..b18db5f876e --- /dev/null +++ b/mysql-test/suite/innodb_plugin/combinations @@ -0,0 +1,12 @@ +[innodb_plugin] +ignore-builtin-innodb +plugin-load=$HA_INNODB_PLUGIN_SO +innodb + +[xtradb_plugin] +ignore-builtin-innodb +plugin-load=$HA_XTRADB_SO +innodb + +[xtradb] +innodb diff --git a/mysql-test/suite/innodb_plugin/suite.pm b/mysql-test/suite/innodb_plugin/suite.pm new file mode 100644 index 00000000000..2a146b8a52f --- /dev/null +++ b/mysql-test/suite/innodb_plugin/suite.pm @@ -0,0 +1,19 @@ +package My::Suite::InnoDB_plugin; + +@ISA = qw(My::Suite); + +############# initialization ###################### +my @combinations; + +push @combinations, 'innodb_plugin' if $ENV{HA_INNODB_PLUGIN_SO}; +push @combinations, 'xtradb_plugin' if $ENV{HA_XTRADB_SO}; +push @combinations, 'xtradb' if $::mysqld_variables{'innodb'} eq "ON"; + +return "Neither innodb_plugin nor xtradb are available" unless @combinations; + +$ENV{INNODB_PLUGIN_COMBINATIONS}=join ':', @combinations + unless $ENV{INNODB_PLUGIN_COMBINATIONS}; + +############# return an object ###################### +bless { }; + diff --git a/mysql-test/suite/innodb_plugin/t/innodb-consistent-master.opt b/mysql-test/suite/innodb_plugin/t/innodb-consistent-master.opt index e76299453d3..cb48f1aaf60 100644 --- a/mysql-test/suite/innodb_plugin/t/innodb-consistent-master.opt +++ b/mysql-test/suite/innodb_plugin/t/innodb-consistent-master.opt @@ -1 +1 @@ ---innodb_lock_wait_timeout=2 +--loose-innodb_lock_wait_timeout=2 diff --git a/mysql-test/suite/innodb_plugin/t/innodb-master.opt b/mysql-test/suite/innodb_plugin/t/innodb-master.opt index 4901efb416c..08a79432e47 100644 --- a/mysql-test/suite/innodb_plugin/t/innodb-master.opt +++ b/mysql-test/suite/innodb_plugin/t/innodb-master.opt @@ -1 +1 @@ ---binlog_cache_size=32768 --innodb_lock_wait_timeout=1 +--binlog_cache_size=32768 --loose-innodb_lock_wait_timeout=1 diff --git a/mysql-test/suite/innodb_plugin/t/innodb-semi-consistent-master.opt b/mysql-test/suite/innodb_plugin/t/innodb-semi-consistent-master.opt index e76299453d3..cb48f1aaf60 100644 --- a/mysql-test/suite/innodb_plugin/t/innodb-semi-consistent-master.opt +++ b/mysql-test/suite/innodb_plugin/t/innodb-semi-consistent-master.opt @@ -1 +1 @@ ---innodb_lock_wait_timeout=2 +--loose-innodb_lock_wait_timeout=2 diff --git a/mysql-test/suite/innodb_plugin/t/innodb-use-sys-malloc-master.opt b/mysql-test/suite/innodb_plugin/t/innodb-use-sys-malloc-master.opt index acf3b8729ed..fc8582b5887 100644 --- a/mysql-test/suite/innodb_plugin/t/innodb-use-sys-malloc-master.opt +++ b/mysql-test/suite/innodb_plugin/t/innodb-use-sys-malloc-master.opt @@ -1 +1 @@ ---innodb-use-sys-malloc=true +--loose-innodb-use-sys-malloc=true diff --git a/mysql-test/suite/innodb_plugin/t/innodb_autoinc_lock_mode_zero-master.opt b/mysql-test/suite/innodb_plugin/t/innodb_autoinc_lock_mode_zero-master.opt index fad0da2ac2e..e27ee9b2c78 100644 --- a/mysql-test/suite/innodb_plugin/t/innodb_autoinc_lock_mode_zero-master.opt +++ b/mysql-test/suite/innodb_plugin/t/innodb_autoinc_lock_mode_zero-master.opt @@ -1 +1 @@ ---innodb-autoinc-lock-mode=0 +--loose-innodb-autoinc-lock-mode=0 diff --git a/mysql-test/suite/innodb_plugin/t/innodb_bug30919-master.opt b/mysql-test/suite/innodb_plugin/t/innodb_bug30919-master.opt index 8636d2d8734..b21ee4fb85e 100644 --- a/mysql-test/suite/innodb_plugin/t/innodb_bug30919-master.opt +++ b/mysql-test/suite/innodb_plugin/t/innodb_bug30919-master.opt @@ -1 +1 @@ ---innodb --innodb_autoinc_lock_mode=0 +--loose-innodb_autoinc_lock_mode=0 diff --git a/mysql-test/suite/innodb_plugin/t/innodb_bug39438-master.opt b/mysql-test/suite/innodb_plugin/t/innodb_bug39438-master.opt index 43fac202fd4..0746d13d1c0 100644 --- a/mysql-test/suite/innodb_plugin/t/innodb_bug39438-master.opt +++ b/mysql-test/suite/innodb_plugin/t/innodb_bug39438-master.opt @@ -1 +1 @@ ---innodb-file-per-table=1 +--loose-innodb-file-per-table=1 diff --git a/mysql-test/suite/innodb_plugin/t/innodb_bug42101-nonzero-master.opt b/mysql-test/suite/innodb_plugin/t/innodb_bug42101-nonzero-master.opt index d71dbe17d5b..3e6a61f4511 100644 --- a/mysql-test/suite/innodb_plugin/t/innodb_bug42101-nonzero-master.opt +++ b/mysql-test/suite/innodb_plugin/t/innodb_bug42101-nonzero-master.opt @@ -1 +1 @@ ---innodb_commit_concurrency=1 +--loose-innodb_commit_concurrency=1 diff --git a/mysql-test/suite/innodb_plugin/t/innodb_bug53674-master.opt b/mysql-test/suite/innodb_plugin/t/innodb_bug53674-master.opt index f1cfd7ab6c7..352b408dd3a 100644 --- a/mysql-test/suite/innodb_plugin/t/innodb_bug53674-master.opt +++ b/mysql-test/suite/innodb_plugin/t/innodb_bug53674-master.opt @@ -1 +1 @@ ---log-bin --innodb-locks-unsafe-for-binlog --binlog-format=mixed +--log-bin=master-bin --loose-innodb-locks-unsafe-for-binlog --binlog-format=mixed diff --git a/mysql-test/suite/innodb_plugin/t/innodb_lock_wait_timeout_1-master.opt b/mysql-test/suite/innodb_plugin/t/innodb_lock_wait_timeout_1-master.opt index 462f8fbe828..82dec8b25fd 100644 --- a/mysql-test/suite/innodb_plugin/t/innodb_lock_wait_timeout_1-master.opt +++ b/mysql-test/suite/innodb_plugin/t/innodb_lock_wait_timeout_1-master.opt @@ -1 +1 @@ ---innodb_lock_wait_timeout=1 +--loose-innodb_lock_wait_timeout=1 diff --git a/mysql-test/suite/innodb_plugin/t/innodb_mysql-master.opt b/mysql-test/suite/innodb_plugin/t/innodb_mysql-master.opt index 205c733455d..5b4331aa7a6 100644 --- a/mysql-test/suite/innodb_plugin/t/innodb_mysql-master.opt +++ b/mysql-test/suite/innodb_plugin/t/innodb_mysql-master.opt @@ -1 +1 @@ ---innodb-lock-wait-timeout=2 +--loose-innodb-lock-wait-timeout=2 diff --git a/mysql-test/suite/innodb_plugin/t/innodb_mysql_rbk-master.opt b/mysql-test/suite/innodb_plugin/t/innodb_mysql_rbk-master.opt index 0e400f9c36b..0de618855c3 100644 --- a/mysql-test/suite/innodb_plugin/t/innodb_mysql_rbk-master.opt +++ b/mysql-test/suite/innodb_plugin/t/innodb_mysql_rbk-master.opt @@ -1 +1 @@ ---innodb_lock_wait_timeout=1 --innodb_rollback_on_timeout=1 +--loose-innodb_lock_wait_timeout=1 --loose-innodb_rollback_on_timeout=1 diff --git a/mysql-test/suite/innodb_plugin/t/innodb_timeout_rollback-master.opt b/mysql-test/suite/innodb_plugin/t/innodb_timeout_rollback-master.opt index 50921bb4df0..a451be2eef0 100644 --- a/mysql-test/suite/innodb_plugin/t/innodb_timeout_rollback-master.opt +++ b/mysql-test/suite/innodb_plugin/t/innodb_timeout_rollback-master.opt @@ -1 +1 @@ ---innodb_lock_wait_timeout=2 --innodb_rollback_on_timeout +--loose-innodb_lock_wait_timeout=2 --loose-innodb_rollback_on_timeout diff --git a/mysql-test/suite/ndb_team/t/rpl_ndb_mix_innodb-master.opt b/mysql-test/suite/ndb_team/t/rpl_ndb_mix_innodb-master.opt index 3596fc4d3bd..416f8692654 100644 --- a/mysql-test/suite/ndb_team/t/rpl_ndb_mix_innodb-master.opt +++ b/mysql-test/suite/ndb_team/t/rpl_ndb_mix_innodb-master.opt @@ -1 +1 @@ ---innodb --default-storage-engine=innodb +--loose-innodb --default-storage-engine=innodb diff --git a/mysql-test/suite/parts/t/partition_debug_sync_innodb-master.opt b/mysql-test/suite/parts/t/partition_debug_sync_innodb-master.opt index 9854fda301d..c610ea42924 100644 --- a/mysql-test/suite/parts/t/partition_debug_sync_innodb-master.opt +++ b/mysql-test/suite/parts/t/partition_debug_sync_innodb-master.opt @@ -1 +1 @@ ---innodb_file_per_table=1 +--loose-innodb_file_per_table=1 diff --git a/mysql-test/suite/parts/t/partition_special_innodb-master.opt b/mysql-test/suite/parts/t/partition_special_innodb-master.opt index e76299453d3..cb48f1aaf60 100644 --- a/mysql-test/suite/parts/t/partition_special_innodb-master.opt +++ b/mysql-test/suite/parts/t/partition_special_innodb-master.opt @@ -1 +1 @@ ---innodb_lock_wait_timeout=2 +--loose-innodb_lock_wait_timeout=2 diff --git a/mysql-test/suite/pbxt/my.cnf b/mysql-test/suite/pbxt/my.cnf index 46c9bf8da4a..93308e4a1f2 100644 --- a/mysql-test/suite/pbxt/my.cnf +++ b/mysql-test/suite/pbxt/my.cnf @@ -2,6 +2,7 @@ !include include/default_mysqld.cnf [mysqld.1] +pbxt default-storage-engine=pbxt [ENV] diff --git a/mysql-test/suite/pbxt/t/suite.opt b/mysql-test/suite/pbxt/t/suite.opt deleted file mode 100644 index 3036df38940..00000000000 --- a/mysql-test/suite/pbxt/t/suite.opt +++ /dev/null @@ -1 +0,0 @@ ---default-storage-engine=pbxt diff --git a/mysql-test/suite/percona/percona_innodb_doublewrite_file-master.opt b/mysql-test/suite/percona/percona_innodb_doublewrite_file-master.opt index 0f4d0c45410..54f9f550277 100644 --- a/mysql-test/suite/percona/percona_innodb_doublewrite_file-master.opt +++ b/mysql-test/suite/percona/percona_innodb_doublewrite_file-master.opt @@ -1 +1 @@ ---innodb_doublewrite_file=ib_doublewrite +--loose-innodb_doublewrite_file=ib_doublewrite diff --git a/mysql-test/suite/rpl/r/rpl_row_basic_11bugs-master.opt b/mysql-test/suite/rpl/r/rpl_row_basic_11bugs-master.opt index 627becdbfb5..48457b17309 100644 --- a/mysql-test/suite/rpl/r/rpl_row_basic_11bugs-master.opt +++ b/mysql-test/suite/rpl/r/rpl_row_basic_11bugs-master.opt @@ -1 +1 @@ ---innodb +--loose-innodb diff --git a/mysql-test/suite/rpl/r/rpl_row_basic_11bugs-slave.opt b/mysql-test/suite/rpl/r/rpl_row_basic_11bugs-slave.opt index 627becdbfb5..48457b17309 100644 --- a/mysql-test/suite/rpl/r/rpl_row_basic_11bugs-slave.opt +++ b/mysql-test/suite/rpl/r/rpl_row_basic_11bugs-slave.opt @@ -1 +1 @@ ---innodb +--loose-innodb diff --git a/mysql-test/suite/rpl/rpl_1slave_base.cnf b/mysql-test/suite/rpl/rpl_1slave_base.cnf index 23b7ded9a7d..8cdc3a1f6b0 100644 --- a/mysql-test/suite/rpl/rpl_1slave_base.cnf +++ b/mysql-test/suite/rpl/rpl_1slave_base.cnf @@ -8,8 +8,6 @@ log-bin= master-bin -loose-innodb - [mysqld.2] # Run the slave.sh script before starting this process #!run-slave-sh @@ -18,7 +16,6 @@ loose-innodb # starting the mysqld #!use-slave-opt -log-bin= slave-bin relay-log= slave-relay-bin init-rpl-role= slave diff --git a/mysql-test/suite/rpl/t/rpl_begin_commit_rollback-master.opt b/mysql-test/suite/rpl/t/rpl_begin_commit_rollback-master.opt index 9e6e2b7829a..a8de78ed6f5 100644 --- a/mysql-test/suite/rpl/t/rpl_begin_commit_rollback-master.opt +++ b/mysql-test/suite/rpl/t/rpl_begin_commit_rollback-master.opt @@ -1 +1 @@ ---innodb --binlog-ignore-db=db2 +--loose-innodb --binlog-ignore-db=db2 diff --git a/mysql-test/suite/rpl/t/rpl_begin_commit_rollback-slave.opt b/mysql-test/suite/rpl/t/rpl_begin_commit_rollback-slave.opt index b4abda5893f..264b17285a2 100644 --- a/mysql-test/suite/rpl/t/rpl_begin_commit_rollback-slave.opt +++ b/mysql-test/suite/rpl/t/rpl_begin_commit_rollback-slave.opt @@ -1 +1 @@ ---innodb --replicate-do-db=db1 +--loose-innodb --replicate-do-db=db1 diff --git a/mysql-test/suite/rpl/t/rpl_circular_for_4_hosts.cnf b/mysql-test/suite/rpl/t/rpl_circular_for_4_hosts.cnf index 141aaa7788d..536551ec3dc 100644 --- a/mysql-test/suite/rpl/t/rpl_circular_for_4_hosts.cnf +++ b/mysql-test/suite/rpl/t/rpl_circular_for_4_hosts.cnf @@ -2,19 +2,19 @@ [mysqld.1] log-slave-updates -innodb +loose-innodb [mysqld.2] log-slave-updates -innodb +loose-innodb [mysqld.3] log-slave-updates -innodb +loose-innodb [mysqld.4] log-slave-updates -innodb +loose-innodb [ENV] SLAVE_MYPORT1= @mysqld.3.port diff --git a/mysql-test/suite/rpl/t/rpl_concurrency_error-master.opt b/mysql-test/suite/rpl/t/rpl_concurrency_error-master.opt index a6ef074a120..3f82baff598 100644 --- a/mysql-test/suite/rpl/t/rpl_concurrency_error-master.opt +++ b/mysql-test/suite/rpl/t/rpl_concurrency_error-master.opt @@ -1 +1 @@ ---innodb-lock-wait-timeout=1 +--loose-innodb-lock-wait-timeout=1 diff --git a/mysql-test/suite/rpl/t/rpl_ddl-slave.opt b/mysql-test/suite/rpl/t/rpl_ddl-slave.opt new file mode 100644 index 00000000000..21356507809 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_ddl-slave.opt @@ -0,0 +1 @@ +--loose-skip-innodb diff --git a/mysql-test/suite/rpl/t/rpl_deadlock_innodb-slave.opt b/mysql-test/suite/rpl/t/rpl_deadlock_innodb-slave.opt index 3819e7c3f7b..f516b1b7003 100644 --- a/mysql-test/suite/rpl/t/rpl_deadlock_innodb-slave.opt +++ b/mysql-test/suite/rpl/t/rpl_deadlock_innodb-slave.opt @@ -1 +1 @@ ---innodb_lock_wait_timeout=4 --slave-transaction-retries=2 --max-relay-log-size=4096 +--loose-innodb-lock-wait-timeout=4 --slave-transaction-retries=2 --max-relay-log-size=4096 diff --git a/mysql-test/suite/rpl/t/rpl_innodb-master.opt b/mysql-test/suite/rpl/t/rpl_innodb-master.opt index 0eed7aaadad..e27ee9b2c78 100644 --- a/mysql-test/suite/rpl/t/rpl_innodb-master.opt +++ b/mysql-test/suite/rpl/t/rpl_innodb-master.opt @@ -1 +1 @@ ---innodb_autoinc_lock_mode=0 +--loose-innodb-autoinc-lock-mode=0 diff --git a/mysql-test/suite/rpl/t/rpl_innodb_bug28430-master.opt b/mysql-test/suite/rpl/t/rpl_innodb_bug28430-master.opt index 0eed7aaadad..e27ee9b2c78 100644 --- a/mysql-test/suite/rpl/t/rpl_innodb_bug28430-master.opt +++ b/mysql-test/suite/rpl/t/rpl_innodb_bug28430-master.opt @@ -1 +1 @@ ---innodb_autoinc_lock_mode=0 +--loose-innodb-autoinc-lock-mode=0 diff --git a/mysql-test/suite/rpl/t/rpl_innodb_bug28430-slave.opt b/mysql-test/suite/rpl/t/rpl_innodb_bug28430-slave.opt index 0eed7aaadad..e27ee9b2c78 100644 --- a/mysql-test/suite/rpl/t/rpl_innodb_bug28430-slave.opt +++ b/mysql-test/suite/rpl/t/rpl_innodb_bug28430-slave.opt @@ -1 +1 @@ ---innodb_autoinc_lock_mode=0 +--loose-innodb-autoinc-lock-mode=0 diff --git a/mysql-test/suite/rpl/t/rpl_start_stop_slave-slave.opt b/mysql-test/suite/rpl/t/rpl_start_stop_slave-slave.opt index 00ea161cd6e..c7cdc20fe18 100644 --- a/mysql-test/suite/rpl/t/rpl_start_stop_slave-slave.opt +++ b/mysql-test/suite/rpl/t/rpl_start_stop_slave-slave.opt @@ -1 +1 @@ ---innodb_lock_wait_timeout=60 +--loose-innodb-lock-wait-timeout=60 diff --git a/mysql-test/suite/rpl/t/rpl_trigger.test b/mysql-test/suite/rpl/t/rpl_trigger.test index e296da01bad..442f18ca61d 100644 --- a/mysql-test/suite/rpl/t/rpl_trigger.test +++ b/mysql-test/suite/rpl/t/rpl_trigger.test @@ -4,6 +4,11 @@ # TODO: Remove statement include once 12574 is patched --source include/have_binlog_format_mixed_or_statement.inc --source include/master-slave.inc +--source include/have_innodb.inc +connection slave; +--source include/have_innodb.inc +connection master; + CALL mtr.add_suppression("Statement may not be safe to log in statement format."); @@ -506,11 +511,9 @@ sync_slave_with_master; connection master; source include/master-slave-reset.inc; -source include/have_innodb.inc; connection slave; -source include/have_innodb.inc; - connection master; + create table t1 ( f int ) engine = innodb; create table log ( r int ) engine = myisam; create trigger tr diff --git a/mysql-test/suite/rpl/t/rpl_typeconv-slave.opt b/mysql-test/suite/rpl/t/rpl_typeconv-slave.opt index 73ca7001985..48457b17309 100644 --- a/mysql-test/suite/rpl/t/rpl_typeconv-slave.opt +++ b/mysql-test/suite/rpl/t/rpl_typeconv-slave.opt @@ -1 +1 @@ ---innodb
\ No newline at end of file +--loose-innodb diff --git a/mysql-test/suite/rpl_ndb/t/rpl_ndb_2innodb-slave.opt b/mysql-test/suite/rpl_ndb/t/rpl_ndb_2innodb-slave.opt index 0d3f1619f1e..4dda0e45a63 100644 --- a/mysql-test/suite/rpl_ndb/t/rpl_ndb_2innodb-slave.opt +++ b/mysql-test/suite/rpl_ndb/t/rpl_ndb_2innodb-slave.opt @@ -1 +1 @@ ---innodb --default-storage-engine=innodb --ndbcluster=0 +--loose-innodb --default-storage-engine=innodb --ndbcluster=0 diff --git a/mysql-test/suite/rpl_ndb/t/rpl_ndb_2other-slave.opt b/mysql-test/suite/rpl_ndb/t/rpl_ndb_2other-slave.opt index dff423702b4..7dc78d6f05b 100644 --- a/mysql-test/suite/rpl_ndb/t/rpl_ndb_2other-slave.opt +++ b/mysql-test/suite/rpl_ndb/t/rpl_ndb_2other-slave.opt @@ -1 +1 @@ ---innodb --loose-ndbcluster=OFF --log-slave-updates=0 +--loose-innodb --loose-ndbcluster=OFF --log-slave-updates=0 diff --git a/mysql-test/suite/rpl_ndb/t/rpl_ndb_circular_2ch.cnf b/mysql-test/suite/rpl_ndb/t/rpl_ndb_circular_2ch.cnf index b1b010ef0f3..64f69427643 100644 --- a/mysql-test/suite/rpl_ndb/t/rpl_ndb_circular_2ch.cnf +++ b/mysql-test/suite/rpl_ndb/t/rpl_ndb_circular_2ch.cnf @@ -2,15 +2,12 @@ [mysqld.1.1] server-id= 1 -log-bin [mysqld.2.1] server-id= 1 -log-bin [mysqld.1.slave] server-id= 2 -log-bin skip-slave-start [mysqld.2.slave] @@ -21,7 +18,6 @@ master-password= @mysqld.2.1.#password master-user= @mysqld.2.1.#user master-connect-retry= 1 init-rpl-role= slave -log-bin skip-slave-start ndb_connectstring= @mysql_cluster.slave.ndb_connectstring diff --git a/mysql-test/suite/rpl_ndb/t/rpl_ndb_innodb2ndb-master.opt b/mysql-test/suite/rpl_ndb/t/rpl_ndb_innodb2ndb-master.opt index 627becdbfb5..48457b17309 100644 --- a/mysql-test/suite/rpl_ndb/t/rpl_ndb_innodb2ndb-master.opt +++ b/mysql-test/suite/rpl_ndb/t/rpl_ndb_innodb2ndb-master.opt @@ -1 +1 @@ ---innodb +--loose-innodb diff --git a/mysql-test/suite/rpl_ndb/t/rpl_ndb_innodb_trans-slave.opt b/mysql-test/suite/rpl_ndb/t/rpl_ndb_innodb_trans-slave.opt index 627becdbfb5..48457b17309 100644 --- a/mysql-test/suite/rpl_ndb/t/rpl_ndb_innodb_trans-slave.opt +++ b/mysql-test/suite/rpl_ndb/t/rpl_ndb_innodb_trans-slave.opt @@ -1 +1 @@ ---innodb +--loose-innodb diff --git a/mysql-test/suite/rpl_ndb/t/rpl_ndb_mixed_engines_transactions-master.opt b/mysql-test/suite/rpl_ndb/t/rpl_ndb_mixed_engines_transactions-master.opt index 627becdbfb5..48457b17309 100644 --- a/mysql-test/suite/rpl_ndb/t/rpl_ndb_mixed_engines_transactions-master.opt +++ b/mysql-test/suite/rpl_ndb/t/rpl_ndb_mixed_engines_transactions-master.opt @@ -1 +1 @@ ---innodb +--loose-innodb diff --git a/mysql-test/suite/rpl_ndb/t/rpl_ndb_mixed_engines_transactions-slave.opt b/mysql-test/suite/rpl_ndb/t/rpl_ndb_mixed_engines_transactions-slave.opt index 627becdbfb5..48457b17309 100644 --- a/mysql-test/suite/rpl_ndb/t/rpl_ndb_mixed_engines_transactions-slave.opt +++ b/mysql-test/suite/rpl_ndb/t/rpl_ndb_mixed_engines_transactions-slave.opt @@ -1 +1 @@ ---innodb +--loose-innodb diff --git a/mysql-test/suite/rpl_ndb/t/rpl_ndb_mixed_tables-master.opt b/mysql-test/suite/rpl_ndb/t/rpl_ndb_mixed_tables-master.opt index b74354b22e1..0f4722c3fbd 100644 --- a/mysql-test/suite/rpl_ndb/t/rpl_ndb_mixed_tables-master.opt +++ b/mysql-test/suite/rpl_ndb/t/rpl_ndb_mixed_tables-master.opt @@ -1 +1 @@ ---innodb --ndbcluster +--loose-innodb --ndbcluster diff --git a/mysql-test/suite/rpl_ndb/t/rpl_ndb_mixed_tables-slave.opt b/mysql-test/suite/rpl_ndb/t/rpl_ndb_mixed_tables-slave.opt index bbb86b2991b..a8829991a6d 100644 --- a/mysql-test/suite/rpl_ndb/t/rpl_ndb_mixed_tables-slave.opt +++ b/mysql-test/suite/rpl_ndb/t/rpl_ndb_mixed_tables-slave.opt @@ -1 +1 @@ ---innodb --ndbcluster --replicate-ignore-table=mysql.ndb_apply_status +--loose-innodb --ndbcluster --replicate-ignore-table=mysql.ndb_apply_status diff --git a/mysql-test/suite/rpl_ndb/t/rpl_ndb_stm_innodb-master.opt b/mysql-test/suite/rpl_ndb/t/rpl_ndb_stm_innodb-master.opt index 3596fc4d3bd..416f8692654 100644 --- a/mysql-test/suite/rpl_ndb/t/rpl_ndb_stm_innodb-master.opt +++ b/mysql-test/suite/rpl_ndb/t/rpl_ndb_stm_innodb-master.opt @@ -1 +1 @@ ---innodb --default-storage-engine=innodb +--loose-innodb --default-storage-engine=innodb diff --git a/mysql-test/suite/sys_vars/t/autocommit_func-master.opt b/mysql-test/suite/sys_vars/t/autocommit_func-master.opt index 627becdbfb5..48457b17309 100644 --- a/mysql-test/suite/sys_vars/t/autocommit_func-master.opt +++ b/mysql-test/suite/sys_vars/t/autocommit_func-master.opt @@ -1 +1 @@ ---innodb +--loose-innodb diff --git a/mysql-test/suite/sys_vars/t/character_set_filesystem_func-master.opt b/mysql-test/suite/sys_vars/t/character_set_filesystem_func-master.opt index 52a49182a53..303377e796b 100644 --- a/mysql-test/suite/sys_vars/t/character_set_filesystem_func-master.opt +++ b/mysql-test/suite/sys_vars/t/character_set_filesystem_func-master.opt @@ -1 +1 @@ ---secure-file-priv=$MYSQL_TEST_DIR --innodb +--secure-file-priv=$MYSQL_TEST_DIR --loose-innodb diff --git a/mysql-test/suite/sys_vars/t/identity_func-master.opt b/mysql-test/suite/sys_vars/t/identity_func-master.opt index 66f581b56d0..03f5ae2d108 100644 --- a/mysql-test/suite/sys_vars/t/identity_func-master.opt +++ b/mysql-test/suite/sys_vars/t/identity_func-master.opt @@ -1,2 +1,2 @@ ---innodb +--loose-innodb diff --git a/mysql-test/suite/sys_vars/t/innodb_autoinc_lock_mode_func-master.opt b/mysql-test/suite/sys_vars/t/innodb_autoinc_lock_mode_func-master.opt index ab9fcb75678..f0b6727d6d8 100644 --- a/mysql-test/suite/sys_vars/t/innodb_autoinc_lock_mode_func-master.opt +++ b/mysql-test/suite/sys_vars/t/innodb_autoinc_lock_mode_func-master.opt @@ -1,2 +1,2 @@ ---innodb-autoinc-lock-mode=1 +--loose-innodb-autoinc-lock-mode=1 diff --git a/mysql-test/suite/sys_vars/t/last_insert_id_func-master.opt b/mysql-test/suite/sys_vars/t/last_insert_id_func-master.opt index 66f581b56d0..03f5ae2d108 100644 --- a/mysql-test/suite/sys_vars/t/last_insert_id_func-master.opt +++ b/mysql-test/suite/sys_vars/t/last_insert_id_func-master.opt @@ -1,2 +1,2 @@ ---innodb +--loose-innodb diff --git a/mysql-test/suite/sys_vars/t/max_binlog_cache_size_func-master.opt b/mysql-test/suite/sys_vars/t/max_binlog_cache_size_func-master.opt index 6e00d7157d6..2cadd0c7b3f 100644 --- a/mysql-test/suite/sys_vars/t/max_binlog_cache_size_func-master.opt +++ b/mysql-test/suite/sys_vars/t/max_binlog_cache_size_func-master.opt @@ -1,2 +1,2 @@ --log-bin ---innodb +--loose-innodb diff --git a/mysql-test/suite/sys_vars/t/storage_engine_basic-master.opt b/mysql-test/suite/sys_vars/t/storage_engine_basic-master.opt index 627becdbfb5..48457b17309 100644 --- a/mysql-test/suite/sys_vars/t/storage_engine_basic-master.opt +++ b/mysql-test/suite/sys_vars/t/storage_engine_basic-master.opt @@ -1 +1 @@ ---innodb +--loose-innodb diff --git a/mysql-test/suite/sys_vars/t/tx_isolation_func-master.opt b/mysql-test/suite/sys_vars/t/tx_isolation_func-master.opt index c15943a7544..67166a46cd1 100644 --- a/mysql-test/suite/sys_vars/t/tx_isolation_func-master.opt +++ b/mysql-test/suite/sys_vars/t/tx_isolation_func-master.opt @@ -1,3 +1,3 @@ ---innodb ---innodb_lock_wait_timeout=2 +--loose-innodb +--loose-innodb_lock_wait_timeout=2 --binlog-format=row
\ No newline at end of file diff --git a/mysql-test/t/bug46760-master.opt b/mysql-test/t/bug46760-master.opt index f830d135149..2d7be7fb9b1 100644 --- a/mysql-test/t/bug46760-master.opt +++ b/mysql-test/t/bug46760-master.opt @@ -1,2 +1,2 @@ ---innodb-lock-wait-timeout=2 ---innodb-file-per-table +--loose-innodb-lock-wait-timeout=2 +--loose-innodb-file-per-table diff --git a/mysql-test/t/concurrent_innodb_safelog-master.opt b/mysql-test/t/concurrent_innodb_safelog-master.opt index 462f8fbe828..82dec8b25fd 100644 --- a/mysql-test/t/concurrent_innodb_safelog-master.opt +++ b/mysql-test/t/concurrent_innodb_safelog-master.opt @@ -1 +1 @@ ---innodb_lock_wait_timeout=1 +--loose-innodb_lock_wait_timeout=1 diff --git a/mysql-test/t/concurrent_innodb_unsafelog-master.opt b/mysql-test/t/concurrent_innodb_unsafelog-master.opt index 210212a40bc..ea9c1b860e9 100644 --- a/mysql-test/t/concurrent_innodb_unsafelog-master.opt +++ b/mysql-test/t/concurrent_innodb_unsafelog-master.opt @@ -1,2 +1,2 @@ ---innodb_locks_unsafe_for_binlog ---innodb_lock_wait_timeout=1 +--loose-innodb_locks_unsafe_for_binlog +--loose-innodb_lock_wait_timeout=1 diff --git a/mysql-test/t/connect.cnf b/mysql-test/t/connect.cnf index 6c52a4b144d..caf51ee2085 100644 --- a/mysql-test/t/connect.cnf +++ b/mysql-test/t/connect.cnf @@ -5,4 +5,4 @@ extra-port= @mysqld.1.#extra-port extra-max-connections=1 [ENV] -MASTER_EXTRA_PORT= @mysqld.1.extra-port +MASTER_EXTRA_PORT= @mysqld.1.#extra-port diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index cede26f555a..1de9d1c9847 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -14,3 +14,4 @@ query_cache_28249 : Bug#43861 2009-03-25 main.query_cache_28249 fails spo partition_innodb_plugin : Bug#53307 2010-04-30 VasilDimov valgrind warnings main.mysqlhotcopy_myisam : bug#54129 2010-06-04 Horst main.mysqlhotcopy_archive: bug#54129 2010-06-04 Horst +main.events_time_zone : Test is not predictable as it depends on precise timing. diff --git a/mysql-test/t/exampledb.test b/mysql-test/t/exampledb.test deleted file mode 100644 index fbb2a18f344..00000000000 --- a/mysql-test/t/exampledb.test +++ /dev/null @@ -1,22 +0,0 @@ -# -# Simple test for the example storage engine -# Taken fromm the select test -# --- source include/have_exampledb.inc - ---disable_warnings -# Clean up if event's test fails -drop database if exists events_test; -drop database if exists events_test2; - -drop table if exists t1; ---enable_warnings - -CREATE TABLE t1 ( - Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, - Varor_period smallint(4) unsigned DEFAULT '0' NOT NULL -) ENGINE=example; - -drop table t1; - -# End of 4.1 tests diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test index c5b27ee1a62..c640a58d597 100644 --- a/mysql-test/t/group_by.test +++ b/mysql-test/t/group_by.test @@ -1219,6 +1219,23 @@ EXPLAIN SELECT MAX(t2.a) FROM t2 LEFT JOIN t1 ON t2.a = t1.a; SELECT MAX(t2.a) FROM t2 LEFT JOIN t1 ON t2.a = t1.a; DROP TABLE t1, t2; +# +# min() returns wrong value when used in expression when there is no matching +# rows +# + +CREATE TABLE t1 (a int(11) NOT NULL); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 ( + key_col int(11) NOT NULL, + KEY (key_col) +); +INSERT INTO t2 VALUES (1),(2); + +select min(t2.key_col) from t1,t2 where t1.a=1; +select min(t2.key_col) from t1,t2 where t1.a > 1000; +select min(t2.key_col)+1 from t1,t2 where t1.a> 1000; +drop table t1,t2; --echo # diff --git a/mysql-test/t/partition_innodb-master.opt b/mysql-test/t/partition_innodb-master.opt index 462f8fbe828..82dec8b25fd 100644 --- a/mysql-test/t/partition_innodb-master.opt +++ b/mysql-test/t/partition_innodb-master.opt @@ -1 +1 @@ ---innodb_lock_wait_timeout=1 +--loose-innodb_lock_wait_timeout=1 diff --git a/mysql-test/t/partition_innodb_semi_consistent-master.opt b/mysql-test/t/partition_innodb_semi_consistent-master.opt index e76299453d3..cb48f1aaf60 100644 --- a/mysql-test/t/partition_innodb_semi_consistent-master.opt +++ b/mysql-test/t/partition_innodb_semi_consistent-master.opt @@ -1 +1 @@ ---innodb_lock_wait_timeout=2 +--loose-innodb_lock_wait_timeout=2 diff --git a/mysql-test/t/pool_of_threads.cnf b/mysql-test/t/pool_of_threads.cnf index b96953ad1c5..9ab0571df9f 100644 --- a/mysql-test/t/pool_of_threads.cnf +++ b/mysql-test/t/pool_of_threads.cnf @@ -11,4 +11,4 @@ extra-max-connections=1 connect-timeout= 2 [ENV] -MASTER_EXTRA_PORT= @mysqld.1.extra-port +MASTER_EXTRA_PORT= @mysqld.1.#extra-port diff --git a/mysql-test/t/sp_trans_log.test b/mysql-test/t/sp_trans_log.test index 5eccbf81fef..ed054a0ebc6 100644 --- a/mysql-test/t/sp_trans_log.test +++ b/mysql-test/t/sp_trans_log.test @@ -3,7 +3,7 @@ # part of sp_trans test that appeared to be sensitive to binlog format --source include/have_innodb.inc ---source include/have_binlog_format_mixed_or_row.inc +--source include/have_binlog_format_mixed.inc delimiter |; diff --git a/mysql-test/t/subselect4.test b/mysql-test/t/subselect4.test index 440eca22828..c287091ab54 100644 --- a/mysql-test/t/subselect4.test +++ b/mysql-test/t/subselect4.test @@ -62,3 +62,29 @@ FROM t3 WHERE 1 = 0 GROUP BY 1; DROP TABLE t1,t2,t3; --echo End of 5.0 tests. + +# +# Fix for LP#612894 +# Some aggregate functions (such as MIN MAX) work incorrectly in subqueries +# after getting NULL value +# + +CREATE TABLE t1 (col_int_nokey int(11) NOT NULL, col_varchar_nokey varchar(1) NOT NULL) engine=myisam; +INSERT INTO t1 VALUES (2,'s'),(0,'v'),(2,'s'); +CREATE TABLE t2 ( + pk int(11) NOT NULL AUTO_INCREMENT, + `col_int_key` int(11) NOT NULL, + col_varchar_key varchar(1) NOT NULL, + PRIMARY KEY (pk), + KEY `col_int_key` (`col_int_key`), + KEY `col_varchar_key` (`col_varchar_key`) +) ENGINE=MyISAM; +INSERT INTO t2 VALUES (4,10,'g'), (5,20,'v'); + +SELECT t1.col_int_nokey,(SELECT MIN( t2_a.col_int_key ) FROM t2 t2_a, t2 t2_b, t1 t1_a WHERE t1_a.col_varchar_nokey = t2_b.col_varchar_key and t1.col_int_nokey ) as sub FROM t1; + +SELECT t1.col_int_nokey,(SELECT MIN( t2_a.col_int_key ) +1 FROM t2 t2_a, t2 t2_b, t1 t1_a WHERE t1_a.col_varchar_nokey = t2_b.col_varchar_key and t1.col_int_nokey ) as sub FROM t1; + +DROP TABLE t1,t2; + +--echo End of 5.1 tests. diff --git a/mysql-test/t/unsafe_binlog_innodb-master.opt b/mysql-test/t/unsafe_binlog_innodb-master.opt index 9581c225d6d..d5ecd2ed9a5 100644 --- a/mysql-test/t/unsafe_binlog_innodb-master.opt +++ b/mysql-test/t/unsafe_binlog_innodb-master.opt @@ -1 +1 @@ ---innodb_locks_unsafe_for_binlog=true --innodb_lock_wait_timeout=1 +--loose-innodb_locks_unsafe_for_binlog=true --loose-innodb_lock_wait_timeout=1 diff --git a/mysql-test/t/warnings_engine_disabled.test b/mysql-test/t/warnings_engine_disabled.test index b8751a062b7..07a7e54c46c 100644 --- a/mysql-test/t/warnings_engine_disabled.test +++ b/mysql-test/t/warnings_engine_disabled.test @@ -2,23 +2,22 @@ # Only run this test with a compiled in but disabled # engine # -disable_query_log; ---require r/true.require -select support = 'NO' as `TRUE` from information_schema.engines where engine = 'ndbcluster'; -enable_query_log; +if (!`SELECT count(*) FROM information_schema.engines WHERE + support = 'NO' AND engine = 'innodb'`){ + skip Needs innodb engine; +} # # Test for handler type, will select MyISAM and print a warning -# about that - since NDB is disabled +# about that - since InnoDB is disabled # -create table t1 (id int) engine=NDB; -alter table t1 engine=NDB; +create table t1 (id int) engine=InnoDB; +alter table t1 engine=InnoDB; drop table t1; # # Bug#29263 disabled storage engines omitted in SHOW ENGINES # -SELECT ENGINE, SUPPORT FROM INFORMATION_SCHEMA.ENGINES WHERE ENGINE='ndbcluster'; -SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE -PLUGIN_NAME='ndbcluster'; +SELECT ENGINE, SUPPORT FROM INFORMATION_SCHEMA.ENGINES WHERE ENGINE='InnoDB'; +SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME='InnoDB'; diff --git a/mysys/my_getwd.c b/mysys/my_getwd.c index e6b867e2753..a18c296a7e1 100644 --- a/mysys/my_getwd.c +++ b/mysys/my_getwd.c @@ -51,7 +51,7 @@ int my_getwd(char * buf, size_t size, myf MyFlags) (long) buf, (uint) size, MyFlags)); if (size < 1) - return(-1); + DBUG_RETURN(-1); if (curr_dir[0]) /* Current pos is saved here */ VOID(strmake(buf,&curr_dir[0],size-1)); @@ -59,12 +59,12 @@ int my_getwd(char * buf, size_t size, myf MyFlags) { #if defined(HAVE_GETCWD) if (size < 2) - return(-1); + DBUG_RETURN(-1); if (!getcwd(buf,(uint) (size-2)) && MyFlags & MY_WME) { my_errno=errno; my_error(EE_GETWD,MYF(ME_BELL+ME_WAITTANG),errno); - return(-1); + DBUG_RETURN(-1); } #elif defined(HAVE_GETWD) { @@ -74,12 +74,12 @@ int my_getwd(char * buf, size_t size, myf MyFlags) } #elif defined(VMS) if (size < 2) - return(-1); + DBUG_RETURN(-1); if (!getcwd(buf,size-2,1) && MyFlags & MY_WME) { my_errno=errno; my_error(EE_GETWD,MYF(ME_BELL+ME_WAITTANG),errno); - return(-1); + DBUG_RETURN(-1); } intern_filename(buf,buf); #else diff --git a/scripts/Makefile.am b/scripts/Makefile.am index b74e7b8df8b..be9354bd628 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -37,7 +37,8 @@ bin_SCRIPTS = @server_scripts@ \ mysqld_multi noinst_SCRIPTS = make_binary_distribution \ - make_sharedlib_distribution + make_sharedlib_distribution \ + convert-debug-for-diff EXTRA_SCRIPTS = make_binary_distribution.sh \ make_sharedlib_distribution.sh \ @@ -59,7 +60,8 @@ EXTRA_SCRIPTS = make_binary_distribution.sh \ mysqlhotcopy.sh \ mysqldumpslow.sh \ mysqld_multi.sh \ - mysqld_safe.sh + mysqld_safe.sh \ + convert-debug-for-diff.sh EXTRA_DIST = $(EXTRA_SCRIPTS) \ mysqlaccess.conf \ @@ -91,6 +93,7 @@ CLEANFILES = @server_scripts@ \ mysqlhotcopy \ mysqldumpslow \ mysqld_multi \ + convert-debug-for-diff \ $(EXTRA_PROGRAMS) pkgplugindir = $(pkglibdir)/plugin diff --git a/scripts/convert-debug-for-diff.sh b/scripts/convert-debug-for-diff.sh new file mode 100755 index 00000000000..b6c837504cb --- /dev/null +++ b/scripts/convert-debug-for-diff.sh @@ -0,0 +1,25 @@ +#!/usr/bin/perl -i +# +# This script converts all numbers that look like addresses or memory sizes, +# in a debug files generated by --debug (like mysqld --debug), to #. +# The script also deletes all thread id's from the start of the line. + +# This allows you to easily compare the files (for example with diff) +# to find out what changes between different executions. +# This is extremely useful for comparing two mysqld versions to see +# why things now work differently. + +# The script converts the files in place. +# +# Typical usage: +# +# convert-debug-for-diff /tmp/mysqld.trace /tmp/mysqld-old.trace +# diff /tmp/mysqld.trace /tmp/mysqld-old.trace + +while (<>) +{ + s/^T@[0-9]+\s*://g; + s/0x[0-9a-f]+(\s|\n|\))/#$1/g; + s/size: [0-9]+/size: #/g; + print $_; +} diff --git a/sql/item.h b/sql/item.h index 865f9cf0886..ec98ed44229 100644 --- a/sql/item.h +++ b/sql/item.h @@ -870,6 +870,7 @@ public: set value of aggregate function in case of no rows for grouping were found */ virtual void no_rows_in_result() {} + virtual void restore_to_before_no_rows_in_result() {} virtual Item *copy_or_same(THD *thd) { return this; } virtual Item *copy_andor_structure(THD *thd) { return this; } virtual Item *real_item() { return this; } @@ -926,6 +927,21 @@ public: virtual bool register_field_in_read_map(uchar *arg) { return 0; } virtual bool enumerate_field_refs_processor(uchar *arg) { return 0; } virtual bool mark_as_eliminated_processor(uchar *arg) { return 0; } + + /* To call bool function for all arguments */ + struct bool_func_call_args + { + Item *original_func_item; + void (Item::*bool_function)(); + }; + bool call_bool_func_processor(uchar *org_item) + { + bool_func_call_args *info= (bool_func_call_args*) org_item; + /* Avoid recursion, as walk also calls for original item */ + if (info->original_func_item != this) + (this->*(info->bool_function))(); + return FALSE; + } /* The next function differs from the previous one that a bitmap to be updated is passed as uchar *arg. @@ -2404,6 +2420,14 @@ public: return (*ref)->walk(processor, walk_subquery, arg) || (this->*processor)(arg); } + void no_rows_in_result() + { + (*ref)->no_rows_in_result(); + } + void restore_to_before_no_rows_in_result() + { + (*ref)->restore_to_before_no_rows_in_result(); + } virtual void print(String *str, enum_query_type query_type); bool result_as_longlong() { diff --git a/sql/item_func.h b/sql/item_func.h index 507f5d21a3e..b999782274a 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -217,6 +217,21 @@ public: { return functype() == *(Functype *) arg; } + + void no_rows_in_result() + { + bool_func_call_args info; + info.original_func_item= this; + info.bool_function= &Item::no_rows_in_result; + walk(&Item::call_bool_func_processor, FALSE, (uchar*) &info); + } + void restore_to_before_no_rows_in_result() + { + bool_func_call_args info; + info.original_func_item= this; + info.bool_function= &Item::restore_to_before_no_rows_in_result; + walk(&Item::call_bool_func_processor, FALSE, (uchar*) &info); + } }; diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 2f79fd65ff3..b3b07119066 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -1638,8 +1638,22 @@ void Item_sum_hybrid::cleanup() void Item_sum_hybrid::no_rows_in_result() { - was_values= FALSE; - clear(); + /* We may be called here twice in case of ref field in function */ + if (was_values) + { + was_values= FALSE; + was_null_value= value->null_value; + clear(); + } +} + +void Item_sum_hybrid::restore_to_before_no_rows_in_result() +{ + if (!was_values) + { + was_values= TRUE; + null_value= value->null_value= was_null_value; + } } diff --git a/sql/item_sum.h b/sql/item_sum.h index 7720de2450f..a47939187dd 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -500,7 +500,7 @@ public: enum Sumfunctype sum_func () const { return SUM_DISTINCT_FUNC; } void reset_field() {} // not used void update_field() {} // not used - virtual void no_rows_in_result() {} + void no_rows_in_result() {} void fix_length_and_dec(); enum Item_result result_type () const { return val.traits->type(); } virtual void calculate_val_and_count(); @@ -857,6 +857,7 @@ protected: enum_field_types hybrid_field_type; int cmp_sign; bool was_values; // Set if we have found at least one row (for max/min only) + bool was_null_value; public: Item_sum_hybrid(Item *item_par,int sign) @@ -888,6 +889,7 @@ protected: void cleanup(); bool any_value() { return was_values; } void no_rows_in_result(); + void restore_to_before_no_rows_in_result(); Field *create_tmp_field(bool group, TABLE *table, uint convert_blob_length); }; diff --git a/sql/log.cc b/sql/log.cc index 570418d97dd..9cbf33d9890 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -372,6 +372,7 @@ bool Log_to_csv_event_handler:: Open_tables_state open_tables_backup; ulonglong save_thd_options; bool save_time_zone_used; + DBUG_ENTER("log_general"); /* CSV uses TIME_to_timestamp() internally if table needs to be repaired @@ -490,7 +491,7 @@ err: thd->options= save_thd_options; thd->time_zone_used= save_time_zone_used; - return result; + DBUG_RETURN(result); } diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 6cd48716357..ccbc7fd3ba1 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -9380,6 +9380,8 @@ bool is_secure_file_path(char *path) static int fix_paths(void) { char buff[FN_REFLEN],*pos; + DBUG_ENTER("fix_paths"); + convert_dirname(mysql_home,mysql_home,NullS); /* Resolve symlinks to allow 'mysql_home' to be a relative symlink */ my_realpath(mysql_home,mysql_home,MYF(0)); @@ -9424,12 +9426,12 @@ static int fix_paths(void) charsets_dir=mysql_charsets_dir; if (init_tmpdir(&mysql_tmpdir_list, opt_mysql_tmpdir)) - return 1; + DBUG_RETURN(1); #ifdef HAVE_REPLICATION if (!slave_load_tmpdir) { if (!(slave_load_tmpdir = (char*) my_strdup(mysql_tmpdir, MYF(MY_FAE)))) - return 1; + DBUG_RETURN(1); } #endif /* HAVE_REPLICATION */ /* @@ -9450,7 +9452,7 @@ static int fix_paths(void) if (my_realpath(buff, opt_secure_file_priv, 0)) { sql_print_warning("Failed to normalize the argument for --secure-file-priv."); - return 1; + DBUG_RETURN(1); } secure_file_real_path= (char *)my_malloc(FN_REFLEN, MYF(MY_FAE)); convert_dirname(secure_file_real_path, buff, NullS); @@ -9458,7 +9460,7 @@ static int fix_paths(void) opt_secure_file_priv= secure_file_real_path; } } - return 0; + DBUG_RETURN(0); } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 69e4f302803..2e966dbdde3 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1688,6 +1688,16 @@ JOIN::reinit() func->clear(); } + if (no_rows_in_result_called) + { + /* Reset effect of possible no_rows_in_result() */ + List_iterator_fast<Item> it(fields_list); + Item *item; + + no_rows_in_result_called= 0; + while ((item= it++)) + item->restore_to_before_no_rows_in_result(); + } DBUG_RETURN(0); } @@ -12697,8 +12707,11 @@ end_send_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), { List_iterator_fast<Item> it(*join->fields); Item *item; + DBUG_PRINT("info", ("no matching rows")); + /* No matching rows for group function */ join->clear(); + join->no_rows_in_result_called= 1; while ((item= it++)) item->no_rows_in_result(); diff --git a/sql/sql_select.h b/sql/sql_select.h index 285019b4a5c..fe3cc1af400 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -365,24 +365,31 @@ public: the number of rows in it may vary from one subquery execution to another. */ bool no_const_tables; + /* + This flag is set if we call no_rows_in_result() as par of end_group(). + This is used as a simple speed optimization to avoiding calling + restore_no_rows_in_result() in ::reinit() + */ + bool no_rows_in_result_called; /** Copy of this JOIN to be used with temporary tables. - tmp_join is used when the JOIN needs to be "reusable" (e.g. in a subquery - that gets re-executed several times) and we know will use temporary tables - for materialization. The materialization to a temporary table overwrites the - JOIN structure to point to the temporary table after the materialization is - done. This is where tmp_join is used : it's a copy of the JOIN before the - materialization and is used in restoring before re-execution by overwriting - the current JOIN structure with the saved copy. - Because of this we should pay extra care of not freeing up helper structures - that are referenced by the original contents of the JOIN. We can check for - this by making sure the "current" join is not the temporary copy, e.g. - !tmp_join || tmp_join != join + tmp_join is used when the JOIN needs to be "reusable" (e.g. in a + subquery that gets re-executed several times) and we know will use + temporary tables for materialization. The materialization to a + temporary table overwrites the JOIN structure to point to the + temporary table after the materialization is done. This is where + tmp_join is used : it's a copy of the JOIN before the + materialization and is used in restoring before re-execution by + overwriting the current JOIN structure with the saved copy. + Because of this we should pay extra care of not freeing up helper + structures that are referenced by the original contents of the + JOIN. We can check for this by making sure the "current" join is + not the temporary copy, e.g. !tmp_join || tmp_join != join - We should free these sub-structures at JOIN::destroy() if the "current" join - has a copy is not that copy. + We should free these sub-structures at JOIN::destroy() if the + "current" join has a copy is not that copy. */ JOIN *tmp_join; ROLLUP rollup; ///< Used with rollup @@ -512,6 +519,7 @@ public: optimized= 0; cond_equal= 0; group_optimized_away= 0; + no_rows_in_result_called= 0; all_fields= fields_arg; if (&fields_list != &fields_arg) /* Avoid valgrind-warning */ diff --git a/storage/federatedx/federatedx_io_mysql.cc b/storage/federatedx/federatedx_io_mysql.cc index 5245395b060..d6844fab2c6 100644 --- a/storage/federatedx/federatedx_io_mysql.cc +++ b/storage/federatedx/federatedx_io_mysql.cc @@ -1,4 +1,4 @@ -/* +/* Copyright (c) 2007, Antony T Curtis All rights reserved. @@ -51,6 +51,12 @@ typedef struct federatedx_savepoint uint flags; } SAVEPT; +struct mysql_position +{ + MYSQL_RES* result; + MYSQL_ROW_OFFSET offset; +}; + class federatedx_io_mysql :public federatedx_io { @@ -76,16 +82,16 @@ public: virtual int error_code(); virtual const char *error_str(); - + void reset(); int commit(); int rollback(); - + int savepoint_set(ulong sp); ulong savepoint_release(ulong sp); ulong savepoint_rollback(ulong sp); void savepoint_restrict(ulong sp); - + ulong last_savepoint() const; ulong actual_savepoint() const; bool is_autocommit() const; @@ -94,7 +100,7 @@ public: uint table_name_length, uint flag); /* resultset operations */ - + virtual void free_result(FEDERATEDX_IO_RESULT *io_result); virtual unsigned int get_num_fields(FEDERATEDX_IO_RESULT *io_result); virtual my_ulonglong get_num_rows(FEDERATEDX_IO_RESULT *io_result); @@ -104,6 +110,12 @@ public: unsigned int column); virtual bool is_column_null(const FEDERATEDX_IO_ROW *row, unsigned int column) const; + + virtual size_t get_ref_length() const; + virtual void mark_position(FEDERATEDX_IO_RESULT *io_result, + void *ref); + virtual int seek_position(FEDERATEDX_IO_RESULT **io_result, + const void *ref); }; @@ -466,14 +478,13 @@ const char *federatedx_io_mysql::error_str() return mysql_error(&mysql); } - FEDERATEDX_IO_RESULT *federatedx_io_mysql::store_result() { FEDERATEDX_IO_RESULT *result; DBUG_ENTER("federatedx_io_mysql::store_result"); - + result= (FEDERATEDX_IO_RESULT *) mysql_store_result(&mysql); - + DBUG_RETURN(result); } @@ -590,3 +601,45 @@ error: free_result(result); return 1; } + + + +size_t federatedx_io_mysql::get_ref_length() const +{ + return sizeof(mysql_position); +} + + +void federatedx_io_mysql::mark_position(FEDERATEDX_IO_RESULT *io_result, + void *ref) +{ + MYSQL_ROWS *tmp= 0; + mysql_position& pos= *reinterpret_cast<mysql_position*>(ref); + pos.result= (MYSQL_RES *) io_result; + + if (pos.result && pos.result->data) + { + for (tmp= pos.result->data->data; + tmp && (tmp->next != pos.result->data_cursor); + tmp= tmp->next) + {} + } + + pos.offset= tmp; +} + +int federatedx_io_mysql::seek_position(FEDERATEDX_IO_RESULT **io_result, + const void *ref) +{ + const mysql_position& pos= *reinterpret_cast<const mysql_position*>(ref); + + if (!pos.result || !pos.offset) + return HA_ERR_END_OF_FILE; + + pos.result->current_row= 0; + pos.result->data_cursor= pos.offset; + *io_result= (FEDERATEDX_IO_RESULT*) pos.result; + + return 0; +} + diff --git a/storage/federatedx/federatedx_io_null.cc b/storage/federatedx/federatedx_io_null.cc index cd8fc3eaf85..49f93ab6546 100644 --- a/storage/federatedx/federatedx_io_null.cc +++ b/storage/federatedx/federatedx_io_null.cc @@ -96,6 +96,11 @@ public: unsigned int column); virtual bool is_column_null(const FEDERATEDX_IO_ROW *row, unsigned int column) const; + virtual size_t get_ref_length() const; + virtual void mark_position(FEDERATEDX_IO_RESULT *io_result, + void *ref); + virtual int seek_position(FEDERATEDX_IO_RESULT **io_result, + const void *ref); }; @@ -275,3 +280,20 @@ bool federatedx_io_null::table_metadata(ha_statistics *stats, return 0; } + +size_t federatedx_io_null::get_ref_length() const +{ + return sizeof(int); +} + + +void federatedx_io_null::mark_position(FEDERATEDX_IO_RESULT *io_result, + void *ref) +{ +} + +int federatedx_io_null::seek_position(FEDERATEDX_IO_RESULT **io_result, + const void *ref) +{ + return 0; +} diff --git a/storage/federatedx/ha_federatedx.cc b/storage/federatedx/ha_federatedx.cc index 04ba9984492..8735e5625e6 100644 --- a/storage/federatedx/ha_federatedx.cc +++ b/storage/federatedx/ha_federatedx.cc @@ -1717,14 +1717,14 @@ federatedx_txn *ha_federatedx::get_txn(THD *thd, bool no_create) return *txnp; } - + int ha_federatedx::disconnect(handlerton *hton, MYSQL_THD thd) { federatedx_txn *txn= (federatedx_txn *) thd_get_ha_data(thd, hton); delete txn; return 0; } - + /* Used for opening tables. The name will be the name of the file. @@ -1756,14 +1756,15 @@ int ha_federatedx::open(const char *name, int mode, uint test_if_locked) free_share(txn, share); DBUG_RETURN(error); } - + + ref_length= io->get_ref_length(); + txn->release(&io); - - ref_length= (table->s->primary_key != MAX_KEY ? - table->key_info[table->s->primary_key].key_length : - table->s->reclength); + DBUG_PRINT("info", ("ref_length: %u", ref_length)); + my_init_dynamic_array(&results, sizeof(FEDERATEDX_IO_RESULT*), 4, 4); + reset(); DBUG_RETURN(0); @@ -1788,8 +1789,9 @@ int ha_federatedx::close(void) DBUG_ENTER("ha_federatedx::close"); /* free the result set */ - if (stored_result) - retval= free_result(); + reset(); + + delete_dynamic(&results); /* Disconnect from mysql */ if (!thd || !(txn= get_txn(thd, true))) @@ -1799,7 +1801,7 @@ int ha_federatedx::close(void) tmp_txn.release(&io); DBUG_ASSERT(io == NULL); - + if ((error= free_share(&tmp_txn, share))) retval= error; } @@ -2525,7 +2527,7 @@ int ha_federatedx::index_read_idx(uchar *buf, uint index, const uchar *key, uint key_len, enum ha_rkey_function find_flag) { int retval; - FEDERATEDX_IO_RESULT *io_result; + FEDERATEDX_IO_RESULT *io_result= 0; DBUG_ENTER("ha_federatedx::index_read_idx"); if ((retval= index_read_idx_with_result_set(buf, index, key, @@ -2601,7 +2603,7 @@ int ha_federatedx::index_read_idx_with_result_set(uchar *buf, uint index, if (!(retval= read_next(buf, *result))) DBUG_RETURN(retval); - io->free_result(*result); + insert_dynamic(&results, (uchar*) result); *result= 0; table->status= STATUS_NOT_FOUND; DBUG_RETURN(retval); @@ -2669,10 +2671,7 @@ int ha_federatedx::read_range_first(const key_range *start_key, DBUG_RETURN(retval); if (stored_result) - { - io->free_result(stored_result); - stored_result= 0; - } + (void) free_result(); if (io->query(sql_query.ptr(), sql_query.length())) { @@ -2773,10 +2772,7 @@ int ha_federatedx::rnd_init(bool scan) DBUG_RETURN(error); if (stored_result) - { - io->free_result(stored_result); - stored_result= 0; - } + (void) free_result(); if (io->query(share->select_query, strlen(share->select_query))) @@ -2803,17 +2799,35 @@ int ha_federatedx::rnd_end() int ha_federatedx::free_result() { int error; - federatedx_io *tmp_io= 0, **iop; + DBUG_ENTER("ha_federatedx::free_result"); DBUG_ASSERT(stored_result); - if (!*(iop= &io) && (error= txn->acquire(share, TRUE, (iop= &tmp_io)))) + for (uint i= 0; i < results.elements; ++i) { - DBUG_ASSERT(0); // Fail when testing - return error; + FEDERATEDX_IO_RESULT *result= 0; + get_dynamic(&results, (uchar*) &result, i); + if (result == stored_result) + goto end; } - (*iop)->free_result(stored_result); + if (position_called) + { + insert_dynamic(&results, (uchar*) &stored_result); + } + else + { + federatedx_io *tmp_io= 0, **iop; + if (!*(iop= &io) && (error= txn->acquire(share, TRUE, (iop= &tmp_io)))) + { + DBUG_ASSERT(0); // Fail when testing + insert_dynamic(&results, (uchar*) &stored_result); + goto end; + } + (*iop)->free_result(stored_result); + txn->release(&tmp_io); + } +end: stored_result= 0; - txn->release(&tmp_io); - return 0; + position_called= FALSE; + DBUG_RETURN(0); } int ha_federatedx::index_end(void) @@ -2862,8 +2876,8 @@ int ha_federatedx::rnd_next(uchar *buf) SYNOPSIS field_in_record_is_null() - buf byte pointer to record - result mysql result set + buf byte pointer to record + result mysql result set DESCRIPTION This method is a wrapper method that reads one record from a result @@ -2896,24 +2910,43 @@ int ha_federatedx::read_next(uchar *buf, FEDERATEDX_IO_RESULT *result) } -/* - store reference to current row so that we can later find it for - a re-read, update or delete. - - In case of federatedx, a reference is either a primary key or - the whole record. +/** + @brief Store a reference to current row. + + @details During a query execution we may have different result sets (RS), + e.g. for different ranges. All the RS's used are stored in + memory and placed in @c results dynamic array. At the end of + execution all stored RS's are freed at once in the + @c ha_federated::reset(). + So, in case of federated, a reference to current row is a + stored result address and current data cursor position. + As we keep all RS in memory during a query execution, + we can get any record using the reference any time until + @c ha_federated::reset() is called. + TODO: we don't have to store all RS's rows but only those + we call @c ha_federated::position() for, so we can free memory + where we store other rows in the @c ha_federated::index_end(). + + @param[in] record record data (unused) - Called from filesort.cc, sql_select.cc, sql_delete.cc and sql_update.cc. */ -void ha_federatedx::position(const uchar *record) +void ha_federatedx::position(const uchar *record __attribute__ ((unused))) { DBUG_ENTER("ha_federatedx::position"); - if (table->s->primary_key != MAX_KEY) - key_copy(ref, (uchar *)record, table->key_info + table->s->primary_key, - ref_length); - else - memcpy(ref, record, ref_length); + + bzero(ref, ref_length); + + if (!stored_result) + DBUG_VOID_RETURN; + + if (txn->acquire(share, TRUE, &io)) + DBUG_VOID_RETURN; + + io->mark_position(stored_result, ref); + + position_called= TRUE; + DBUG_VOID_RETURN; } @@ -2929,23 +2962,23 @@ void ha_federatedx::position(const uchar *record) int ha_federatedx::rnd_pos(uchar *buf, uchar *pos) { - int result; + int retval; + FEDERATEDX_IO_RESULT *result= stored_result; DBUG_ENTER("ha_federatedx::rnd_pos"); ha_statistic_increment(&SSV::ha_read_rnd_count); - if (table->s->primary_key != MAX_KEY) - { - /* We have a primary key, so use index_read_idx to find row */ - result= index_read_idx(buf, table->s->primary_key, pos, - ref_length, HA_READ_KEY_EXACT); - } - else - { - /* otherwise, get the old record ref as obtained in ::position */ - memcpy(buf, pos, ref_length); - result= 0; - } - table->status= result ? STATUS_NOT_FOUND : 0; - DBUG_RETURN(result); + + if ((retval= txn->acquire(share, TRUE, &io))) + goto error; + + if ((retval= io->seek_position(&result, pos))) + goto error; + + retval= read_next(buf, result); + DBUG_RETURN(retval); + +error: + table->status= STATUS_NOT_FOUND; + DBUG_RETURN(retval); } @@ -2996,15 +3029,20 @@ int ha_federatedx::rnd_pos(uchar *buf, uchar *pos) int ha_federatedx::info(uint flag) { uint error_code; + THD *thd= current_thd; + federatedx_txn *tmp_txn; federatedx_io *tmp_io= 0, **iop= 0; DBUG_ENTER("ha_federatedx::info"); error_code= ER_QUERY_ON_FOREIGN_DATA_SOURCE; + // external_lock may not have been called so txn may not be set + tmp_txn= get_txn(thd); + /* we want not to show table status if not needed to do so */ if (flag & (HA_STATUS_VARIABLE | HA_STATUS_CONST | HA_STATUS_AUTO)) { - if (!*(iop= &io) && (error_code= txn->acquire(share, TRUE, (iop= &tmp_io)))) + if (!*(iop= &io) && (error_code= tmp_txn->acquire(share, TRUE, (iop= &tmp_io)))) goto fail; } @@ -3029,14 +3067,14 @@ int ha_federatedx::info(uint flag) If ::info created it's own transaction, close it. This happens in case of show table status; */ - txn->release(&tmp_io); + tmp_txn->release(&tmp_io); DBUG_RETURN(0); error: if (iop && *iop) { - my_printf_error((*iop)->error_code(), "Got error: %d : %s", MYF(0), + my_printf_error((*iop)->error_code(), "Received error: %d : %s", MYF(0), (*iop)->error_code(), (*iop)->error_str()); } else if (remote_error_number != -1 /* error already reported */) @@ -3045,7 +3083,7 @@ error: my_error(error_code, MYF(0), ER(error_code)); } fail: - txn->release(&tmp_io); + tmp_txn->release(&tmp_io); DBUG_RETURN(error_code); } @@ -3105,12 +3143,44 @@ int ha_federatedx::extra(ha_extra_function operation) int ha_federatedx::reset(void) { + int error = 0; + insert_dup_update= FALSE; ignore_duplicates= FALSE; replace_duplicates= FALSE; - return 0; -} + position_called= FALSE; + + if (stored_result) + insert_dynamic(&results, (uchar*) &stored_result); + stored_result= 0; + + if (results.elements) + { + federatedx_txn *tmp_txn; + federatedx_io *tmp_io= 0, **iop; + + // external_lock may not have been called so txn may not be set + tmp_txn= get_txn(current_thd); + + if (!*(iop= &io) && (error= tmp_txn->acquire(share, TRUE, (iop= &tmp_io)))) + { + DBUG_ASSERT(0); // Fail when testing + return error; + } + + for (uint i= 0; i < results.elements; ++i) + { + FEDERATEDX_IO_RESULT *result= 0; + get_dynamic(&results, (uchar*) &result, i); + (*iop)->free_result(result); + } + tmp_txn->release(&tmp_io); + reset_dynamic(&results); + } + + return error; +} /* Used to delete all rows in a table. Both for cases of truncate and @@ -3237,7 +3307,7 @@ static int test_connection(MYSQL_THD thd, federatedx_io *io, str.length(0); str.append(STRING_WITH_LEN("SELECT * FROM ")); - append_identifier(thd, &str, share->table_name, + append_identifier(thd, &str, share->table_name, share->table_name_length); str.append(STRING_WITH_LEN(" WHERE 1=0")); @@ -3288,14 +3358,14 @@ int ha_federatedx::create(const char *name, TABLE *table_arg, pthread_mutex_lock(&federatedx_mutex); tmp_share.s= get_server(&tmp_share, NULL); pthread_mutex_unlock(&federatedx_mutex); - + if (tmp_share.s) { tmp_txn= get_txn(thd); if (!(retval= tmp_txn->acquire(&tmp_share, TRUE, &tmp_io))) { retval= test_connection(thd, tmp_io, &tmp_share); - tmp_txn->release(&tmp_io); + tmp_txn->release(&tmp_io); } free_server(tmp_txn, tmp_share.s); } diff --git a/storage/federatedx/ha_federatedx.h b/storage/federatedx/ha_federatedx.h index 2fd3c559321..2820f8a6c29 100644 --- a/storage/federatedx/ha_federatedx.h +++ b/storage/federatedx/ha_federatedx.h @@ -1,5 +1,5 @@ -/* -Copyright (c) 2008, Patrick Galbraith +/* +Copyright (c) 2008, Patrick Galbraith All rights reserved. Redistribution and use in source and binary forms, with or without @@ -43,7 +43,7 @@ class federatedx_io; typedef struct st_fedrated_server { MEM_ROOT mem_root; uint use_count, io_count; - + uchar *key; uint key_length; @@ -74,10 +74,10 @@ typedef struct st_fedrated_server { #include <mysql.h> -/* +/* handler::print_error has a case statement for error numbers. - This value is (10000) is far out of range and will envoke the - default: case. + This value is (10000) is far out of range and will envoke the + default: case. (Current error range is 120-159 from include/my_base.h) */ #define HA_FEDERATEDX_ERROR_WITH_REMOTE_SYSTEM 10000 @@ -158,7 +158,7 @@ public: const char * get_database() const { return server->database; } ushort get_port() const { return server->port; } const char * get_socket() const { return server->socket; } - + static bool handles_scheme(const char *scheme); static federatedx_io *construct(MEM_ROOT *server_root, FEDERATEDX_SERVER *server); @@ -167,7 +167,7 @@ public: { return alloc_root(mem_root, size); } static void operator delete(void *ptr, size_t size) { TRASH(ptr, size); } - + virtual int query(const char *buffer, uint length)=0; virtual FEDERATEDX_IO_RESULT *store_result()=0; @@ -178,25 +178,25 @@ public: virtual int error_code()=0; virtual const char *error_str()=0; - + virtual void reset()=0; virtual int commit()=0; virtual int rollback()=0; - + virtual int savepoint_set(ulong sp)=0; virtual ulong savepoint_release(ulong sp)=0; virtual ulong savepoint_rollback(ulong sp)=0; virtual void savepoint_restrict(ulong sp)=0; - + virtual ulong last_savepoint() const=0; virtual ulong actual_savepoint() const=0; virtual bool is_autocommit() const=0; virtual bool table_metadata(ha_statistics *stats, const char *table_name, uint table_name_length, uint flag) = 0; - + /* resultset operations */ - + virtual void free_result(FEDERATEDX_IO_RESULT *io_result)=0; virtual unsigned int get_num_fields(FEDERATEDX_IO_RESULT *io_result)=0; virtual my_ulonglong get_num_rows(FEDERATEDX_IO_RESULT *io_result)=0; @@ -206,6 +206,13 @@ public: unsigned int column)=0; virtual bool is_column_null(const FEDERATEDX_IO_ROW *row, unsigned int column) const=0; + + virtual size_t get_ref_length() const=0; + virtual void mark_position(FEDERATEDX_IO_RESULT *io_result, + void *ref)=0; + virtual int seek_position(FEDERATEDX_IO_RESULT **io_result, + const void *ref)=0; + }; @@ -215,12 +222,12 @@ class federatedx_txn ulong savepoint_level; ulong savepoint_stmt; ulong savepoint_next; - + void release_scan(); public: federatedx_txn(); ~federatedx_txn(); - + bool has_connections() const { return txn_list != NULL; } bool in_transaction() const { return savepoint_next != 0; } int acquire(FEDERATEDX_SHARE *share, bool readonly, federatedx_io **io); @@ -254,8 +261,12 @@ class ha_federatedx: public handler federatedx_txn *txn; federatedx_io *io; FEDERATEDX_IO_RESULT *stored_result; + /** + Array of all stored results we get during a query execution. + */ + DYNAMIC_ARRAY results; + bool position_called; uint fetch_num; // stores the fetch num - FEDERATEDX_IO_OFFSET current_position; // Current position used by ::position() int remote_error_number; char remote_error_buf[FEDERATEDX_QUERY_BUFFER_SIZE]; bool ignore_duplicates, replace_duplicates; @@ -269,7 +280,7 @@ private: */ uint convert_row_to_internal_format(uchar *buf, FEDERATEDX_IO_ROW *row, FEDERATEDX_IO_RESULT *result); - bool create_where_from_key(String *to, KEY *key_info, + bool create_where_from_key(String *to, KEY *key_info, const key_range *start_key, const key_range *end_key, bool records_in_range, bool eq_range); @@ -348,18 +359,18 @@ public: Talk to Kostja about this - how to get the number of rows * ... disk scan time on other side (block size, size of the row) + network time ... - The reason for "records * 1000" is that such a large number forces + The reason for "records * 1000" is that such a large number forces this to use indexes " */ double scan_time() { DBUG_PRINT("info", ("records %lu", (ulong) stats.records)); - return (double)(stats.records*1000); + return (double)(stats.records*1000); } /* The next method will never be called if you do not implement indexes. */ - double read_time(uint index, uint ranges, ha_rows rows) + double read_time(uint index, uint ranges, ha_rows rows) { /* Per Brian, this number is bugus, but this method must be implemented, diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc index b8f31cce755..1475cd52488 100644 --- a/storage/maria/ha_maria.cc +++ b/storage/maria/ha_maria.cc @@ -248,7 +248,7 @@ static MYSQL_THDVAR_ULONG(repair_threads, PLUGIN_VAR_RQCMDARG, static MYSQL_THDVAR_ULONG(sort_buffer_size, PLUGIN_VAR_RQCMDARG, "The buffer that is allocated when sorting the index when doing a " "REPAIR or when creating indexes with CREATE INDEX or ALTER TABLE.", - 0, 0, 8192*1024, 4, ~0L, 1); + 0, 0, 128L*1024L*1024L, 4, ~0L, 1); static MYSQL_THDVAR_ENUM(stats_method, PLUGIN_VAR_RQCMDARG, "Specifies how maria index statistics collection code should treat " @@ -1850,7 +1850,7 @@ int ha_maria::enable_indexes(uint mode) "retrying", my_errno, param.db_name, param.table_name); /* This should never fail normally */ - DBUG_ASSERT(0); + DBUG_ASSERT(thd->killed != 0); /* Repairing by sort failed. Now try standard repair method. */ param.testflag &= ~T_REP_BY_SORT; error= (repair(thd, ¶m, 0) != HA_ADMIN_OK); diff --git a/storage/maria/ma_bitmap.c b/storage/maria/ma_bitmap.c index 70617160d03..a76b36e1115 100644 --- a/storage/maria/ma_bitmap.c +++ b/storage/maria/ma_bitmap.c @@ -365,8 +365,8 @@ my_bool _ma_bitmap_flush_all(MARIA_SHARE *share) */ if (bitmap->changed) { - res= write_changed_bitmap(share, bitmap); bitmap->changed= FALSE; + res= write_changed_bitmap(share, bitmap); } /* We do NOT use FLUSH_KEEP_LAZY because we must be sure that bitmap @@ -2063,6 +2063,13 @@ my_bool _ma_bitmap_set_full_page_bits(MARIA_HA *info, safe_mutex_assert_owner(&info->s->bitmap.bitmap_lock); bitmap_page= page - page % bitmap->pages_covered; + if (page == bitmap_page || + page + page_count >= bitmap_page + bitmap->pages_covered) + { + DBUG_ASSERT(0); /* Wrong in data */ + DBUG_RETURN(1); + } + if (bitmap_page != bitmap->page && _ma_change_bitmap_page(info, bitmap, bitmap_page)) DBUG_RETURN(1); @@ -2142,12 +2149,12 @@ void _ma_bitmap_flushable(MARIA_HA *info, int non_flushable_inc) DBUG_VOID_RETURN; bitmap= &share->bitmap; + pthread_mutex_lock(&bitmap->bitmap_lock); + if (non_flushable_inc == -1) { - pthread_mutex_lock(&bitmap->bitmap_lock); DBUG_ASSERT((int) bitmap->non_flushable > 0); DBUG_ASSERT(info->non_flushable_state == 1); - info->non_flushable_state= 0; if (--bitmap->non_flushable == 0) { /* @@ -2164,11 +2171,11 @@ void _ma_bitmap_flushable(MARIA_HA *info, int non_flushable_inc) } DBUG_PRINT("info", ("bitmap->non_flushable: %u", bitmap->non_flushable)); pthread_mutex_unlock(&bitmap->bitmap_lock); + info->non_flushable_state= 0; DBUG_VOID_RETURN; } DBUG_ASSERT(non_flushable_inc == 1); DBUG_ASSERT(info->non_flushable_state == 0); - pthread_mutex_lock(&bitmap->bitmap_lock); while (unlikely(bitmap->flush_all_requested)) { /* @@ -2186,9 +2193,9 @@ void _ma_bitmap_flushable(MARIA_HA *info, int non_flushable_inc) pthread_cond_wait(&bitmap->bitmap_cond, &bitmap->bitmap_lock); } bitmap->non_flushable++; - info->non_flushable_state= 1; DBUG_PRINT("info", ("bitmap->non_flushable: %u", bitmap->non_flushable)); pthread_mutex_unlock(&bitmap->bitmap_lock); + info->non_flushable_state= 1; DBUG_VOID_RETURN; } @@ -2217,6 +2224,8 @@ void _ma_bitmap_flushable(MARIA_HA *info, int non_flushable_inc) Note that we may have 'filler blocks' that are used to split a block in half; These can be recognized by that they have page_count == 0. + This code also reverse the effect of ma_bitmap_flushable(.., 1); + RETURN 0 ok 1 error (Couldn't write or read bitmap page) diff --git a/storage/maria/ma_blockrec.c b/storage/maria/ma_blockrec.c index f62a4e2ce6d..0779564c8af 100644 --- a/storage/maria/ma_blockrec.c +++ b/storage/maria/ma_blockrec.c @@ -334,12 +334,13 @@ typedef struct st_maria_extent_cursor } \ } while (0) + static my_bool delete_tails(MARIA_HA *info, MARIA_RECORD_POS *tails); static my_bool delete_head_or_tail(MARIA_HA *info, pgcache_page_no_t page, uint record_number, my_bool head, my_bool from_update); #ifndef DBUG_OFF -static void _ma_print_directory(uchar *buff, uint block_size); +static void _ma_print_directory(FILE *file, uchar *buff, uint block_size); #endif static uchar *store_page_range(uchar *to, MARIA_BITMAP_BLOCK *block, uint block_size, ulong length, @@ -615,7 +616,7 @@ static inline uint end_of_previous_entry(uchar *dir, uchar *end) #ifndef DBUG_OFF -static void _ma_print_directory(uchar *buff, uint block_size) +static void _ma_print_directory(FILE *file, uchar *buff, uint block_size) { uint max_entry= (uint) ((uchar *) buff)[DIR_COUNT_OFFSET], row= 0; uint end_of_prev_row= PAGE_HEADER_SIZE; @@ -624,40 +625,46 @@ static void _ma_print_directory(uchar *buff, uint block_size) dir= dir_entry_pos(buff, block_size, max_entry-1); end= dir_entry_pos(buff, block_size, 0); - DBUG_LOCK_FILE; - fprintf(DBUG_FILE,"Directory dump (pos:length):\n"); + DBUG_LOCK_FILE; /* If using DBUG_FILE */ + fprintf(file,"Directory dump (pos:length):\n"); for (row= 1; dir <= end ; end-= DIR_ENTRY_SIZE, row++) { uint offset= uint2korr(end); uint length= uint2korr(end+2); - fprintf(DBUG_FILE, " %4u:%4u", offset, offset ? length : 0); + fprintf(file, " %4u:%4u", offset, offset ? length : 0); if (!(row % (80/12))) - fputc('\n', DBUG_FILE); + fputc('\n', file); if (offset) { DBUG_ASSERT(offset >= end_of_prev_row); end_of_prev_row= offset + length; } } - fputc('\n', DBUG_FILE); - fflush(DBUG_FILE); + fputc('\n', file); + fflush(file); DBUG_UNLOCK_FILE; } -static void check_directory(uchar *buff, uint block_size, uint min_row_length) +static void check_directory(uchar *buff, uint block_size, uint min_row_length, + uint real_empty_size) { uchar *dir, *end; uint max_entry= (uint) buff[DIR_COUNT_OFFSET]; uint start_of_dir, deleted; - uchar free_entry, prev_free_entry; uint end_of_prev_row= PAGE_HEADER_SIZE; + uint empty_size_on_page; + uint empty_size; + uchar free_entry, prev_free_entry; dir= dir_entry_pos(buff, block_size, max_entry-1); start_of_dir= (uint) (dir - buff); end= dir_entry_pos(buff, block_size, 0); - deleted= 0; + deleted= empty_size= 0; + + empty_size_on_page= (real_empty_size != (uint) -1 ? real_empty_size : + uint2korr(buff + EMPTY_SPACE_OFFSET)); /* Ensure that all rows are in increasing order and no overlaps */ for (; dir <= end ; end-= DIR_ENTRY_SIZE) @@ -668,12 +675,15 @@ static void check_directory(uchar *buff, uint block_size, uint min_row_length) { DBUG_ASSERT(offset >= end_of_prev_row); DBUG_ASSERT(!length || length >= min_row_length); + empty_size+= offset - end_of_prev_row; end_of_prev_row= offset + length; } else deleted++; } + empty_size+= start_of_dir - end_of_prev_row; DBUG_ASSERT(end_of_prev_row <= start_of_dir); + DBUG_ASSERT(empty_size == empty_size_on_page); /* check free links */ free_entry= buff[DIR_FREE_OFFSET]; @@ -690,7 +700,7 @@ static void check_directory(uchar *buff, uint block_size, uint min_row_length) DBUG_ASSERT(deleted == 0); } #else -#define check_directory(A,B,C) +#define check_directory(A,B,C,D) #endif /* DBUG_OFF */ @@ -792,20 +802,27 @@ static my_bool extend_area_on_page(MARIA_HA *info, uint *empty_space, uint *ret_offset, uint *ret_length) { - uint rec_offset, length; + uint rec_offset, length, org_rec_length; uint max_entry= (uint) buff[DIR_COUNT_OFFSET]; DBUG_ENTER("extend_area_on_page"); + /* + We can't check for min length here as we may have called + extend_directory() to create a new (empty) entry just before + */ + check_directory(buff, block_size, 0, *empty_space); + rec_offset= uint2korr(dir); if (rec_offset) { /* Extending old row; Mark current space as 'free' */ - length= uint2korr(dir + 2); + length= org_rec_length= uint2korr(dir + 2); DBUG_PRINT("info", ("rec_offset: %u length: %u request_length: %u " "empty_space: %u", - rec_offset, length, request_length, *empty_space)); + rec_offset, org_rec_length, request_length, + *empty_space)); - *empty_space+= length; + *empty_space+= org_rec_length; } else { @@ -875,6 +892,7 @@ static my_bool extend_area_on_page(MARIA_HA *info, "length: %u request_length: %u", length, request_length)); my_errno= HA_ERR_WRONG_IN_RECORD; /* File crashed */ + DBUG_ASSERT(0); /* For debugging */ DBUG_RETURN(1); /* Error in block */ } *empty_space= length; /* All space is here */ @@ -885,7 +903,9 @@ static my_bool extend_area_on_page(MARIA_HA *info, int2store(dir + 2, length); *ret_offset= rec_offset; *ret_length= length; - check_directory(buff, block_size, info ? info->s->base.min_block_length : 0); + + check_directory(buff, block_size, info ? info->s->base.min_block_length : 0, + *empty_space - length); DBUG_RETURN(0); } @@ -1094,7 +1114,7 @@ static uchar *find_free_position(MARIA_HA *info, *res_length= length; check_directory(buff, block_size, - info ? info->s->base.min_block_length : 0); + info ? info->s->base.min_block_length : 0, (uint) -1); DBUG_RETURN(dir); } /* No free places in dir; create a new one */ @@ -1115,7 +1135,8 @@ static uchar *find_free_position(MARIA_HA *info, *res_rownr= max_entry; *res_length= length; - check_directory(buff, block_size, info ? info->s->base.min_block_length : 0); + check_directory(buff, block_size, info ? info->s->base.min_block_length : 0, + *empty_space); DBUG_RETURN(dir); } @@ -1195,7 +1216,8 @@ static my_bool extend_directory(MARIA_HA *info, uchar *buff, uint block_size, } check_directory(buff, block_size, - info ? min(info->s->base.min_block_length, length) : 0); + info ? min(info->s->base.min_block_length, length) : 0, + *empty_space); DBUG_RETURN(0); } @@ -1496,6 +1518,8 @@ void _ma_compact_block_page(uchar *buff, uint block_size, uint rownr, { /* Move all entries after rownr to end of page */ uint rownr_length; + + DBUG_ASSERT(extend_block); /* Should always be true */ next_free_pos= end_of_found_block= page_pos= block_size - DIR_ENTRY_SIZE * max_entry - PAGE_SUFFIX_SIZE; diff= 0; @@ -1567,13 +1591,13 @@ void _ma_compact_block_page(uchar *buff, uint block_size, uint rownr, int2store(dir, offset + diff); /* correct current pos */ next_free_pos= offset; } - if (page_pos != end_of_found_block) { uint length= (end_of_found_block - next_free_pos); memmove(buff + page_pos - length, buff + next_free_pos, length); next_free_pos= page_pos- length; } + /* Extend rownr block to cover hole */ rownr_length= next_free_pos - start_of_found_block; int2store(dir+2, rownr_length); @@ -1596,8 +1620,9 @@ void _ma_compact_block_page(uchar *buff, uint block_size, uint rownr, } buff[PAGE_TYPE_OFFSET]&= ~(uchar) PAGE_CAN_BE_COMPACTED; } - check_directory(buff, block_size, min_row_length); - DBUG_EXECUTE("directory", _ma_print_directory(buff, block_size);); + check_directory(buff, block_size, min_row_length, + extend_block ? 0 : (uint) -1); + DBUG_EXECUTE("directory", _ma_print_directory(DBUG_FILE, buff, block_size);); DBUG_VOID_RETURN; } @@ -1826,16 +1851,11 @@ static my_bool get_rowpos_in_head_or_tail_page(MARIA_HA *info, goto err; } + /* + The following dir entry is unused in case of insert / update but + not in case of undo_update / undo_delete + */ dir= dir_entry_pos(buff, block_size, rownr); -#ifdef SANITY_CHECKS - /* Tail's should always be unused */ - if (page_type == TAIL_PAGE && max_entry > rownr && - (dir[0] != 0 || dir[1] != 0)) - { - DBUG_ASSERT(0); - goto err; - } -#endif if (extend_area_on_page(page_type == HEAD_PAGE ? info : 0, buff, dir, rownr, block_size, length, @@ -2212,6 +2232,8 @@ static void store_extent_info(uchar *to, MARIA_BITMAP_BLOCK *block, *end_block; uint copy_length; my_bool first_found= 0; + DBUG_ENTER("store_extent_info"); + DBUG_PRINT("enter", ("count: %u", count)); for (block= first_block, end_block= first_block+count ; block < end_block; block++) @@ -2231,6 +2253,7 @@ static void store_extent_info(uchar *to, page_count|= START_EXTENT_BIT; } pagerange_store(to + PAGE_STORE_SIZE, page_count); + DBUG_DUMP("extent", to, ROW_EXTENT_SIZE); to+= ROW_EXTENT_SIZE; if (!first_found) { @@ -2245,6 +2268,7 @@ static void store_extent_info(uchar *to, data. */ bzero(to, (size_t) (row_extents_second_part + copy_length - to)); + DBUG_VOID_RETURN; } @@ -2263,7 +2287,8 @@ static void store_extent_info(uchar *to, @return @retval 0 ok - @retval 1 Error (out of memory or disk error changing bitmap) + @retval 1 Error (out of memory or disk error changing bitmap) or + wrong information in extent information */ static my_bool extent_to_bitmap_blocks(MARIA_HA *info, @@ -2274,7 +2299,7 @@ static my_bool extent_to_bitmap_blocks(MARIA_HA *info, { MARIA_BITMAP_BLOCK *block, *start_block; MARIA_SHARE *share= info->s; - uint i; + uint i, tail_page; DBUG_ENTER("extent_to_bitmap_blocks"); if (allocate_dynamic(&info->bitmap_blocks, extent_count + 2)) @@ -2300,13 +2325,36 @@ static my_bool extent_to_bitmap_blocks(MARIA_HA *info, page_count&= ~START_EXTENT_BIT; start_block->sub_blocks= (uint) (block - start_block); start_block= block; - } block->page= page_korr(extent_info); block->page_count= page_count; block->sub_blocks= 0; + if (block->page_count == 0) + { + /* Extend allocated but not used by write_block_record() */ + DBUG_ASSERT(block->page == 0); + /* This is the last block */ + blocks->count= i; + break; + } + if ((tail_page= page_count & TAIL_BIT)) + page_count= 1; - if (page_count & TAIL_BIT) + /* Check if wrong data */ + if (block->page == 0 || page_count == 0 || + (block->page + page_count) * share->block_size > + share->state.state.data_file_length) + { + DBUG_PRINT("error", ("page: %lu page_count: %u tail: %u length: %ld data_length: %ld", + (ulong) block->page, + (block->page_count & ~TAIL_BIT), + (uint) test(block->page_count & TAIL_BIT), + (ulong) ((block->page + (page_count & ~TAIL_BIT)) * + share->block_size), + (ulong) share->state.state.data_file_length)); + DBUG_RETURN(1); + } + if (tail_page) { block->org_bitmap_value= _ma_bitmap_get_page_bits(info, &share->bitmap, block->page); @@ -2318,7 +2366,7 @@ static my_bool extent_to_bitmap_blocks(MARIA_HA *info, my_bool res; pthread_mutex_lock(&share->bitmap.bitmap_lock); res= _ma_bitmap_set_full_page_bits(info, &share->bitmap, - block->page, block->page_count); + block->page, page_count); pthread_mutex_unlock(&share->bitmap.bitmap_lock); if (res) DBUG_RETURN(1); @@ -2740,9 +2788,16 @@ static my_bool write_block_record(MARIA_HA *info, sizeof(char*)); memcpy(data, tmp_pos, *blob_lengths); data+= *blob_lengths; - /* Skip over tail page that was to be used to store blob */ - block++; - bitmap_blocks->tail_page_skipped= 1; + /* + The following is not true when we want to insert data into original + place. In this case we don't have any extra blocks allocated + */ + if (likely(undo_lsn == LSN_ERROR)) + { + /* Skip over tail page that was prepared for storing blob */ + block++; + bitmap_blocks->tail_page_skipped= 1; + } } if (head_block->sub_blocks > 1) { @@ -2755,7 +2810,9 @@ static my_bool write_block_record(MARIA_HA *info, /* Update page directory */ head_length= (uint) (data - row_pos->data); - DBUG_PRINT("info", ("Used head length on page: %u", head_length)); + DBUG_PRINT("info", ("Used head length on page: %u header_length: %u", + head_length, + (uint) (flag & ROW_FLAG_TRANSID ? TRANSID_SIZE : 0))); DBUG_ASSERT(data <= end_of_data); if (head_length < share->base.min_block_length) { @@ -2765,6 +2822,7 @@ static my_bool write_block_record(MARIA_HA *info, data+= diff_length; head_length= share->base.min_block_length; } + DBUG_ASSERT(undo_lsn == LSN_ERROR || head_length == row_pos->length); int2store(row_pos->dir + 2, head_length); /* update empty space at start of block */ row_pos->empty_space-= head_length; @@ -2776,7 +2834,8 @@ static my_bool write_block_record(MARIA_HA *info, head_block->empty_space= 0; /* Page is full */ head_block->used|= BLOCKUSED_USED; - check_directory(page_buff, share->block_size, share->base.min_block_length); + check_directory(page_buff, share->block_size, share->base.min_block_length, + (uint) -1); /* Now we have to write tail pages, as we need to store the position @@ -2827,11 +2886,13 @@ static my_bool write_block_record(MARIA_HA *info, { /* Set only a bit, to not cause bitmap code to believe a block is full - when there is still a lot of entries in it + when there is still a lot of entries in it. */ block->used|= BLOCKUSED_USED; } } + DBUG_ASSERT((undo_lsn == LSN_ERROR || + block == bitmap_blocks->block + bitmap_blocks->count)); column= save_column; block= save_block; blob_lengths= save_blob_lengths; @@ -3225,9 +3286,10 @@ static my_bool write_block_record(MARIA_HA *info, else { uchar log_data[LSN_STORE_SIZE + FILEID_STORE_SIZE + - PAGE_STORE_SIZE + DIRPOS_STORE_SIZE + + PAGE_STORE_SIZE + DIRPOS_STORE_SIZE + 2 + HA_CHECKSUM_STORE_SIZE + 2 + PAGERANGE_STORE_SIZE + ROW_EXTENT_SIZE]; + uchar *log_pos; ha_checksum checksum_delta; /* LOGREC_UNDO_ROW_INSERT & LOGREC_UNDO_ROW_UPDATE share same header */ @@ -3237,18 +3299,17 @@ static my_bool write_block_record(MARIA_HA *info, dirpos_store(log_data + LSN_STORE_SIZE + FILEID_STORE_SIZE + PAGE_STORE_SIZE, row_pos->rownr); - - log_array[TRANSLOG_INTERNAL_PARTS + 0].str= log_data; - log_array[TRANSLOG_INTERNAL_PARTS + 0].length= - (LSN_STORE_SIZE + FILEID_STORE_SIZE + PAGE_STORE_SIZE + - DIRPOS_STORE_SIZE); + log_pos= (log_data + LSN_STORE_SIZE + FILEID_STORE_SIZE + + PAGE_STORE_SIZE + DIRPOS_STORE_SIZE); store_checksum_in_rec(share, checksum_delta, row->checksum - old_record_checksum, - log_data + LSN_STORE_SIZE + FILEID_STORE_SIZE + - PAGE_STORE_SIZE + DIRPOS_STORE_SIZE, - log_array[TRANSLOG_INTERNAL_PARTS + 0].length); + log_pos, log_pos); compile_time_assert(sizeof(ha_checksum) == HA_CHECKSUM_STORE_SIZE); + log_array[TRANSLOG_INTERNAL_PARTS + 0].str= log_data; + log_array[TRANSLOG_INTERNAL_PARTS + 0].length= (uint) (log_pos - + log_data); + if (!old_record) { /* Store undo_lsn in case we are aborting the insert */ @@ -3267,16 +3328,18 @@ static my_bool write_block_record(MARIA_HA *info, else { /* Write UNDO log record for the UPDATE */ - uchar *log_pos= (log_data + - log_array[TRANSLOG_INTERNAL_PARTS + 0].length); size_t row_length, extents_length; - uint row_parts_count; + uint row_parts_count, cur_head_length; /* Write head length and extents of the original row so that we - during UNDO can put it back in the original position + during UNDO can put it back in the original position. + We don't store size for TRANSID, as we don't write this during + UNDO. */ - int2store(log_pos, info->cur_row.head_length); + cur_head_length= (info->cur_row.head_length - + info->cur_row.header_length); + int2store(log_pos, cur_head_length); pagerange_store(log_pos + 2, info->cur_row.extents_count); log_pos+= 2 + PAGERANGE_STORE_SIZE; log_array[TRANSLOG_INTERNAL_PARTS + 0].length+= (2 + @@ -3589,6 +3652,7 @@ static my_bool _ma_update_block_record2(MARIA_HA *info, MARIA_PINNED_PAGE page_link; uint rownr, org_empty_size, head_length; uint block_size= info->s->block_size; + uint errpos= 0; uchar *dir; pgcache_page_no_t page; struct st_row_pos_info row_pos; @@ -3627,11 +3691,21 @@ static my_bool _ma_update_block_record2(MARIA_HA *info, rownr= ma_recordpos_to_dir_entry(record_pos); dir= dir_entry_pos(buff, block_size, rownr); - if ((org_empty_size + cur_row->head_length) >= new_row->total_length) + /* + We can't use cur_row->head_length as the block may have been compacted + since we read it. + */ + head_length= uint2korr(dir + 2); + + if ((org_empty_size + head_length) >= new_row->total_length) { uint rec_offset, length; MARIA_BITMAP_BLOCK block; + DBUG_PRINT("info", ("org_empty_size: %u org_length: %u new_length: %lu", + org_empty_size, head_length, + new_row->total_length)); + /* We can fit the new row in the same page as the original head part of the row @@ -3641,7 +3715,10 @@ static my_bool _ma_update_block_record2(MARIA_HA *info, if (extend_area_on_page(info, buff, dir, rownr, block_size, new_row->total_length, &org_empty_size, &rec_offset, &length)) + { + errpos= 1; goto err; + } row_pos.buff= buff; row_pos.rownr= rownr; @@ -3658,9 +3735,15 @@ static my_bool _ma_update_block_record2(MARIA_HA *info, if (*cur_row->tail_positions && delete_tails(info, cur_row->tail_positions)) + { + errpos= 2; goto err; + } if (cur_row->extents_count && free_full_pages(info, cur_row)) + { + errpos= 3; goto err; + } res= write_block_record(info, oldrec, record, new_row, blocks, 1, &row_pos, undo_lsn, old_checksum); /* We can't update or delete this without re-reading it again */ @@ -3670,14 +3753,23 @@ static my_bool _ma_update_block_record2(MARIA_HA *info, /* Delete old row */ if (*cur_row->tail_positions && delete_tails(info, cur_row->tail_positions)) + { + errpos= 4; goto err; + } if (cur_row->extents_count && free_full_pages(info, cur_row)) + { + errpos= 5; goto err; + } head_length= uint2korr(dir + 2); if (_ma_bitmap_find_new_place(info, new_row, page, head_length + org_empty_size, blocks)) + { + errpos= 6; goto err; + } /* Allocate all size in block for record @@ -3704,10 +3796,14 @@ static my_bool _ma_update_block_record2(MARIA_HA *info, row_pos.length= head_length; if ((res= write_block_record(info, oldrec, record, new_row, blocks, 1, &row_pos, undo_lsn, old_checksum))) + { + errpos= 7; goto err; + } DBUG_RETURN(0); err: + DBUG_PRINT("error", ("errpos: %d", errpos)); if (info->non_flushable_state) _ma_bitmap_flushable(info, -1); _ma_unpin_all_pages_and_finalize_row(info, LSN_IMPOSSIBLE); @@ -3725,6 +3821,8 @@ err: This is the main reason we don't make a lot of subfunctions that are common between _ma_update_block_record2() and this function. + + Note: If something goes wrong we mark the file crashed */ static my_bool _ma_update_at_original_place(MARIA_HA *info, @@ -3780,6 +3878,10 @@ static my_bool _ma_update_at_original_place(MARIA_HA *info, if ((org_empty_size + cur_row->head_length) < length_on_head_page) { + DBUG_PRINT("error", + ("org_empty_size: %u head_length: %u length_on_page: %u", + org_empty_size, (uint) cur_row->head_length, + length_on_head_page)); my_errno= HA_ERR_WRONG_IN_RECORD; goto err; } @@ -3799,7 +3901,6 @@ static my_bool _ma_update_at_original_place(MARIA_HA *info, row_pos.empty_space= empty_size; row_pos.dir= dir; row_pos.data= buff + rec_offset; - row_pos.length= length_on_head_page; /* Delete old row */ if (*cur_row->tail_positions && @@ -3829,12 +3930,17 @@ static my_bool _ma_update_at_original_place(MARIA_HA *info, max(new_row->total_length, share->base.min_block_length) <= length_on_head_page); + /* Store same amount of data on head page as on original page */ + row_pos.length= (length_on_head_page - + (extent_count + 1 - blocks->count) * ROW_EXTENT_SIZE); + set_if_bigger(row_pos.length, share->base.min_block_length); if ((res= write_block_record(info, oldrec, record, new_row, blocks, 1, &row_pos, undo_lsn, old_checksum))) goto err; DBUG_RETURN(0); err: + _ma_mark_file_crashed(share); if (info->non_flushable_state) _ma_bitmap_flushable(info, -1); _ma_unpin_all_pages_and_finalize_row(info, LSN_IMPOSSIBLE); @@ -3888,7 +3994,7 @@ static int delete_dir_entry(uchar *buff, uint block_size, uint record_number, } #endif - check_directory(buff, block_size, 0); + check_directory(buff, block_size, 0, (uint) -1); empty_space= uint2korr(buff + EMPTY_SPACE_OFFSET); dir= dir_entry_pos(buff, block_size, record_number); length= uint2korr(dir + 2); @@ -3963,7 +4069,7 @@ static int delete_dir_entry(uchar *buff, uint block_size, uint record_number, *empty_space_res= empty_space; - check_directory(buff, block_size, 0); + check_directory(buff, block_size, 0, empty_space); DBUG_RETURN(0); } @@ -4165,7 +4271,8 @@ my_bool _ma_delete_block_record(MARIA_HA *info, const uchar *record) log_pos= log_data + LSN_STORE_SIZE + FILEID_STORE_SIZE + PAGE_STORE_SIZE; dirpos_store(log_pos, record_number); log_pos+= DIRPOS_STORE_SIZE; - int2store(log_pos, info->cur_row.head_length); + int2store(log_pos, info->cur_row.head_length - + info->cur_row.header_length); log_pos+= 2; pagerange_store(log_pos, info->cur_row.extents_count); log_pos+= PAGERANGE_STORE_SIZE; @@ -4543,6 +4650,8 @@ int _ma_read_block_record2(MARIA_HA *info, uchar *record, cur_row->head_length= (uint) (end_of_data - data); cur_row->full_page_count= cur_row->tail_count= 0; cur_row->blob_length= 0; + /* Number of bytes in header that we don't need to write during undo */ + cur_row->header_length= total_header_size[(flag & PRECALC_HEADER_BITMASK)]-1; if (flag & ROW_FLAG_TRANSID) { @@ -4554,7 +4663,7 @@ int _ma_read_block_record2(MARIA_HA *info, uchar *record, } /* Skip trans header (for now, until we have MVCC csupport) */ - data+= total_header_size[(flag & PRECALC_HEADER_BITMASK)]; + data+= cur_row->header_length + 1 ; if (flag & ROW_FLAG_NULLS_EXTENDED) cur_null_bytes+= data[-1]; @@ -4950,7 +5059,10 @@ int _ma_read_block_record(MARIA_HA *info, uchar *record, uint offset; uint block_size= share->block_size; DBUG_ENTER("_ma_read_block_record"); - DBUG_PRINT("enter", ("rowid: %lu", (long) record_pos)); + DBUG_PRINT("enter", ("rowid: %lu page: %lu rownr: %u", + (ulong) record_pos, + (ulong) ma_recordpos_to_page(record_pos), + ma_recordpos_to_dir_entry(record_pos))); offset= ma_recordpos_to_dir_entry(record_pos); @@ -6698,7 +6810,7 @@ my_bool _ma_apply_undo_row_insert(MARIA_HA *info, LSN undo_lsn, pgcache_page_no_t page; uint rownr; uchar *buff; - my_bool res= 1; + my_bool res; MARIA_PINNED_PAGE page_link; MARIA_SHARE *share= info->s; ha_checksum checksum; @@ -6744,11 +6856,16 @@ my_bool _ma_apply_undo_row_insert(MARIA_HA *info, LSN undo_lsn, goto err; res= 0; -err: +end: if (info->non_flushable_state) _ma_bitmap_flushable(info, -1); _ma_unpin_all_pages_and_finalize_row(info, lsn); DBUG_RETURN(res); + +err: + res= 1; + _ma_mark_file_crashed(share); + goto end; } @@ -6971,6 +7088,10 @@ my_bool _ma_apply_undo_row_delete(MARIA_HA *info, LSN undo_lsn, { DBUG_ASSERT(row.checksum == (share->calc_checksum)(info, record)); } + /* Store same amount of data on head page as on original page */ + row_pos.length= (length_on_head_page - + (extent_count + 1 - blocks->count) * ROW_EXTENT_SIZE); + set_if_bigger(row_pos.length, share->base.min_block_length); if (write_block_record(info, (uchar*) 0, record, &row, blocks, blocks->block->org_bitmap_value != 0, &row_pos, undo_lsn, 0)) @@ -6980,6 +7101,7 @@ my_bool _ma_apply_undo_row_delete(MARIA_HA *info, LSN undo_lsn, DBUG_RETURN(0); err: + _ma_mark_file_crashed(share); if (info->non_flushable_state) _ma_bitmap_flushable(info, -1); _ma_unpin_all_pages_and_finalize_row(info, LSN_IMPOSSIBLE); @@ -7010,7 +7132,7 @@ my_bool _ma_apply_undo_row_update(MARIA_HA *info, LSN undo_lsn, pgcache_page_no_t page; ha_checksum checksum_delta; uint rownr, field_length_header, extent_count, length_on_head_page; - int error= 1; + int error; DBUG_ENTER("_ma_apply_undo_row_update"); LINT_INIT(checksum_delta); @@ -7018,6 +7140,7 @@ my_bool _ma_apply_undo_row_update(MARIA_HA *info, LSN undo_lsn, header+= PAGE_STORE_SIZE; rownr= dirpos_korr(header); header+= DIRPOS_STORE_SIZE; + record_pos= ma_recordpos(page, rownr); DBUG_PRINT("enter", ("rowid: %lu page: %lu rownr: %u", (ulong) record_pos, (ulong) page, rownr)); @@ -7147,9 +7270,14 @@ my_bool _ma_apply_undo_row_update(MARIA_HA *info, LSN undo_lsn, goto err; error= 0; -err: +end: my_free(current_record, MYF(0)); DBUG_RETURN(error); + +err: + error= 1; + _ma_mark_file_crashed(share); + goto end; } @@ -7229,3 +7357,25 @@ void maria_ignore_trids(MARIA_HA *info) info->trn->min_read_from= ~(TrID) 0; } } + + +#ifndef DBUG_OFF + +/* The following functions are useful to call from debugger */ + +void _ma_print_block_info(uchar *buff) +{ + LSN lsn= lsn_korr(buff); + + printf("LSN: %lu,0x%lx type: %u dir_entries: %u dir_free: %u empty_space: %u\n", + LSN_IN_PARTS(lsn), + (uint)buff[PAGE_TYPE_OFFSET], + (uint)buff[DIR_COUNT_OFFSET], + (uint)buff[DIR_FREE_OFFSET], + (uint) uint2korr(buff + EMPTY_SPACE_OFFSET)); + printf("Start of directory: %lu\n", + maria_block_size - PAGE_SUFFIX_SIZE - + (uint) buff[DIR_COUNT_OFFSET] * DIR_ENTRY_SIZE); + _ma_print_directory(stdout, buff, maria_block_size); +} +#endif diff --git a/storage/maria/ma_check.c b/storage/maria/ma_check.c index 28b808cf27e..086cff67dab 100644 --- a/storage/maria/ma_check.c +++ b/storage/maria/ma_check.c @@ -1930,7 +1930,7 @@ static int check_block_record(HA_CHECK *param, MARIA_HA *info, int extend, _ma_check_print_error(param, "Page %9s: Wrong data in bitmap. Page_type: " "%d full: %d empty_space: %u Bitmap-bits: %d", - llstr(page, llbuff), full_dir, page_type, + llstr(page, llbuff), page_type, full_dir, empty_space, bitmap_pattern); if (param->err_count++ > MAXERR || !(param->testflag & T_VERBOSE)) goto err; diff --git a/storage/maria/ma_checkpoint.c b/storage/maria/ma_checkpoint.c index b75267f81f1..cf13cee9452 100644 --- a/storage/maria/ma_checkpoint.c +++ b/storage/maria/ma_checkpoint.c @@ -789,7 +789,6 @@ static int collect_tables(LEX_STRING *str, LSN checkpoint_start_log_horizon) not seen again in the loop. */ share->in_checkpoint= MARIA_CHECKPOINT_LOOKS_AT_ME; - /** @todo avoid strlen() */ total_names_length+= share->open_file_name.length; } } diff --git a/storage/maria/ma_key_recover.c b/storage/maria/ma_key_recover.c index 4dc902f9418..82f8099fe6a 100644 --- a/storage/maria/ma_key_recover.c +++ b/storage/maria/ma_key_recover.c @@ -64,8 +64,9 @@ void _ma_unpin_all_pages(MARIA_HA *info, LSN undo_lsn) builds. */ #ifdef EXTRA_DEBUG - DBUG_ASSERT(!pinned_page->changed || - undo_lsn != LSN_IMPOSSIBLE || !info->s->now_transactional); + DBUG_ASSERT((!pinned_page->changed || + undo_lsn != LSN_IMPOSSIBLE || !info->s->now_transactional) || + (info->s->state.changed & STATE_CRASHED)); #endif pagecache_unlock_by_link(info->s->pagecache, pinned_page->link, pinned_page->unlock, PAGECACHE_UNPIN, @@ -923,7 +924,7 @@ uint _ma_apply_redo_index(MARIA_HA *info, if (length < 0) bmove(buff + page_offset, buff + page_offset - length, page_length - page_offset + length); - else + else if (page_length != page_offset) bmove_upp(buff + page_length + length, buff + page_length, page_length - page_offset); page_length+= length; diff --git a/storage/maria/ma_recovery.c b/storage/maria/ma_recovery.c index 58f16658957..a10fac9a15d 100644 --- a/storage/maria/ma_recovery.c +++ b/storage/maria/ma_recovery.c @@ -494,8 +494,10 @@ end: } else if (!error && max_trid_in_control_file != max_long_trid) { - /* Set max trid in log file so that one can run maria_chk on the tables */ - max_trid_in_control_file= trnman_get_max_trid(); + /* + maria_end() will set max trid in log file so that one can run + maria_chk on the tables + */ maria_recovery_changed_data= 1; } @@ -2395,6 +2397,7 @@ static int run_redo_phase(LSN lsn, LSN lsn_end, enum maria_apply_log_way apply) struct st_translog_scanner_data scanner; int len; uint i; + DBUG_ENTER("run_redo_phase"); /* install hooks for execution */ #define install_redo_exec_hook(R) \ @@ -2459,7 +2462,7 @@ static int run_redo_phase(LSN lsn, LSN lsn_end, enum maria_apply_log_way apply) { tprint(tracef, "checkpoint address refers to the log end log or " "log is empty, nothing to do.\n"); - return 0; + DBUG_RETURN(0); } len= translog_read_record_header(lsn, &rec); @@ -2467,12 +2470,12 @@ static int run_redo_phase(LSN lsn, LSN lsn_end, enum maria_apply_log_way apply) if (len == RECHEADER_READ_ERROR) { eprint(tracef, "Failed to read header of the first record."); - return 1; + DBUG_RETURN(1); } if (translog_scanner_init(lsn, 1, &scanner, 1)) { tprint(tracef, "Scanner init failed\n"); - return 1; + DBUG_RETURN(1); } for (i= 1;;i++) { @@ -2525,7 +2528,7 @@ static int run_redo_phase(LSN lsn, LSN lsn_end, enum maria_apply_log_way apply) LSN_IN_PARTS(rec2.lsn)); translog_destroy_scanner(&scanner); translog_free_record_header(&rec); - return(0); + DBUG_RETURN(0); } if (translog_scanner_init(rec2.lsn, 1, &scanner2, 1)) @@ -2623,12 +2626,12 @@ static int run_redo_phase(LSN lsn, LSN lsn_end, enum maria_apply_log_way apply) fflush(stderr); procent_printed= 1; } - return 0; + DBUG_RETURN(0); err: translog_destroy_scanner(&scanner); translog_free_record_header(&rec); - return 1; + DBUG_RETURN(1); } @@ -3167,6 +3170,8 @@ static LSN parse_checkpoint_record(LSN lsn) return LSN_ERROR; next_dirty_page_in_pool= dirty_pages_pool; minimum_rec_lsn_of_dirty_pages= LSN_MAX; + if (maria_recovery_verbose) + tprint(tracef, "Table_id Is_index Page_id Rec_lsn\n"); for (i= 0; i < nb_dirty_pages ; i++) { pgcache_page_no_t page_id; @@ -3183,6 +3188,9 @@ static LSN parse_checkpoint_record(LSN lsn) if (new_page((is_index << 16) | table_id, page_id, rec_lsn, next_dirty_page_in_pool++)) return LSN_ERROR; + if (maria_recovery_verbose) + tprint(tracef, "%8u %8u %12lu %lu,0x%lx\n", (uint) table_id, + (uint) is_index, (ulong) page_id, LSN_IN_PARTS(rec_lsn)); set_if_smaller(minimum_rec_lsn_of_dirty_pages, rec_lsn); } /* after that, there will be no insert/delete into the hash */ diff --git a/storage/maria/ma_static.c b/storage/maria/ma_static.c index d870b034eb8..917385f9568 100644 --- a/storage/maria/ma_static.c +++ b/storage/maria/ma_static.c @@ -37,7 +37,7 @@ my_bool maria_flush= 0, maria_single_user= 0; my_bool maria_delay_key_write= 0, maria_page_checksums= 1; my_bool maria_inited= FALSE; my_bool maria_in_ha_maria= FALSE; /* If used from ha_maria or not */ -my_bool maria_recovery_changed_data= 0; +my_bool maria_recovery_changed_data= 0, maria_recovery_verbose= 0; pthread_mutex_t THR_LOCK_maria; #if defined(THREAD) && !defined(DONT_USE_RW_LOCKS) ulong maria_concurrent_insert= 2; diff --git a/storage/maria/ma_test2.c b/storage/maria/ma_test2.c index 081cac8a2aa..9e2f32f767b 100644 --- a/storage/maria/ma_test2.c +++ b/storage/maria/ma_test2.c @@ -83,6 +83,9 @@ int main(int argc, char *argv[]) if (! async_io) my_disable_async_io=1; + /* If we sync or not have no affect on this test */ + my_disable_sync= 1; + maria_data_root= (char *)"."; /* Maria requires that we always have a page cache */ if (maria_init() || @@ -351,7 +354,10 @@ int main(int argc, char *argv[]) key3[atoi((char*) read_record+keyinfo[2].seg[0].start)]=0; } else + { puts("Warning: Skipping delete test because no dupplicate keys"); + break; + } } if (testflag == 3) goto end; diff --git a/storage/maria/ma_write.c b/storage/maria/ma_write.c index 6ce7a4179e8..6a5c2995ae5 100644 --- a/storage/maria/ma_write.c +++ b/storage/maria/ma_write.c @@ -1973,6 +1973,21 @@ my_bool _ma_log_change(MARIA_PAGE *ma_page, const uchar *key_pos, uint length, /** @brief Write log entry for page splitting + @fn _ma_log_split() + @param + ma_page Page that is changed + org_length Original length of page + new_length New length of page + key_pos Where key is inserted on page (may be 0 if no key) + key_length Number of bytes changed at key_pos + move_length Number of bytes moved at key_pos to make room for key + prefix_or_suffix KEY_OP_NONE Ignored + KEY_OP_ADD_PREFIX Add data to start of page + KEY_OP_ADD_SUFFIX Add data to end of page + data What data was added + data_length Number of bytes added first or last + changed_length Number of bytes changed first or last. + @note Write log entry for page that has got a key added to the page under one and only one of the following senarios: @@ -1980,9 +1995,6 @@ my_bool _ma_log_change(MARIA_PAGE *ma_page, const uchar *key_pos, uint length, - Data is added to end of page - Data added at front of page - @param prefix_or_suffix KEY_OP_NONE Ignored - KEY_OP_ADD_PREFIX Add data to start of page - KEY_OP_ADD_SUFFIX Add data to end of page */ @@ -2005,6 +2017,8 @@ static my_bool _ma_log_split(MARIA_PAGE *ma_page, DBUG_PRINT("enter", ("page: %lu org_length: %u new_length: %u", (ulong) ma_page->pos, org_length, new_length)); + DBUG_ASSERT(changed_length >= data_length); + log_pos= log_data + FILEID_STORE_SIZE; page= ma_page->pos / info->s->block_size; page_store(log_pos, page); @@ -2027,6 +2041,7 @@ static my_bool _ma_log_split(MARIA_PAGE *ma_page, log_pos+= 3; translog_parts= 1; extra_length= 0; + DBUG_ASSERT(data_length == 0); } else { @@ -2046,10 +2061,13 @@ static my_bool _ma_log_split(MARIA_PAGE *ma_page, log_pos[0]= KEY_OP_DEL_SUFFIX; int2store(log_pos + 1, diff); log_pos+= 3; + DBUG_ASSERT(data_length == 0); /* Page is shortened */ + DBUG_ASSERT(offset <= org_length - diff); } else { DBUG_ASSERT(new_length == org_length + move_length + data_length); + DBUG_ASSERT(offset <= org_length); } log_pos[0]= KEY_OP_OFFSET; diff --git a/storage/maria/maria_chk.c b/storage/maria/maria_chk.c index 511488b977a..18426e468cd 100644 --- a/storage/maria/maria_chk.c +++ b/storage/maria/maria_chk.c @@ -1252,7 +1252,7 @@ static int maria_chk(HA_CHECK *param, char *filename) } else if ((param->testflag & T_CHECK) || !(param->testflag & T_AUTO_INC)) { - if (!(param->testflag & T_SILENT) || param->testflag & T_INFO) + if (!(param->testflag & T_VERY_SILENT) || param->testflag & T_INFO) printf("Checking MARIA file: %s\n",filename); if (!(param->testflag & T_SILENT)) printf("Data records: %7s Deleted blocks: %7s\n", diff --git a/storage/maria/maria_def.h b/storage/maria/maria_def.h index e9980cf9695..bde04186931 100644 --- a/storage/maria/maria_def.h +++ b/storage/maria/maria_def.h @@ -459,8 +459,9 @@ typedef struct st_maria_row uint *null_field_lengths; /* All null field lengths */ ulong *blob_lengths; /* Length for each blob */ ulong min_length, normal_length, char_length, varchar_length; - ulong blob_length, head_length, total_length; + ulong blob_length, total_length; size_t extents_buffer_length; /* Size of 'extents' buffer */ + uint head_length, header_length; uint field_lengths_length; /* Length of data in field_lengths */ uint extents_count; /* number of extents in 'extents' */ uint full_page_count, tail_count; /* For maria_chk */ @@ -797,6 +798,7 @@ extern uint maria_quick_table_bits; extern char *maria_data_root; extern uchar maria_zero_string[]; extern my_bool maria_inited, maria_in_ha_maria, maria_recovery_changed_data; +extern my_bool maria_recovery_verbose; extern HASH maria_stored_state; extern int (*maria_create_trn_hook)(MARIA_HA *); diff --git a/storage/maria/maria_pack.c b/storage/maria/maria_pack.c index 0673f571a6b..167d0af3078 100644 --- a/storage/maria/maria_pack.c +++ b/storage/maria/maria_pack.c @@ -261,8 +261,8 @@ static struct my_option my_long_options[] = {"backup", 'b', "Make a backup of the table as table_name.OLD.", &backup, &backup, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"character-sets-dir", OPT_CHARSETS_DIR_MP, - "Directory where character sets are.", &charsets_dir, - &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + "Directory where character sets are.", (char**) &charsets_dir, + (char**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.", 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"force", 'f', diff --git a/storage/maria/maria_read_log.c b/storage/maria/maria_read_log.c index 1002260afe5..98bc638c77f 100644 --- a/storage/maria/maria_read_log.c +++ b/storage/maria/maria_read_log.c @@ -33,7 +33,7 @@ static my_bool opt_display_only, opt_apply, opt_apply_undo, opt_silent; static my_bool opt_check; static const char *opt_tmpdir; static ulong opt_page_buffer_size; -static ulonglong opt_start_from_lsn, opt_end_lsn; +static ulonglong opt_start_from_lsn, opt_end_lsn, opt_start_from_checkpoint; static MY_TMPDIR maria_chk_tmpdir; @@ -94,7 +94,6 @@ int main(int argc, char **argv) if (opt_display_only) printf("You are using --display-only, NOTHING will be written to disk\n"); - /* LSN could be also --start-from-lsn=# */ lsn= translog_first_lsn_in_log(); if (lsn == LSN_ERROR) { @@ -105,8 +104,16 @@ int main(int argc, char **argv) { fprintf(stdout, "The transaction log is empty\n"); } - fprintf(stdout, "The transaction log starts from lsn (%lu,0x%lx)\n", - LSN_IN_PARTS(lsn)); + if (opt_start_from_checkpoint && !opt_start_from_lsn && + last_checkpoint_lsn != LSN_IMPOSSIBLE) + { + lsn= LSN_IMPOSSIBLE; /* LSN set in maria_apply_log() */ + fprintf(stdout, "Starting from checkpoint (%lu,0x%lx)\n", + LSN_IN_PARTS(last_checkpoint_lsn)); + } + else + fprintf(stdout, "The transaction log starts from lsn (%lu,0x%lx)\n", + LSN_IN_PARTS(lsn)); if (opt_start_from_lsn) { @@ -183,7 +190,7 @@ static struct my_option my_long_options[] = {"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"display-only", 'd', "display brief info read from records' header", - (uchar **) &opt_display_only, (uchar **) &opt_display_only, 0, GET_BOOL, + &opt_display_only, &opt_display_only, 0, GET_BOOL, NO_ARG,0, 0, 0, 0, 0, 0}, {"maria-log-dir-path", 'l', "Path to the directory where to store transactional log", @@ -197,11 +204,17 @@ static struct my_option my_long_options[] = { "start-from-lsn", 'o', "Start reading log from this lsn", &opt_start_from_lsn, &opt_start_from_lsn, 0, GET_ULL, REQUIRED_ARG, 0, 0, ~(longlong) 0, 0, 0, 0 }, + {"start-from-checkpoint", 'C', "Start applying from last checkpoint", + &opt_start_from_checkpoint, &opt_start_from_checkpoint, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, { "end-lsn", 'e', "Stop applying at this lsn. If end-lsn is used, UNDO:s " "will not be applied", &opt_end_lsn, &opt_end_lsn, 0, GET_ULL, REQUIRED_ARG, 0, 0, ~(longlong) 0, 0, 0, 0 }, {"silent", 's', "Print less information during apply/undo phase", - (uchar **) &opt_silent, (uchar **) &opt_silent, 0, + &opt_silent, &opt_silent, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"verbose", 'v', "Print more information during apply/undo phase", + &maria_recovery_verbose, &maria_recovery_verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"tmpdir", 't', "Path for temporary files. Multiple paths can be specified, " "separated by " diff --git a/storage/maria/unittest/ma_test_recovery.pl b/storage/maria/unittest/ma_test_recovery.pl index 58b9cc3b56b..130ab4131fe 100755 --- a/storage/maria/unittest/ma_test_recovery.pl +++ b/storage/maria/unittest/ma_test_recovery.pl @@ -300,7 +300,7 @@ sub check_table_is_same $com.= "| grep -v \"file length\" | grep -v \"LSNs:\" | grep -v \"UUID:\" > $tmp/maria_chk_message.txt 2>&1"; $res= `$com`; print MY_LOG $res; - $res= `$maria_exe_path/maria_chk$suffix -s -e --read-only $table`; + $res= `$maria_exe_path/maria_chk$suffix -ss -e --read-only $table`; print MY_LOG $res; $checksum2= `$maria_exe_path/maria_chk$suffix -dss $table`; if ("$checksum" ne "$checksum2") @@ -415,7 +415,7 @@ sub physical_cmp # save original tables to restore them later copy("$table.MAD", "$tmp/before_zerofill$table_no.MAD") || die(); copy("$table.MAI", "$tmp/before_zerofill$table_no.MAI") || die(); - $com= "$maria_exe_path/maria_chk$suffix -s --zerofill-keep-lsn $table"; + $com= "$maria_exe_path/maria_chk$suffix -ss --zerofill-keep-lsn $table"; $res= `$com`; print MY_LOG $res; $table_no= $table_no + 1; diff --git a/storage/xtradb/buf/buf0lru.c b/storage/xtradb/buf/buf0lru.c index 65fdf342e4f..7b01c4aec50 100644 --- a/storage/xtradb/buf/buf0lru.c +++ b/storage/xtradb/buf/buf0lru.c @@ -2131,7 +2131,7 @@ ibool buf_LRU_file_dump(void) /*===================*/ { - os_file_t dump_file = -1; + os_file_t dump_file = (os_file_t) -1; ibool success; byte* buffer_base = NULL; byte* buffer = NULL; @@ -2221,7 +2221,7 @@ buf_LRU_file_dump(void) ret = TRUE; end: - if (dump_file != -1) + if (dump_file != (os_file_t) -1) os_file_close(dump_file); if (buffer_base) ut_free(buffer_base); @@ -2235,7 +2235,7 @@ ibool buf_LRU_file_restore(void) /*======================*/ { - os_file_t dump_file = -1; + os_file_t dump_file = (os_file_t) -1; ibool success; byte* buffer_base = NULL; byte* buffer = NULL; @@ -2326,7 +2326,7 @@ buf_LRU_file_restore(void) " (requested: %lu, read: %lu)\n", req, reads); ret = TRUE; end: - if (dump_file != -1) + if (dump_file != (os_file_t) -1) os_file_close(dump_file); if (buffer_base) ut_free(buffer_base); diff --git a/storage/xtradb/fil/fil0fil.c b/storage/xtradb/fil/fil0fil.c index 08789691159..189c0e706f9 100644 --- a/storage/xtradb/fil/fil0fil.c +++ b/storage/xtradb/fil/fil0fil.c @@ -3044,7 +3044,7 @@ fil_open_single_table_tablespace( dulint new_id[31]; ulint root_page[31]; ulint n_index; - os_file_t info_file = -1; + os_file_t info_file = (os_file_t) -1; char* info_file_path; ulint i; int len; @@ -3130,7 +3130,7 @@ fil_open_single_table_tablespace( } skip_info: - if (info_file != -1) + if (info_file != (os_file_t) -1) os_file_close(info_file); /* diff --git a/storage/xtradb/handler/i_s.cc b/storage/xtradb/handler/i_s.cc index cc30bdee1dd..7cb4a7ac718 100644 --- a/storage/xtradb/handler/i_s.cc +++ b/storage/xtradb/handler/i_s.cc @@ -3459,7 +3459,7 @@ i_s_innodb_table_stats_fill( field_store_string(i_s_table->field[0], buf); field_store_string(i_s_table->field[1], ptr); - i_s_table->field[2]->store(table->stat_n_rows); + i_s_table->field[2]->store(table->stat_n_rows, 1); i_s_table->field[3]->store(table->stat_clustered_index_size); i_s_table->field[4]->store(table->stat_sum_of_other_index_sizes); i_s_table->field[5]->store(table->stat_modified_counter); diff --git a/storage/xtradb/srv/srv0srv.c b/storage/xtradb/srv/srv0srv.c index 86bf309bac1..bc2dd562697 100644 --- a/storage/xtradb/srv/srv0srv.c +++ b/storage/xtradb/srv/srv0srv.c @@ -2897,7 +2897,7 @@ loop: if (bpl) { retry_flush_batch: n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, - bpl, + (ulint) bpl, oldest_lsn + (lsn - lsn_old)); if (n_pages_flushed == ULINT_UNDEFINED) { os_thread_sleep(5000); diff --git a/support-files/compiler_warnings.supp b/support-files/compiler_warnings.supp index 94e5b54d6fa..41ebf1bcf8a 100644 --- a/support-files/compiler_warnings.supp +++ b/support-files/compiler_warnings.supp @@ -44,6 +44,7 @@ buf/buf0buf\.c: .*block_mutex.* might be used uninitialized btr/btr0cur\.c: null argument where non-null required: 1800-3000 btr/btr0btr\.c: null argument where non-null required: 2500-3000 ibuf/ibuf0ibuf.c: null argument where non-null required: 700-1000 +fsp/fsp0fsp\.c: result of 32-bit shift implicitly converted to 64 bits # # bdb is not critical to keep up to date @@ -108,6 +109,7 @@ signal\.c : .*unused parameter.* .* : conversion from '.*size_t' to 'UINT'.* .* : conversion from '.*size_t' to 'uInt'.* .* : conversion from '.*size_t' to 'uint16'.* +.* : The following environment variables were not found.* # # The following should be fixed by the ndb team @@ -125,6 +127,8 @@ storage/maria/ma_pagecache.c: .*'info_check_pin' defined but not used # Pbxt # xaction_xt\.cc: may be used uninitialized in this function +lock_xt\.cc : uninitialized local variable .* used +restart_xt\.cc : dereferencing pointer .* does break strict-aliasing # # I think these are due to mix of C and C++. diff --git a/unittest/mytap/tap.h b/unittest/mytap/tap.h index 206a939e43b..a75d0a4932b 100644 --- a/unittest/mytap/tap.h +++ b/unittest/mytap/tap.h @@ -106,7 +106,7 @@ extern int skip_big_tests; @param count The planned number of tests to run. */ -void plan(int const count); +void plan(int count); /** @@ -125,7 +125,7 @@ void plan(int const count); which case nothing is printed. */ -void ok(int const pass, char const *fmt, ...) +void ok(int pass, char const *fmt, ...) __attribute__((format(printf,2,3))); |