From 54dcbf2cbe97d8e5274c451bc960ed1b9ab54f54 Mon Sep 17 00:00:00 2001 From: Bjorn Munch Date: Tue, 16 Jun 2009 15:26:17 +0200 Subject: [PATCH 01/80] Bug #45298 plugin.test is skipped in PB2 on UNIX platforms Added search for example plugin in lib/mysql/plugin --- mysql-test/mysql-test-run.pl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 2a6a069d81c..4e89fd899ce 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -1763,7 +1763,8 @@ sub environment_setup { if ($mysql_version_id >= 50100) { my $lib_example_plugin= mtr_file_exists(vs_config_dirs('storage/example', 'ha_example.dll'), - "$basedir/storage/example/.libs/ha_example.so",); + "$basedir/storage/example/.libs/ha_example.so", + "$basedir/lib/mysql/plugin/ha_example.so",); $ENV{'EXAMPLE_PLUGIN'}= ($lib_example_plugin ? basename($lib_example_plugin) : ""); $ENV{'EXAMPLE_PLUGIN_OPT'}= "--plugin-dir=". From a9b438b2229a340343055f36528f10f504efb19d Mon Sep 17 00:00:00 2001 From: Bjorn Munch Date: Mon, 22 Jun 2009 16:27:05 +0200 Subject: [PATCH 02/80] Bug #43780 mysql-test-run uses deprecated server options Updated to use general_log[_file] and slow_query_log[_file] --- mysql-test/lib/My/ConfigFactory.pm | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mysql-test/lib/My/ConfigFactory.pm b/mysql-test/lib/My/ConfigFactory.pm index 852f706c858..c1e8f7cd826 100644 --- a/mysql-test/lib/My/ConfigFactory.pm +++ b/mysql-test/lib/My/ConfigFactory.pm @@ -204,8 +204,10 @@ my @mysqld_rules= { 'port' => \&fix_port }, { 'socket' => \&fix_socket }, { '#log-error' => \&fix_log_error }, - { 'log' => \&fix_log }, - { 'log-slow-queries' => \&fix_log_slow_queries }, + { 'general_log' => 1 }, + { 'general_log_file' => \&fix_log }, + { 'slow_query_log' => 1 }, + { 'slow_query_log_file' => \&fix_log_slow_queries }, { '#user' => sub { return shift->{ARGS}->{user} || ""; } }, { '#password' => sub { return shift->{ARGS}->{password} || ""; } }, { 'server-id' => \&fix_server_id, }, From 47fa03abe75414040dc5ab96f6dc29f01ed7017b Mon Sep 17 00:00:00 2001 From: Bjorn Munch Date: Mon, 22 Jun 2009 16:29:02 +0200 Subject: [PATCH 03/80] Bug #45532 MTR displays wrong option name 'print_testcases' in usage text Fix the name.... --- mysql-test/mysql-test-run.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 4e89fd899ce..e6e8a77f3ed 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -5113,7 +5113,7 @@ Options to control what test suites or cases to run skip-rpl Skip the replication test cases. big-test Also run tests marked as "big" enable-disabled Run also tests marked as disabled - print_testcases Don't run the tests but print details about all the + print-testcases Don't run the tests but print details about all the selected tests, in the order they would be run. Options that specify ports From 6fed1e15c23dd882ddc8e522a0156269c9424635 Mon Sep 17 00:00:00 2001 From: Bjorn Munch Date: Wed, 15 Jul 2009 14:20:56 +0200 Subject: [PATCH 04/80] Bug #43005 main.init_connect fais on Windows in PB2 Server args containing spaces do not work on Windows Fixed my_safe_rprocess-win to re-apply "" around such args --- mysql-test/lib/My/SafeProcess/safe_process_win.cc | 9 ++++++++- mysql-test/suite/rpl/t/disabled.def | 1 - mysql-test/t/disabled.def | 1 - 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/mysql-test/lib/My/SafeProcess/safe_process_win.cc b/mysql-test/lib/My/SafeProcess/safe_process_win.cc index 80c1b7a97f2..d85a9558a62 100755 --- a/mysql-test/lib/My/SafeProcess/safe_process_win.cc +++ b/mysql-test/lib/My/SafeProcess/safe_process_win.cc @@ -188,7 +188,14 @@ int main(int argc, const char** argv ) die("No real args -> nothing to do"); /* Copy the remaining args to child_arg */ for (int j= i+1; j < argc; j++) { - to+= _snprintf(to, child_args + sizeof(child_args) - to, "%s ", argv[j]); + if (strchr (argv[j], ' ')) { + /* Protect with "" if this arg contains a space */ + to+= _snprintf(to, child_args + sizeof(child_args) - to, + "\"%s\" ", argv[j]); + } else { + to+= _snprintf(to, child_args + sizeof(child_args) - to, + "%s ", argv[j]); + } } break; } else { diff --git a/mysql-test/suite/rpl/t/disabled.def b/mysql-test/suite/rpl/t/disabled.def index fcc3d56a9f5..38fc9e21322 100644 --- a/mysql-test/suite/rpl/t/disabled.def +++ b/mysql-test/suite/rpl/t/disabled.def @@ -11,4 +11,3 @@ ############################################################################## rpl_cross_version : Bug#42311 2009-03-27 joro rpl_cross_version fails on macosx -rpl_init_slave : Bug#44920 2009-05-18 pcrews MTR2 is not processing master.opt input properly on Windows diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index af4eb44b464..6d8f0af0c28 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -12,4 +12,3 @@ kill : Bug#37780 2008-12-03 HHunger need some changes to be robust enough for pushbuild. innodb_bug39438 : Bug#42383 2009-01-28 lsoares "This fails in embedded and on windows. Note that this test is not run on windows and on embedded in PB for main trees currently" query_cache_28249 : Bug#43861 2009-03-25 main.query_cache_28249 fails sporadically -init_connect : Bug#44920 2009-05-18 pcrews MTR2 is not processing master.opt input properly on Windows From 5a2d043f1d8e4c00f98ae33dd009d91ee6a0ec78 Mon Sep 17 00:00:00 2001 From: Bjorn Munch Date: Thu, 16 Jul 2009 14:05:46 +0200 Subject: [PATCH 05/80] Bug #45698 MTR_VERSION=1 ./mtr --force does not work General problem: some test cannot run in V1, expect more in future Implement general mechanism for listing incompatible tests --- mysql-test/lib/v1/incompatible.tests | 6 ++++++ mysql-test/lib/v1/mtr_cases.pl | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 mysql-test/lib/v1/incompatible.tests diff --git a/mysql-test/lib/v1/incompatible.tests b/mysql-test/lib/v1/incompatible.tests new file mode 100644 index 00000000000..fefdad9ce4c --- /dev/null +++ b/mysql-test/lib/v1/incompatible.tests @@ -0,0 +1,6 @@ +# This file lists tests that cannot run in MTR v1 for some reason. +# They will be skipped. +# Any text following white space after full test name is ignored +# Only exact test names can be used, no regexp. + +main.fulltext_plugin # Refers to $SIMPLE_PARSER_OPT which is not set diff --git a/mysql-test/lib/v1/mtr_cases.pl b/mysql-test/lib/v1/mtr_cases.pl index 4d7b1f4ec70..bed24bcabfb 100644 --- a/mysql-test/lib/v1/mtr_cases.pl +++ b/mysql-test/lib/v1/mtr_cases.pl @@ -32,6 +32,7 @@ sub mtr_options_from_test_file($$); my $do_test; my $skip_test; +my %incompatible; sub init_pattern { my ($from, $what)= @_; @@ -47,6 +48,15 @@ sub init_pattern { } +sub collect_incomp_tests { + open (INCOMP, "lib/v1/incompatible.tests"); + while () + { + next unless /^\w/; + s/\s.*\n//; # Ignore anything from first white space + $incompatible{$_}= 1; + } +} ############################################################################## # @@ -58,6 +68,8 @@ sub collect_test_cases ($) { $do_test= init_pattern($::opt_do_test, "--do-test"); $skip_test= init_pattern($::opt_skip_test, "--skip-test"); + collect_incomp_tests(); + my $suites= shift; # Semicolon separated list of test suites my $cases = []; # Array of hash @@ -528,6 +540,13 @@ sub collect_one_test_case($$$$$$$$$) { $tinfo->{'component_id'} = $component_id; push(@$cases, $tinfo); + if (exists ($incompatible{$tinfo->{'name'}})) + { + $tinfo->{'skip'}= 1; + $tinfo->{'comment'}= "Test cannot run in mtr v1"; + return; + } + # ---------------------------------------------------------------------- # Skip some tests but include in list, just mark them to skip # ---------------------------------------------------------------------- From b9720c71700ad91b2320750ea72c787338d08810 Mon Sep 17 00:00:00 2001 From: Bjorn Munch Date: Fri, 17 Jul 2009 10:41:04 +0200 Subject: [PATCH 06/80] Bug #45700 MTR v1 --start-and-exit --default-storage-engine=Innodb is froken Change of variable states in Bug 19027 was not backported to v1 Changed ne "TRUE" to eq "OFF" --- mysql-test/lib/v1/mtr_cases.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/lib/v1/mtr_cases.pl b/mysql-test/lib/v1/mtr_cases.pl index bed24bcabfb..906e330282a 100644 --- a/mysql-test/lib/v1/mtr_cases.pl +++ b/mysql-test/lib/v1/mtr_cases.pl @@ -860,7 +860,7 @@ sub collect_one_test_case($$$$$$$$$) { if ( $tinfo->{'innodb_test'} ) { # This is a test that need innodb - if ( $::mysqld_variables{'innodb'} ne "TRUE" ) + if ( $::mysqld_variables{'innodb'} eq "OFF" ) { # innodb is not supported, skip it $tinfo->{'skip'}= 1; From a80bd0b5d7267d420aa876ed7d7edaed2c7e898d Mon Sep 17 00:00:00 2001 From: Bjorn Munch Date: Thu, 23 Jul 2009 19:01:24 +0200 Subject: [PATCH 07/80] Bug #46212 safe_process: FATAL ERROR, Unknown option: --nocore Also fixed mysqld.cc to avoid popup-boxes --- .../lib/My/SafeProcess/safe_process_win.cc | 30 ++++++++++++------- sql/mysqld.cc | 19 ++++++------ 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/mysql-test/lib/My/SafeProcess/safe_process_win.cc b/mysql-test/lib/My/SafeProcess/safe_process_win.cc index d85a9558a62..455262b29f5 100755 --- a/mysql-test/lib/My/SafeProcess/safe_process_win.cc +++ b/mysql-test/lib/My/SafeProcess/safe_process_win.cc @@ -163,6 +163,7 @@ int main(int argc, const char** argv ) HANDLE job_handle; HANDLE wait_handles[NUM_HANDLES]= {0}; PROCESS_INFORMATION process_info= {0}; + BOOL nocore= FALSE; sprintf(safe_process_name, "safe_process[%d]", pid); @@ -199,18 +200,22 @@ int main(int argc, const char** argv ) } break; } else { - if ( strcmp(arg, "--verbose") == 0 ) + if (strcmp(arg, "--verbose") == 0) verbose++; - else if ( strncmp(arg, "--parent-pid", 10) == 0 ) - { - /* Override parent_pid with a value provided by user */ - const char* start; + else if (strncmp(arg, "--parent-pid", 10) == 0) + { + /* Override parent_pid with a value provided by user */ + const char* start; if ((start= strstr(arg, "=")) == NULL) - die("Could not find start of option value in '%s'", arg); - start++; /* Step past = */ - if ((parent_pid= atoi(start)) == 0) - die("Invalid value '%s' passed to --parent-id", start); - } + die("Could not find start of option value in '%s'", arg); + start++; /* Step past = */ + if ((parent_pid= atoi(start)) == 0) + die("Invalid value '%s' passed to --parent-id", start); + } + else if (strcmp(arg, "--nocore") == 0) + { + nocore= TRUE; + } else die("Unknown option: %s", arg); } @@ -248,6 +253,11 @@ int main(int argc, const char** argv ) &jeli, sizeof(jeli)) == 0) message("SetInformationJobObject failed, continue anyway..."); + /* Avoid popup box */ + if (nocore) + SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX + | SEM_NOOPENFILEERRORBOX); + #if 0 /* Setup stdin, stdout and stderr redirect */ si.dwFlags= STARTF_USESTDHANDLES; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 080f78993a1..fa8b4a971d7 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2103,15 +2103,14 @@ static void init_signals(void) win_install_sigabrt_handler(); if(opt_console) SetConsoleCtrlHandler(console_event_handler,TRUE); - else - { + /* Avoid MessageBox()es*/ - _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); - _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR); - _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); - _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); - _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); - _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); + _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); + _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR); + _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); + _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); + _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); + _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); /* Do not use SEM_NOGPFAULTERRORBOX in the following SetErrorMode (), @@ -2120,8 +2119,8 @@ static void init_signals(void) exception filter is not guaranteed to work in all situation (like heap corruption or stack overflow) */ - SetErrorMode(SetErrorMode(0)|SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX); - } + SetErrorMode(SetErrorMode(0) | SEM_FAILCRITICALERRORS + | SEM_NOOPENFILEERRORBOX); SetUnhandledExceptionFilter(my_unhandler_exception_filter); } From 252c37a6399355a05310f183645373c851a26a56 Mon Sep 17 00:00:00 2001 From: Bjorn Munch Date: Fri, 31 Jul 2009 11:22:57 +0200 Subject: [PATCH 08/80] Bug #45698 MTR_VERSION=1 ./mtr --force does not work Small amendment to original fix, as it did not work in azalea Need to handle combinations, would eventually break in 5.1 too --- mysql-test/lib/v1/mtr_cases.pl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/mysql-test/lib/v1/mtr_cases.pl b/mysql-test/lib/v1/mtr_cases.pl index 906e330282a..288e8c22b44 100644 --- a/mysql-test/lib/v1/mtr_cases.pl +++ b/mysql-test/lib/v1/mtr_cases.pl @@ -540,7 +540,11 @@ sub collect_one_test_case($$$$$$$$$) { $tinfo->{'component_id'} = $component_id; push(@$cases, $tinfo); - if (exists ($incompatible{$tinfo->{'name'}})) + # Remove "combinations" part of test name + my $test_base_name= $tinfo->{'name'}; + $test_base_name=~ s/\s.*\n//; + + if (exists ($incompatible{$test_base_name})) { $tinfo->{'skip'}= 1; $tinfo->{'comment'}= "Test cannot run in mtr v1"; From 47227d7f6a064a91034e2571135e76e2ce9b6dd8 Mon Sep 17 00:00:00 2001 From: Bjorn Munch Date: Wed, 5 Aug 2009 09:41:40 +0200 Subject: [PATCH 09/80] Bug #45771 AIX and i5/OS Perl bug: check_socket_path_length in MTR fails Bug is actually in Perl Fixed by trapping and ignoring error from IO::Socket::UNIX --- mysql-test/lib/My/Platform.pm | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/mysql-test/lib/My/Platform.pm b/mysql-test/lib/My/Platform.pm index 69ffdfbb4ce..7c7741a5c9e 100644 --- a/mysql-test/lib/My/Platform.pm +++ b/mysql-test/lib/My/Platform.pm @@ -126,13 +126,29 @@ sub check_socket_path_length { die "Could not create UNIX domain socket: $!" unless defined $sock; + my $hostpath = eval {$sock->hostpath()}; + if ($@) { + die unless $@ =~ /^Bad arg length for Socket::unpack_sockaddr_un/; + + # Bug on AIX and i5/OS Perl IO::Socket::UNIX which dies with something + # like: + # Bad arg length for Socket::unpack_sockaddr_un, length is 25, + # should be 106 at /path/to/perl/lib/5.8.0/aix/Socket.pm line 380. + # + # Just fake it that everything is fine + $hostpath = $testfile; + } + die "UNIX domain socket path was truncated" - unless ($testfile eq $sock->hostpath()); + unless ($testfile eq $hostpath); $truncated= 0; # Yes, it worked! }; + die "Unexpected failure when checking socket path length: $@" + if $@ and $@ !~ /^UNIX domain socket path was truncated/; + $sock= undef; # Close socket rmtree($tmpdir); # Remove the tempdir and any socket file created return $truncated; From 6ddeb379fe3b5dec58de5372666a640b1622659f Mon Sep 17 00:00:00 2001 From: Bjorn Munch Date: Thu, 6 Aug 2009 09:30:53 +0200 Subject: [PATCH 10/80] Bug #45771 AIX and i5/OS Perl bug: check_socket_path_length in MTR fails Bug in Perl Scrap attempt to do this smartly on AIX, just drop the test and assume it's OK This commit undoes the previous push and adds a line to ignore on AIX --- mysql-test/lib/My/Platform.pm | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/mysql-test/lib/My/Platform.pm b/mysql-test/lib/My/Platform.pm index 7c7741a5c9e..371120ab644 100644 --- a/mysql-test/lib/My/Platform.pm +++ b/mysql-test/lib/My/Platform.pm @@ -106,10 +106,13 @@ sub check_socket_path_length { my ($path)= @_; return 0 if IS_WINDOWS; + # This may not be true, but we can't test for it on AIX due to Perl bug + # See Bug #45771 + return 0 if ($^O eq 'aix'); require IO::Socket::UNIX; - my $truncated= 1; # Be negative + my $truncated= undef; # Create a tempfile name with same length as "path" my $tmpdir = tempdir( CLEANUP => 0); @@ -122,32 +125,20 @@ sub check_socket_path_length { Local => $testfile, Listen => 1, ); + $truncated= 1; # Be negatvie die "Could not create UNIX domain socket: $!" unless defined $sock; - my $hostpath = eval {$sock->hostpath()}; - if ($@) { - die unless $@ =~ /^Bad arg length for Socket::unpack_sockaddr_un/; - - # Bug on AIX and i5/OS Perl IO::Socket::UNIX which dies with something - # like: - # Bad arg length for Socket::unpack_sockaddr_un, length is 25, - # should be 106 at /path/to/perl/lib/5.8.0/aix/Socket.pm line 380. - # - # Just fake it that everything is fine - $hostpath = $testfile; - } - die "UNIX domain socket path was truncated" - unless ($testfile eq $hostpath); + unless ($testfile eq $sock->hostpath()); $truncated= 0; # Yes, it worked! }; die "Unexpected failure when checking socket path length: $@" - if $@ and $@ !~ /^UNIX domain socket path was truncated/; + if $@ and not defined $truncated; $sock= undef; # Close socket rmtree($tmpdir); # Remove the tempdir and any socket file created From 013717d110af5d94eab703567ef72744c0d174e4 Mon Sep 17 00:00:00 2001 From: Bjorn Munch Date: Tue, 11 Aug 2009 12:59:43 +0200 Subject: [PATCH 11/80] Bug #44479 mysql-test-run does not detect that external server has Innodb support Variable name mismatch Map variable have_innodb=YES to innodb=ON --- mysql-test/mysql-test-run.pl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index e6e8a77f3ed..06f02afaf5b 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -1506,6 +1506,10 @@ sub collect_mysqld_features_from_running_server () } } + # "Convert" innodb flag + $mysqld_variables{'innodb'}= "ON" + if ($mysqld_variables{'have_innodb'} eq "YES"); + # Parse version my $version_str= $mysqld_variables{'version'}; if ( $version_str =~ /^([0-9]*)\.([0-9]*)\.([0-9]*)/ ) From 1d99f9eae5f24b0c60872041ea960985386c4371 Mon Sep 17 00:00:00 2001 From: Bjorn Munch Date: Tue, 11 Aug 2009 15:59:05 +0200 Subject: [PATCH 12/80] Bug #45847 make --gdb disable all the timeouts by default Set to one week for testcase and suite timeout Also set one day timeout for PID file creation (not currently needed in 5.1 but might become, and is needed in azalea) --- mysql-test/mysql-test-run.pl | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 06f02afaf5b..6a2e84d9c78 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -1241,6 +1241,13 @@ sub command_line_setup { { mtr_error("Can't use --extern when using debugger"); } + # Set one week timeout (check-testcase timeout will be 1/10th) + $opt_testcase_timeout= 7 * 24 * 60; + $opt_suite_timeout= 7 * 24 * 60; + # One day to shutdown + $opt_shutdown_timeout= 24 * 60; + # One day for PID file creation (this is given in seconds not minutes) + $opt_start_timeout= 24 * 60 * 60; } # -------------------------------------------------------------------------- From b742c771afac36558d3355172f416381ea96f3da Mon Sep 17 00:00:00 2001 From: Bjorn Munch Date: Tue, 11 Aug 2009 23:41:44 +0200 Subject: [PATCH 13/80] Bug #44012 mtr: test cases that are not supposed to return output always fail Output would match an empty result file but we don't check Allow empty output IFF there is an empty result file. --- client/mysqltest.cc | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/client/mysqltest.cc b/client/mysqltest.cc index a39cabdc64d..a40ee1cd1d0 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -7987,6 +7987,8 @@ int main(int argc, char **argv) if (parsing_disabled) die("Test ended with parsing disabled"); + my_bool empty_result= FALSE; + /* The whole test has been executed _sucessfully_. Time to compare result or save it to record file. @@ -8027,11 +8029,20 @@ int main(int argc, char **argv) } else { - die("The test didn't produce any output"); + /* Empty output is an error *unless* we also have an empty result file */ + if (! result_file_name || record || + compare_files (log_file.file_name(), result_file_name)) + { + die("The test didn't produce any output"); + } + else + { + empty_result= TRUE; /* Meaning empty was expected */ + } } - if (!command_executed && result_file_name) - die("No queries executed but result file found!"); + if (!command_executed && result_file_name && !empty_result) + die("No queries executed but non-empty result file found!"); verbose_msg("Test has succeeded!"); timer_output(); From 00eec234ee79ae9859a98fe906e78cb3af4e89cc Mon Sep 17 00:00:00 2001 From: Jonathan Perkin Date: Wed, 12 Aug 2009 22:06:44 +0200 Subject: [PATCH 14/80] Apply build fix --- .bzrignore | 1 + storage/innodb_plugin/include/btr0cur.h | 2 +- storage/innodb_plugin/include/trx0types.h | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.bzrignore b/.bzrignore index fad758b54b8..6c6a43dacab 100644 --- a/.bzrignore +++ b/.bzrignore @@ -3063,3 +3063,4 @@ sql/share/slovak sql/share/spanish sql/share/swedish sql/share/ukrainian +libmysqld/examples/mysqltest.cc diff --git a/storage/innodb_plugin/include/btr0cur.h b/storage/innodb_plugin/include/btr0cur.h index b2d43ae3254..480a3877e54 100644 --- a/storage/innodb_plugin/include/btr0cur.h +++ b/storage/innodb_plugin/include/btr0cur.h @@ -618,7 +618,7 @@ enum btr_cur_method { hash_node, and might be necessary to update */ BTR_CUR_BINARY, /*!< success using the binary search */ - BTR_CUR_INSERT_TO_IBUF, /*!< performed the intended insert to + BTR_CUR_INSERT_TO_IBUF /*!< performed the intended insert to the insert buffer */ }; diff --git a/storage/innodb_plugin/include/trx0types.h b/storage/innodb_plugin/include/trx0types.h index 08cc9622d02..24cf57d53d5 100644 --- a/storage/innodb_plugin/include/trx0types.h +++ b/storage/innodb_plugin/include/trx0types.h @@ -70,7 +70,7 @@ typedef struct trx_named_savept_struct trx_named_savept_t; enum trx_rb_ctx { RB_NONE = 0, /*!< no rollback */ RB_NORMAL, /*!< normal rollback */ - RB_RECOVERY, /*!< rolling back an incomplete transaction, + RB_RECOVERY /*!< rolling back an incomplete transaction, in crash recovery */ }; From 2000cef72ab3fbb6afd2f6612ed561bc67da3a92 Mon Sep 17 00:00:00 2001 From: Bjorn Munch Date: Thu, 13 Aug 2009 15:29:19 +0200 Subject: [PATCH 15/80] Bug #44979 Enhance MTR --experimental to support platform qualifier Adding @ syntax --- mysql-test/collections/README.experimental | 7 +++++++ mysql-test/collections/default.experimental | 1 + mysql-test/mysql-test-run.pl | 12 ++++++++++++ 3 files changed, 20 insertions(+) diff --git a/mysql-test/collections/README.experimental b/mysql-test/collections/README.experimental index 9eee2394423..2f5ee7b00ab 100644 --- a/mysql-test/collections/README.experimental +++ b/mysql-test/collections/README.experimental @@ -23,3 +23,10 @@ The syntax is as follows: start with the same characters up to the last letter before the asterisk are considered experimental: main.a* # get rid of main.alias, main.alibaba and main.agliolio + +6) Optionally, the test case may be followed by one or more platform + qualifiers beginning with @ or @!. The test will then be considered + experimental only/except on that platform. Basic OS names as + reported by $^O in Perl, or 'windows' are supported, this includes + solaris, linux, windows, aix, darwin, ... Example: + main.alias @aix @windows # Fails on those diff --git a/mysql-test/collections/default.experimental b/mysql-test/collections/default.experimental index 103069f79cf..161af45f133 100644 --- a/mysql-test/collections/default.experimental +++ b/mysql-test/collections/default.experimental @@ -1 +1,2 @@ funcs_1.charset_collation_1 # depends on compile-time decisions +main.plugin_load @solaris # Bug #42144 diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 6a2e84d9c78..40fc7446c9e 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -984,6 +984,9 @@ sub command_line_setup { if ( $opt_experimental ) { + # $^O on Windows considered not generic enough + my $plat= (IS_WINDOWS) ? 'windows' : $^O; + # read the list of experimental test cases from the file specified on # the command line open(FILE, "<", $opt_experimental) or mtr_error("Can't read experimental file: $opt_experimental"); @@ -994,6 +997,15 @@ sub command_line_setup { # remove comments (# foo) at the beginning of the line, or after a # blank at the end of the line s/( +|^)#.*$//; + # If @ platform specifier given, use this entry only if it contains + # @ or @! where xxx != platform + if (/\@.*/) + { + next if (/\@!$plat/); + next unless (/\@$plat/ or /\@!/); + # Then remove @ and everything after it + s/\@.*$//; + } # remove whitespace s/^ +//; s/ +$//; From a162954858bbffe7f3d11a780183b0ec2606e93a Mon Sep 17 00:00:00 2001 From: Jonathan Perkin Date: Fri, 14 Aug 2009 17:18:52 +0200 Subject: [PATCH 16/80] Build fixes for Windows, AIX, HP/UX and Sun Studio11, from Timothy Smith. --- CMakeLists.txt | 1 + cmd-line-utils/readline/util.c | 9 +++++++-- storage/innodb_plugin/handler/i_s.cc | 18 ++++++++++-------- storage/innodb_plugin/include/univ.i | 3 ++- 4 files changed, 20 insertions(+), 11 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 947dc1786ff..7d91e39eb6d 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -137,6 +137,7 @@ ENDIF(MSVC) IF(WIN32) ADD_DEFINITIONS("-D_WINDOWS -D__WIN__ -D_CRT_SECURE_NO_DEPRECATE") + ADD_DEFINITIONS("-D_WIN32_WINNT=0x0501") ENDIF(WIN32) # default to x86 platform. We'll check for X64 in a bit diff --git a/cmd-line-utils/readline/util.c b/cmd-line-utils/readline/util.c index 50cfea75cb9..342224facd7 100644 --- a/cmd-line-utils/readline/util.c +++ b/cmd-line-utils/readline/util.c @@ -81,8 +81,13 @@ rl_alphabetic (c) #if defined (HANDLE_MULTIBYTE) int -_rl_walphabetic (wc) - wchar_t wc; +/* + Portability issue with VisualAge C++ Professional / C for AIX Compiler, Version 6: + "util.c", line 84.1: 1506-343 (S) Redeclaration of _rl_walphabetic differs + from previous declaration on line 110 of "rlmbutil.h". + So, put type in the function signature here. +*/ +_rl_walphabetic (wchar_t wc) { int c; diff --git a/storage/innodb_plugin/handler/i_s.cc b/storage/innodb_plugin/handler/i_s.cc index c0d488d1c49..524fe696de2 100644 --- a/storage/innodb_plugin/handler/i_s.cc +++ b/storage/innodb_plugin/handler/i_s.cc @@ -69,14 +69,16 @@ do { \ #define STRUCT_FLD(name, value) value #endif -static const ST_FIELD_INFO END_OF_ST_FIELD_INFO = - {STRUCT_FLD(field_name, NULL), - STRUCT_FLD(field_length, 0), - STRUCT_FLD(field_type, MYSQL_TYPE_NULL), - STRUCT_FLD(value, 0), - STRUCT_FLD(field_flags, 0), - STRUCT_FLD(old_name, ""), - STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}; +/* Don't use a static const variable here, as some C++ compilers (notably +HPUX aCC: HP ANSI C++ B3910B A.03.65) can't handle it. */ +#define END_OF_ST_FIELD_INFO \ + {STRUCT_FLD(field_name, NULL), \ + STRUCT_FLD(field_length, 0), \ + STRUCT_FLD(field_type, MYSQL_TYPE_NULL), \ + STRUCT_FLD(value, 0), \ + STRUCT_FLD(field_flags, 0), \ + STRUCT_FLD(old_name, ""), \ + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)} /* Use the following types mapping: diff --git a/storage/innodb_plugin/include/univ.i b/storage/innodb_plugin/include/univ.i index 6bce6dd765e..023a6c9cd89 100644 --- a/storage/innodb_plugin/include/univ.i +++ b/storage/innodb_plugin/include/univ.i @@ -408,7 +408,8 @@ it is read. */ /* Minimize cache-miss latency by moving data at addr into a cache before it is read or written. */ # define UNIV_PREFETCH_RW(addr) __builtin_prefetch(addr, 1, 3) -#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) +/* Sun Studio includes sun_prefetch.h as of version 5.9 */ +#elif (defined(__SUNPRO_C) && __SUNPRO_C >= 0x590) || (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x590) # include #if __SUNPRO_C >= 0x550 # undef UNIV_INTERN From e5ae860e32e5536c5c19dc3196199fb0a896b9a8 Mon Sep 17 00:00:00 2001 From: Bjorn Munch Date: Mon, 17 Aug 2009 11:21:02 +0200 Subject: [PATCH 17/80] Bug #46755 Wrong grammar in some skip messages: Test need instead of Test needs Fixed in two comments as well --- mysql-test/lib/mtr_cases.pm | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mysql-test/lib/mtr_cases.pm b/mysql-test/lib/mtr_cases.pm index 2a7b07debd0..94a4ab240b4 100644 --- a/mysql-test/lib/mtr_cases.pm +++ b/mysql-test/lib/mtr_cases.pm @@ -847,14 +847,14 @@ sub collect_one_test_case { if ( $tinfo->{'big_test'} and ! $::opt_big_test ) { $tinfo->{'skip'}= 1; - $tinfo->{'comment'}= "Test need 'big-test' option"; + $tinfo->{'comment'}= "Test needs 'big-test' option"; return $tinfo } if ( $tinfo->{'need_debug'} && ! $::debug_compiled_binaries ) { $tinfo->{'skip'}= 1; - $tinfo->{'comment'}= "Test need debug binaries"; + $tinfo->{'comment'}= "Test needs debug binaries"; return $tinfo } @@ -890,14 +890,14 @@ sub collect_one_test_case { if ($tinfo->{'federated_test'}) { - # This is a test that need federated, enable it + # 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 need innodb + # This is a test that needs innodb if ( $::mysqld_variables{'innodb'} eq "OFF" || ! exists $::mysqld_variables{'innodb'} ) { @@ -918,7 +918,7 @@ sub collect_one_test_case { if (grep(/^--skip-log-bin/, @::opt_extra_mysqld_opt) ) { $tinfo->{'skip'}= 1; - $tinfo->{'comment'}= "Test need binlog"; + $tinfo->{'comment'}= "Test needs binlog"; return $tinfo; } } From ca7bf9fad5f13122ae235a94f9299a6659b80686 Mon Sep 17 00:00:00 2001 From: Bjorn Munch Date: Tue, 18 Aug 2009 09:38:18 +0200 Subject: [PATCH 18/80] Bug #44222 mysql-test-run --start analyses which tests it would skip. This is redundant. Quicker test collection and better output with --start[-dirty] --- mysql-test/lib/mtr_cases.pm | 15 +++++++++++++-- mysql-test/mysql-test-run.pl | 22 +++++++++++++++++++--- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/mysql-test/lib/mtr_cases.pm b/mysql-test/lib/mtr_cases.pm index 2a7b07debd0..5ce936352ce 100644 --- a/mysql-test/lib/mtr_cases.pm +++ b/mysql-test/lib/mtr_cases.pm @@ -41,6 +41,7 @@ our $opt_with_ndbcluster_only; our $defaults_file; our $defaults_extra_file; our $reorder= 1; +our $quick_collect; sub collect_option { my ($opt, $value)= @_; @@ -68,6 +69,9 @@ require "mtr_misc.pl"; my $do_test_reg; my $skip_test_reg; +# If "Quick collect", set to 1 once a test to run has been found. +my $some_test_found; + sub init_pattern { my ($from, $what)= @_; return undef unless defined $from; @@ -102,6 +106,7 @@ sub collect_test_cases ($$) { foreach my $suite (split(",", $suites)) { push(@$cases, collect_one_suite($suite, $opt_cases)); + last if $some_test_found; } if ( @$opt_cases ) @@ -139,7 +144,7 @@ sub collect_test_cases ($$) { } } - if ( $reorder ) + if ( $reorder && !$quick_collect) { # Reorder the test cases in an order that will make them faster to run my %sort_criteria; @@ -386,7 +391,7 @@ sub collect_one_suite($) # Read combinations for this suite and build testcases x combinations # if any combinations exists # ---------------------------------------------------------------------- - if ( ! $skip_combinations ) + if ( ! $skip_combinations && ! $quick_collect ) { my @combinations; my $combination_file= "$suitedir/combinations"; @@ -583,6 +588,12 @@ sub optimize_cases { if ( $default_engine =~ /^innodb/i ); } } + + if ($quick_collect && ! $tinfo->{'skip'}) + { + $some_test_found= 1; + return; + } } } diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 40fc7446c9e..28ddd718f16 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -209,6 +209,7 @@ sub check_timeout { return $opt_testcase_timeout * 6; }; my $opt_start; my $opt_start_dirty; +my $start_only; my $opt_wait_all; my $opt_repeat= 1; my $opt_retry= 3; @@ -1262,11 +1263,19 @@ sub command_line_setup { $opt_start_timeout= 24 * 60 * 60; } + # -------------------------------------------------------------------------- + # Modified behavior with --start options + # -------------------------------------------------------------------------- + if ($opt_start or $opt_start_dirty) { + collect_option ('quick-collect', 1); + $start_only= 1; + } + # -------------------------------------------------------------------------- # Check use of wait-all # -------------------------------------------------------------------------- - if ($opt_wait_all && ! ($opt_start_dirty || $opt_start)) + if ($opt_wait_all && ! $start_only) { mtr_error("--wait-all can only be used with --start or --start-dirty"); } @@ -2824,7 +2833,7 @@ sub run_testcase_check_skip_test($) if ( $tinfo->{'skip'} ) { - mtr_report_test_skipped($tinfo); + mtr_report_test_skipped($tinfo) unless $start_only; return 1; } @@ -3311,9 +3320,16 @@ sub run_testcase ($) { # server exits # ---------------------------------------------------------------------- - if ( $opt_start or $opt_start_dirty ) + if ( $start_only ) { mtr_print("\nStarted", started(all_servers())); + mtr_print("Using config for test", $tinfo->{name}); + mtr_print("Port and socket path for server(s):"); + foreach my $mysqld ( mysqlds() ) + { + mtr_print ($mysqld->name() . " " . $mysqld->value('port') . + " " . $mysqld->value('socket')); + } mtr_print("Waiting for server(s) to exit..."); if ( $opt_wait_all ) { My::SafeProcess->wait_all(); From b9d1c04b79ac63d9116acab774c01abfa2e64934 Mon Sep 17 00:00:00 2001 From: Bjorn Munch Date: Tue, 18 Aug 2009 15:26:17 +0200 Subject: [PATCH 19/80] Bug #46164 memory leak in mysqltest after parse error with --debug Moved some dynstr_free() further up --- client/mysqltest.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/client/mysqltest.cc b/client/mysqltest.cc index a40ee1cd1d0..fb4b9c6ec13 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -7161,6 +7161,10 @@ void run_query(struct st_connection *cn, struct st_command *command, int flags) run_query_normal(cn, command, flags, query, query_len, ds, &ds_warnings); + dynstr_free(&ds_warnings); + if (command->type == Q_EVAL) + dynstr_free(&eval_query); + if (display_result_sorted) { /* Sort the result set and append it to result */ @@ -7191,11 +7195,8 @@ void run_query(struct st_connection *cn, struct st_command *command, int flags) check_require(ds, command->require_file); } - dynstr_free(&ds_warnings); if (ds == &ds_result) dynstr_free(&ds_result); - if (command->type == Q_EVAL) - dynstr_free(&eval_query); DBUG_VOID_RETURN; } From f0e14f7181be4e68856060280d03f5e32d30ac4d Mon Sep 17 00:00:00 2001 From: Jonathan Perkin Date: Tue, 18 Aug 2009 16:23:15 +0200 Subject: [PATCH 20/80] Install innodb_plugin on Windows. --- scripts/make_win_bin_dist | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/scripts/make_win_bin_dist b/scripts/make_win_bin_dist index 3360d8459f8..ce89ea28303 100755 --- a/scripts/make_win_bin_dist +++ b/scripts/make_win_bin_dist @@ -279,6 +279,7 @@ cp include/mysql/plugin.h $DESTDIR/include/mysql/ # ---------------------------------------------------------------------- mkdir -p $DESTDIR/lib/opt +mkdir -p $DESTDIR/lib/plugin cp libmysql/$TARGET/libmysql.dll \ libmysql/$TARGET/libmysql.lib \ libmysql/$TARGET/mysqlclient.lib \ @@ -286,6 +287,8 @@ cp libmysql/$TARGET/libmysql.dll \ regex/$TARGET/regex.lib \ strings/$TARGET/strings.lib \ zlib/$TARGET/zlib.lib $DESTDIR/lib/opt/ +cp storage/innodb_plugin/$TARGET/ha_innodb_plugin.dll \ + $DESTDIR/lib/plugin/ if [ x"$TARGET" != x"release" ] ; then cp libmysql/$TARGET/libmysql.pdb \ @@ -294,11 +297,15 @@ if [ x"$TARGET" != x"release" ] ; then regex/$TARGET/regex.pdb \ strings/$TARGET/strings.pdb \ zlib/$TARGET/zlib.pdb $DESTDIR/lib/opt/ + cp storage/innodb_plugin/$TARGET/ha_innodb_plugin.pdb \ + $DESTDIR/lib/plugin/ fi + if [ x"$PACK_DEBUG" = x"" -a -f "libmysql/debug/libmysql.lib" -o \ x"$PACK_DEBUG" = x"yes" ] ; then mkdir -p $DESTDIR/lib/debug + mkdir -p $DESTDIR/lib/plugin/debug cp libmysql/debug/libmysql.dll \ libmysql/debug/libmysql.lib \ libmysql/debug/libmysql.pdb \ @@ -312,6 +319,10 @@ if [ x"$PACK_DEBUG" = x"" -a -f "libmysql/debug/libmysql.lib" -o \ strings/debug/strings.pdb \ zlib/debug/zlib.lib \ zlib/debug/zlib.pdb $DESTDIR/lib/debug/ + cp storage/innodb_plugin/debug/ha_innodb_plugin.dll \ + storage/innodb_plugin/debug/ha_innodb_plugin.lib \ + storage/innodb_plugin/debug/ha_innodb_plugin.pdb \ + $DESTDIR/lib/plugin/debug/ fi # ---------------------------------------------------------------------- From d19eda4a9b59de353c9047376fd513bc0f5d69da Mon Sep 17 00:00:00 2001 From: Bjorn Munch Date: Wed, 19 Aug 2009 13:48:56 +0200 Subject: [PATCH 21/80] Bug #39003 mtr's diff_files command failed in pushbuild without printing a result diff diff was actually called but result never outputted before exiting Added extra code to dump output *unless* failure was expected --- client/mysqltest.cc | 9 +++++++-- mysql-test/t/mysqltest.test | 12 ------------ 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/client/mysqltest.cc b/client/mysqltest.cc index a40ee1cd1d0..09b31599268 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -3440,12 +3440,17 @@ void do_diff_files(struct st_command *command) die("command \"diff_files\" failed, file '%s' does not exist", ds_filename2.str); - if ((error= compare_files(ds_filename.str, ds_filename2.str))) + if ((error= compare_files(ds_filename.str, ds_filename2.str)) && + match_expected_error(command, error, NULL) < 0) { /* Compare of the two files failed, append them to output - so the failure can be analyzed + so the failure can be analyzed, but only if it was not + expected to fail. */ show_diff(&ds_res, ds_filename.str, ds_filename2.str); + log_file.write(&ds_res); + log_file.flush(); + dynstr_set(&ds_res, 0); } dynstr_free(&ds_filename); diff --git a/mysql-test/t/mysqltest.test b/mysql-test/t/mysqltest.test index 578b2bf5c6c..92f39d943b9 100644 --- a/mysql-test/t/mysqltest.test +++ b/mysql-test/t/mysqltest.test @@ -1710,10 +1710,6 @@ EOF --diff_files $MYSQLTEST_VARDIR/tmp/diff1.tmp $MYSQLTEST_VARDIR/tmp/diff2.tmp --diff_files $MYSQLTEST_VARDIR/tmp/diff2.tmp $MYSQLTEST_VARDIR/tmp/diff1.tmp -# Write the below commands to a intermediary file and execute them with -# mysqltest in --exec, since the output will vary depending on what "diff" -# is available it is sent to /dev/null ---write_file $MYSQLTEST_VARDIR/tmp/diff.test # Compare files that differ in size --error 2 --diff_files $MYSQLTEST_VARDIR/tmp/diff1.tmp $MYSQLTEST_VARDIR/tmp/diff3.tmp @@ -1725,13 +1721,6 @@ EOF --diff_files $MYSQLTEST_VARDIR/tmp/diff1.tmp $MYSQLTEST_VARDIR/tmp/diff4.tmp --error 1 --diff_files $MYSQLTEST_VARDIR/tmp/diff4.tmp $MYSQLTEST_VARDIR/tmp/diff1.tmp -exit; -EOF - -# Execute the above diffs, and send their output to /dev/null - only -# interesting to see that it returns correct error codes ---exec $MYSQL_TEST < $MYSQLTEST_VARDIR/tmp/diff.test > /dev/null 2>&1 - # Compare equal files, again... --diff_files $MYSQLTEST_VARDIR/tmp/diff1.tmp $MYSQLTEST_VARDIR/tmp/diff2.tmp @@ -1740,7 +1729,6 @@ EOF --remove_file $MYSQLTEST_VARDIR/tmp/diff2.tmp --remove_file $MYSQLTEST_VARDIR/tmp/diff3.tmp --remove_file $MYSQLTEST_VARDIR/tmp/diff4.tmp ---remove_file $MYSQLTEST_VARDIR/tmp/diff.test # ---------------------------------------------------------------------------- From 58903aecd310c6470a666fd8bed63a30bece55f0 Mon Sep 17 00:00:00 2001 From: Jonathan Perkin Date: Fri, 21 Aug 2009 13:52:30 +0200 Subject: [PATCH 22/80] Add plugins to RPMs. Disable example plugins. --- support-files/mysql.spec.sh | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index 778b04b30fe..081489f7053 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -301,6 +301,8 @@ sh -c "PATH=\"${MYSQL_BUILD_PATH:-$PATH}\" \ --with-csv-storage-engine \ --with-blackhole-storage-engine \ --with-federated-storage-engine \ + --without-plugin-daemon_example \ + --without-plugin-example \ --with-partition \ --with-big-tables \ --enable-shared \ @@ -693,6 +695,8 @@ fi %attr(755, root, root) %{_bindir}/resolve_stack_dump %attr(755, root, root) %{_bindir}/resolveip +%attr(755, root, root) %{_libdir}/plugin/*.so* + %attr(755, root, root) %{_sbindir}/mysqld %attr(755, root, root) %{_sbindir}/mysqld-debug %attr(755, root, root) %{_sbindir}/mysqlmanager @@ -818,6 +822,8 @@ fi %{_libdir}/mysql/libvio.a %{_libdir}/mysql/libz.a %{_libdir}/mysql/libz.la +%{_libdir}/plugin/*.a +%{_libdir}/plugin/*.la %files shared %defattr(-, root, root, 0755) @@ -847,6 +853,11 @@ fi # itself - note that they must be ordered by date (important when # merging BK trees) %changelog +* Fri Aug 21 2009 Jonathan Perkin + +- Install plugin libraries in appropriate packages. +- Disable example plugins. + * Fri Nov 07 2008 Joerg Bruehe - Correct yesterday's fix, so that it also works for the last flag, From 769d9f3803ada97d0032944aa1447520957aa73b Mon Sep 17 00:00:00 2001 From: Jonathan Perkin Date: Fri, 21 Aug 2009 13:58:33 +0200 Subject: [PATCH 23/80] Apply patch from bug#46834 to install the test suite in RPMs. --- mysql-test/Makefile.am | 3 ++- mysql-test/lib/My/SafeProcess/Makefile.am | 3 ++- storage/ndb/test/run-test/Makefile.am | 3 ++- support-files/mysql.spec.sh | 6 +++++- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/mysql-test/Makefile.am b/mysql-test/Makefile.am index 810bead1adc..b1d0e85c70e 100644 --- a/mysql-test/Makefile.am +++ b/mysql-test/Makefile.am @@ -17,7 +17,8 @@ ## Process this file with automake to create Makefile.in -testdir = $(prefix)/mysql-test +testroot = $(prefix) +testdir = $(testroot)/mysql-test test_SCRIPTS = mtr \ mysql-test-run \ diff --git a/mysql-test/lib/My/SafeProcess/Makefile.am b/mysql-test/lib/My/SafeProcess/Makefile.am index 623c0e9a87a..722331453fe 100644 --- a/mysql-test/lib/My/SafeProcess/Makefile.am +++ b/mysql-test/lib/My/SafeProcess/Makefile.am @@ -13,7 +13,8 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -safedir = $(prefix)/mysql-test/lib/My/SafeProcess +testroot = $(prefix) +safedir = $(testroot)/mysql-test/lib/My/SafeProcess #nobase_bin_PROGRAMS = ... safe_PROGRAMS = my_safe_process diff --git a/storage/ndb/test/run-test/Makefile.am b/storage/ndb/test/run-test/Makefile.am index 65aa62d11f0..54ca0c009b2 100644 --- a/storage/ndb/test/run-test/Makefile.am +++ b/storage/ndb/test/run-test/Makefile.am @@ -13,7 +13,8 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -testdir=$(prefix)/mysql-test/ndb +testroot=$(prefix) +testdir=$(testroot)/mysql-test/ndb include $(top_srcdir)/storage/ndb/config/common.mk.am include $(top_srcdir)/storage/ndb/config/type_util.mk.am diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index 081489f7053..8a181375cfb 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -428,7 +428,7 @@ install -d $RBR%{_sbindir} # Install all binaries -(cd $MBD && make install DESTDIR=$RBR benchdir_root=%{_datadir}) +(cd $MBD && make install DESTDIR=$RBR testroot=%{_datadir}) # Old packages put shared libs in %{_libdir}/ (not %{_libdir}/mysql), so do # the same here. mv $RBR/%{_libdir}/mysql/*.so* $RBR/%{_libdir}/ @@ -858,6 +858,10 @@ fi - Install plugin libraries in appropriate packages. - Disable example plugins. +* Thu Aug 20 2009 Jonathan Perkin + +- Update variable used for mysql-test suite location to match source. + * Fri Nov 07 2008 Joerg Bruehe - Correct yesterday's fix, so that it also works for the last flag, From df91ff571b36a2428b31d667944eb72a10cf1449 Mon Sep 17 00:00:00 2001 From: Jonathan Perkin Date: Mon, 24 Aug 2009 10:50:04 +0200 Subject: [PATCH 24/80] Add conditionals for bundled zlib and innodb plugin --- support-files/mysql.spec.sh | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index 8a181375cfb..5b8d7a5922d 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -31,6 +31,20 @@ %{?_with_yassl:%define YASSL_BUILD 1} %{!?_with_yassl:%define YASSL_BUILD 0} +# ---------------------------------------------------------------------- +# use "rpmbuild --with bundled_zlib" or "rpm --define '_with_bundled_zlib 1'" +# (for RPM 3.x) to build using the bundled zlib (off by default) +# ---------------------------------------------------------------------- +%{?_with_bundled_zlib:%define WITH_BUNDLED_ZLIB 1} +%{!?_with_bundled_zlib:%define WITH_BUNDLED_ZLIB 0} + +# ---------------------------------------------------------------------- +# use "rpmbuild --without innodb_plugin" or "rpm --define '_without_innodb_plugin 1'" +# (for RPM 3.x) to not build the innodb plugin (on by default with innodb builds) +# ---------------------------------------------------------------------- +%{?_without_innodb_plugin:%define WITHOUT_INNODB_PLUGIN 1} +%{!?_without_innodb_plugin:%define WITHOUT_INNODB_PLUGIN 0} + # use "rpmbuild --with cluster" or "rpm --define '_with_cluster 1'" (for RPM 3.x) # to build with cluster support (off by default) %{?_with_cluster:%define CLUSTER_BUILD 1} @@ -292,6 +306,9 @@ sh -c "PATH=\"${MYSQL_BUILD_PATH:-$PATH}\" \ --enable-thread-safe-client \ --with-readline \ --with-innodb \ +%if %{WITHOUT_INNODB_PLUGIN} + --without-plugin-innodb_plugin \ +%endif %if %{CLUSTER_BUILD} --with-ndbcluster \ %else @@ -305,6 +322,9 @@ sh -c "PATH=\"${MYSQL_BUILD_PATH:-$PATH}\" \ --without-plugin-example \ --with-partition \ --with-big-tables \ +%if %{WITH_BUNDLED_ZLIB} + --with-zlib-dir=bundled \ +%endif --enable-shared \ " make @@ -853,6 +873,10 @@ fi # itself - note that they must be ordered by date (important when # merging BK trees) %changelog +* Mon Aug 24 2009 Jonathan Perkin + +- Add conditionals for bundled zlib and innodb plugin + * Fri Aug 21 2009 Jonathan Perkin - Install plugin libraries in appropriate packages. From c2bd07ca9cd848c58dcd243551e4d52e68bbb449 Mon Sep 17 00:00:00 2001 From: Jonathan Perkin Date: Mon, 24 Aug 2009 14:06:01 +0200 Subject: [PATCH 25/80] Tidy previous, put example storage engine back as it's used by tests. --- support-files/mysql.spec.sh | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index 5b8d7a5922d..fbb569e0c8c 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -319,7 +319,6 @@ sh -c "PATH=\"${MYSQL_BUILD_PATH:-$PATH}\" \ --with-blackhole-storage-engine \ --with-federated-storage-engine \ --without-plugin-daemon_example \ - --without-plugin-example \ --with-partition \ --with-big-tables \ %if %{WITH_BUNDLED_ZLIB} @@ -715,7 +714,11 @@ fi %attr(755, root, root) %{_bindir}/resolve_stack_dump %attr(755, root, root) %{_bindir}/resolveip -%attr(755, root, root) %{_libdir}/plugin/*.so* +%attr(755, root, root) %{_libdir}/mysql/plugin/ha_example.so* +%if %{WITHOUT_INNODB_PLUGIN} +%else +%attr(755, root, root) %{_libdir}/mysql/plugin/ha_innodb_plugin.so* +%endif %attr(755, root, root) %{_sbindir}/mysqld %attr(755, root, root) %{_sbindir}/mysqld-debug @@ -842,8 +845,15 @@ fi %{_libdir}/mysql/libvio.a %{_libdir}/mysql/libz.a %{_libdir}/mysql/libz.la -%{_libdir}/plugin/*.a -%{_libdir}/plugin/*.la +%{_libdir}/mysql/plugin/ha_example.a +%{_libdir}/mysql/plugin/ha_example.la +%if %{WITHOUT_INNODB_PLUGIN} +%else +%{_libdir}/mysql/plugin/ha_innodb_plugin.a +%{_libdir}/mysql/plugin/ha_innodb_plugin.la +%endif +%{_libdir}/mysql/plugin/mypluglib.a +%{_libdir}/mysql/plugin/mypluglib.la %files shared %defattr(-, root, root, 0755) @@ -880,7 +890,7 @@ fi * Fri Aug 21 2009 Jonathan Perkin - Install plugin libraries in appropriate packages. -- Disable example plugins. +- Disable libdaemon_example plugin. * Thu Aug 20 2009 Jonathan Perkin From 74092a8e5bfa037e32f2cca266fad0f59b0dbd9a Mon Sep 17 00:00:00 2001 From: Jonathan Perkin Date: Tue, 25 Aug 2009 13:00:23 +0200 Subject: [PATCH 26/80] Disable ftexample to match other packages, ride previous changelog entry. --- support-files/mysql.spec.sh | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index fbb569e0c8c..cd8af76faa2 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -319,6 +319,7 @@ sh -c "PATH=\"${MYSQL_BUILD_PATH:-$PATH}\" \ --with-blackhole-storage-engine \ --with-federated-storage-engine \ --without-plugin-daemon_example \ + --without-plugin-ftexample \ --with-partition \ --with-big-tables \ %if %{WITH_BUNDLED_ZLIB} @@ -852,8 +853,6 @@ fi %{_libdir}/mysql/plugin/ha_innodb_plugin.a %{_libdir}/mysql/plugin/ha_innodb_plugin.la %endif -%{_libdir}/mysql/plugin/mypluglib.a -%{_libdir}/mysql/plugin/mypluglib.la %files shared %defattr(-, root, root, 0755) @@ -890,7 +889,7 @@ fi * Fri Aug 21 2009 Jonathan Perkin - Install plugin libraries in appropriate packages. -- Disable libdaemon_example plugin. +- Disable libdaemon_example and ftexample plugins. * Thu Aug 20 2009 Jonathan Perkin From 3a766492913ecf1d3642063c1fa57b5d94c182a6 Mon Sep 17 00:00:00 2001 From: Bjorn Munch Date: Tue, 25 Aug 2009 15:56:50 +0200 Subject: [PATCH 27/80] Bug #42408 Faulty regex for detecting [Warning] and [ERROR] in mysqld error log Enabled proper pattern for Warnings and ERRORs Added some suppressions --- mysql-test/include/mtr_warnings.sql | 6 +++++- mysql-test/mysql-test-run.pl | 6 ++---- mysql-test/r/almost_full.result | 1 + mysql-test/r/upgrade.result | 4 ---- mysql-test/suite/rpl/r/rpl_idempotency.result | 3 ++- mysql-test/suite/rpl/t/rpl_idempotency.test | 3 ++- mysql-test/t/almost_full.test | 2 ++ mysql-test/t/upgrade.test | 2 ++ 8 files changed, 16 insertions(+), 11 deletions(-) diff --git a/mysql-test/include/mtr_warnings.sql b/mysql-test/include/mtr_warnings.sql index 73287900f3c..157244a9b0a 100644 --- a/mysql-test/include/mtr_warnings.sql +++ b/mysql-test/include/mtr_warnings.sql @@ -132,7 +132,7 @@ INSERT INTO global_suppressions VALUES ("Error in Log_event::read_log_event\\\(\\\): 'Sanity check failed', data_len: 258, event_type: 49"), - ("Statement is not safe to log in statement format"), + ("Statement may not be safe to log in statement format"), /* test case for Bug#bug29807 copies a stray frm into database */ ("InnoDB: Error: table `test`.`bug29807` does not exist in the InnoDB internal"), @@ -172,6 +172,10 @@ INSERT INTO global_suppressions VALUES */ ("Can't find file: '.\\\\test\\\\\\?{8}.frm'"), + /* Added 2009-08-XX after fixing Bug #42408 */ + + ("Slave: Operation DROP USER failed for '.*'@'localhost' Error_code: 1396"), + ("THE_LAST_SUPPRESSION")|| diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 28ddd718f16..c15f3990ec4 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -3624,10 +3624,8 @@ sub extract_warning_lines ($) { # and correcting them shows a few additional harmless warnings. # Thus those patterns are temporarily removed from the list # of patterns. For more info see BUG#42408 - # qr/^Warning:|mysqld: Warning|\[Warning\]/, - # qr/^Error:|\[ERROR\]/, - qr/^Warning:|mysqld: Warning/, - qr/^Error:/, + qr/^Warning:|mysqld: Warning|\[Warning\]/, + qr/^Error:|\[ERROR\]/, qr/^==.* at 0x/, qr/InnoDB: Warning|InnoDB: Error/, qr/^safe_mutex:|allocated at line/, diff --git a/mysql-test/r/almost_full.result b/mysql-test/r/almost_full.result index eb28f12fa51..b2d7092aa51 100644 --- a/mysql-test/r/almost_full.result +++ b/mysql-test/r/almost_full.result @@ -1,3 +1,4 @@ +call mtr.add_suppression("The table 't1' is full"); drop table if exists t1; set global myisam_data_pointer_size=2; CREATE TABLE t1 (a int auto_increment primary key not null, b longtext) ENGINE=MyISAM; diff --git a/mysql-test/r/upgrade.result b/mysql-test/r/upgrade.result index da6201692a9..034242079b1 100644 --- a/mysql-test/r/upgrade.result +++ b/mysql-test/r/upgrade.result @@ -108,11 +108,7 @@ a-b-c show create view `a-b-c`.v1; View Create View character_set_client collation_connection v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `a`.`f1` AS `f1` from (`a-b-c`.`t1` `a` join `information_schema`.`tables` `b`) where (convert(`a`.`f1` using utf8) = `b`.`TABLE_NAME`) utf8 utf8_general_ci -Warnings: -Note 1600 Creation context of view `a-b-c`.`v1' is invalid select * from `a-b-c`.v1; f1 -Warnings: -Note 1600 Creation context of view `a-b-c`.`v1' is invalid drop database `a-b-c`; use test; diff --git a/mysql-test/suite/rpl/r/rpl_idempotency.result b/mysql-test/suite/rpl/r/rpl_idempotency.result index 3341c03db0f..bfdcbc6fa23 100644 --- a/mysql-test/suite/rpl/r/rpl_idempotency.result +++ b/mysql-test/suite/rpl/r/rpl_idempotency.result @@ -4,7 +4,8 @@ reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; -call mtr.add_suppression("Slave: Can\'t find record in \'t1\' Error_code: 1032"); +call mtr.add_suppression("Slave: Can't find record in 't.' Error_code: 1032"); +call mtr.add_suppression("Slave: Cannot delete or update a parent row: a foreign key constraint fails .* Error_code: 1451"); call mtr.add_suppression("Slave: Cannot add or update a child row: a foreign key constraint fails .* Error_code: 1452"); SET @old_slave_exec_mode= @@global.slave_exec_mode; CREATE TABLE t1 (a INT PRIMARY KEY); diff --git a/mysql-test/suite/rpl/t/rpl_idempotency.test b/mysql-test/suite/rpl/t/rpl_idempotency.test index bfd1860759e..c96b88a1b1a 100644 --- a/mysql-test/suite/rpl/t/rpl_idempotency.test +++ b/mysql-test/suite/rpl/t/rpl_idempotency.test @@ -8,7 +8,8 @@ connection slave; source include/have_innodb.inc; # Add suppression for expected warning(s) in slaves error log -call mtr.add_suppression("Slave: Can\'t find record in \'t1\' Error_code: 1032"); +call mtr.add_suppression("Slave: Can't find record in 't.' Error_code: 1032"); +call mtr.add_suppression("Slave: Cannot delete or update a parent row: a foreign key constraint fails .* Error_code: 1451"); call mtr.add_suppression("Slave: Cannot add or update a child row: a foreign key constraint fails .* Error_code: 1452"); SET @old_slave_exec_mode= @@global.slave_exec_mode; diff --git a/mysql-test/t/almost_full.test b/mysql-test/t/almost_full.test index 5c67ab3c088..24801f9cbc3 100644 --- a/mysql-test/t/almost_full.test +++ b/mysql-test/t/almost_full.test @@ -2,6 +2,8 @@ # Some special cases with empty tables # +call mtr.add_suppression("The table 't1' is full"); + --disable_warnings drop table if exists t1; --enable_warnings diff --git a/mysql-test/t/upgrade.test b/mysql-test/t/upgrade.test index d571a2efc7c..e390e8a1253 100644 --- a/mysql-test/t/upgrade.test +++ b/mysql-test/t/upgrade.test @@ -124,6 +124,8 @@ with_check_option=0 timestamp=2009-04-10 11:53:37 create-version=1 source=select f1 from `a-b-c`.t1 a, information_schema.tables b\nwhere a.f1 = b.table_name +client_cs_name=utf8 +connection_cl_name=utf8_general_ci EOF show databases like '%a-b-c%'; From 9a8ef8f7a4f3a1bf88be69526763a667843e6870 Mon Sep 17 00:00:00 2001 From: Bjorn Munch Date: Thu, 27 Aug 2009 15:17:09 +0200 Subject: [PATCH 28/80] Bug #46322 Sporadic timeout in mysql_upgrade.test Apparently caused by logging to table Turn on logging to file only, add to .opt file for tests needing log to table --- mysql-test/mysql-test-run.pl | 4 ++-- mysql-test/t/events_logs_tests-master.opt | 2 +- mysql-test/t/log_tables-master.opt | 2 +- mysql-test/t/ps-master.opt | 2 +- mysql-test/t/show_check-master.opt | 2 +- mysql-test/t/status-master.opt | 1 + 6 files changed, 7 insertions(+), 6 deletions(-) create mode 100644 mysql-test/t/status-master.opt diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index c15f3990ec4..429fbfe41c6 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -4105,8 +4105,8 @@ sub mysqld_arguments ($$$) { if ( $mysql_version_id >= 50106 ) { - # Turn on logging to both tables and file - mtr_add_arg($args, "--log-output=table,file"); + # Turn on logging to file + mtr_add_arg($args, "--log-output=file"); } # Check if "extra_opt" contains skip-log-bin diff --git a/mysql-test/t/events_logs_tests-master.opt b/mysql-test/t/events_logs_tests-master.opt index 35ff7911705..3ece9710a45 100644 --- a/mysql-test/t/events_logs_tests-master.opt +++ b/mysql-test/t/events_logs_tests-master.opt @@ -1 +1 @@ ---log-slow-queries +--log-output=table,file --log-slow-queries diff --git a/mysql-test/t/log_tables-master.opt b/mysql-test/t/log_tables-master.opt index 35ff7911705..3ece9710a45 100644 --- a/mysql-test/t/log_tables-master.opt +++ b/mysql-test/t/log_tables-master.opt @@ -1 +1 @@ ---log-slow-queries +--log-output=table,file --log-slow-queries diff --git a/mysql-test/t/ps-master.opt b/mysql-test/t/ps-master.opt index 3eb98fc3d6b..31c287d2bb5 100644 --- a/mysql-test/t/ps-master.opt +++ b/mysql-test/t/ps-master.opt @@ -1 +1 @@ ---log-slow-queries --log-long-format --log-queries-not-using-indexes +--log-output=table,file --log-slow-queries --log-long-format --log-queries-not-using-indexes diff --git a/mysql-test/t/show_check-master.opt b/mysql-test/t/show_check-master.opt index 7a438da06cc..aab832e2848 100644 --- a/mysql-test/t/show_check-master.opt +++ b/mysql-test/t/show_check-master.opt @@ -1 +1 @@ ---log-slow-queries --log-long-format --log-queries-not-using-indexes --myisam-recover="" +--log-output=table,file --log-slow-queries --log-long-format --log-queries-not-using-indexes --myisam-recover="" diff --git a/mysql-test/t/status-master.opt b/mysql-test/t/status-master.opt new file mode 100644 index 00000000000..eb3bb4fe50d --- /dev/null +++ b/mysql-test/t/status-master.opt @@ -0,0 +1 @@ +--log-output=table,file From de5ab42de65abb375a9c6cebdc2e490340816b96 Mon Sep 17 00:00:00 2001 From: Bjorn Munch Date: Fri, 28 Aug 2009 15:02:48 +0200 Subject: [PATCH 29/80] Bug #46973 MTR: extract_warning_lines does not check it's extracting lines for current test Rewrote logic (first commit was incomplete, sorry) --- mysql-test/mysql-test-run.pl | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 429fbfe41c6..5a5d063c105 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -3571,8 +3571,8 @@ sub run_testcase ($) { # error log and write all lines that look # suspicious into $error_log.warnings # -sub extract_warning_lines ($) { - my ($error_log) = @_; +sub extract_warning_lines ($$) { + my ($error_log, $tname) = @_; # Open the servers .err log file and read all lines # belonging to current tets into @lines @@ -3580,14 +3580,27 @@ sub extract_warning_lines ($) { or mtr_error("Could not open file '$error_log' for reading: $!"); my @lines; + my $found_test= 0; # Set once we've found the log of this test while ( my $line = <$Ferr> ) { - if ( $line =~ /^CURRENT_TEST:/ ) + if ($found_test) { - # Throw away lines from previous tests - @lines = (); + # If test wasn't last after all, discard what we found, test again. + if ( $line =~ /^CURRENT_TEST:/) + { + @lines= (); + $found_test= $line =~ /^CURRENT_TEST: $tname/; + } + else + { + push(@lines, $line); + } + } + else + { + # Search for beginning of test, until found + $found_test= 1 if ($line =~ /^CURRENT_TEST: $tname/); } - push(@lines, $line); } $Ferr = undef; # Close error log file @@ -3665,7 +3678,7 @@ sub start_check_warnings ($$) { my $log_error= $mysqld->value('#log-error'); # To be communicated to the test $ENV{MTR_LOG_ERROR}= $log_error; - extract_warning_lines($log_error); + extract_warning_lines($log_error, $tinfo->{name}); my $args; mtr_init_args(\$args); From fa4f05139d0de6dc827cb72dd62a615e9365bc94 Mon Sep 17 00:00:00 2001 From: Bjorn Munch Date: Fri, 28 Aug 2009 16:13:27 +0200 Subject: [PATCH 30/80] Bug #42408 Faulty regex for detecting [Warning] and [ERROR] in mysqld error log Some follow-up test fixes after seeing effect in PB2 --- mysql-test/extra/rpl_tests/rpl_extraSlave_Col.test | 2 ++ mysql-test/r/lowercase_table3.result | 2 +- mysql-test/suite/rpl/r/rpl_bug33931.result | 2 +- mysql-test/suite/rpl/r/rpl_extraCol_innodb.result | 1 + mysql-test/suite/rpl/r/rpl_extraCol_myisam.result | 1 + mysql-test/suite/rpl/r/rpl_init_slave_errors.result | 1 + mysql-test/suite/rpl/t/rpl_bug33931.test | 2 +- mysql-test/suite/rpl/t/rpl_init_slave_errors.test | 1 + mysql-test/t/lowercase_table3.test | 2 +- 9 files changed, 10 insertions(+), 4 deletions(-) diff --git a/mysql-test/extra/rpl_tests/rpl_extraSlave_Col.test b/mysql-test/extra/rpl_tests/rpl_extraSlave_Col.test index 6890913b7d1..a7b02065144 100644 --- a/mysql-test/extra/rpl_tests/rpl_extraSlave_Col.test +++ b/mysql-test/extra/rpl_tests/rpl_extraSlave_Col.test @@ -22,6 +22,8 @@ DROP TABLE IF EXISTS t1, t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t14a,t15,t1 # should stop the slave. # ################################################# +call mtr.add_suppression("Slave: Unknown table 't6' Error_code: 1051"); + --echo **** Diff Table Def Start **** ############################################## diff --git a/mysql-test/r/lowercase_table3.result b/mysql-test/r/lowercase_table3.result index 1ef7d04bb1d..22e80aaeb26 100644 --- a/mysql-test/r/lowercase_table3.result +++ b/mysql-test/r/lowercase_table3.result @@ -1,4 +1,4 @@ -call mtr.add_suppression("Cannot find or open table test/BUG29839 from .*"); +call mtr.add_suppression("Cannot find or open table test/BUG29839 from"); DROP TABLE IF EXISTS t1,T1; CREATE TABLE t1 (a INT); SELECT * FROM T1; diff --git a/mysql-test/suite/rpl/r/rpl_bug33931.result b/mysql-test/suite/rpl/r/rpl_bug33931.result index 85c8fb0da9c..a17941f6ba9 100644 --- a/mysql-test/suite/rpl/r/rpl_bug33931.result +++ b/mysql-test/suite/rpl/r/rpl_bug33931.result @@ -1,5 +1,5 @@ reset master; -call mtr.add_suppression("Failed during slave thread initialization"); +call mtr.add_suppression("Failed during slave I/O thread initialization"); stop slave; reset slave; SET GLOBAL debug="d,simulate_io_slave_error_on_init,simulate_sql_slave_error_on_init"; diff --git a/mysql-test/suite/rpl/r/rpl_extraCol_innodb.result b/mysql-test/suite/rpl/r/rpl_extraCol_innodb.result index e57daad3342..e2ec78e7adc 100644 --- a/mysql-test/suite/rpl/r/rpl_extraCol_innodb.result +++ b/mysql-test/suite/rpl/r/rpl_extraCol_innodb.result @@ -4,6 +4,7 @@ reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; +call mtr.add_suppression("Slave: Unknown table 't6' Error_code: 1051"); **** Diff Table Def Start **** *** On Slave *** STOP SLAVE; diff --git a/mysql-test/suite/rpl/r/rpl_extraCol_myisam.result b/mysql-test/suite/rpl/r/rpl_extraCol_myisam.result index 6696ddc7789..ed5b4eac27d 100644 --- a/mysql-test/suite/rpl/r/rpl_extraCol_myisam.result +++ b/mysql-test/suite/rpl/r/rpl_extraCol_myisam.result @@ -4,6 +4,7 @@ reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; +call mtr.add_suppression("Slave: Unknown table 't6' Error_code: 1051"); **** Diff Table Def Start **** *** On Slave *** STOP SLAVE; diff --git a/mysql-test/suite/rpl/r/rpl_init_slave_errors.result b/mysql-test/suite/rpl/r/rpl_init_slave_errors.result index ab957e6d9bc..c6ee82b13f3 100644 --- a/mysql-test/suite/rpl/r/rpl_init_slave_errors.result +++ b/mysql-test/suite/rpl/r/rpl_init_slave_errors.result @@ -9,6 +9,7 @@ reset slave; SET GLOBAL debug= "d,simulate_io_slave_error_on_init,simulate_sql_slave_error_on_init"; start slave; Reporting the following error: Failed during slave thread initialization +call mtr.add_suppression("Failed during slave I/O thread initialization"); SET GLOBAL debug= ""; stop slave; reset slave; diff --git a/mysql-test/suite/rpl/t/rpl_bug33931.test b/mysql-test/suite/rpl/t/rpl_bug33931.test index 13f781c644b..1316ddb7401 100644 --- a/mysql-test/suite/rpl/t/rpl_bug33931.test +++ b/mysql-test/suite/rpl/t/rpl_bug33931.test @@ -15,7 +15,7 @@ reset master; connection slave; # Add suppression for expected warnings in slaves error log -call mtr.add_suppression("Failed during slave thread initialization"); +call mtr.add_suppression("Failed during slave I/O thread initialization"); --disable_warnings stop slave; diff --git a/mysql-test/suite/rpl/t/rpl_init_slave_errors.test b/mysql-test/suite/rpl/t/rpl_init_slave_errors.test index 4ca0de6ec66..180821730ec 100644 --- a/mysql-test/suite/rpl/t/rpl_init_slave_errors.test +++ b/mysql-test/suite/rpl/t/rpl_init_slave_errors.test @@ -57,6 +57,7 @@ source include/wait_for_slave_to_stop.inc; let $error= query_get_value(SHOW SLAVE STATUS, Last_Error, 1); echo Reporting the following error: $error; +call mtr.add_suppression("Failed during slave I/O thread initialization"); SET GLOBAL debug= ""; diff --git a/mysql-test/t/lowercase_table3.test b/mysql-test/t/lowercase_table3.test index 4748953fe95..f7ca8211288 100644 --- a/mysql-test/t/lowercase_table3.test +++ b/mysql-test/t/lowercase_table3.test @@ -9,7 +9,7 @@ --source include/have_case_insensitive_file_system.inc --source include/not_windows.inc -call mtr.add_suppression("Cannot find or open table test/BUG29839 from .*"); +call mtr.add_suppression("Cannot find or open table test/BUG29839 from"); --disable_warnings DROP TABLE IF EXISTS t1,T1; From abe47a0ebebf6ced1f71e8a79760d254962b52d4 Mon Sep 17 00:00:00 2001 From: Bjorn Munch Date: Sat, 29 Aug 2009 10:30:59 +0200 Subject: [PATCH 31/80] A few more suppression fixes after 42408 --- mysql-test/suite/rpl/r/rpl_slave_load_remove_tmpfile.result | 1 + mysql-test/suite/rpl/t/rpl_slave_load_remove_tmpfile.test | 3 +++ mysql-test/suite/rpl_ndb/r/rpl_ndb_extraCol.result | 1 + 3 files changed, 5 insertions(+) diff --git a/mysql-test/suite/rpl/r/rpl_slave_load_remove_tmpfile.result b/mysql-test/suite/rpl/r/rpl_slave_load_remove_tmpfile.result index 777f7d8427b..71c17321117 100644 --- a/mysql-test/suite/rpl/r/rpl_slave_load_remove_tmpfile.result +++ b/mysql-test/suite/rpl/r/rpl_slave_load_remove_tmpfile.result @@ -1,3 +1,4 @@ +call mtr.add_suppression("Slave: Error writing file 'UNKNOWN' (Errcode: 9) Error_code: 3"); stop slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; reset master; diff --git a/mysql-test/suite/rpl/t/rpl_slave_load_remove_tmpfile.test b/mysql-test/suite/rpl/t/rpl_slave_load_remove_tmpfile.test index 39f3b700f94..3a1fbe04e17 100644 --- a/mysql-test/suite/rpl/t/rpl_slave_load_remove_tmpfile.test +++ b/mysql-test/suite/rpl/t/rpl_slave_load_remove_tmpfile.test @@ -7,6 +7,9 @@ # 1 - Creates a table and populates it through "LOAD DATA INFILE". # 2 - Catches error. ########################################################################## + +call mtr.add_suppression("Slave: Error writing file 'UNKNOWN' (Errcode: 9) Error_code: 3"); + --source include/have_binlog_format_mixed_or_statement.inc --source include/have_innodb.inc --source include/have_debug.inc diff --git a/mysql-test/suite/rpl_ndb/r/rpl_ndb_extraCol.result b/mysql-test/suite/rpl_ndb/r/rpl_ndb_extraCol.result index d51599fd18b..f812509de6f 100644 --- a/mysql-test/suite/rpl_ndb/r/rpl_ndb_extraCol.result +++ b/mysql-test/suite/rpl_ndb/r/rpl_ndb_extraCol.result @@ -4,6 +4,7 @@ reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; +call mtr.add_suppression("Slave: Unknown table 't6' Error_code: 1051"); **** Diff Table Def Start **** *** On Slave *** STOP SLAVE; From aa7e21c68fd36c66ac0603c416a29b1ca5d59b71 Mon Sep 17 00:00:00 2001 From: Bjorn Munch Date: Sat, 29 Aug 2009 23:29:47 +0200 Subject: [PATCH 32/80] even more suppression fixes --- mysql-test/suite/parts/r/partition_recover_myisam.result | 2 ++ mysql-test/suite/parts/t/partition_recover_myisam.test | 4 ++++ mysql-test/suite/rpl/r/rpl_slave_load_remove_tmpfile.result | 2 +- mysql-test/suite/rpl/t/rpl_slave_load_remove_tmpfile.test | 4 ++-- 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/mysql-test/suite/parts/r/partition_recover_myisam.result b/mysql-test/suite/parts/r/partition_recover_myisam.result index df737ec2853..49775ee498e 100644 --- a/mysql-test/suite/parts/r/partition_recover_myisam.result +++ b/mysql-test/suite/parts/r/partition_recover_myisam.result @@ -1,3 +1,5 @@ +call mtr.add_suppression("./test/t1_will_crash"); +call mtr.add_suppression("Got an error from unknown thread, ha_myisam.cc"); CREATE TABLE t1_will_crash (a INT, KEY (a)) ENGINE=MyISAM; INSERT INTO t1_will_crash VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10), (11); FLUSH TABLES; diff --git a/mysql-test/suite/parts/t/partition_recover_myisam.test b/mysql-test/suite/parts/t/partition_recover_myisam.test index 14604bfeb15..64bc821ac37 100644 --- a/mysql-test/suite/parts/t/partition_recover_myisam.test +++ b/mysql-test/suite/parts/t/partition_recover_myisam.test @@ -1,4 +1,8 @@ # test the auto-recover (--myisam-recover) of partitioned myisam tables + +call mtr.add_suppression("./test/t1_will_crash"); +call mtr.add_suppression("Got an error from unknown thread, ha_myisam.cc"); + --source include/have_partition.inc --disable_warnings --disable_query_log diff --git a/mysql-test/suite/rpl/r/rpl_slave_load_remove_tmpfile.result b/mysql-test/suite/rpl/r/rpl_slave_load_remove_tmpfile.result index 71c17321117..bc6fa377dc3 100644 --- a/mysql-test/suite/rpl/r/rpl_slave_load_remove_tmpfile.result +++ b/mysql-test/suite/rpl/r/rpl_slave_load_remove_tmpfile.result @@ -1,4 +1,3 @@ -call mtr.add_suppression("Slave: Error writing file 'UNKNOWN' (Errcode: 9) Error_code: 3"); stop slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; reset master; @@ -52,3 +51,4 @@ Last_SQL_Errno 9 Last_SQL_Error Error in Begin_load_query event: write to '../../tmp/SQL_LOAD.data' failed drop table t1; drop table t1; +call mtr.add_suppression("Slave: Error writing file 'UNKNOWN' (Errcode: 9) Error_code: 3"); diff --git a/mysql-test/suite/rpl/t/rpl_slave_load_remove_tmpfile.test b/mysql-test/suite/rpl/t/rpl_slave_load_remove_tmpfile.test index 3a1fbe04e17..fe1fc730ba8 100644 --- a/mysql-test/suite/rpl/t/rpl_slave_load_remove_tmpfile.test +++ b/mysql-test/suite/rpl/t/rpl_slave_load_remove_tmpfile.test @@ -8,8 +8,6 @@ # 2 - Catches error. ########################################################################## -call mtr.add_suppression("Slave: Error writing file 'UNKNOWN' (Errcode: 9) Error_code: 3"); - --source include/have_binlog_format_mixed_or_statement.inc --source include/have_innodb.inc --source include/have_debug.inc @@ -50,3 +48,5 @@ drop table t1; connection slave; drop table t1; + +call mtr.add_suppression("Slave: Error writing file 'UNKNOWN' (Errcode: 9) Error_code: 3"); From 02f67d5b1f484ffd7e363ab8f3b108ea7b27e26c Mon Sep 17 00:00:00 2001 From: Bjorn Munch Date: Sun, 30 Aug 2009 12:01:08 +0200 Subject: [PATCH 33/80] yet another 42408 followup --- mysql-test/suite/rpl/t/disabled.def | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/suite/rpl/t/disabled.def b/mysql-test/suite/rpl/t/disabled.def index 38fc9e21322..cb7a2a98925 100644 --- a/mysql-test/suite/rpl/t/disabled.def +++ b/mysql-test/suite/rpl/t/disabled.def @@ -11,3 +11,4 @@ ############################################################################## rpl_cross_version : Bug#42311 2009-03-27 joro rpl_cross_version fails on macosx +rpl_slave_load_remove_tmpfile Bug#46996, unable to suppress warning From 5166a56d0406fe6ab51e0b3cb91202497c888b8c Mon Sep 17 00:00:00 2001 From: Bjorn Munch Date: Mon, 31 Aug 2009 09:24:59 +0200 Subject: [PATCH 34/80] forgot : in rpl's disabled.def --- mysql-test/suite/rpl/t/disabled.def | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/suite/rpl/t/disabled.def b/mysql-test/suite/rpl/t/disabled.def index cb7a2a98925..546c0e6b194 100644 --- a/mysql-test/suite/rpl/t/disabled.def +++ b/mysql-test/suite/rpl/t/disabled.def @@ -11,4 +11,4 @@ ############################################################################## rpl_cross_version : Bug#42311 2009-03-27 joro rpl_cross_version fails on macosx -rpl_slave_load_remove_tmpfile Bug#46996, unable to suppress warning +rpl_slave_load_remove_tmpfile : Bug#46996, unable to suppress warning From 71f4bfd6c7dba0ea4b00469d48e458f0e5eeaf67 Mon Sep 17 00:00:00 2001 From: Jonathan Perkin Date: Tue, 1 Sep 2009 08:40:13 +0200 Subject: [PATCH 35/80] Only install the innodb plugin if the plugin directory exists. --- scripts/make_win_bin_dist | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/scripts/make_win_bin_dist b/scripts/make_win_bin_dist index ce89ea28303..9c17c26b445 100755 --- a/scripts/make_win_bin_dist +++ b/scripts/make_win_bin_dist @@ -287,8 +287,10 @@ cp libmysql/$TARGET/libmysql.dll \ regex/$TARGET/regex.lib \ strings/$TARGET/strings.lib \ zlib/$TARGET/zlib.lib $DESTDIR/lib/opt/ -cp storage/innodb_plugin/$TARGET/ha_innodb_plugin.dll \ - $DESTDIR/lib/plugin/ +if [ -d storage/innodb_plugin ]; then + cp storage/innodb_plugin/$TARGET/ha_innodb_plugin.dll \ + $DESTDIR/lib/plugin/ +fi if [ x"$TARGET" != x"release" ] ; then cp libmysql/$TARGET/libmysql.pdb \ @@ -297,8 +299,10 @@ if [ x"$TARGET" != x"release" ] ; then regex/$TARGET/regex.pdb \ strings/$TARGET/strings.pdb \ zlib/$TARGET/zlib.pdb $DESTDIR/lib/opt/ - cp storage/innodb_plugin/$TARGET/ha_innodb_plugin.pdb \ - $DESTDIR/lib/plugin/ + if [ -d storage/innodb_plugin ]; then + cp storage/innodb_plugin/$TARGET/ha_innodb_plugin.pdb \ + $DESTDIR/lib/plugin/ + fi fi @@ -319,10 +323,12 @@ if [ x"$PACK_DEBUG" = x"" -a -f "libmysql/debug/libmysql.lib" -o \ strings/debug/strings.pdb \ zlib/debug/zlib.lib \ zlib/debug/zlib.pdb $DESTDIR/lib/debug/ - cp storage/innodb_plugin/debug/ha_innodb_plugin.dll \ - storage/innodb_plugin/debug/ha_innodb_plugin.lib \ - storage/innodb_plugin/debug/ha_innodb_plugin.pdb \ - $DESTDIR/lib/plugin/debug/ + if [ -d storage/innodb_plugin ]; then + cp storage/innodb_plugin/debug/ha_innodb_plugin.dll \ + storage/innodb_plugin/debug/ha_innodb_plugin.lib \ + storage/innodb_plugin/debug/ha_innodb_plugin.pdb \ + $DESTDIR/lib/plugin/debug/ + fi fi # ---------------------------------------------------------------------- From 3a78dbe48208e786f0e8ad81c78a0a09a1cf191a Mon Sep 17 00:00:00 2001 From: Bjorn Munch Date: Tue, 1 Sep 2009 13:38:17 +0200 Subject: [PATCH 36/80] 46996 workaruond --- mysql-test/include/mtr_warnings.sql | 4 ---- mysql-test/suite/rpl/r/rpl_do_grant.result | 3 +++ .../suite/rpl/r/rpl_slave_load_remove_tmpfile.result | 2 +- mysql-test/suite/rpl/t/disabled.def | 1 - mysql-test/suite/rpl/t/rpl_do_grant.test | 7 ++++++- mysql-test/suite/rpl/t/rpl_slave_load_remove_tmpfile.test | 2 +- 6 files changed, 11 insertions(+), 8 deletions(-) diff --git a/mysql-test/include/mtr_warnings.sql b/mysql-test/include/mtr_warnings.sql index 157244a9b0a..b73234e6142 100644 --- a/mysql-test/include/mtr_warnings.sql +++ b/mysql-test/include/mtr_warnings.sql @@ -172,10 +172,6 @@ INSERT INTO global_suppressions VALUES */ ("Can't find file: '.\\\\test\\\\\\?{8}.frm'"), - /* Added 2009-08-XX after fixing Bug #42408 */ - - ("Slave: Operation DROP USER failed for '.*'@'localhost' Error_code: 1396"), - ("THE_LAST_SUPPRESSION")|| diff --git a/mysql-test/suite/rpl/r/rpl_do_grant.result b/mysql-test/suite/rpl/r/rpl_do_grant.result index 69bcfad4347..0913b1afdbf 100644 --- a/mysql-test/suite/rpl/r/rpl_do_grant.result +++ b/mysql-test/suite/rpl/r/rpl_do_grant.result @@ -166,4 +166,7 @@ DROP FUNCTION upgrade_del_func; DROP FUNCTION upgrade_alter_func; DROP DATABASE bug42217_db; DROP USER 'create_rout_db'@'localhost'; +call mtr.add_suppression("Slave: Operation DROP USER failed for 'create_rout_db'@'localhost' Error_code: 1396"); +USE mtr; +call mtr.add_suppression("Slave: Operation DROP USER failed for 'create_rout_db'@'localhost' Error_code: 1396"); "End of test" diff --git a/mysql-test/suite/rpl/r/rpl_slave_load_remove_tmpfile.result b/mysql-test/suite/rpl/r/rpl_slave_load_remove_tmpfile.result index bc6fa377dc3..e2efcf08d7a 100644 --- a/mysql-test/suite/rpl/r/rpl_slave_load_remove_tmpfile.result +++ b/mysql-test/suite/rpl/r/rpl_slave_load_remove_tmpfile.result @@ -51,4 +51,4 @@ Last_SQL_Errno 9 Last_SQL_Error Error in Begin_load_query event: write to '../../tmp/SQL_LOAD.data' failed drop table t1; drop table t1; -call mtr.add_suppression("Slave: Error writing file 'UNKNOWN' (Errcode: 9) Error_code: 3"); +call mtr.add_suppression("Slave: Error writing file 'UNKNOWN' .Errcode: 9. Error_code: 3"); diff --git a/mysql-test/suite/rpl/t/disabled.def b/mysql-test/suite/rpl/t/disabled.def index 546c0e6b194..38fc9e21322 100644 --- a/mysql-test/suite/rpl/t/disabled.def +++ b/mysql-test/suite/rpl/t/disabled.def @@ -11,4 +11,3 @@ ############################################################################## rpl_cross_version : Bug#42311 2009-03-27 joro rpl_cross_version fails on macosx -rpl_slave_load_remove_tmpfile : Bug#46996, unable to suppress warning diff --git a/mysql-test/suite/rpl/t/rpl_do_grant.test b/mysql-test/suite/rpl/t/rpl_do_grant.test index 806de780086..a8b15516682 100644 --- a/mysql-test/suite/rpl/t/rpl_do_grant.test +++ b/mysql-test/suite/rpl/t/rpl_do_grant.test @@ -207,5 +207,10 @@ DROP FUNCTION upgrade_del_func; DROP FUNCTION upgrade_alter_func; DROP DATABASE bug42217_db; DROP USER 'create_rout_db'@'localhost'; - + +call mtr.add_suppression("Slave: Operation DROP USER failed for 'create_rout_db'@'localhost' Error_code: 1396"); +connection slave; +USE mtr; +call mtr.add_suppression("Slave: Operation DROP USER failed for 'create_rout_db'@'localhost' Error_code: 1396"); + --echo "End of test" diff --git a/mysql-test/suite/rpl/t/rpl_slave_load_remove_tmpfile.test b/mysql-test/suite/rpl/t/rpl_slave_load_remove_tmpfile.test index fe1fc730ba8..437e1ebb92d 100644 --- a/mysql-test/suite/rpl/t/rpl_slave_load_remove_tmpfile.test +++ b/mysql-test/suite/rpl/t/rpl_slave_load_remove_tmpfile.test @@ -49,4 +49,4 @@ connection slave; drop table t1; -call mtr.add_suppression("Slave: Error writing file 'UNKNOWN' (Errcode: 9) Error_code: 3"); +call mtr.add_suppression("Slave: Error writing file 'UNKNOWN' .Errcode: 9. Error_code: 3"); From fe3ea31d9310e14ffce99d23a9b5979864e96fe2 Mon Sep 17 00:00:00 2001 From: Bjorn Munch Date: Wed, 2 Sep 2009 11:17:33 +0200 Subject: [PATCH 37/80] Bug #32296 mysqltest fails to parse "append_file" inside a "while", it works inside a "if" Bug #41913 mysqltest cannot source files from if inside while Some commands require additional processing which only works first time Keep content for write_file or append_file with the st_command struct Add tests for those cases to mysqltest.test --- client/mysqltest.cc | 56 ++++++++++++++++++++++++++++------- mysql-test/r/mysqltest.result | 19 ++++-------- mysql-test/t/mysqltest.test | 26 ++++++++++++---- 3 files changed, 73 insertions(+), 28 deletions(-) diff --git a/client/mysqltest.cc b/client/mysqltest.cc index 0cf7e62ac8c..7965dafb863 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -417,6 +417,7 @@ static struct st_expected_errors saved_expected_errors; struct st_command { char *query, *query_buf,*first_argument,*last_argument,*end; + DYNAMIC_STRING content; int first_word_len, query_len; my_bool abort_on_error; struct st_expected_errors expected_errors; @@ -1138,6 +1139,8 @@ void free_used_memory() { struct st_command **q= dynamic_element(&q_lines, i, struct st_command**); my_free((*q)->query_buf,MYF(MY_ALLOW_ZERO_PTR)); + if ((*q)->content.str) + dynstr_free(&(*q)->content); my_free((*q),MYF(0)); } for (i= 0; i < 10; i++) @@ -3283,21 +3286,30 @@ void do_write_file_command(struct st_command *command, my_bool append) sizeof(write_file_args)/sizeof(struct command_arg), ' '); - /* If no delimiter was provided, use EOF */ - if (ds_delimiter.length == 0) - dynstr_set(&ds_delimiter, "EOF"); - if (!append && access(ds_filename.str, F_OK) == 0) { /* The file should not be overwritten */ die("File already exist: '%s'", ds_filename.str); } - init_dynamic_string(&ds_content, "", 1024, 1024); - read_until_delimiter(&ds_content, &ds_delimiter); - DBUG_PRINT("info", ("Writing to file: %s", ds_filename.str)); - str_to_file2(ds_filename.str, ds_content.str, ds_content.length, append); - dynstr_free(&ds_content); + ds_content= command->content; + /* If it hasn't been done already by a loop iteration, fill it in */ + if (! ds_content.str) + { + /* If no delimiter was provided, use EOF */ + if (ds_delimiter.length == 0) + dynstr_set(&ds_delimiter, "EOF"); + + init_dynamic_string(&ds_content, "", 1024, 1024); + read_until_delimiter(&ds_content, &ds_delimiter); + command->content= ds_content; + } + /* This function could be called even if "false", so check before printing */ + if (cur_block->ok) + { + DBUG_PRINT("info", ("Writing to file: %s", ds_filename.str)); + str_to_file2(ds_filename.str, ds_content.str, ds_content.length, append); + } dynstr_free(&ds_filename); dynstr_free(&ds_delimiter); DBUG_VOID_RETURN; @@ -7684,7 +7696,31 @@ int main(int argc, char **argv) command->type= Q_COMMENT; } - if (cur_block->ok) + my_bool ok_to_do= cur_block->ok; + /* + Some commands need to be "done" the first time if they may get + re-iterated over in a true context. This can only happen if there's + a while loop at some level above the current block. + */ + if (!ok_to_do) + { + if (command->type == Q_SOURCE || + command->type == Q_WRITE_FILE || + command->type == Q_APPEND_FILE || + command->type == Q_PERL) + { + for (struct st_block *stb= cur_block-1; stb >= block_stack; stb--) + { + if (stb->cmd == cmd_while) + { + ok_to_do= 1; + break; + } + } + } + } + + if (ok_to_do) { command->last_argument= command->first_argument; processed = 1; diff --git a/mysql-test/r/mysqltest.result b/mysql-test/r/mysqltest.result index 52a1734ea54..f68413264e4 100644 --- a/mysql-test/r/mysqltest.result +++ b/mysql-test/r/mysqltest.result @@ -314,21 +314,10 @@ here is the sourced script 1 = outer loop variable before dec 0 = outer loop variable after dec - -2 = outer loop variable after while +outer=2 ifval=0 +outer=1 ifval=1 here is the sourced script -2 = outer loop variable before dec - -1 = outer loop variable after dec - -1 = outer loop variable after while -here is the sourced script - -1 = outer loop variable before dec - -0 = outer loop variable after dec - In loop here is the sourced script @@ -538,6 +527,10 @@ mysqltest: At line 1: Missing required argument 'filename' to command 'write_fil mysqltest: At line 1: End of file encountered before 'EOF' delimiter was found Content for test_file1 mysqltest: At line 1: File already exist: 'MYSQLTEST_VARDIR/tmp/test_file1.tmp' +These lines should be repeated, +if things work as expected +These lines should be repeated, +if things work as expected Some data for cat_file command of mysqltest diff --git a/mysql-test/t/mysqltest.test b/mysql-test/t/mysqltest.test index 92f39d943b9..9859e73cfae 100644 --- a/mysql-test/t/mysqltest.test +++ b/mysql-test/t/mysqltest.test @@ -853,16 +853,18 @@ while ($outer) eval SELECT '$outer = outer loop variable after dec' AS ""; } +# Test source in an if in a while which is false on 1st iteration let $outer= 2; # Number of outer loops +let $ifval= 0; # false 1st time while ($outer) { - eval SELECT '$outer = outer loop variable after while' AS ""; + echo outer=$outer ifval=$ifval; - echo here is the sourced script; - - eval SELECT '$outer = outer loop variable before dec' AS ""; + if ($ifval) { + --source $MYSQLTEST_VARDIR/tmp/sourced.inc + } dec $outer; - eval SELECT '$outer = outer loop variable after dec' AS ""; + inc $ifval; } @@ -1663,6 +1665,20 @@ EOF remove_file $MYSQLTEST_VARDIR/tmp/test_file1.tmp; +# Test append_file within while +let $outer= 2; # Number of outer loops +while ($outer) +{ + append_file $MYSQLTEST_VARDIR/tmp/app_while.tmp; +These lines should be repeated, +if things work as expected +EOF + dec $outer; +} + +cat_file $MYSQLTEST_VARDIR/tmp/app_while.tmp; +remove_file $MYSQLTEST_VARDIR/tmp/app_while.tmp; + # ---------------------------------------------------------------------------- # test for cat_file # ---------------------------------------------------------------------------- From 4d676f314c5f41d3060b1326e677dc92487dcbcc Mon Sep 17 00:00:00 2001 From: Bjorn Munch Date: Thu, 3 Sep 2009 08:19:54 +0200 Subject: [PATCH 38/80] Bug #47075 Wildcards in experimental test names destroyed when tested first time Extract substr into local variable --- mysql-test/lib/mtr_report.pm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/lib/mtr_report.pm b/mysql-test/lib/mtr_report.pm index a246c5bbef6..f2131b9bd76 100644 --- a/mysql-test/lib/mtr_report.pm +++ b/mysql-test/lib/mtr_report.pm @@ -134,8 +134,8 @@ sub mtr_report_test ($) { # an asterisk at the end, determine if the characters up to # but excluding the asterisk are the same if ( $exp ne "" && substr($exp, -1, 1) eq "*" ) { - $exp = substr($exp, 0, length($exp) - 1); - if ( substr($test_name, 0, length($exp)) ne $exp ) { + my $nexp = substr($exp, 0, length($exp) - 1); + if ( substr($test_name, 0, length($nexp)) ne $nexp ) { # no match, try next entry next; } From b5e3f4a35837b8fc924b54cc26a803cfe770d2f5 Mon Sep 17 00:00:00 2001 From: Bjorn Munch Date: Thu, 3 Sep 2009 08:38:06 +0200 Subject: [PATCH 39/80] A few suppression follow-ups --- mysql-test/r/bug46080.result | 2 ++ mysql-test/r/partition_csv.result | 1 + mysql-test/t/bug46080.test | 3 +++ mysql-test/t/partition_csv.test | 2 ++ 4 files changed, 8 insertions(+) diff --git a/mysql-test/r/bug46080.result b/mysql-test/r/bug46080.result index 18c7c22829a..2173768cdad 100644 --- a/mysql-test/r/bug46080.result +++ b/mysql-test/r/bug46080.result @@ -2,6 +2,8 @@ # Bug #46080: group_concat(... order by) crashes server when # sort_buffer_size cannot allocate # +call mtr.add_suppression("Out of memory at line .*, 'my_alloc.c'"); +call mtr.add_suppression("needed .* byte .*k., memory in use: .* bytes .*k"); CREATE TABLE t1(a CHAR(255)); INSERT INTO t1 VALUES ('a'); SET @@SESSION.sort_buffer_size=5*16*1000000; diff --git a/mysql-test/r/partition_csv.result b/mysql-test/r/partition_csv.result index 07651f29da4..18e28d4670a 100644 --- a/mysql-test/r/partition_csv.result +++ b/mysql-test/r/partition_csv.result @@ -1,3 +1,4 @@ +call mtr.add_suppression("Failed to write to mysql.general_log"); drop table if exists t1; create table t1 (a int) engine = csv diff --git a/mysql-test/t/bug46080.test b/mysql-test/t/bug46080.test index 7e56e3ce421..8b4cee4d8b0 100644 --- a/mysql-test/t/bug46080.test +++ b/mysql-test/t/bug46080.test @@ -3,6 +3,9 @@ --echo # sort_buffer_size cannot allocate --echo # +call mtr.add_suppression("Out of memory at line .*, 'my_alloc.c'"); +call mtr.add_suppression("needed .* byte .*k., memory in use: .* bytes .*k"); + CREATE TABLE t1(a CHAR(255)); INSERT INTO t1 VALUES ('a'); diff --git a/mysql-test/t/partition_csv.test b/mysql-test/t/partition_csv.test index dd2ef7c1d1f..44013dd4b0a 100644 --- a/mysql-test/t/partition_csv.test +++ b/mysql-test/t/partition_csv.test @@ -10,6 +10,8 @@ --source include/have_partition.inc --source include/have_csv.inc +call mtr.add_suppression("Failed to write to mysql.general_log"); + # # Bug#19307: Partitions: csv delete failure # = CSV engine crashes From 76b8bd35898ea74734b4c57c10bdb2928dd7dd55 Mon Sep 17 00:00:00 2001 From: Kristofer Pettersson Date: Thu, 3 Sep 2009 12:08:55 +0200 Subject: [PATCH 40/80] Bug#46486 warnings produced when running mysql_install_db During start up some plugins are disabled by default. This caused an additional warning level message to be emitted as a result of a previous bug patch. Since there is risk of unnecessary confusion regarding the operation level of the server the redundant information is removed. --- sql/sql_plugin.cc | 3 --- 1 file changed, 3 deletions(-) diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index da168d36429..f00e1f72390 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -1565,9 +1565,6 @@ void plugin_shutdown(void) } } - if (count > free_slots) - sql_print_warning("Forcing shutdown of %d plugins", count - free_slots); - plugins= (struct st_plugin_int **) my_alloca(sizeof(void*) * (count+1)); /* From 19d0529819c65dc4662b6a388fea7fbc7323b2f1 Mon Sep 17 00:00:00 2001 From: Jonathan Perkin Date: Thu, 3 Sep 2009 18:20:43 +0200 Subject: [PATCH 41/80] Raise version number after cloning 5.1.39 --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index 5b9f3e0f200..b974d7076d7 100644 --- a/configure.in +++ b/configure.in @@ -10,7 +10,7 @@ AC_CANONICAL_SYSTEM # # When changing major version number please also check switch statement # in mysqlbinlog::check_master_version(). -AM_INIT_AUTOMAKE(mysql, 5.1.39) +AM_INIT_AUTOMAKE(mysql, 5.1.40) AM_CONFIG_HEADER([include/config.h:config.h.in]) PROTOCOL_VERSION=10 From 0c4c2d7b8db1fead32aa48b12d538b5a8b522c59 Mon Sep 17 00:00:00 2001 From: Kristofer Pettersson Date: Fri, 4 Sep 2009 12:32:21 +0200 Subject: [PATCH 42/80] Bug#46486 warnings produced when running mysql_install_db Incremental patch part 2 Removing dead code and changing a note level message to a warning. sql/sql_plugin.cc: * Remove free_slots. The only purpose for this variable was to trigger a redundant warning message and it failed. * Change the note level message about shutting down plugins which didn't end nicely to a warning level message. (If this shutdown fails and there still are reference counts in the plugin an additional error level message is emitted) --- sql/sql_plugin.cc | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index f00e1f72390..025c8a8248d 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -1520,7 +1520,7 @@ error: void plugin_shutdown(void) { - uint i, count= plugin_array.elements, free_slots= 0; + uint i, count= plugin_array.elements; struct st_plugin_int **plugins, *plugin; struct st_plugin_dl **dl; DBUG_ENTER("plugin_shutdown"); @@ -1541,18 +1541,13 @@ void plugin_shutdown(void) while (reap_needed && (count= plugin_array.elements)) { reap_plugins(); - for (i= free_slots= 0; i < count; i++) + for (i= 0; i < count; i++) { plugin= *dynamic_element(&plugin_array, i, struct st_plugin_int **); - switch (plugin->state) { - case PLUGIN_IS_READY: + if (plugin->state == PLUGIN_IS_READY) + { plugin->state= PLUGIN_IS_DELETED; reap_needed= true; - break; - case PLUGIN_IS_FREED: - case PLUGIN_IS_UNINITIALIZED: - free_slots++; - break; } } if (!reap_needed) @@ -1586,8 +1581,8 @@ void plugin_shutdown(void) if (!(plugins[i]->state & (PLUGIN_IS_UNINITIALIZED | PLUGIN_IS_FREED | PLUGIN_IS_DISABLED))) { - sql_print_information("Plugin '%s' will be forced to shutdown", - plugins[i]->name.str); + sql_print_warning("Plugin '%s' will be forced to shutdown", + plugins[i]->name.str); /* We are forcing deinit on plugins so we don't want to do a ref_count check until we have processed all the plugins. From c7d32876f345785580a7cf286542ccf390b4e1fa Mon Sep 17 00:00:00 2001 From: Jonathan Perkin Date: Fri, 4 Sep 2009 17:45:07 +0200 Subject: [PATCH 43/80] Install mysqld.lib --- scripts/make_win_bin_dist | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/make_win_bin_dist b/scripts/make_win_bin_dist index 9c17c26b445..fdb34f2f48d 100755 --- a/scripts/make_win_bin_dist +++ b/scripts/make_win_bin_dist @@ -280,6 +280,7 @@ cp include/mysql/plugin.h $DESTDIR/include/mysql/ mkdir -p $DESTDIR/lib/opt mkdir -p $DESTDIR/lib/plugin +cp sql/$TARGET/mysqld.lib $DESTDIR/lib/ cp libmysql/$TARGET/libmysql.dll \ libmysql/$TARGET/libmysql.lib \ libmysql/$TARGET/mysqlclient.lib \ From 540b2dc0041c292220d389bbb5b87a8410aef3f4 Mon Sep 17 00:00:00 2001 From: Ingo Struewing Date: Mon, 7 Sep 2009 18:35:37 +0200 Subject: [PATCH 44/80] Bug#17332 - changing key_buffer_size on a running server can crash under load Backport from 5.1. Does also include key cache fixes from: Bug 44068 (RESTORE can disable the MyISAM Key Cache) Bug 40944 (Backup: crash after myisampack) include/keycache.h: Bug#17332 - changing key_buffer_size on a running server can crash under load Added KEY_CACHE components in_resize and waiting_for_resize_cnt. myisam/mi_preload.c: Bug#17332 - changing key_buffer_size on a running server can crash under load Added code to allow LOAD INDEX to load indexes of different block size. mysys/mf_keycache.c: Bug#17332 - changing key_buffer_size on a running server can crash under load . Changed resize_key_cache() to not disable the key cache after the flush phase. Changed queue handling to use standard functions. Wake all threads waiting on resize_queue. We can now have read/write threads waiting there (see below). . Combined add_to_queue() and the wait loops that were always following it to the new function wait_on_queue(). Combined release_queue() and the condition that was always preceding it to the new function release_whole_queue(). . Added code to flag and respect the exceptional situation BLOCK_IN_EVICTION. . Rewrote the resize branch of find_key_block(). . Added code to the eviction handling in find_key_block() to catch more exceptional cases. . Changed key_cache_read(), key_cache_insert() and key_cache_write() so that they lock keycache->cache_lock whenever the key cache is initialized. Checking for a disabled cache and incrementing and decrementing the "resize counter" is always done within the lock. Locking and unlocking as well as counting the "resize counter" is now done once outside the loop. All three functions can now handle a NULL return from find_key_block. This happens in the flush phase of a resize and demands direct file I/O. Care is taken for secondary requests (PAGE_WAIT_TO_BE_READ) to wait in any case. Moved block status changes behind the copying of buffer data. key_cache_insert() does now read the block if the caller did supply less data than a full cache block. key_cache_write() does now take care of parallel running flushes (BLOCK_FOR_UPDATE, BLOCK_IN_FLUSHWRITE). . Changed free_block() to un-initialize block variables in the correct order and respect an exceptional BLOCK_IN_EVICTION state. . Changed flushing to take care for parallel running writes. Changed flushing to avoid freeing blocks in eviction. Changed flushing to consider that parallel writes can move blocks from the file_blocks hash to the changed_blocks hash. Changed flushing to take care for other parallel flushes. Changed flushing to assure that it ends with everything flushed. Optimized normal flush at end of statement (FLUSH_KEEP), but let other flush types be stringent. . Added some comments and debugging statements. mysys/my_static.c: Bug#17332 - changing key_buffer_size on a running server can crash under load Removed an unused global variable. sql/ha_myisam.cc: Bug#17332 - changing key_buffer_size on a running server can crash under load Moved an automatic (stack) variable to the scope where it is used. sql/sql_table.cc: Bug#17332 - changing key_buffer_size on a running server can crash under load Changed TL_READ to TL_READ_NO_INSERT in mysql_preload_keys. --- include/keycache.h | 6 + myisam/mi_preload.c | 13 +- mysys/mf_keycache.c | 2687 +++++++++++++++++++++++++++++++++++-------- mysys/my_static.c | 3 - sql/ha_myisam.cc | 2 +- sql/sql_table.cc | 7 +- 6 files changed, 2210 insertions(+), 508 deletions(-) diff --git a/include/keycache.h b/include/keycache.h index 424b4086cb4..b2e959955d0 100644 --- a/include/keycache.h +++ b/include/keycache.h @@ -44,6 +44,7 @@ typedef struct st_keycache_wqueue typedef struct st_key_cache { my_bool key_cache_inited; + my_bool in_resize; /* true during resize operation */ my_bool resize_in_flush; /* true during flush of resize operation */ my_bool can_be_used; /* usage of cache for read/write is allowed */ size_t key_cache_mem_size; /* specified size of the cache memory */ @@ -71,6 +72,11 @@ typedef struct st_key_cache BLOCK_LINK *used_ins; /* ptr to the insertion block in LRU chain */ pthread_mutex_t cache_lock; /* to lock access to the cache structure */ KEYCACHE_WQUEUE resize_queue; /* threads waiting during resize operation */ + /* + Waiting for a zero resize count. Using a queue for symmetry though + only one thread can wait here. + */ + KEYCACHE_WQUEUE waiting_for_resize_cnt; KEYCACHE_WQUEUE waiting_for_hash_link; /* waiting for a free hash link */ KEYCACHE_WQUEUE waiting_for_block; /* requests waiting for a free block */ BLOCK_LINK *changed_blocks[CHANGED_BLOCKS_HASH]; /* hash for dirty file bl.*/ diff --git a/myisam/mi_preload.c b/myisam/mi_preload.c index 78729f18424..06c66c06bf4 100644 --- a/myisam/mi_preload.c +++ b/myisam/mi_preload.c @@ -55,12 +55,17 @@ int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves) block_length= keyinfo[0].block_length; - /* Check whether all indexes use the same block size */ - for (i= 1 ; i < keys ; i++) + if (ignore_leaves) { - if (keyinfo[i].block_length != block_length) - DBUG_RETURN(my_errno= HA_ERR_NON_UNIQUE_BLOCK_SIZE); + /* Check whether all indexes use the same block size */ + for (i= 1 ; i < keys ; i++) + { + if (keyinfo[i].block_length != block_length) + DBUG_RETURN(my_errno= HA_ERR_NON_UNIQUE_BLOCK_SIZE); + } } + else + block_length= share->key_cache->key_cache_block_size; length= info->preload_buff_size/block_length * block_length; set_if_bigger(length, block_length); diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c index 0720d172317..f9898e263aa 100644 --- a/mysys/mf_keycache.c +++ b/mysys/mf_keycache.c @@ -13,7 +13,8 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* +/** + @file These functions handle keyblock cacheing for ISAM and MyISAM tables. One cache can handle many files. @@ -38,7 +39,73 @@ as such gives the maximum number of in-use blocks at any time. */ +/* + Key Cache Locking + ================= + + All key cache locking is done with a single mutex per key cache: + keycache->cache_lock. This mutex is locked almost all the time + when executing code in this file (mf_keycache.c). + However it is released for I/O and some copy operations. + + The cache_lock is also released when waiting for some event. Waiting + and signalling is done via condition variables. In most cases the + thread waits on its thread->suspend condition variable. Every thread + has a my_thread_var structure, which contains this variable and a + '*next' and '**prev' pointer. These pointers are used to insert the + thread into a wait queue. + + A thread can wait for one block and thus be in one wait queue at a + time only. + + Before starting to wait on its condition variable with + pthread_cond_wait(), the thread enters itself to a specific wait queue + with link_into_queue() (double linked with '*next' + '**prev') or + wait_on_queue() (single linked with '*next'). + + Another thread, when releasing a resource, looks up the waiting thread + in the related wait queue. It sends a signal with + pthread_cond_signal() to the waiting thread. + + NOTE: Depending on the particular wait situation, either the sending + thread removes the waiting thread from the wait queue with + unlink_from_queue() or release_whole_queue() respectively, or the waiting + thread removes itself. + + There is one exception from this locking scheme when one thread wants + to reuse a block for some other address. This works by first marking + the block reserved (status= BLOCK_IN_SWITCH) and then waiting for all + threads that are reading the block to finish. Each block has a + reference to a condition variable (condvar). It holds a reference to + the thread->suspend condition variable for the waiting thread (if such + a thread exists). When that thread is signaled, the reference is + cleared. The number of readers of a block is registered in + block->hash_link->requests. See wait_for_readers() / remove_reader() + for details. This is similar to the above, but it clearly means that + only one thread can wait for a particular block. There is no queue in + this case. Strangely enough block->convar is used for waiting for the + assigned hash_link only. More precisely it is used to wait for all + requests to be unregistered from the assigned hash_link. + + The resize_queue serves two purposes: + 1. Threads that want to do a resize wait there if in_resize is set. + This is not used in the server. The server refuses a second resize + request if one is already active. keycache->in_init is used for the + synchronization. See set_var.cc. + 2. Threads that want to access blocks during resize wait here during + the re-initialization phase. + When the resize is done, all threads on the queue are signalled. + Hypothetical resizers can compete for resizing, and read/write + requests will restart to request blocks from the freshly resized + cache. If the cache has been resized too small, it is disabled and + 'can_be_used' is false. In this case read/write requests bypass the + cache. Since they increment and decrement 'cnt_for_resize_op', the + next resizer can wait on the queue 'waiting_for_resize_cnt' until all + I/O finished. +*/ + #include "mysys_priv.h" +#include "mysys_err.h" #include #include "my_static.h" #include @@ -119,12 +186,16 @@ struct st_hash_link }; /* simple states of a block */ -#define BLOCK_ERROR 1 /* an error occured when performing disk i/o */ -#define BLOCK_READ 2 /* the is page in the block buffer */ -#define BLOCK_IN_SWITCH 4 /* block is preparing to read new page */ -#define BLOCK_REASSIGNED 8 /* block does not accept requests for old page */ -#define BLOCK_IN_FLUSH 16 /* block is in flush operation */ -#define BLOCK_CHANGED 32 /* block buffer contains a dirty page */ +#define BLOCK_ERROR 1 /* an error occured when performing file i/o */ +#define BLOCK_READ 2 /* file block is in the block buffer */ +#define BLOCK_IN_SWITCH 4 /* block is preparing to read new page */ +#define BLOCK_REASSIGNED 8 /* blk does not accept requests for old page */ +#define BLOCK_IN_FLUSH 16 /* block is selected for flush */ +#define BLOCK_CHANGED 32 /* block buffer contains a dirty page */ +#define BLOCK_IN_USE 64 /* block is not free */ +#define BLOCK_IN_EVICTION 128 /* block is selected for eviction */ +#define BLOCK_IN_FLUSHWRITE 256 /* block is in write to file */ +#define BLOCK_FOR_UPDATE 512 /* block is selected for buffer modification */ /* page status, returned by find_key_block */ #define PAGE_READ 0 @@ -161,13 +232,15 @@ KEY_CACHE *dflt_key_cache= &dflt_key_cache_var; static int flush_all_key_blocks(KEY_CACHE *keycache); #ifdef THREAD -static void link_into_queue(KEYCACHE_WQUEUE *wqueue, - struct st_my_thread_var *thread); -static void unlink_from_queue(KEYCACHE_WQUEUE *wqueue, - struct st_my_thread_var *thread); +static void wait_on_queue(KEYCACHE_WQUEUE *wqueue, + pthread_mutex_t *mutex); +static void release_whole_queue(KEYCACHE_WQUEUE *wqueue); +#else +#define wait_on_queue(wqueue, mutex) do {} while (0) +#define release_whole_queue(wqueue) do {} while (0) #endif static void free_block(KEY_CACHE *keycache, BLOCK_LINK *block); -#ifndef DBUG_OFF +#if !defined(DBUG_OFF) static void test_key_cache(KEY_CACHE *keycache, const char *where, my_bool lock); #endif @@ -263,6 +336,16 @@ static int keycache_pthread_cond_signal(pthread_cond_t *cond); #define keycache_pthread_cond_signal pthread_cond_signal #endif /* defined(KEYCACHE_DEBUG) */ +#if !defined(DBUG_OFF) +#if defined(inline) +#undef inline +#endif +#define inline /* disabled inline for easier debugging */ +static int fail_block(BLOCK_LINK *block); +static int fail_hlink(HASH_LINK *hlink); +static int cache_empty(KEY_CACHE *keycache); +#endif + static uint next_power(uint value) { uint old_value= 1; @@ -323,6 +406,14 @@ int init_key_cache(KEY_CACHE *keycache, uint key_cache_block_size, if (! keycache->key_cache_inited) { keycache->key_cache_inited= 1; + /* + Initialize these variables once only. + Their value must survive re-initialization during resizing. + */ + keycache->in_resize= 0; + keycache->resize_in_flush= 0; + keycache->cnt_for_resize_op= 0; + keycache->waiting_for_resize_cnt.last_thread= NULL; keycache->in_init= 0; pthread_mutex_init(&keycache->cache_lock, MY_MUTEX_INIT_FAST); keycache->resize_queue.last_thread= NULL; @@ -336,7 +427,7 @@ int init_key_cache(KEY_CACHE *keycache, uint key_cache_block_size, blocks= (ulong) (use_mem / (sizeof(BLOCK_LINK) + 2 * sizeof(HASH_LINK) + sizeof(HASH_LINK*) * 5/4 + key_cache_block_size)); /* It doesn't make sense to have too few blocks (less than 8) */ - if (blocks >= 8 && keycache->disk_blocks < 0) + if (blocks >= 8) { for ( ; ; ) { @@ -356,8 +447,8 @@ int init_key_cache(KEY_CACHE *keycache, uint key_cache_block_size, blocks--; /* Allocate memory for cache page buffers */ if ((keycache->block_mem= - my_large_malloc((size_t) blocks * keycache->key_cache_block_size, - MYF(MY_WME)))) + my_large_malloc((size_t) blocks * keycache->key_cache_block_size, + MYF(0)))) { /* Allocate memory for blocks, hash_links and hash entries; @@ -372,6 +463,7 @@ int init_key_cache(KEY_CACHE *keycache, uint key_cache_block_size, if (blocks < 8) { my_errno= ENOMEM; + my_error(EE_OUTOFMEMORY, MYF(0), blocks * keycache->key_cache_block_size); goto err; } blocks= blocks / 4*3; @@ -410,8 +502,6 @@ int init_key_cache(KEY_CACHE *keycache, uint key_cache_block_size, blocks * age_threshold / 100 : blocks); - keycache->cnt_for_resize_op= 0; - keycache->resize_in_flush= 0; keycache->can_be_used= 1; keycache->waiting_for_hash_link.last_thread= NULL; @@ -427,6 +517,11 @@ int init_key_cache(KEY_CACHE *keycache, uint key_cache_block_size, bzero((gptr) keycache->file_blocks, sizeof(keycache->file_blocks[0]) * CHANGED_BLOCKS_HASH); } + else + { + /* key_buffer_size is specified too small. Disable the cache. */ + keycache->can_be_used= 0; + } keycache->blocks= keycache->disk_blocks > 0 ? keycache->disk_blocks : 0; DBUG_RETURN((int) keycache->disk_blocks); @@ -485,8 +580,6 @@ int resize_key_cache(KEY_CACHE *keycache, uint key_cache_block_size, uint age_threshold) { int blocks; - struct st_my_thread_var *thread; - KEYCACHE_WQUEUE *wqueue; DBUG_ENTER("resize_key_cache"); if (!keycache->key_cache_inited) @@ -502,54 +595,86 @@ int resize_key_cache(KEY_CACHE *keycache, uint key_cache_block_size, keycache_pthread_mutex_lock(&keycache->cache_lock); #ifdef THREAD - wqueue= &keycache->resize_queue; - thread= my_thread_var; - link_into_queue(wqueue, thread); - - while (wqueue->last_thread->next != thread) + /* + We may need to wait for another thread which is doing a resize + already. This cannot happen in the MySQL server though. It allows + one resizer only. In set_var.cc keycache->in_init is used to block + multiple attempts. + */ + while (keycache->in_resize) { - keycache_pthread_cond_wait(&thread->suspend, &keycache->cache_lock); + /* purecov: begin inspected */ + wait_on_queue(&keycache->resize_queue, &keycache->cache_lock); + /* purecov: end */ } #endif - keycache->resize_in_flush= 1; - if (flush_all_key_blocks(keycache)) + /* + Mark the operation in progress. This blocks other threads from doing + a resize in parallel. It prohibits new blocks to enter the cache. + Read/write requests can bypass the cache during the flush phase. + */ + keycache->in_resize= 1; + + /* Need to flush only if keycache is enabled. */ + if (keycache->can_be_used) { - /* TODO: if this happens, we should write a warning in the log file ! */ + /* Start the flush phase. */ + keycache->resize_in_flush= 1; + + if (flush_all_key_blocks(keycache)) + { + /* TODO: if this happens, we should write a warning in the log file ! */ + keycache->resize_in_flush= 0; + blocks= 0; + keycache->can_be_used= 0; + goto finish; + } + DBUG_ASSERT(cache_empty(keycache)); + + /* End the flush phase. */ keycache->resize_in_flush= 0; - blocks= 0; - keycache->can_be_used= 0; - goto finish; } - keycache->resize_in_flush= 0; - keycache->can_be_used= 0; + #ifdef THREAD + /* + Some direct read/write operations (bypassing the cache) may still be + unfinished. Wait until they are done. If the key cache can be used, + direct I/O is done in increments of key_cache_block_size. That is, + every block is checked if it is in the cache. We need to wait for + pending I/O before re-initializing the cache, because we may change + the block size. Otherwise they could check for blocks at file + positions where the new block division has none. We do also want to + wait for I/O done when (if) the cache was disabled. It must not + run in parallel with normal cache operation. + */ while (keycache->cnt_for_resize_op) - { - KEYCACHE_DBUG_PRINT("resize_key_cache: wait", - ("suspend thread %ld", thread->id)); - keycache_pthread_cond_wait(&thread->suspend, &keycache->cache_lock); - } + wait_on_queue(&keycache->waiting_for_resize_cnt, &keycache->cache_lock); #else KEYCACHE_DBUG_ASSERT(keycache->cnt_for_resize_op == 0); #endif + /* + Free old cache structures, allocate new structures, and initialize + them. Note that the cache_lock mutex and the resize_queue are left + untouched. We do not lose the cache_lock and will release it only at + the end of this function. + */ end_key_cache(keycache, 0); /* Don't free mutex */ /* The following will work even if use_mem is 0 */ blocks= init_key_cache(keycache, key_cache_block_size, use_mem, division_limit, age_threshold); finish: -#ifdef THREAD - unlink_from_queue(wqueue, thread); - /* Signal for the next resize request to proceeed if any */ - if (wqueue->last_thread) - { - KEYCACHE_DBUG_PRINT("resize_key_cache: signal", - ("thread %ld", wqueue->last_thread->next->id)); - keycache_pthread_cond_signal(&wqueue->last_thread->next->suspend); - } -#endif + /* + Mark the resize finished. This allows other threads to start a + resize or to request new cache blocks. + */ + keycache->in_resize= 0; + + /* Signal waiting threads. */ + release_whole_queue(&keycache->resize_queue); + keycache_pthread_mutex_unlock(&keycache->cache_lock); DBUG_RETURN(blocks); } @@ -570,18 +695,8 @@ static inline void inc_counter_for_resize_op(KEY_CACHE *keycache) */ static inline void dec_counter_for_resize_op(KEY_CACHE *keycache) { -#ifdef THREAD - struct st_my_thread_var *last_thread; - if (!--keycache->cnt_for_resize_op && - (last_thread= keycache->resize_queue.last_thread)) - { - KEYCACHE_DBUG_PRINT("dec_counter_for_resize_op: signal", - ("thread %ld", last_thread->next->id)); - keycache_pthread_cond_signal(&last_thread->next->suspend); - } -#else - keycache->cnt_for_resize_op--; -#endif + if (!--keycache->cnt_for_resize_op) + release_whole_queue(&keycache->waiting_for_resize_cnt); } /* @@ -661,6 +776,13 @@ void end_key_cache(KEY_CACHE *keycache, my_bool cleanup) (ulong) keycache->global_cache_r_requests, (ulong) keycache->global_cache_read)); + /* + Reset these values to be able to detect a disabled key cache. + See Bug#44068 (RESTORE can disable the MyISAM Key Cache). + */ + keycache->blocks_used= 0; + keycache->blocks_unused= 0; + if (cleanup) { pthread_mutex_destroy(&keycache->cache_lock); @@ -672,6 +794,7 @@ void end_key_cache(KEY_CACHE *keycache, my_bool cleanup) #ifdef THREAD + /* Link a thread into double-linked queue of waiting threads. @@ -693,6 +816,8 @@ static void link_into_queue(KEYCACHE_WQUEUE *wqueue, struct st_my_thread_var *thread) { struct st_my_thread_var *last; + + DBUG_ASSERT(!thread->next && !thread->prev); if (! (last= wqueue->last_thread)) { /* Queue is empty */ @@ -728,6 +853,7 @@ static void unlink_from_queue(KEYCACHE_WQUEUE *wqueue, struct st_my_thread_var *thread) { KEYCACHE_DBUG_PRINT("unlink_from_queue", ("thread %ld", thread->id)); + DBUG_ASSERT(thread->next && thread->prev); if (thread->next == thread) /* The queue contains only one member */ wqueue->last_thread= NULL; @@ -740,6 +866,13 @@ static void unlink_from_queue(KEYCACHE_WQUEUE *wqueue, thread->prev); } thread->next= NULL; +#if !defined(DBUG_OFF) + /* + This makes it easier to see it's not in a chain during debugging. + And some DBUG_ASSERT() rely on it. + */ + thread->prev= NULL; +#endif } @@ -747,9 +880,9 @@ static void unlink_from_queue(KEYCACHE_WQUEUE *wqueue, Add a thread to single-linked queue of waiting threads SYNOPSIS - add_to_queue() - wqueue pointer to the queue structure - thread pointer to the thread to be added to the queue + wait_on_queue() + wqueue Pointer to the queue structure. + mutex Cache_lock to acquire after awake. RETURN VALUE none @@ -758,12 +891,23 @@ static void unlink_from_queue(KEYCACHE_WQUEUE *wqueue, Queue is represented by a circular list of the thread structures The list is single-linked of the type (*next), accessed by a pointer to the last element. + + The function protects against stray signals by verifying that the + current thread is unlinked from the queue when awaking. However, + since several threads can wait for the same event, it might be + necessary for the caller of the function to check again if the + condition for awake is indeed matched. */ -static inline void add_to_queue(KEYCACHE_WQUEUE *wqueue, - struct st_my_thread_var *thread) +static void wait_on_queue(KEYCACHE_WQUEUE *wqueue, + pthread_mutex_t *mutex) { struct st_my_thread_var *last; + struct st_my_thread_var *thread= my_thread_var; + + /* Add to queue. */ + DBUG_ASSERT(!thread->next); + DBUG_ASSERT(!thread->prev); /* Not required, but must be true anyway. */ if (! (last= wqueue->last_thread)) thread->next= thread; else @@ -772,6 +916,17 @@ static inline void add_to_queue(KEYCACHE_WQUEUE *wqueue, last->next= thread; } wqueue->last_thread= thread; + + /* + Wait until thread is removed from queue by the signalling thread. + The loop protects against stray signals. + */ + do + { + KEYCACHE_DBUG_PRINT("wait", ("suspend thread %ld", thread->id)); + keycache_pthread_cond_wait(&thread->suspend, mutex); + } + while (thread->next); } @@ -779,36 +934,47 @@ static inline void add_to_queue(KEYCACHE_WQUEUE *wqueue, Remove all threads from queue signaling them to proceed SYNOPSIS - realease_queue() - wqueue pointer to the queue structure - thread pointer to the thread to be added to the queue + release_whole_queue() + wqueue pointer to the queue structure RETURN VALUE none NOTES. - See notes for add_to_queue + See notes for wait_on_queue(). When removed from the queue each thread is signaled via condition variable thread->suspend. */ -static void release_queue(KEYCACHE_WQUEUE *wqueue) +static void release_whole_queue(KEYCACHE_WQUEUE *wqueue) { - struct st_my_thread_var *last= wqueue->last_thread; - struct st_my_thread_var *next= last->next; + struct st_my_thread_var *last; + struct st_my_thread_var *next; struct st_my_thread_var *thread; + + /* Queue may be empty. */ + if (!(last= wqueue->last_thread)) + return; + + next= last->next; do { thread=next; - KEYCACHE_DBUG_PRINT("release_queue: signal", ("thread %ld", thread->id)); + KEYCACHE_DBUG_PRINT("release_whole_queue: signal", + ("thread %ld", thread->id)); + /* Signal the thread. */ keycache_pthread_cond_signal(&thread->suspend); + /* Take thread from queue. */ next=thread->next; thread->next= NULL; } while (thread != last); + + /* Now queue is definitely empty. */ wqueue->last_thread= NULL; } -#endif + +#endif /* THREAD */ /* @@ -817,9 +983,19 @@ static void release_queue(KEYCACHE_WQUEUE *wqueue) static inline void unlink_changed(BLOCK_LINK *block) { + DBUG_ASSERT(block->prev_changed && *block->prev_changed == block); if (block->next_changed) block->next_changed->prev_changed= block->prev_changed; *block->prev_changed= block->next_changed; + +#if !defined(DBUG_OFF) + /* + This makes it easier to see it's not in a chain during debugging. + And some DBUG_ASSERT() rely on it. + */ + block->next_changed= NULL; + block->prev_changed= NULL; +#endif } @@ -829,6 +1005,8 @@ static inline void unlink_changed(BLOCK_LINK *block) static inline void link_changed(BLOCK_LINK *block, BLOCK_LINK **phead) { + DBUG_ASSERT(!block->next_changed); + DBUG_ASSERT(!block->prev_changed); block->prev_changed= phead; if ((block->next_changed= *phead)) (*phead)->prev_changed= &block->next_changed; @@ -837,14 +1015,37 @@ static inline void link_changed(BLOCK_LINK *block, BLOCK_LINK **phead) /* - Unlink a block from the chain of dirty/clean blocks, if it's asked for, - and link it to the chain of clean blocks for the specified file + Link a block in a chain of clean blocks of a file. + + SYNOPSIS + link_to_file_list() + keycache Key cache handle + block Block to relink + file File to be linked to + unlink If to unlink first + + DESCRIPTION + Unlink a block from whichever chain it is linked in, if it's + asked for, and link it to the chain of clean blocks of the + specified file. + + NOTE + Please do never set/clear BLOCK_CHANGED outside of + link_to_file_list() or link_to_changed_list(). + You would risk to damage correct counting of changed blocks + and to find blocks in the wrong hash. + + RETURN + void */ static void link_to_file_list(KEY_CACHE *keycache, BLOCK_LINK *block, int file, my_bool unlink_block) { + DBUG_ASSERT(block->status & BLOCK_IN_USE); + DBUG_ASSERT(block->hash_link && block->hash_link->block == block); + DBUG_ASSERT(block->hash_link->file == file); if (unlink_block) unlink_changed(block); link_changed(block, &keycache->file_blocks[FILE_HASH(file)]); @@ -858,13 +1059,34 @@ static void link_to_file_list(KEY_CACHE *keycache, /* - Unlink a block from the chain of clean blocks for the specified - file and link it to the chain of dirty blocks for this file + Re-link a block from the clean chain to the dirty chain of a file. + + SYNOPSIS + link_to_changed_list() + keycache key cache handle + block block to relink + + DESCRIPTION + Unlink a block from the chain of clean blocks of a file + and link it to the chain of dirty blocks of the same file. + + NOTE + Please do never set/clear BLOCK_CHANGED outside of + link_to_file_list() or link_to_changed_list(). + You would risk to damage correct counting of changed blocks + and to find blocks in the wrong hash. + + RETURN + void */ -static inline void link_to_changed_list(KEY_CACHE *keycache, - BLOCK_LINK *block) +static void link_to_changed_list(KEY_CACHE *keycache, + BLOCK_LINK *block) { + DBUG_ASSERT(block->status & BLOCK_IN_USE); + DBUG_ASSERT(!(block->status & BLOCK_CHANGED)); + DBUG_ASSERT(block->hash_link && block->hash_link->block == block); + unlink_changed(block); link_changed(block, &keycache->changed_blocks[FILE_HASH(block->hash_link->file)]); @@ -889,13 +1111,13 @@ static inline void link_to_changed_list(KEY_CACHE *keycache, none NOTES. - The LRU chain is represented by a curcular list of block structures. + The LRU ring is represented by a circular list of block structures. The list is double-linked of the type (**prev,*next) type. - The LRU chain is divided into two parts - hot and warm. + The LRU ring is divided into two parts - hot and warm. There are two pointers to access the last blocks of these two parts. The beginning of the warm part follows right after the end of the hot part. - Only blocks of the warm part can be used for replacement. + Only blocks of the warm part can be used for eviction. The first block from the beginning of this subchain is always taken for eviction (keycache->last_used->next) @@ -908,6 +1130,9 @@ static inline void link_to_changed_list(KEY_CACHE *keycache, +----| beg |---->...----| end |----+ +------+ +------+ins first for eviction + + It is also possible that the block is selected for eviction and thus + not linked in the LRU ring. */ static void link_block(KEY_CACHE *keycache, BLOCK_LINK *block, my_bool hot, @@ -916,7 +1141,12 @@ static void link_block(KEY_CACHE *keycache, BLOCK_LINK *block, my_bool hot, BLOCK_LINK *ins; BLOCK_LINK **pins; - KEYCACHE_DBUG_ASSERT(! (block->hash_link && block->hash_link->requests)); + DBUG_ASSERT((block->status & ~BLOCK_CHANGED) == (BLOCK_READ | BLOCK_IN_USE)); + DBUG_ASSERT(block->hash_link); /*backptr to block NULL from free_block()*/ + DBUG_ASSERT(!block->requests); + DBUG_ASSERT(block->prev_changed && *block->prev_changed == block); + DBUG_ASSERT(!block->next_used); + DBUG_ASSERT(!block->prev_used); #ifdef THREAD if (!hot && keycache->waiting_for_block.last_thread) { @@ -945,6 +1175,29 @@ static void link_block(KEY_CACHE *keycache, BLOCK_LINK *block, my_bool hot, } while (thread != last_thread); hash_link->block= block; + /* + NOTE: We assigned the block to the hash_link and signalled the + requesting thread(s). But it is possible that other threads runs + first. These threads see the hash_link assigned to a block which + is assigned to another hash_link and not marked BLOCK_IN_SWITCH. + This can be a problem for functions that do not select the block + via its hash_link: flush and free. They do only see a block which + is in a "normal" state and don't know that it will be evicted soon. + + We cannot set BLOCK_IN_SWITCH here because only one of the + requesting threads must handle the eviction. All others must wait + for it to complete. If we set the flag here, the threads would not + know who is in charge of the eviction. Without the flag, the first + thread takes the stick and sets the flag. + + But we need to note in the block that is has been selected for + eviction. It must not be freed. The evicting thread will not + expect the block in the free list. Before freeing we could also + check if block->requests > 1. But I think including another flag + in the check of block->status is slightly more efficient and + probably easier to read. + */ + block->status|= BLOCK_IN_EVICTION; KEYCACHE_THREAD_TRACE("link_block: after signaling"); #if defined(KEYCACHE_DEBUG) KEYCACHE_DBUG_PRINT("link_block", @@ -971,7 +1224,7 @@ static void link_block(KEY_CACHE *keycache, BLOCK_LINK *block, my_bool hot, } else { - /* The LRU chain is empty */ + /* The LRU ring is empty. Let the block point to itself. */ keycache->used_last= keycache->used_ins= block->next_used= block; block->prev_used= &block->next_used; } @@ -1005,6 +1258,13 @@ static void link_block(KEY_CACHE *keycache, BLOCK_LINK *block, my_bool hot, static void unlink_block(KEY_CACHE *keycache, BLOCK_LINK *block) { + DBUG_ASSERT((block->status & ~BLOCK_CHANGED) == (BLOCK_READ | BLOCK_IN_USE)); + DBUG_ASSERT(block->hash_link); /*backptr to block NULL from free_block()*/ + DBUG_ASSERT(!block->requests); + DBUG_ASSERT(block->prev_changed && *block->prev_changed == block); + DBUG_ASSERT(block->next_used && block->prev_used && + (block->next_used->prev_used == &block->next_used) && + (*block->prev_used == block)); if (block->next_used == block) /* The list contains only one member */ keycache->used_last= keycache->used_ins= NULL; @@ -1018,26 +1278,48 @@ static void unlink_block(KEY_CACHE *keycache, BLOCK_LINK *block) keycache->used_ins=STRUCT_PTR(BLOCK_LINK, next_used, block->prev_used); } block->next_used= NULL; +#if !defined(DBUG_OFF) + /* + This makes it easier to see it's not in a chain during debugging. + And some DBUG_ASSERT() rely on it. + */ + block->prev_used= NULL; +#endif KEYCACHE_THREAD_TRACE("unlink_block"); #if defined(KEYCACHE_DEBUG) + KEYCACHE_DBUG_ASSERT(keycache->blocks_available != 0); keycache->blocks_available--; KEYCACHE_DBUG_PRINT("unlink_block", ("unlinked block %u status=%x #requests=%u #available=%u", BLOCK_NUMBER(block), block->status, block->requests, keycache->blocks_available)); - KEYCACHE_DBUG_ASSERT(keycache->blocks_available >= 0); #endif } /* - Register requests for a block + Register requests for a block. + + SYNOPSIS + reg_requests() + keycache Pointer to a key cache data structure. + block Pointer to the block to register a request on. + count Number of requests. Always 1. + + NOTE + The first request unlinks the block from the LRU ring. This means + that it is protected against eveiction. + + RETURN + void */ static void reg_requests(KEY_CACHE *keycache, BLOCK_LINK *block, int count) { - if (! block->requests) - /* First request for the block unlinks it */ + DBUG_ASSERT(block->status & BLOCK_IN_USE); + DBUG_ASSERT(block->hash_link); + + if (!block->requests) unlink_block(keycache, block); block->requests+=count; } @@ -1057,7 +1339,7 @@ static void reg_requests(KEY_CACHE *keycache, BLOCK_LINK *block, int count) none NOTES. - Every linking to the LRU chain decrements by one a special block + Every linking to the LRU ring decrements by one a special block counter (if it's positive). If the at_end parameter is TRUE the block is added either at the end of warm sub-chain or at the end of hot sub-chain. It is added to the hot subchain if its counter is zero and number of @@ -1070,12 +1352,25 @@ static void reg_requests(KEY_CACHE *keycache, BLOCK_LINK *block, int count) At the same time the block at the very beginning of the hot subchain might be moved to the beginning of the warm subchain if it stays untouched for a too long time (this time is determined by parameter age_threshold). + + It is also possible that the block is selected for eviction and thus + not linked in the LRU ring. */ static void unreg_request(KEY_CACHE *keycache, BLOCK_LINK *block, int at_end) { - if (! --block->requests) + DBUG_ASSERT(block->status & (BLOCK_READ | BLOCK_IN_USE)); + DBUG_ASSERT(block->hash_link); /*backptr to block NULL from free_block()*/ + DBUG_ASSERT(block->requests); + DBUG_ASSERT(block->prev_changed && *block->prev_changed == block); + DBUG_ASSERT(!block->next_used); + DBUG_ASSERT(!block->prev_used); + /* + Unregister the request, but do not link erroneous blocks into the + LRU ring. + */ + if (!--block->requests && !(block->status & BLOCK_ERROR)) { my_bool hot; if (block->hits_left) @@ -1093,9 +1388,22 @@ static void unreg_request(KEY_CACHE *keycache, link_block(keycache, block, hot, (my_bool)at_end); block->last_hit_time= keycache->keycache_time; keycache->keycache_time++; + /* + At this place, the block might be in the LRU ring or not. If an + evicter was waiting for a block, it was selected for eviction and + not linked in the LRU ring. + */ + /* + Check if we should link a hot block to the warm block sub-chain. + It is possible that we select the same block as above. But it can + also be another block. In any case a block from the LRU ring is + selected. In other words it works even if the above block was + selected for eviction and not linked in the LRU ring. Since this + happens only if the LRU ring is empty, the block selected below + would be NULL and the rest of the function skipped. + */ block= keycache->used_ins; - /* Check if we should link a hot block to the warm block */ if (block && keycache->keycache_time - block->last_hit_time > keycache->age_threshold) { @@ -1116,10 +1424,20 @@ static void unreg_request(KEY_CACHE *keycache, Remove a reader of the page in block */ -static inline void remove_reader(BLOCK_LINK *block) +static void remove_reader(BLOCK_LINK *block) { + DBUG_ASSERT(block->status & (BLOCK_READ | BLOCK_IN_USE)); + DBUG_ASSERT(block->hash_link && block->hash_link->block == block); + DBUG_ASSERT(block->prev_changed && *block->prev_changed == block); + DBUG_ASSERT(!block->next_used); + DBUG_ASSERT(!block->prev_used); + DBUG_ASSERT(block->hash_link->requests); +#ifdef THREAD if (! --block->hash_link->requests && block->condvar) keycache_pthread_cond_signal(block->condvar); +#else + --block->hash_link->requests; +#endif } @@ -1128,15 +1446,27 @@ static inline void remove_reader(BLOCK_LINK *block) signals on its termination */ -static inline void wait_for_readers(KEY_CACHE *keycache, BLOCK_LINK *block) +static void wait_for_readers(KEY_CACHE *keycache, + BLOCK_LINK *block) { #ifdef THREAD struct st_my_thread_var *thread= my_thread_var; + DBUG_ASSERT(block->status & (BLOCK_READ | BLOCK_IN_USE)); + DBUG_ASSERT(!(block->status & (BLOCK_IN_FLUSH | BLOCK_CHANGED))); + DBUG_ASSERT(block->hash_link); + DBUG_ASSERT(block->hash_link->block == block); + /* Linked in file_blocks or changed_blocks hash. */ + DBUG_ASSERT(block->prev_changed && *block->prev_changed == block); + /* Not linked in LRU ring. */ + DBUG_ASSERT(!block->next_used); + DBUG_ASSERT(!block->prev_used); while (block->hash_link->requests) { KEYCACHE_DBUG_PRINT("wait_for_readers: wait", ("suspend thread %ld block %u", thread->id, BLOCK_NUMBER(block))); + /* There must be no other waiter. We have no queue here. */ + DBUG_ASSERT(!block->condvar); block->condvar= &thread->suspend; keycache_pthread_cond_wait(&thread->suspend, &keycache->cache_lock); block->condvar= NULL; @@ -1225,7 +1555,6 @@ static HASH_LINK *get_hash_link(KEY_CACHE *keycache, int file, my_off_t filepos) { reg1 HASH_LINK *hash_link, **start; - KEYCACHE_PAGE page; #if defined(KEYCACHE_DEBUG) int cnt; #endif @@ -1280,6 +1609,7 @@ restart: #ifdef THREAD /* Wait for a free hash link */ struct st_my_thread_var *thread= my_thread_var; + KEYCACHE_PAGE page; KEYCACHE_DBUG_PRINT("get_hash_link", ("waiting")); page.file= file; page.filepos= filepos; @@ -1365,77 +1695,308 @@ static BLOCK_LINK *find_key_block(KEY_CACHE *keycache, #endif restart: - /* Find the hash link for the requested page (file, filepos) */ + /* + If the flush phase of a resize operation fails, the cache is left + unusable. This will be detected only after "goto restart". + */ + if (!keycache->can_be_used) + DBUG_RETURN(0); + + /* + Find the hash_link for the requested file block (file, filepos). We + do always get a hash_link here. It has registered our request so + that no other thread can use it for another file block until we + release the request (which is done by remove_reader() usually). The + hash_link can have a block assigned to it or not. If there is a + block, it may be assigned to this hash_link or not. In cases where a + block is evicted from the cache, it is taken from the LRU ring and + referenced by the new hash_link. But the block can still be assigned + to its old hash_link for some time if it needs to be flushed first, + or if there are other threads still reading it. + + Summary: + hash_link is always returned. + hash_link->block can be: + - NULL or + - not assigned to this hash_link or + - assigned to this hash_link. If assigned, the block can have + - invalid data (when freshly assigned) or + - valid data. Valid data can be + - changed over the file contents (dirty) or + - not changed (clean). + */ hash_link= get_hash_link(keycache, file, filepos); + DBUG_ASSERT((hash_link->file == file) && (hash_link->diskpos == filepos)); page_status= -1; if ((block= hash_link->block) && block->hash_link == hash_link && (block->status & BLOCK_READ)) - page_status= PAGE_READ; - - if (wrmode && keycache->resize_in_flush) { - /* This is a write request during the flush phase of a resize operation */ + /* Assigned block with valid (changed or unchanged) contents. */ + page_status= PAGE_READ; + } + /* + else (page_status == -1) + - block == NULL or + - block not assigned to this hash_link or + - block assigned but not yet read from file (invalid data). + */ - if (page_status != PAGE_READ) + if (keycache->in_resize) + { + /* This is a request during a resize operation */ + + if (!block) { - /* We don't need the page in the cache: we are going to write on disk */ - hash_link->requests--; - unlink_hash(keycache, hash_link); - DBUG_RETURN(0); - } - if (!(block->status & BLOCK_IN_FLUSH)) - { - hash_link->requests--; + struct st_my_thread_var *thread; + /* - Remove block to invalidate the page in the block buffer - as we are going to write directly on disk. - Although we have an exlusive lock for the updated key part - the control can be yieded by the current thread as we might - have unfinished readers of other key parts in the block - buffer. Still we are guaranteed not to have any readers - of the key part we are writing into until the block is - removed from the cache as we set the BLOCL_REASSIGNED - flag (see the code below that handles reading requests). + The file block is not in the cache. We don't need it in the + cache: we are going to read or write directly to file. Cancel + the request. We can simply decrement hash_link->requests because + we did not release cache_lock since increasing it. So no other + thread can wait for our request to become released. */ - free_block(keycache, block); - DBUG_RETURN(0); - } - /* Wait intil the page is flushed on disk */ - hash_link->requests--; - { -#ifdef THREAD - struct st_my_thread_var *thread= my_thread_var; - add_to_queue(&block->wqueue[COND_FOR_SAVED], thread); + if (hash_link->requests == 1) + { + /* + We are the only one to request this hash_link (this file/pos). + Free the hash_link. + */ + hash_link->requests--; + unlink_hash(keycache, hash_link); + DBUG_RETURN(0); + } + + /* + More requests on the hash_link. Someone tries to evict a block + for this hash_link (could have started before resizing started). + This means that the LRU ring is empty. Otherwise a block could + be assigned immediately. Behave like a thread that wants to + evict a block for this file/pos. Add to the queue of threads + waiting for a block. Wait until there is one assigned. + + Refresh the request on the hash-link so that it cannot be reused + for another file/pos. + */ + thread= my_thread_var; + thread->opt_info= (void *) hash_link; + link_into_queue(&keycache->waiting_for_block, thread); do { KEYCACHE_DBUG_PRINT("find_key_block: wait", ("suspend thread %ld", thread->id)); keycache_pthread_cond_wait(&thread->suspend, &keycache->cache_lock); - } - while(thread->next); -#else - KEYCACHE_DBUG_ASSERT(0); + } while (thread->next); + thread->opt_info= NULL; /* - Given the use of "resize_in_flush", it seems impossible - that this whole branch is ever entered in single-threaded case - because "(wrmode && keycache->resize_in_flush)" cannot be true. - TODO: Check this, and then put the whole branch into the - "#ifdef THREAD" guard. + A block should now be assigned to the hash_link. But it may + still need to be evicted. Anyway, we should re-check the + situation. page_status must be set correctly. */ -#endif + hash_link->requests--; + goto restart; + } /* end of if (!block) */ + + /* + There is a block for this file/pos in the cache. Register a + request on it. This unlinks it from the LRU ring (if it is there) + and hence protects it against eviction (if not already in + eviction). We need this for returning the block to the caller, for + calling remove_reader() (for debugging purposes), and for calling + free_block(). The only case where we don't need the request is if + the block is in eviction. In that case we have to unregister the + request later. + */ + reg_requests(keycache, block, 1); + + if (page_status != PAGE_READ) + { + /* + - block not assigned to this hash_link or + - block assigned but not yet read from file (invalid data). + + This must be a block in eviction. It will be read soon. We need + to wait here until this happened. Otherwise the caller could + access a wrong block or a block which is in read. While waiting + we cannot lose hash_link nor block. We have registered a request + on the hash_link. Everything can happen to the block but changes + in the hash_link -> block relationship. In other words: + everything can happen to the block but free or another completed + eviction. + + Note that we bahave like a secondary requestor here. We just + cannot return with PAGE_WAIT_TO_BE_READ. This would work for + read requests and writes on dirty blocks that are not in flush + only. Waiting here on COND_FOR_REQUESTED works in all + situations. + */ + DBUG_ASSERT(((block->hash_link != hash_link) && + (block->status & (BLOCK_IN_EVICTION | BLOCK_IN_SWITCH))) || + ((block->hash_link == hash_link) && + !(block->status & BLOCK_READ))); + wait_on_queue(&block->wqueue[COND_FOR_REQUESTED], &keycache->cache_lock); + /* + Here we can trust that the block has been assigned to this + hash_link (block->hash_link == hash_link) and read into the + buffer (BLOCK_READ). The worst things possible here are that the + block is in free (BLOCK_REASSIGNED). But the block is still + assigned to the hash_link. The freeing thread waits until we + release our request on the hash_link. The block must not be + again in eviction because we registered an request on it before + starting to wait. + */ + DBUG_ASSERT(block->hash_link == hash_link); + DBUG_ASSERT(block->status & (BLOCK_READ | BLOCK_IN_USE)); + DBUG_ASSERT(!(block->status & (BLOCK_IN_EVICTION | BLOCK_IN_SWITCH))); } - /* Invalidate page in the block if it has not been done yet */ - if (block->status) + /* + The block is in the cache. Assigned to the hash_link. Valid data. + Note that in case of page_st == PAGE_READ, the block can be marked + for eviction. In any case it can be marked for freeing. + */ + + if (!wrmode) + { + /* A reader can just read the block. */ + *page_st= PAGE_READ; + DBUG_ASSERT((hash_link->file == file) && + (hash_link->diskpos == filepos) && + (block->hash_link == hash_link)); + DBUG_RETURN(block); + } + + /* + This is a writer. No two writers for the same block can exist. + This must be assured by locks outside of the key cache. + */ + DBUG_ASSERT(!(block->status & BLOCK_FOR_UPDATE) || fail_block(block)); + + while (block->status & BLOCK_IN_FLUSH) + { + /* + Wait until the block is flushed to file. Do not release the + request on the hash_link yet to prevent that the block is freed + or reassigned while we wait. While we wait, several things can + happen to the block, including another flush. But the block + cannot be reassigned to another hash_link until we release our + request on it. But it can be marked BLOCK_REASSIGNED from free + or eviction, while they wait for us to release the hash_link. + */ + wait_on_queue(&block->wqueue[COND_FOR_SAVED], &keycache->cache_lock); + /* + If the flush phase failed, the resize could have finished while + we waited here. + */ + if (!keycache->in_resize) + { + remove_reader(block); + unreg_request(keycache, block, 1); + goto restart; + } + DBUG_ASSERT(block->status & (BLOCK_READ | BLOCK_IN_USE)); + DBUG_ASSERT(!(block->status & BLOCK_FOR_UPDATE) || fail_block(block)); + DBUG_ASSERT(block->hash_link == hash_link); + } + + if (block->status & BLOCK_CHANGED) + { + /* + We want to write a block with changed contents. If the cache + block size is bigger than the callers block size (e.g. MyISAM), + the caller may replace part of the block only. Changes of the + other part of the block must be preserved. Since the block has + not yet been selected for flush, we can still add our changes. + */ + *page_st= PAGE_READ; + DBUG_ASSERT((hash_link->file == file) && + (hash_link->diskpos == filepos) && + (block->hash_link == hash_link)); + DBUG_RETURN(block); + } + + /* + This is a write request for a clean block. We do not want to have + new dirty blocks in the cache while resizing. We will free the + block and write directly to file. If the block is in eviction or + in free, we just let it go. + + Unregister from the hash_link. This must be done before freeing + the block. And it must be done if not freeing the block. Because + we could have waited above, we need to call remove_reader(). Other + threads could wait for us to release our request on the hash_link. + */ + remove_reader(block); + + /* If the block is not in eviction and not in free, we can free it. */ + if (!(block->status & (BLOCK_IN_EVICTION | BLOCK_IN_SWITCH | + BLOCK_REASSIGNED))) + { + /* + Free block as we are going to write directly to file. + Although we have an exlusive lock for the updated key part, + the control can be yielded by the current thread as we might + have unfinished readers of other key parts in the block + buffer. Still we are guaranteed not to have any readers + of the key part we are writing into until the block is + removed from the cache as we set the BLOCK_REASSIGNED + flag (see the code below that handles reading requests). + */ free_block(keycache, block); + } + else + { + /* + The block will be evicted/freed soon. Don't touch it in any way. + Unregister the request that we registered above. + */ + unreg_request(keycache, block, 1); + + /* + The block is still assigned to the hash_link (the file/pos that + we are going to write to). Wait until the eviction/free is + complete. Otherwise the direct write could complete before all + readers are done with the block. So they could read outdated + data. + + Since we released our request on the hash_link, it can be reused + for another file/pos. Hence we cannot just check for + block->hash_link == hash_link. As long as the resize is + proceeding the block cannot be reassigned to the same file/pos + again. So we can terminate the loop when the block is no longer + assigned to this file/pos. + */ + do + { + wait_on_queue(&block->wqueue[COND_FOR_SAVED], + &keycache->cache_lock); + /* + If the flush phase failed, the resize could have finished + while we waited here. + */ + if (!keycache->in_resize) + goto restart; + } while (block->hash_link && + (block->hash_link->file == file) && + (block->hash_link->diskpos == filepos)); + } DBUG_RETURN(0); } if (page_status == PAGE_READ && - (block->status & (BLOCK_IN_SWITCH | BLOCK_REASSIGNED))) + (block->status & (BLOCK_IN_EVICTION | BLOCK_IN_SWITCH | + BLOCK_REASSIGNED))) { - /* This is a request for a page to be removed from cache */ + /* + This is a request for a block to be removed from cache. The block + is assigned to this hash_link and contains valid data, but is + marked for eviction or to be freed. Possible reasons why it has + not yet been evicted/freed can be a flush before reassignment + (BLOCK_IN_SWITCH), readers of the block have not finished yet + (BLOCK_REASSIGNED), or the evicting thread did not yet awake after + the block has been selected for it (BLOCK_IN_EVICTION). + */ KEYCACHE_DBUG_PRINT("find_key_block", ("request for old page in block %u " @@ -1446,43 +2007,58 @@ restart: all others are to be suspended, then resubmitted */ if (!wrmode && !(block->status & BLOCK_REASSIGNED)) + { + /* + This is a read request and the block not yet reassigned. We can + register our request and proceed. This unlinks the block from + the LRU ring and protects it against eviction. + */ reg_requests(keycache, block, 1); + } else { + /* + Either this is a write request for a block that is in eviction + or in free. We must not use it any more. Instead we must evict + another block. But we cannot do this before the eviction/free is + done. Otherwise we would find the same hash_link + block again + and again. + + Or this is a read request for a block in eviction/free that does + not require a flush, but waits for readers to finish with the + block. We do not read this block to let the eviction/free happen + as soon as possible. Again we must wait so that we don't find + the same hash_link + block again and again. + */ + DBUG_ASSERT(hash_link->requests); hash_link->requests--; KEYCACHE_DBUG_PRINT("find_key_block", ("request waiting for old page to be saved")); - { -#ifdef THREAD - struct st_my_thread_var *thread= my_thread_var; - /* Put the request into the queue of those waiting for the old page */ - add_to_queue(&block->wqueue[COND_FOR_SAVED], thread); - /* Wait until the request can be resubmitted */ - do - { - KEYCACHE_DBUG_PRINT("find_key_block: wait", - ("suspend thread %ld", thread->id)); - keycache_pthread_cond_wait(&thread->suspend, - &keycache->cache_lock); - } - while(thread->next); -#else - KEYCACHE_DBUG_ASSERT(0); - /* No parallel requests in single-threaded case */ -#endif - } + wait_on_queue(&block->wqueue[COND_FOR_SAVED], &keycache->cache_lock); KEYCACHE_DBUG_PRINT("find_key_block", ("request for old page resubmitted")); - /* Resubmit the request */ + /* + The block is no longer assigned to this hash_link. + Get another one. + */ goto restart; } } else { - /* This is a request for a new page or for a page not to be removed */ + /* + This is a request for a new block or for a block not to be removed. + Either + - block == NULL or + - block not assigned to this hash_link or + - block assigned but not yet read from file, + or + - block assigned with valid (changed or unchanged) data and + - it will not be reassigned/freed. + */ if (! block) { - /* No block is assigned for the page yet */ + /* No block is assigned to the hash_link yet. */ if (keycache->blocks_unused) { if (keycache->free_block_list) @@ -1494,25 +2070,36 @@ restart: } else { + size_t block_mem_offset; /* There are some never used blocks, take first of them */ + DBUG_ASSERT(keycache->blocks_used < + (ulong) keycache->disk_blocks); block= &keycache->block_root[keycache->blocks_used]; + block_mem_offset= + ((size_t) keycache->blocks_used) * keycache->key_cache_block_size; block->buffer= ADD_TO_PTR(keycache->block_mem, - ((ulong) keycache->blocks_used* - keycache->key_cache_block_size), + block_mem_offset, byte*); keycache->blocks_used++; + DBUG_ASSERT(!block->next_used); } + DBUG_ASSERT(!block->prev_used); + DBUG_ASSERT(!block->next_changed); + DBUG_ASSERT(!block->prev_changed); + DBUG_ASSERT(!block->hash_link); + DBUG_ASSERT(!block->status); + DBUG_ASSERT(!block->requests); keycache->blocks_unused--; - block->status= 0; + block->status= BLOCK_IN_USE; block->length= 0; block->offset= keycache->key_cache_block_size; block->requests= 1; block->temperature= BLOCK_COLD; block->hits_left= init_hits_left; block->last_hit_time= 0; - link_to_file_list(keycache, block, file, 0); block->hash_link= hash_link; hash_link->block= block; + link_to_file_list(keycache, block, file, 0); page_status= PAGE_TO_BE_READ; KEYCACHE_DBUG_PRINT("find_key_block", ("got free or never used block %u", @@ -1520,17 +2107,26 @@ restart: } else { - /* There are no never used blocks, use a block from the LRU chain */ - - /* - Wait until a new block is added to the LRU chain; - several threads might wait here for the same page, - all of them must get the same block + /* + There are no free blocks and no never used blocks, use a block + from the LRU ring. */ #ifdef THREAD if (! keycache->used_last) { + /* + The LRU ring is empty. Wait until a new block is added to + it. Several threads might wait here for the same hash_link, + all of them must get the same block. While waiting for a + block, after a block is selected for this hash_link, other + threads can run first before this one awakes. During this + time interval other threads find this hash_link pointing to + the block, which is still assigned to another hash_link. In + this case the block is not marked BLOCK_IN_SWITCH yet, but + it is marked BLOCK_IN_EVICTION. + */ + struct st_my_thread_var *thread= my_thread_var; thread->opt_info= (void *) hash_link; link_into_queue(&keycache->waiting_for_block, thread); @@ -1543,24 +2139,50 @@ restart: } while (thread->next); thread->opt_info= NULL; + /* Assert that block has a request registered. */ + DBUG_ASSERT(hash_link->block->requests); + /* Assert that block is not in LRU ring. */ + DBUG_ASSERT(!hash_link->block->next_used); + DBUG_ASSERT(!hash_link->block->prev_used); } #else KEYCACHE_DBUG_ASSERT(keycache->used_last); #endif + /* + If we waited above, hash_link->block has been assigned by + link_block(). Otherwise it is still NULL. In the latter case + we need to grab a block from the LRU ring ourselves. + */ block= hash_link->block; if (! block) { - /* - Take the first block from the LRU chain - unlinking it from the chain - */ + /* Select the last block from the LRU ring. */ block= keycache->used_last->next_used; block->hits_left= init_hits_left; block->last_hit_time= 0; - reg_requests(keycache, block,1); hash_link->block= block; + /* + Register a request on the block. This unlinks it from the + LRU ring and protects it against eviction. + */ + DBUG_ASSERT(!block->requests); + reg_requests(keycache, block,1); + /* + We do not need to set block->status|= BLOCK_IN_EVICTION here + because we will set block->status|= BLOCK_IN_SWITCH + immediately without releasing the lock in between. This does + also support debugging. When looking at the block, one can + see if the block has been selected by link_block() after the + LRU ring was empty, or if it was grabbed directly from the + LRU ring in this branch. + */ } + /* + If we had to wait above, there is a small chance that another + thread grabbed this block for the same file block already. But + in most cases the first condition is true. + */ if (block->hash_link != hash_link && ! (block->status & BLOCK_IN_SWITCH) ) { @@ -1575,44 +2197,117 @@ restart: /* The block contains a dirty page - push it out of the cache */ KEYCACHE_DBUG_PRINT("find_key_block", ("block is dirty")); + if (block->status & BLOCK_IN_FLUSH) + { + /* + The block is marked for flush. If we do not wait here, + it could happen that we write the block, reassign it to + another file block, then, before the new owner can read + the new file block, the flusher writes the cache block + (which still has the old contents) to the new file block! + */ + wait_on_queue(&block->wqueue[COND_FOR_SAVED], + &keycache->cache_lock); + /* + The block is marked BLOCK_IN_SWITCH. It should be left + alone except for reading. No free, no write. + */ + DBUG_ASSERT(block->status & (BLOCK_READ | BLOCK_IN_USE)); + DBUG_ASSERT(!(block->status & (BLOCK_REASSIGNED | + BLOCK_CHANGED | + BLOCK_FOR_UPDATE))); + } + else + { + block->status|= BLOCK_IN_FLUSH | BLOCK_IN_FLUSHWRITE; + /* + BLOCK_IN_EVICTION may be true or not. Other flags must + have a fixed value. + */ + DBUG_ASSERT((block->status & ~BLOCK_IN_EVICTION) == + (BLOCK_READ | BLOCK_IN_SWITCH | + BLOCK_IN_FLUSH | BLOCK_IN_FLUSHWRITE | + BLOCK_CHANGED | BLOCK_IN_USE)); + DBUG_ASSERT(block->hash_link); - keycache_pthread_mutex_unlock(&keycache->cache_lock); - /* - The call is thread safe because only the current - thread might change the block->hash_link value - */ - error= my_pwrite(block->hash_link->file, - block->buffer+block->offset, - block->length - block->offset, - block->hash_link->diskpos+ block->offset, - MYF(MY_NABP | MY_WAIT_IF_FULL)); - keycache_pthread_mutex_lock(&keycache->cache_lock); - keycache->global_cache_write++; + keycache_pthread_mutex_unlock(&keycache->cache_lock); + /* + The call is thread safe because only the current + thread might change the block->hash_link value + */ + error= my_pwrite(block->hash_link->file, + block->buffer + block->offset, + block->length - block->offset, + block->hash_link->diskpos + block->offset, + MYF(MY_NABP | MY_WAIT_IF_FULL)); + keycache_pthread_mutex_lock(&keycache->cache_lock); + + /* Block status must not have changed. */ + DBUG_ASSERT((block->status & ~BLOCK_IN_EVICTION) == + (BLOCK_READ | BLOCK_IN_SWITCH | + BLOCK_IN_FLUSH | BLOCK_IN_FLUSHWRITE | + BLOCK_CHANGED | BLOCK_IN_USE) || fail_block(block)); + keycache->global_cache_write++; + } } block->status|= BLOCK_REASSIGNED; + /* + The block comes from the LRU ring. It must have a hash_link + assigned. + */ + DBUG_ASSERT(block->hash_link); if (block->hash_link) { /* + All pending requests for this page must be resubmitted. + This must be done before waiting for readers. They could + wait for the flush to complete. And we must also do it + after the wait. Flushers might try to free the block while + we wait. They would wait until the reassignment is + complete. Also the block status must reflect the correct + situation: The block is not changed nor in flush any more. + Note that we must not change the BLOCK_CHANGED flag + outside of link_to_file_list() so that it is always in the + correct queue and the *blocks_changed counters are + correct. + */ + block->status&= ~(BLOCK_IN_FLUSH | BLOCK_IN_FLUSHWRITE); + link_to_file_list(keycache, block, block->hash_link->file, 1); + release_whole_queue(&block->wqueue[COND_FOR_SAVED]); + /* + The block is still assigned to its old hash_link. Wait until all pending read requests for this page are executed (we could have avoided this waiting, if we had read a page in the cache in a sweep, without yielding control) */ wait_for_readers(keycache, block); + DBUG_ASSERT(block->hash_link && block->hash_link->block == block && + block->prev_changed); + /* The reader must not have been a writer. */ + DBUG_ASSERT(!(block->status & BLOCK_CHANGED)); - /* Remove the hash link for this page from the hash table */ + /* Wake flushers that might have found the block in between. */ + release_whole_queue(&block->wqueue[COND_FOR_SAVED]); + + /* Remove the hash link for the old file block from the hash. */ unlink_hash(keycache, block->hash_link); - /* All pending requests for this page must be resubmitted */ - if (block->wqueue[COND_FOR_SAVED].last_thread) - release_queue(&block->wqueue[COND_FOR_SAVED]); + + /* + For sanity checks link_to_file_list() asserts that block + and hash_link refer to each other. Hence we need to assign + the hash_link first, but then we would not know if it was + linked before. Hence we would not know if to unlink it. So + unlink it here and call link_to_file_list(..., FALSE). + */ + unlink_changed(block); } - link_to_file_list(keycache, block, file, - (my_bool)(block->hash_link ? 1 : 0)); - block->status= error? BLOCK_ERROR : 0; + block->status= error ? BLOCK_ERROR : BLOCK_IN_USE ; block->length= 0; block->offset= keycache->key_cache_block_size; block->hash_link= hash_link; + link_to_file_list(keycache, block, file, 0); page_status= PAGE_TO_BE_READ; KEYCACHE_DBUG_ASSERT(block->hash_link->block == block); @@ -1620,7 +2315,20 @@ restart: } else { - /* This is for secondary requests for a new page only */ + /* + Either (block->hash_link == hash_link), + or (block->status & BLOCK_IN_SWITCH). + + This is for secondary requests for a new file block only. + Either it is already assigned to the new hash_link meanwhile + (if we had to wait due to empty LRU), or it is already in + eviction by another thread. Since this block has been + grabbed from the LRU ring and attached to this hash_link, + another thread cannot grab the same block from the LRU ring + anymore. If the block is in eviction already, it must become + attached to the same hash_link and as such destined for the + same file block. + */ KEYCACHE_DBUG_PRINT("find_key_block", ("block->hash_link: %p hash_link: %p " "block->status: %u", block->hash_link, @@ -1630,10 +2338,35 @@ restart: PAGE_READ : PAGE_WAIT_TO_BE_READ); } } - keycache->global_cache_read++; } else { + /* + Block is not NULL. This hash_link points to a block. + Either + - block not assigned to this hash_link (yet) or + - block assigned but not yet read from file, + or + - block assigned with valid (changed or unchanged) data and + - it will not be reassigned/freed. + + The first condition means hash_link points to a block in + eviction. This is not necessarily marked by BLOCK_IN_SWITCH yet. + But then it is marked BLOCK_IN_EVICTION. See the NOTE in + link_block(). In both cases it is destined for this hash_link + and its file block address. When this hash_link got its block + address, the block was removed from the LRU ring and cannot be + selected for eviction (for another hash_link) again. + + Register a request on the block. This is another protection + against eviction. + */ + DBUG_ASSERT(((block->hash_link != hash_link) && + (block->status & (BLOCK_IN_EVICTION | BLOCK_IN_SWITCH))) || + ((block->hash_link == hash_link) && + !(block->status & BLOCK_READ)) || + ((block->status & BLOCK_READ) && + !(block->status & (BLOCK_IN_EVICTION | BLOCK_IN_SWITCH)))); reg_requests(keycache, block, 1); KEYCACHE_DBUG_PRINT("find_key_block", ("block->hash_link: %p hash_link: %p " @@ -1646,11 +2379,21 @@ restart: } KEYCACHE_DBUG_ASSERT(page_status != -1); + /* Same assert basically, but be very sure. */ + KEYCACHE_DBUG_ASSERT(block); + /* Assert that block has a request and is not in LRU ring. */ + DBUG_ASSERT(block->requests); + DBUG_ASSERT(!block->next_used); + DBUG_ASSERT(!block->prev_used); + /* Assert that we return the correct block. */ + DBUG_ASSERT((page_status == PAGE_WAIT_TO_BE_READ) || + ((block->hash_link->file == file) && + (block->hash_link->diskpos == filepos))); *page_st=page_status; KEYCACHE_DBUG_PRINT("find_key_block", - ("fd: %d pos: %lu block->status: %u page_status: %u", + ("fd: %d pos: %lu block->status: %u page_status: %d", file, (ulong) filepos, block->status, - (uint) page_status)); + page_status)); #if !defined(DBUG_OFF) && defined(EXTRA_DEBUG) DBUG_EXECUTE("check_keycache2", @@ -1697,13 +2440,22 @@ static void read_block(KEY_CACHE *keycache, if (primary) { /* - This code is executed only by threads - that submitted primary requests + This code is executed only by threads that submitted primary + requests. Until block->status contains BLOCK_READ, all other + request for the block become secondary requests. For a primary + request the block must be properly initialized. */ + DBUG_ASSERT(((block->status & ~BLOCK_FOR_UPDATE) == BLOCK_IN_USE) || + fail_block(block)); + DBUG_ASSERT((block->length == 0) || fail_block(block)); + DBUG_ASSERT((block->offset == keycache->key_cache_block_size) || + fail_block(block)); + DBUG_ASSERT((block->requests > 0) || fail_block(block)); KEYCACHE_DBUG_PRINT("read_block", ("page to be read by primary request")); + keycache->global_cache_read++; /* Page is not in buffer yet, is to be read from disk */ keycache_pthread_mutex_unlock(&keycache->cache_lock); /* @@ -1713,45 +2465,50 @@ static void read_block(KEY_CACHE *keycache, got_length= my_pread(block->hash_link->file, block->buffer, read_length, block->hash_link->diskpos, MYF(0)); keycache_pthread_mutex_lock(&keycache->cache_lock); + /* + The block can now have been marked for free (in case of + FLUSH_RELEASE). Otherwise the state must be unchanged. + */ + DBUG_ASSERT(((block->status & ~(BLOCK_REASSIGNED | + BLOCK_FOR_UPDATE)) == BLOCK_IN_USE) || + fail_block(block)); + DBUG_ASSERT((block->length == 0) || fail_block(block)); + DBUG_ASSERT((block->offset == keycache->key_cache_block_size) || + fail_block(block)); + DBUG_ASSERT((block->requests > 0) || fail_block(block)); + if (got_length < min_length) block->status|= BLOCK_ERROR; else { - block->status= BLOCK_READ; + block->status|= BLOCK_READ; block->length= got_length; + /* + Do not set block->offset here. If this block is marked + BLOCK_CHANGED later, we want to flush only the modified part. So + only a writer may set block->offset down from + keycache->key_cache_block_size. + */ } KEYCACHE_DBUG_PRINT("read_block", ("primary request: new page in cache")); /* Signal that all pending requests for this page now can be processed */ - if (block->wqueue[COND_FOR_REQUESTED].last_thread) - release_queue(&block->wqueue[COND_FOR_REQUESTED]); + release_whole_queue(&block->wqueue[COND_FOR_REQUESTED]); } else { /* - This code is executed only by threads - that submitted secondary requests + This code is executed only by threads that submitted secondary + requests. At this point it could happen that the cache block is + not yet assigned to the hash_link for the requested file block. + But at awake from the wait this should be the case. Unfortunately + we cannot assert this here because we do not know the hash_link + for the requested file block nor the file and position. So we have + to assert this in the caller. */ KEYCACHE_DBUG_PRINT("read_block", ("secondary request waiting for new page to be read")); - { -#ifdef THREAD - struct st_my_thread_var *thread= my_thread_var; - /* Put the request into a queue and wait until it can be processed */ - add_to_queue(&block->wqueue[COND_FOR_REQUESTED], thread); - do - { - KEYCACHE_DBUG_PRINT("read_block: wait", - ("suspend thread %ld", thread->id)); - keycache_pthread_cond_wait(&thread->suspend, - &keycache->cache_lock); - } - while (thread->next); -#else - KEYCACHE_DBUG_ASSERT(0); - /* No parallel requests in single-threaded case */ -#endif - } + wait_on_queue(&block->wqueue[COND_FOR_REQUESTED], &keycache->cache_lock); KEYCACHE_DBUG_PRINT("read_block", ("secondary request: new page in cache")); } @@ -1792,32 +2549,61 @@ byte *key_cache_read(KEY_CACHE *keycache, uint block_length __attribute__((unused)), int return_buffer __attribute__((unused))) { + my_bool locked_and_incremented= FALSE; int error=0; - uint offset= 0; byte *start= buff; DBUG_ENTER("key_cache_read"); DBUG_PRINT("enter", ("fd: %u pos: %lu length: %u", (uint) file, (ulong) filepos, length)); - if (keycache->can_be_used) + if (keycache->key_cache_inited) { /* Key cache is used */ reg1 BLOCK_LINK *block; uint read_length; - uint status; + uint offset; int page_st; + /* + When the key cache is once initialized, we use the cache_lock to + reliably distinguish the cases of normal operation, resizing, and + disabled cache. We always increment and decrement + 'cnt_for_resize_op' so that a resizer can wait for pending I/O. + */ + keycache_pthread_mutex_lock(&keycache->cache_lock); + /* + Cache resizing has two phases: Flushing and re-initializing. In + the flush phase read requests are allowed to bypass the cache for + blocks not in the cache. find_key_block() returns NULL in this + case. + + After the flush phase new I/O requests must wait until the + re-initialization is done. The re-initialization can be done only + if no I/O request is in progress. The reason is that + key_cache_block_size can change. With enabled cache, I/O is done + in chunks of key_cache_block_size. Every chunk tries to use a + cache block first. If the block size changes in the middle, a + block could be missed and old data could be read. + */ + while (keycache->in_resize && !keycache->resize_in_flush) + wait_on_queue(&keycache->resize_queue, &keycache->cache_lock); + /* Register the I/O for the next resize. */ + inc_counter_for_resize_op(keycache); + locked_and_incremented= TRUE; + /* Requested data may not always be aligned to cache blocks. */ offset= (uint) (filepos % keycache->key_cache_block_size); /* Read data in key_cache_block_size increments */ do { - keycache_pthread_mutex_lock(&keycache->cache_lock); + /* Cache could be disabled in a later iteration. */ if (!keycache->can_be_used) { - keycache_pthread_mutex_unlock(&keycache->cache_lock); - goto no_key_cache; + KEYCACHE_DBUG_PRINT("key_cache_read", ("keycache cannot be used")); + goto no_key_cache; } + /* Start reading at the beginning of the cache block. */ filepos-= offset; + /* Do not read beyond the end of the cache block. */ read_length= length; set_if_smaller(read_length, keycache->key_cache_block_size-offset); KEYCACHE_DBUG_ASSERT(read_length > 0); @@ -1827,34 +2613,61 @@ byte *key_cache_read(KEY_CACHE *keycache, return_buffer=0; #endif - inc_counter_for_resize_op(keycache); + /* Request the cache block that matches file/pos. */ keycache->global_cache_r_requests++; block=find_key_block(keycache, file, filepos, level, 0, &page_st); - if (block->status != BLOCK_ERROR && page_st != PAGE_READ) - { - /* The requested page is to be read into the block buffer */ - read_block(keycache, block, - keycache->key_cache_block_size, read_length+offset, - (my_bool)(page_st == PAGE_TO_BE_READ)); - } - else if (! (block->status & BLOCK_ERROR) && - block->length < read_length + offset) + if (!block) { /* - Impossible if nothing goes wrong: - this could only happen if we are using a file with - small key blocks and are trying to read outside the file + This happens only for requests submitted during key cache + resize. The block is not in the cache and shall not go in. + Read directly from file. */ - my_errno= -1; - block->status|= BLOCK_ERROR; + keycache->global_cache_read++; + keycache_pthread_mutex_unlock(&keycache->cache_lock); + error= (my_pread(file, (byte*) buff, read_length, + filepos + offset, MYF(MY_NABP)) != 0); + keycache_pthread_mutex_lock(&keycache->cache_lock); + goto next_block; + } + if (!(block->status & BLOCK_ERROR)) + { + if (page_st != PAGE_READ) + { + /* The requested page is to be read into the block buffer */ + read_block(keycache, block, + keycache->key_cache_block_size, read_length+offset, + (my_bool)(page_st == PAGE_TO_BE_READ)); + /* + A secondary request must now have the block assigned to the + requested file block. It does not hurt to check it for + primary requests too. + */ + DBUG_ASSERT(keycache->can_be_used); + DBUG_ASSERT(block->hash_link->file == file); + DBUG_ASSERT(block->hash_link->diskpos == filepos); + DBUG_ASSERT(block->status & (BLOCK_READ | BLOCK_IN_USE)); + } + else if (block->length < read_length + offset) + { + /* + Impossible if nothing goes wrong: + this could only happen if we are using a file with + small key blocks and are trying to read outside the file + */ + my_errno= -1; + block->status|= BLOCK_ERROR; + } } - if (! ((status= block->status) & BLOCK_ERROR)) + /* block status may have added BLOCK_ERROR in the above 'if'. */ + if (!(block->status & BLOCK_ERROR)) { #ifndef THREAD if (! return_buffer) #endif { + DBUG_ASSERT(block->status & (BLOCK_READ | BLOCK_IN_USE)); #if !defined(SERIALIZED_READ_FROM_CACHE) keycache_pthread_mutex_unlock(&keycache->cache_lock); #endif @@ -1867,44 +2680,68 @@ byte *key_cache_read(KEY_CACHE *keycache, #if !defined(SERIALIZED_READ_FROM_CACHE) keycache_pthread_mutex_lock(&keycache->cache_lock); + DBUG_ASSERT(block->status & (BLOCK_READ | BLOCK_IN_USE)); #endif } } remove_reader(block); - /* - Link the block into the LRU chain - if it's the last submitted request for the block - */ - unreg_request(keycache, block, 1); - dec_counter_for_resize_op(keycache); + /* Error injection for coverage testing. */ + DBUG_EXECUTE_IF("key_cache_read_block_error", + block->status|= BLOCK_ERROR;); - keycache_pthread_mutex_unlock(&keycache->cache_lock); - - if (status & BLOCK_ERROR) - DBUG_RETURN((byte *) 0); + /* Do not link erroneous blocks into the LRU ring, but free them. */ + if (!(block->status & BLOCK_ERROR)) + { + /* + Link the block into the LRU ring if it's the last submitted + request for the block. This enables eviction for the block. + */ + unreg_request(keycache, block, 1); + } + else + { + free_block(keycache, block); + error= 1; + break; + } #ifndef THREAD /* This is only true if we where able to read everything in one block */ if (return_buffer) DBUG_RETURN(block->buffer); #endif + next_block: buff+= read_length; filepos+= read_length+offset; offset= 0; } while ((length-= read_length)); - DBUG_RETURN(start); + goto end; } + KEYCACHE_DBUG_PRINT("key_cache_read", ("keycache not initialized")); -no_key_cache: /* Key cache is not used */ +no_key_cache: + /* Key cache is not used */ - /* We can't use mutex here as the key cache may not be initialized */ keycache->global_cache_r_requests++; keycache->global_cache_read++; - if (my_pread(file, (byte*) buff, length, filepos+offset, MYF(MY_NABP))) + + if (locked_and_incremented) + keycache_pthread_mutex_unlock(&keycache->cache_lock); + if (my_pread(file, (byte*) buff, length, filepos, MYF(MY_NABP))) error= 1; + if (locked_and_incremented) + keycache_pthread_mutex_lock(&keycache->cache_lock); + +end: + if (locked_and_incremented) + { + dec_counter_for_resize_op(keycache); + keycache_pthread_mutex_unlock(&keycache->cache_lock); + } + DBUG_PRINT("exit", ("error: %d", error )); DBUG_RETURN(error ? (byte*) 0 : start); } @@ -1933,90 +2770,220 @@ int key_cache_insert(KEY_CACHE *keycache, File file, my_off_t filepos, int level, byte *buff, uint length) { + int error= 0; DBUG_ENTER("key_cache_insert"); DBUG_PRINT("enter", ("fd: %u pos: %lu length: %u", (uint) file,(ulong) filepos, length)); - if (keycache->can_be_used) + if (keycache->key_cache_inited) { /* Key cache is used */ reg1 BLOCK_LINK *block; uint read_length; - int page_st; - int error; uint offset; + int page_st; + my_bool locked_and_incremented= FALSE; + /* + When the keycache is once initialized, we use the cache_lock to + reliably distinguish the cases of normal operation, resizing, and + disabled cache. We always increment and decrement + 'cnt_for_resize_op' so that a resizer can wait for pending I/O. + */ + keycache_pthread_mutex_lock(&keycache->cache_lock); + /* + We do not load index data into a disabled cache nor into an + ongoing resize. + */ + if (!keycache->can_be_used || keycache->in_resize) + goto no_key_cache; + /* Register the pseudo I/O for the next resize. */ + inc_counter_for_resize_op(keycache); + locked_and_incremented= TRUE; + /* Loaded data may not always be aligned to cache blocks. */ offset= (uint) (filepos % keycache->key_cache_block_size); + /* Load data in key_cache_block_size increments. */ do { - keycache_pthread_mutex_lock(&keycache->cache_lock); - if (!keycache->can_be_used) - { - keycache_pthread_mutex_unlock(&keycache->cache_lock); - DBUG_RETURN(0); - } - /* Read data into key cache from buff in key_cache_block_size incr. */ + /* Cache could be disabled or resizing in a later iteration. */ + if (!keycache->can_be_used || keycache->in_resize) + goto no_key_cache; + /* Start loading at the beginning of the cache block. */ filepos-= offset; + /* Do not load beyond the end of the cache block. */ read_length= length; set_if_smaller(read_length, keycache->key_cache_block_size-offset); KEYCACHE_DBUG_ASSERT(read_length > 0); - inc_counter_for_resize_op(keycache); + /* The block has been read by the caller already. */ + keycache->global_cache_read++; + /* Request the cache block that matches file/pos. */ keycache->global_cache_r_requests++; block= find_key_block(keycache, file, filepos, level, 0, &page_st); - if (block->status != BLOCK_ERROR && page_st != PAGE_READ) + if (!block) { - /* The requested page is to be read into the block buffer */ -#if !defined(SERIALIZED_READ_FROM_CACHE) - keycache_pthread_mutex_unlock(&keycache->cache_lock); /* - Here other threads may step in and register as secondary readers. - They will register in block->wqueue[COND_FOR_REQUESTED]. + This happens only for requests submitted during key cache + resize. The block is not in the cache and shall not go in. + Stop loading index data. */ -#endif + goto no_key_cache; + } + if (!(block->status & BLOCK_ERROR)) + { + if ((page_st == PAGE_WAIT_TO_BE_READ) || + ((page_st == PAGE_TO_BE_READ) && + (offset || (read_length < keycache->key_cache_block_size)))) + { + /* + Either - /* Copy data from buff */ - if (!(read_length & 511)) - bmove512(block->buffer+offset, buff, read_length); - else - memcpy(block->buffer+offset, buff, (size_t) read_length); + this is a secondary request for a block to be read into the + cache. The block is in eviction. It is not yet assigned to + the requested file block (It does not point to the right + hash_link). So we cannot call remove_reader() on the block. + And we cannot access the hash_link directly here. We need to + wait until the assignment is complete. read_block() executes + the correct wait when called with primary == FALSE. + + Or + + this is a primary request for a block to be read into the + cache and the supplied data does not fill the whole block. + + This function is called on behalf of a LOAD INDEX INTO CACHE + statement, which is a read-only task and allows other + readers. It is possible that a parallel running reader tries + to access this block. If it needs more data than has been + supplied here, it would report an error. To be sure that we + have all data in the block that is available in the file, we + read the block ourselves. + + Though reading again what the caller did read already is an + expensive operation, we need to do this for correctness. + */ + read_block(keycache, block, keycache->key_cache_block_size, + read_length + offset, (page_st == PAGE_TO_BE_READ)); + /* + A secondary request must now have the block assigned to the + requested file block. It does not hurt to check it for + primary requests too. + */ + DBUG_ASSERT(keycache->can_be_used); + DBUG_ASSERT(block->hash_link->file == file); + DBUG_ASSERT(block->hash_link->diskpos == filepos); + DBUG_ASSERT(block->status & (BLOCK_READ | BLOCK_IN_USE)); + } + else if (page_st == PAGE_TO_BE_READ) + { + /* + This is a new block in the cache. If we come here, we have + data for the whole block. + */ + DBUG_ASSERT(block->hash_link->requests); + DBUG_ASSERT(block->status & BLOCK_IN_USE); + DBUG_ASSERT((page_st == PAGE_TO_BE_READ) || + (block->status & BLOCK_READ)); #if !defined(SERIALIZED_READ_FROM_CACHE) - keycache_pthread_mutex_lock(&keycache->cache_lock); - /* Here we are alone again. */ + keycache_pthread_mutex_unlock(&keycache->cache_lock); + /* + Here other threads may step in and register as secondary readers. + They will register in block->wqueue[COND_FOR_REQUESTED]. + */ #endif - block->status= BLOCK_READ; - block->length= read_length+offset; - KEYCACHE_DBUG_PRINT("key_cache_insert", - ("primary request: new page in cache")); - /* Signal that all pending requests for this now can be processed. */ - if (block->wqueue[COND_FOR_REQUESTED].last_thread) - release_queue(&block->wqueue[COND_FOR_REQUESTED]); - } + + /* Copy data from buff */ + if (!(read_length & 511)) + bmove512(block->buffer+offset, buff, read_length); + else + memcpy(block->buffer+offset, buff, (size_t) read_length); + +#if !defined(SERIALIZED_READ_FROM_CACHE) + keycache_pthread_mutex_lock(&keycache->cache_lock); + DBUG_ASSERT(block->status & BLOCK_IN_USE); + DBUG_ASSERT((page_st == PAGE_TO_BE_READ) || + (block->status & BLOCK_READ)); +#endif + /* + After the data is in the buffer, we can declare the block + valid. Now other threads do not need to register as + secondary readers any more. They can immediately access the + block. + */ + block->status|= BLOCK_READ; + block->length= read_length+offset; + /* + Do not set block->offset here. If this block is marked + BLOCK_CHANGED later, we want to flush only the modified part. So + only a writer may set block->offset down from + keycache->key_cache_block_size. + */ + KEYCACHE_DBUG_PRINT("key_cache_insert", + ("primary request: new page in cache")); + /* Signal all pending requests. */ + release_whole_queue(&block->wqueue[COND_FOR_REQUESTED]); + } + else + { + /* + page_st == PAGE_READ. The block is in the buffer. All data + must already be present. Blocks are always read with all + data available on file. Assert that the block does not have + less contents than the preloader supplies. If the caller has + data beyond block->length, it means that a file write has + been done while this block was in cache and not extended + with the new data. If the condition is met, we can simply + ignore the block. + */ + DBUG_ASSERT((page_st == PAGE_READ) && + (read_length + offset <= block->length)); + } + + /* + A secondary request must now have the block assigned to the + requested file block. It does not hurt to check it for primary + requests too. + */ + DBUG_ASSERT(block->hash_link->file == file); + DBUG_ASSERT(block->hash_link->diskpos == filepos); + DBUG_ASSERT(block->status & (BLOCK_READ | BLOCK_IN_USE)); + } /* end of if (!(block->status & BLOCK_ERROR)) */ remove_reader(block); - /* - Link the block into the LRU chain - if it's the last submitted request for the block - */ - unreg_request(keycache, block, 1); - error= (block->status & BLOCK_ERROR); + /* Error injection for coverage testing. */ + DBUG_EXECUTE_IF("key_cache_insert_block_error", + block->status|= BLOCK_ERROR; errno=EIO;); - dec_counter_for_resize_op(keycache); - - keycache_pthread_mutex_unlock(&keycache->cache_lock); - - if (error) - DBUG_RETURN(1); + /* Do not link erroneous blocks into the LRU ring, but free them. */ + if (!(block->status & BLOCK_ERROR)) + { + /* + Link the block into the LRU ring if it's the last submitted + request for the block. This enables eviction for the block. + */ + unreg_request(keycache, block, 1); + } + else + { + free_block(keycache, block); + error= 1; + break; + } buff+= read_length; filepos+= read_length+offset; offset= 0; } while ((length-= read_length)); + + no_key_cache: + if (locked_and_incremented) + dec_counter_for_resize_op(keycache); + keycache_pthread_mutex_unlock(&keycache->cache_lock); } - DBUG_RETURN(0); + DBUG_RETURN(error); } @@ -2045,6 +3012,8 @@ int key_cache_insert(KEY_CACHE *keycache, It ensures that this data is flushed to the file if dont_write is FALSE. Filepos must be a multiple of 'block_length', but it doesn't have to be a multiple of key_cache_block_size; + + dont_write is always TRUE in the server (info->lock_type is never F_UNLCK). */ int key_cache_write(KEY_CACHE *keycache, @@ -2053,20 +3022,25 @@ int key_cache_write(KEY_CACHE *keycache, uint block_length __attribute__((unused)), int dont_write) { - reg1 BLOCK_LINK *block; + my_bool locked_and_incremented= FALSE; int error=0; DBUG_ENTER("key_cache_write"); DBUG_PRINT("enter", - ("fd: %u pos: %lu length: %u block_length: %u key_block_length: %u", - (uint) file, (ulong) filepos, length, block_length, - keycache ? keycache->key_cache_block_size : 0)); + ("fd: %u pos: %lu length: %u block_length: %u" + " key_block_length: %u", + (uint) file, (ulong) filepos, length, block_length, + keycache ? keycache->key_cache_block_size : 0)); if (!dont_write) { - /* Force writing from buff into disk */ + /* purecov: begin inspected */ + /* Not used in the server. */ + /* Force writing from buff into disk. */ + keycache->global_cache_w_requests++; keycache->global_cache_write++; if (my_pwrite(file, buff, length, filepos, MYF(MY_NABP | MY_WAIT_IF_FULL))) DBUG_RETURN(1); + /* purecov: end */ } #if !defined(DBUG_OFF) && defined(EXTRA_DEBUG) @@ -2074,92 +3048,231 @@ int key_cache_write(KEY_CACHE *keycache, test_key_cache(keycache, "start of key_cache_write", 1);); #endif - if (keycache->can_be_used) + if (keycache->key_cache_inited) { /* Key cache is used */ + reg1 BLOCK_LINK *block; uint read_length; - int page_st; uint offset; + int page_st; + /* + When the key cache is once initialized, we use the cache_lock to + reliably distinguish the cases of normal operation, resizing, and + disabled cache. We always increment and decrement + 'cnt_for_resize_op' so that a resizer can wait for pending I/O. + */ + keycache_pthread_mutex_lock(&keycache->cache_lock); + /* + Cache resizing has two phases: Flushing and re-initializing. In + the flush phase write requests can modify dirty blocks that are + not yet in flush. Otherwise they are allowed to bypass the cache. + find_key_block() returns NULL in both cases (clean blocks and + non-cached blocks). + + After the flush phase new I/O requests must wait until the + re-initialization is done. The re-initialization can be done only + if no I/O request is in progress. The reason is that + key_cache_block_size can change. With enabled cache I/O is done in + chunks of key_cache_block_size. Every chunk tries to use a cache + block first. If the block size changes in the middle, a block + could be missed and data could be written below a cached block. + */ + while (keycache->in_resize && !keycache->resize_in_flush) + wait_on_queue(&keycache->resize_queue, &keycache->cache_lock); + /* Register the I/O for the next resize. */ + inc_counter_for_resize_op(keycache); + locked_and_incremented= TRUE; + /* Requested data may not always be aligned to cache blocks. */ offset= (uint) (filepos % keycache->key_cache_block_size); + /* Write data in key_cache_block_size increments. */ do { - keycache_pthread_mutex_lock(&keycache->cache_lock); + /* Cache could be disabled in a later iteration. */ if (!keycache->can_be_used) - { - keycache_pthread_mutex_unlock(&keycache->cache_lock); goto no_key_cache; - } - /* Write data in key_cache_block_size increments */ + /* Start writing at the beginning of the cache block. */ filepos-= offset; + /* Do not write beyond the end of the cache block. */ read_length= length; set_if_smaller(read_length, keycache->key_cache_block_size-offset); KEYCACHE_DBUG_ASSERT(read_length > 0); - inc_counter_for_resize_op(keycache); + /* Request the cache block that matches file/pos. */ keycache->global_cache_w_requests++; block= find_key_block(keycache, file, filepos, level, 1, &page_st); if (!block) { - /* It happens only for requests submitted during resize operation */ - dec_counter_for_resize_op(keycache); - keycache_pthread_mutex_unlock(&keycache->cache_lock); - if (dont_write) + /* + This happens only for requests submitted during key cache + resize. The block is not in the cache and shall not go in. + Write directly to file. + */ + if (dont_write) { - keycache->global_cache_w_requests++; + /* Used in the server. */ keycache->global_cache_write++; - if (my_pwrite(file, (byte*) buff, length, filepos, - MYF(MY_NABP | MY_WAIT_IF_FULL))) + keycache_pthread_mutex_unlock(&keycache->cache_lock); + if (my_pwrite(file, (uchar*) buff, read_length, filepos + offset, + MYF(MY_NABP | MY_WAIT_IF_FULL))) error=1; - } + keycache_pthread_mutex_lock(&keycache->cache_lock); + } goto next_block; } + /* + Prevent block from flushing and from being selected for to be + freed. This must be set when we release the cache_lock. + However, we must not set the status of the block before it is + assigned to this file/pos. + */ + if (page_st != PAGE_WAIT_TO_BE_READ) + block->status|= BLOCK_FOR_UPDATE; + /* + We must read the file block first if it is not yet in the cache + and we do not replace all of its contents. - if (block->status != BLOCK_ERROR && page_st != PAGE_READ && - (offset || read_length < keycache->key_cache_block_size)) + In cases where the cache block is big enough to contain (parts + of) index blocks of different indexes, our request can be + secondary (PAGE_WAIT_TO_BE_READ). In this case another thread is + reading the file block. If the read completes after us, it + overwrites our new contents with the old contents. So we have to + wait for the other thread to complete the read of this block. + read_block() takes care for the wait. + */ + if (!(block->status & BLOCK_ERROR) && + ((page_st == PAGE_TO_BE_READ && + (offset || read_length < keycache->key_cache_block_size)) || + (page_st == PAGE_WAIT_TO_BE_READ))) + { read_block(keycache, block, offset + read_length >= keycache->key_cache_block_size? offset : keycache->key_cache_block_size, - offset,(my_bool)(page_st == PAGE_TO_BE_READ)); + offset, (page_st == PAGE_TO_BE_READ)); + DBUG_ASSERT(keycache->can_be_used); + DBUG_ASSERT(block->status & (BLOCK_READ | BLOCK_IN_USE)); + /* + Prevent block from flushing and from being selected for to be + freed. This must be set when we release the cache_lock. + Here we set it in case we could not set it above. + */ + block->status|= BLOCK_FOR_UPDATE; + } + /* + The block should always be assigned to the requested file block + here. It need not be BLOCK_READ when overwriting the whole block. + */ + DBUG_ASSERT(block->hash_link->file == file); + DBUG_ASSERT(block->hash_link->diskpos == filepos); + DBUG_ASSERT(block->status & BLOCK_IN_USE); + DBUG_ASSERT((page_st == PAGE_TO_BE_READ) || (block->status & BLOCK_READ)); + /* + The block to be written must not be marked BLOCK_REASSIGNED. + Otherwise it could be freed in dirty state or reused without + another flush during eviction. It must also not be in flush. + Otherwise the old contens may have been flushed already and + the flusher could clear BLOCK_CHANGED without flushing the + new changes again. + */ + DBUG_ASSERT(!(block->status & BLOCK_REASSIGNED)); + + while (block->status & BLOCK_IN_FLUSHWRITE) + { + /* + Another thread is flushing the block. It was dirty already. + Wait until the block is flushed to file. Otherwise we could + modify the buffer contents just while it is written to file. + An unpredictable file block contents would be the result. + While we wait, several things can happen to the block, + including another flush. But the block cannot be reassigned to + another hash_link until we release our request on it. + */ + wait_on_queue(&block->wqueue[COND_FOR_SAVED], &keycache->cache_lock); + DBUG_ASSERT(keycache->can_be_used); + DBUG_ASSERT(block->status & (BLOCK_READ | BLOCK_IN_USE)); + /* Still must not be marked for free. */ + DBUG_ASSERT(!(block->status & BLOCK_REASSIGNED)); + DBUG_ASSERT(block->hash_link && (block->hash_link->block == block)); + } + + /* + We could perhaps release the cache_lock during access of the + data like in the other functions. Locks outside of the key cache + assure that readers and a writer do not access the same range of + data. Parallel accesses should happen only if the cache block + contains multiple index block(fragment)s. So different parts of + the buffer would be read/written. An attempt to flush during + memcpy() is prevented with BLOCK_FOR_UPDATE. + */ + if (!(block->status & BLOCK_ERROR)) + { +#if !defined(SERIALIZED_READ_FROM_CACHE) + keycache_pthread_mutex_unlock(&keycache->cache_lock); +#endif + if (!(read_length & 511)) + bmove512(block->buffer+offset, buff, read_length); + else + memcpy(block->buffer+offset, buff, (size_t) read_length); + +#if !defined(SERIALIZED_READ_FROM_CACHE) + keycache_pthread_mutex_lock(&keycache->cache_lock); +#endif + } if (!dont_write) { - /* buff has been written to disk at start */ + /* Not used in the server. buff has been written to disk at start. */ if ((block->status & BLOCK_CHANGED) && (!offset && read_length >= keycache->key_cache_block_size)) link_to_file_list(keycache, block, block->hash_link->file, 1); } else if (! (block->status & BLOCK_CHANGED)) link_to_changed_list(keycache, block); - + block->status|=BLOCK_READ; + /* + Allow block to be selected for to be freed. Since it is marked + BLOCK_CHANGED too, it won't be selected for to be freed without + a flush. + */ + block->status&= ~BLOCK_FOR_UPDATE; set_if_smaller(block->offset, offset); set_if_bigger(block->length, read_length+offset); - if (! (block->status & BLOCK_ERROR)) + /* Threads may be waiting for the changes to be complete. */ + release_whole_queue(&block->wqueue[COND_FOR_REQUESTED]); + + /* + If only a part of the cache block is to be replaced, and the + rest has been read from file, then the cache lock has been + released for I/O and it could be possible that another thread + wants to evict or free the block and waits for it to be + released. So we must not just decrement hash_link->requests, but + also wake a waiting thread. + */ + remove_reader(block); + + /* Error injection for coverage testing. */ + DBUG_EXECUTE_IF("key_cache_write_block_error", + block->status|= BLOCK_ERROR;); + + /* Do not link erroneous blocks into the LRU ring, but free them. */ + if (!(block->status & BLOCK_ERROR)) { - if (!(read_length & 511)) - bmove512(block->buffer+offset, buff, read_length); - else - memcpy(block->buffer+offset, buff, (size_t) read_length); + /* + Link the block into the LRU ring if it's the last submitted + request for the block. This enables eviction for the block. + */ + unreg_request(keycache, block, 1); } - - block->status|=BLOCK_READ; - - /* Unregister the request */ - block->hash_link->requests--; - unreg_request(keycache, block, 1); - - if (block->status & BLOCK_ERROR) + else { - keycache_pthread_mutex_unlock(&keycache->cache_lock); + /* Pretend a "clean" block to avoid complications. */ + block->status&= ~(BLOCK_CHANGED); + free_block(keycache, block); error= 1; break; } - dec_counter_for_resize_op(keycache); - - keycache_pthread_mutex_unlock(&keycache->cache_lock); - next_block: buff+= read_length; filepos+= read_length+offset; @@ -2173,14 +3286,24 @@ no_key_cache: /* Key cache is not used */ if (dont_write) { + /* Used in the server. */ keycache->global_cache_w_requests++; keycache->global_cache_write++; + if (locked_and_incremented) + keycache_pthread_mutex_unlock(&keycache->cache_lock); if (my_pwrite(file, (byte*) buff, length, filepos, MYF(MY_NABP | MY_WAIT_IF_FULL))) error=1; + if (locked_and_incremented) + keycache_pthread_mutex_lock(&keycache->cache_lock); } end: + if (locked_and_incremented) + { + dec_counter_for_resize_op(keycache); + keycache_pthread_mutex_unlock(&keycache->cache_lock); + } #if !defined(DBUG_OFF) && defined(EXTRA_DEBUG) DBUG_EXECUTE("exec", test_key_cache(keycache, "end of key_cache_write", 1);); @@ -2190,17 +3313,64 @@ end: /* - Free block: remove reference to it from hash table, - remove it from the chain file of dirty/clean blocks - and add it to the free list. + Free block. + + SYNOPSIS + free_block() + keycache Pointer to a key cache data structure + block Pointer to the block to free + + DESCRIPTION + Remove reference to block from hash table. + Remove block from the chain of clean blocks. + Add block to the free list. + + NOTE + Block must not be free (status == 0). + Block must not be in free_block_list. + Block must not be in the LRU ring. + Block must not be in eviction (BLOCK_IN_EVICTION | BLOCK_IN_SWITCH). + Block must not be in free (BLOCK_REASSIGNED). + Block must not be in flush (BLOCK_IN_FLUSH). + Block must not be dirty (BLOCK_CHANGED). + Block must not be in changed_blocks (dirty) hash. + Block must be in file_blocks (clean) hash. + Block must refer to a hash_link. + Block must have a request registered on it. */ static void free_block(KEY_CACHE *keycache, BLOCK_LINK *block) { KEYCACHE_THREAD_TRACE("free block"); KEYCACHE_DBUG_PRINT("free_block", - ("block %u to be freed, hash_link %p", - BLOCK_NUMBER(block), block->hash_link)); + ("block %u to be freed, hash_link %p status: %u", + BLOCK_NUMBER(block), block->hash_link, + block->status)); + /* + Assert that the block is not free already. And that it is in a clean + state. Note that the block might just be assigned to a hash_link and + not yet read (BLOCK_READ may not be set here). In this case a reader + is registered in the hash_link and free_block() will wait for it + below. + */ + DBUG_ASSERT((block->status & BLOCK_IN_USE) && + !(block->status & (BLOCK_IN_EVICTION | BLOCK_IN_SWITCH | + BLOCK_REASSIGNED | BLOCK_IN_FLUSH | + BLOCK_CHANGED | BLOCK_FOR_UPDATE))); + /* Assert that the block is in a file_blocks chain. */ + DBUG_ASSERT(block->prev_changed && *block->prev_changed == block); + /* Assert that the block is not in the LRU ring. */ + DBUG_ASSERT(!block->next_used && !block->prev_used); + /* + IMHO the below condition (if()) makes no sense. I can't see how it + could be possible that free_block() is entered with a NULL hash_link + pointer. The only place where it can become NULL is in free_block() + (or before its first use ever, but for those blocks free_block() is + not called). I don't remove the conditional as it cannot harm, but + place an DBUG_ASSERT to confirm my hypothesis. Eventually the + condition (if()) can be removed. + */ + DBUG_ASSERT(block->hash_link && block->hash_link->block == block); if (block->hash_link) { /* @@ -2211,24 +3381,81 @@ static void free_block(KEY_CACHE *keycache, BLOCK_LINK *block) */ block->status|= BLOCK_REASSIGNED; wait_for_readers(keycache, block); - unlink_hash(keycache, block->hash_link); + /* + The block must not have been freed by another thread. Repeat some + checks. An additional requirement is that it must be read now + (BLOCK_READ). + */ + DBUG_ASSERT(block->hash_link && block->hash_link->block == block); + DBUG_ASSERT((block->status & (BLOCK_READ | BLOCK_IN_USE | + BLOCK_REASSIGNED)) && + !(block->status & (BLOCK_IN_EVICTION | BLOCK_IN_SWITCH | + BLOCK_IN_FLUSH | BLOCK_CHANGED | + BLOCK_FOR_UPDATE))); + DBUG_ASSERT(block->prev_changed && *block->prev_changed == block); + DBUG_ASSERT(!block->prev_used); + /* + Unset BLOCK_REASSIGNED again. If we hand the block to an evicting + thread (through unreg_request() below), other threads must not see + this flag. They could become confused. + */ + block->status&= ~BLOCK_REASSIGNED; + /* + Do not release the hash_link until the block is off all lists. + At least not if we hand it over for eviction in unreg_request(). + */ } + /* + Unregister the block request and link the block into the LRU ring. + This enables eviction for the block. If the LRU ring was empty and + threads are waiting for a block, then the block wil be handed over + for eviction immediately. Otherwise we will unlink it from the LRU + ring again, without releasing the lock in between. So decrementing + the request counter and updating statistics are the only relevant + operation in this case. Assert that there are no other requests + registered. + */ + DBUG_ASSERT(block->requests == 1); + unreg_request(keycache, block, 0); + /* + Note that even without releasing the cache lock it is possible that + the block is immediately selected for eviction by link_block() and + thus not added to the LRU ring. In this case we must not touch the + block any more. + */ + if (block->status & BLOCK_IN_EVICTION) + return; + + /* Error blocks are not put into the LRU ring. */ + if (!(block->status & BLOCK_ERROR)) + { + /* Here the block must be in the LRU ring. Unlink it again. */ + DBUG_ASSERT(block->next_used && block->prev_used && + *block->prev_used == block); + unlink_block(keycache, block); + } + if (block->temperature == BLOCK_WARM) + keycache->warm_blocks--; + block->temperature= BLOCK_COLD; + + /* Remove from file_blocks hash. */ unlink_changed(block); + + /* Remove reference to block from hash table. */ + unlink_hash(keycache, block->hash_link); + block->hash_link= NULL; + block->status= 0; block->length= 0; block->offset= keycache->key_cache_block_size; KEYCACHE_THREAD_TRACE("free block"); - KEYCACHE_DBUG_PRINT("free_block", - ("block is freed")); - unreg_request(keycache, block, 0); - block->hash_link= NULL; + KEYCACHE_DBUG_PRINT("free_block", ("block is freed")); - /* Remove the free block from the LRU ring. */ - unlink_block(keycache, block); - if (block->temperature == BLOCK_WARM) - keycache->warm_blocks--; - block->temperature= BLOCK_COLD; + /* Enforced by unlink_changed(), but just to be sure. */ + DBUG_ASSERT(!block->next_changed && !block->prev_changed); + /* Enforced by unlink_block(): not in LRU ring nor in free_block_list. */ + DBUG_ASSERT(!block->next_used && !block->prev_used); /* Insert the free block in the free list. */ block->next_used= keycache->free_block_list; keycache->free_block_list= block; @@ -2236,8 +3463,7 @@ static void free_block(KEY_CACHE *keycache, BLOCK_LINK *block) keycache->blocks_unused++; /* All pending requests for this page must be resubmitted. */ - if (block->wqueue[COND_FOR_SAVED].last_thread) - release_queue(&block->wqueue[COND_FOR_SAVED]); + release_whole_queue(&block->wqueue[COND_FOR_SAVED]); } @@ -2271,54 +3497,97 @@ static int flush_cached_blocks(KEY_CACHE *keycache, my_qsort((byte*) cache, count, sizeof(*cache), (qsort_cmp) cmp_sec_link); keycache_pthread_mutex_lock(&keycache->cache_lock); + /* + Note: Do not break the loop. We have registered a request on every + block in 'cache'. These must be unregistered by free_block() or + unreg_request(). + */ for ( ; cache != end ; cache++) { BLOCK_LINK *block= *cache; KEYCACHE_DBUG_PRINT("flush_cached_blocks", ("block %u to be flushed", BLOCK_NUMBER(block))); - keycache_pthread_mutex_unlock(&keycache->cache_lock); - error= my_pwrite(file, - block->buffer+block->offset, - block->length - block->offset, - block->hash_link->diskpos+ block->offset, - MYF(MY_NABP | MY_WAIT_IF_FULL)); - keycache_pthread_mutex_lock(&keycache->cache_lock); - keycache->global_cache_write++; - if (error) + /* + If the block contents is going to be changed, we abandon the flush + for this block. flush_key_blocks_int() will restart its search and + handle the block properly. + */ + if (!(block->status & BLOCK_FOR_UPDATE)) { - block->status|= BLOCK_ERROR; - if (!last_errno) - last_errno= errno ? errno : -1; + /* Blocks coming here must have a certain status. */ + DBUG_ASSERT(block->hash_link); + DBUG_ASSERT(block->hash_link->block == block); + DBUG_ASSERT(block->hash_link->file == file); + DBUG_ASSERT((block->status & ~BLOCK_IN_EVICTION) == + (BLOCK_READ | BLOCK_IN_FLUSH | BLOCK_CHANGED | BLOCK_IN_USE)); + block->status|= BLOCK_IN_FLUSHWRITE; + keycache_pthread_mutex_unlock(&keycache->cache_lock); + error= my_pwrite(file, block->buffer+block->offset, + block->length - block->offset, + block->hash_link->diskpos+ block->offset, + MYF(MY_NABP | MY_WAIT_IF_FULL)); + keycache_pthread_mutex_lock(&keycache->cache_lock); + keycache->global_cache_write++; + if (error) + { + block->status|= BLOCK_ERROR; + if (!last_errno) + last_errno= errno ? errno : -1; + } + block->status&= ~BLOCK_IN_FLUSHWRITE; + /* Block must not have changed status except BLOCK_FOR_UPDATE. */ + DBUG_ASSERT(block->hash_link); + DBUG_ASSERT(block->hash_link->block == block); + DBUG_ASSERT(block->hash_link->file == file); + DBUG_ASSERT((block->status & ~(BLOCK_FOR_UPDATE | BLOCK_IN_EVICTION)) == + (BLOCK_READ | BLOCK_IN_FLUSH | BLOCK_CHANGED | BLOCK_IN_USE)); + /* + Set correct status and link in right queue for free or later use. + free_block() must not see BLOCK_CHANGED and it may need to wait + for readers of the block. These should not see the block in the + wrong hash. If not freeing the block, we need to have it in the + right queue anyway. + */ + link_to_file_list(keycache, block, file, 1); } + block->status&= ~BLOCK_IN_FLUSH; /* Let to proceed for possible waiting requests to write to the block page. It might happen only during an operation to resize the key cache. */ - if (block->wqueue[COND_FOR_SAVED].last_thread) - release_queue(&block->wqueue[COND_FOR_SAVED]); + release_whole_queue(&block->wqueue[COND_FOR_SAVED]); /* type will never be FLUSH_IGNORE_CHANGED here */ - if (! (type == FLUSH_KEEP || type == FLUSH_FORCE_WRITE)) + if (!(type == FLUSH_KEEP || type == FLUSH_FORCE_WRITE) && + !(block->status & (BLOCK_IN_EVICTION | BLOCK_IN_SWITCH | + BLOCK_FOR_UPDATE))) { - keycache->blocks_changed--; - keycache->global_blocks_changed--; + /* + Note that a request has been registered against the block in + flush_key_blocks_int(). + */ free_block(keycache, block); } else { - block->status&= ~BLOCK_IN_FLUSH; - link_to_file_list(keycache, block, file, 1); + /* + Link the block into the LRU ring if it's the last submitted + request for the block. This enables eviction for the block. + Note that a request has been registered against the block in + flush_key_blocks_int(). + */ unreg_request(keycache, block, 1); } - } + } /* end of for ( ; cache != end ; cache++) */ return last_errno; } /* - flush all key blocks for a file to disk, but don't do any mutex locks + Flush all key blocks for a file to disk, but don't do any mutex locks. + SYNOPSIS flush_key_blocks_int() keycache pointer to a key cache data structure file handler for the file to flush to @@ -2329,6 +3598,10 @@ static int flush_cached_blocks(KEY_CACHE *keycache, from flush_key_blocks and flush_all_key_blocks (the later one does the mutex lock in the resize_key_cache() function). + We do only care about changed blocks that exist when the function is + entered. We do not guarantee that all changed blocks of the file are + flushed if more blocks change while this function is running. + RETURN 0 ok 1 error @@ -2339,13 +3612,14 @@ static int flush_key_blocks_int(KEY_CACHE *keycache, { BLOCK_LINK *cache_buff[FLUSH_CACHE],**cache; int last_errno= 0; + int last_errcnt= 0; DBUG_ENTER("flush_key_blocks_int"); DBUG_PRINT("enter",("file: %d blocks_used: %lu blocks_changed: %lu", file, keycache->blocks_used, keycache->blocks_changed)); #if !defined(DBUG_OFF) && defined(EXTRA_DEBUG) - DBUG_EXECUTE("check_keycache", - test_key_cache(keycache, "start of flush_key_blocks", 0);); + DBUG_EXECUTE("check_keycache", + test_key_cache(keycache, "start of flush_key_blocks", 0);); #endif cache= cache_buff; @@ -2354,9 +3628,11 @@ static int flush_key_blocks_int(KEY_CACHE *keycache, { /* Key cache exists and flush is not disabled */ int error= 0; - uint count= 0; + uint count= FLUSH_CACHE; BLOCK_LINK **pos,**end; BLOCK_LINK *first_in_switch= NULL; + BLOCK_LINK *last_in_flush; + BLOCK_LINK *last_for_update; BLOCK_LINK *block, *next; #if defined(KEYCACHE_DEBUG) uint cnt=0; @@ -2368,28 +3644,39 @@ static int flush_key_blocks_int(KEY_CACHE *keycache, Count how many key blocks we have to cache to be able to flush all dirty pages with minimum seek moves */ + count= 0; for (block= keycache->changed_blocks[FILE_HASH(file)] ; block ; block= block->next_changed) { - if (block->hash_link->file == file) + if ((block->hash_link->file == file) && + !(block->status & BLOCK_IN_FLUSH)) { count++; KEYCACHE_DBUG_ASSERT(count<= keycache->blocks_used); } } - /* Allocate a new buffer only if its bigger than the one we have */ - if (count > FLUSH_CACHE && + /* + Allocate a new buffer only if its bigger than the one we have. + Assure that we always have some entries for the case that new + changed blocks appear while we need to wait for something. + */ + if ((count > FLUSH_CACHE) && !(cache= (BLOCK_LINK**) my_malloc(sizeof(BLOCK_LINK*)*count, MYF(0)))) - { cache= cache_buff; + /* + After a restart there could be more changed blocks than now. + So we should not let count become smaller than the fixed buffer. + */ + if (cache == cache_buff) count= FLUSH_CACHE; - } } /* Retrieve the blocks and write them to a buffer to be flushed */ restart: + last_in_flush= NULL; + last_for_update= NULL; end= (pos= cache)+count; for (block= keycache->changed_blocks[FILE_HASH(file)] ; block ; @@ -2402,121 +3689,350 @@ restart: next= block->next_changed; if (block->hash_link->file == file) { - /* - Mark the block with BLOCK_IN_FLUSH in order not to let - other threads to use it for new pages and interfere with - our sequence ot flushing dirty file pages - */ - block->status|= BLOCK_IN_FLUSH; - - if (! (block->status & BLOCK_IN_SWITCH)) + if (!(block->status & (BLOCK_IN_FLUSH | BLOCK_FOR_UPDATE))) { - /* - We care only for the blocks for which flushing was not - initiated by other threads as a result of page swapping + /* + Note: The special handling of BLOCK_IN_SWITCH is obsolete + since we set BLOCK_IN_FLUSH if the eviction includes a + flush. It can be removed in a later version. */ - reg_requests(keycache, block, 1); - if (type != FLUSH_IGNORE_CHANGED) + if (!(block->status & BLOCK_IN_SWITCH)) { - /* It's not a temporary file */ - if (pos == end) + /* + We care only for the blocks for which flushing was not + initiated by another thread and which are not in eviction. + Registering a request on the block unlinks it from the LRU + ring and protects against eviction. + */ + reg_requests(keycache, block, 1); + if (type != FLUSH_IGNORE_CHANGED) { - /* - This happens only if there is not enough - memory for the big block - */ - if ((error= flush_cached_blocks(keycache, file, cache, - end,type))) - last_errno=error; + /* It's not a temporary file */ + if (pos == end) + { + /* + This should happen relatively seldom. Remove the + request because we won't do anything with the block + but restart and pick it again in the next iteration. + */ + unreg_request(keycache, block, 0); + /* + This happens only if there is not enough + memory for the big block + */ + if ((error= flush_cached_blocks(keycache, file, cache, + end,type))) + { + /* Do not loop infinitely trying to flush in vain. */ + if ((last_errno == error) && (++last_errcnt > 5)) + goto err; + last_errno= error; + } + /* + Restart the scan as some other thread might have changed + the changed blocks chain: the blocks that were in switch + state before the flush started have to be excluded + */ + goto restart; + } /* - Restart the scan as some other thread might have changed - the changed blocks chain: the blocks that were in switch - state before the flush started have to be excluded + Mark the block with BLOCK_IN_FLUSH in order not to let + other threads to use it for new pages and interfere with + our sequence of flushing dirty file pages. We must not + set this flag before actually putting the block on the + write burst array called 'cache'. */ - goto restart; + block->status|= BLOCK_IN_FLUSH; + /* Add block to the array for a write burst. */ + *pos++= block; + } + else + { + /* It's a temporary file */ + DBUG_ASSERT(!(block->status & BLOCK_REASSIGNED)); + /* + free_block() must not be called with BLOCK_CHANGED. Note + that we must not change the BLOCK_CHANGED flag outside of + link_to_file_list() so that it is always in the correct + queue and the *blocks_changed counters are correct. + */ + link_to_file_list(keycache, block, file, 1); + if (!(block->status & (BLOCK_IN_EVICTION | BLOCK_IN_SWITCH))) + { + /* A request has been registered against the block above. */ + free_block(keycache, block); + } + else + { + /* + Link the block into the LRU ring if it's the last + submitted request for the block. This enables eviction + for the block. A request has been registered against + the block above. + */ + unreg_request(keycache, block, 1); + } } - *pos++= block; } else { - /* It's a temporary file */ - keycache->blocks_changed--; - keycache->global_blocks_changed--; - free_block(keycache, block); + /* + Link the block into a list of blocks 'in switch'. + + WARNING: Here we introduce a place where a changed block + is not in the changed_blocks hash! This is acceptable for + a BLOCK_IN_SWITCH. Never try this for another situation. + Other parts of the key cache code rely on changed blocks + being in the changed_blocks hash. + */ + unlink_changed(block); + link_changed(block, &first_in_switch); } } - else + else if (type != FLUSH_KEEP) { - /* Link the block into a list of blocks 'in switch' */ - unlink_changed(block); - link_changed(block, &first_in_switch); + /* + During the normal flush at end of statement (FLUSH_KEEP) we + do not need to ensure that blocks in flush or update by + other threads are flushed. They will be flushed by them + later. In all other cases we must assure that we do not have + any changed block of this file in the cache when this + function returns. + */ + if (block->status & BLOCK_IN_FLUSH) + { + /* Remember the last block found to be in flush. */ + last_in_flush= block; + } + else + { + /* Remember the last block found to be selected for update. */ + last_for_update= block; + } } } } if (pos != cache) { if ((error= flush_cached_blocks(keycache, file, cache, pos, type))) + { + /* Do not loop inifnitely trying to flush in vain. */ + if ((last_errno == error) && (++last_errcnt > 5)) + goto err; last_errno= error; + } + /* + Do not restart here during the normal flush at end of statement + (FLUSH_KEEP). We have now flushed at least all blocks that were + changed when entering this function. In all other cases we must + assure that we do not have any changed block of this file in the + cache when this function returns. + */ + if (type != FLUSH_KEEP) + goto restart; } - /* Wait until list of blocks in switch is empty */ + if (last_in_flush) + { + /* + There are no blocks to be flushed by this thread, but blocks in + flush by other threads. Wait until one of the blocks is flushed. + Re-check the condition for last_in_flush. We may have unlocked + the cache_lock in flush_cached_blocks(). The state of the block + could have changed. + */ + if (last_in_flush->status & BLOCK_IN_FLUSH) + wait_on_queue(&last_in_flush->wqueue[COND_FOR_SAVED], + &keycache->cache_lock); + /* Be sure not to lose a block. They may be flushed in random order. */ + goto restart; + } + if (last_for_update) + { + /* + There are no blocks to be flushed by this thread, but blocks for + update by other threads. Wait until one of the blocks is updated. + Re-check the condition for last_for_update. We may have unlocked + the cache_lock in flush_cached_blocks(). The state of the block + could have changed. + */ + if (last_for_update->status & BLOCK_FOR_UPDATE) + wait_on_queue(&last_for_update->wqueue[COND_FOR_REQUESTED], + &keycache->cache_lock); + /* The block is now changed. Flush it. */ + goto restart; + } + + /* + Wait until the list of blocks in switch is empty. The threads that + are switching these blocks will relink them to clean file chains + while we wait and thus empty the 'first_in_switch' chain. + */ while (first_in_switch) { #if defined(KEYCACHE_DEBUG) cnt= 0; #endif - block= first_in_switch; - { -#ifdef THREAD - struct st_my_thread_var *thread= my_thread_var; - add_to_queue(&block->wqueue[COND_FOR_SAVED], thread); - do - { - KEYCACHE_DBUG_PRINT("flush_key_blocks_int: wait", - ("suspend thread %ld", thread->id)); - keycache_pthread_cond_wait(&thread->suspend, - &keycache->cache_lock); - } - while (thread->next); -#else - KEYCACHE_DBUG_ASSERT(0); - /* No parallel requests in single-threaded case */ -#endif - } + wait_on_queue(&first_in_switch->wqueue[COND_FOR_SAVED], + &keycache->cache_lock); #if defined(KEYCACHE_DEBUG) cnt++; KEYCACHE_DBUG_ASSERT(cnt <= keycache->blocks_used); #endif + /* + Do not restart here. We have flushed all blocks that were + changed when entering this function and were not marked for + eviction. Other threads have now flushed all remaining blocks in + the course of their eviction. + */ } - /* The following happens very seldom */ + if (! (type == FLUSH_KEEP || type == FLUSH_FORCE_WRITE)) { -#if defined(KEYCACHE_DEBUG) - cnt=0; -#endif - for (block= keycache->file_blocks[FILE_HASH(file)] ; - block ; - block= next) + BLOCK_LINK *last_for_update= NULL; + BLOCK_LINK *last_in_switch= NULL; + uint total_found= 0; + uint found; + + /* + Finally free all clean blocks for this file. + During resize this may be run by two threads in parallel. + */ + do { -#if defined(KEYCACHE_DEBUG) - cnt++; - KEYCACHE_DBUG_ASSERT(cnt <= keycache->blocks_used); -#endif - next= block->next_changed; - if (block->hash_link->file == file && - (! (block->status & BLOCK_CHANGED) - || type == FLUSH_IGNORE_CHANGED)) + found= 0; + for (block= keycache->file_blocks[FILE_HASH(file)] ; + block ; + block= next) { - reg_requests(keycache, block, 1); - free_block(keycache, block); - } + /* Remember the next block. After freeing we cannot get at it. */ + next= block->next_changed; + + /* Changed blocks cannot appear in the file_blocks hash. */ + DBUG_ASSERT(!(block->status & BLOCK_CHANGED)); + if (block->hash_link->file == file) + { + /* We must skip blocks that will be changed. */ + if (block->status & BLOCK_FOR_UPDATE) + { + last_for_update= block; + continue; + } + + /* + We must not free blocks in eviction (BLOCK_IN_EVICTION | + BLOCK_IN_SWITCH) or blocks intended to be freed + (BLOCK_REASSIGNED). + */ + if (!(block->status & (BLOCK_IN_EVICTION | BLOCK_IN_SWITCH | + BLOCK_REASSIGNED))) + { + struct st_hash_link *next_hash_link; + my_off_t next_diskpos; + File next_file; + uint next_status; + uint hash_requests; + + total_found++; + found++; + KEYCACHE_DBUG_ASSERT(found <= keycache->blocks_used); + + /* + Register a request. This unlinks the block from the LRU + ring and protects it against eviction. This is required + by free_block(). + */ + reg_requests(keycache, block, 1); + + /* + free_block() may need to wait for readers of the block. + This is the moment where the other thread can move the + 'next' block from the chain. free_block() needs to wait + if there are requests for the block pending. + */ + if (next && (hash_requests= block->hash_link->requests)) + { + /* Copy values from the 'next' block and its hash_link. */ + next_status= next->status; + next_hash_link= next->hash_link; + next_diskpos= next_hash_link->diskpos; + next_file= next_hash_link->file; + DBUG_ASSERT(next == next_hash_link->block); + } + + free_block(keycache, block); + /* + If we had to wait and the state of the 'next' block + changed, break the inner loop. 'next' may no longer be + part of the current chain. + + We do not want to break the loop after every free_block(), + not even only after waits. The chain might be quite long + and contain blocks for many files. Traversing it again and + again to find more blocks for this file could become quite + inefficient. + */ + if (next && hash_requests && + ((next_status != next->status) || + (next_hash_link != next->hash_link) || + (next_file != next_hash_link->file) || + (next_diskpos != next_hash_link->diskpos) || + (next != next_hash_link->block))) + break; + } + else + { + last_in_switch= block; + } + } + } /* end for block in file_blocks */ + } while (found); + + /* + If any clean block has been found, we may have waited for it to + become free. In this case it could be possible that another clean + block became dirty. This is possible if the write request existed + before the flush started (BLOCK_FOR_UPDATE). Re-check the hashes. + */ + if (total_found) + goto restart; + + /* + To avoid an infinite loop, wait until one of the blocks marked + for update is updated. + */ + if (last_for_update) + { + /* We did not wait. Block must not have changed status. */ + DBUG_ASSERT(last_for_update->status & BLOCK_FOR_UPDATE); + wait_on_queue(&last_for_update->wqueue[COND_FOR_REQUESTED], + &keycache->cache_lock); + goto restart; } - } - } + + /* + To avoid an infinite loop wait until one of the blocks marked + for eviction is switched. + */ + if (last_in_switch) + { + /* We did not wait. Block must not have changed status. */ + DBUG_ASSERT(last_in_switch->status & (BLOCK_IN_EVICTION | + BLOCK_IN_SWITCH | + BLOCK_REASSIGNED)); + wait_on_queue(&last_in_switch->wqueue[COND_FOR_SAVED], + &keycache->cache_lock); + goto restart; + } + + } /* if (! (type == FLUSH_KEEP || type == FLUSH_FORCE_WRITE)) */ + + } /* if (keycache->disk_blocks > 0 */ #ifndef DBUG_OFF DBUG_EXECUTE("check_keycache", test_key_cache(keycache, "end of flush_key_blocks", 0);); #endif +err: if (cache != cache_buff) my_free((gptr) cache, MYF(0)); if (last_errno) @@ -2543,51 +4059,157 @@ restart: int flush_key_blocks(KEY_CACHE *keycache, File file, enum flush_type type) { - int res; + int res= 0; DBUG_ENTER("flush_key_blocks"); DBUG_PRINT("enter", ("keycache: 0x%lx", (long) keycache)); - if (keycache->disk_blocks <= 0) + if (!keycache->key_cache_inited) DBUG_RETURN(0); + keycache_pthread_mutex_lock(&keycache->cache_lock); - inc_counter_for_resize_op(keycache); - res= flush_key_blocks_int(keycache, file, type); - dec_counter_for_resize_op(keycache); + /* While waiting for lock, keycache could have been ended. */ + if (keycache->disk_blocks > 0) + { + inc_counter_for_resize_op(keycache); + res= flush_key_blocks_int(keycache, file, type); + dec_counter_for_resize_op(keycache); + } keycache_pthread_mutex_unlock(&keycache->cache_lock); DBUG_RETURN(res); } /* - Flush all blocks in the key cache to disk + Flush all blocks in the key cache to disk. + + SYNOPSIS + flush_all_key_blocks() + keycache pointer to key cache root structure + + DESCRIPTION + + Flushing of the whole key cache is done in two phases. + + 1. Flush all changed blocks, waiting for them if necessary. Loop + until there is no changed block left in the cache. + + 2. Free all clean blocks. Normally this means free all blocks. The + changed blocks were flushed in phase 1 and became clean. However we + may need to wait for blocks that are read by other threads. While we + wait, a clean block could become changed if that operation started + before the resize operation started. To be safe we must restart at + phase 1. + + When we can run through the changed_blocks and file_blocks hashes + without finding a block any more, then we are done. + + Note that we hold keycache->cache_lock all the time unless we need + to wait for something. + + RETURN + 0 OK + != 0 Error */ static int flush_all_key_blocks(KEY_CACHE *keycache) { -#if defined(KEYCACHE_DEBUG) - uint cnt=0; -#endif - while (keycache->blocks_changed > 0) + BLOCK_LINK *block; + uint total_found; + uint found; + uint idx; + DBUG_ENTER("flush_all_key_blocks"); + + do { - BLOCK_LINK *block; - for (block= keycache->used_last->next_used ; ; block=block->next_used) + safe_mutex_assert_owner(&keycache->cache_lock); + total_found= 0; + + /* + Phase1: Flush all changed blocks, waiting for them if necessary. + Loop until there is no changed block left in the cache. + */ + do { - if (block->hash_link) + found= 0; + /* Step over the whole changed_blocks hash array. */ + for (idx= 0; idx < CHANGED_BLOCKS_HASH; idx++) { -#if defined(KEYCACHE_DEBUG) - cnt++; - KEYCACHE_DBUG_ASSERT(cnt <= keycache->blocks_used); -#endif - if (flush_key_blocks_int(keycache, block->hash_link->file, - FLUSH_RELEASE)) - return 1; - break; + /* + If an array element is non-empty, use the first block from its + chain to find a file for flush. All changed blocks for this + file are flushed. So the same block will not appear at this + place again with the next iteration. New writes for blocks are + not accepted during the flush. If multiple files share the + same hash bucket, one of them will be flushed per iteration + of the outer loop of phase 1. + */ + if ((block= keycache->changed_blocks[idx])) + { + found++; + /* + Flush dirty blocks but do not free them yet. They can be used + for reading until all other blocks are flushed too. + */ + if (flush_key_blocks_int(keycache, block->hash_link->file, + FLUSH_FORCE_WRITE)) + DBUG_RETURN(1); + } } - if (block == keycache->used_last) - break; - } + + } while (found); + + /* + Phase 2: Free all clean blocks. Normally this means free all + blocks. The changed blocks were flushed in phase 1 and became + clean. However we may need to wait for blocks that are read by + other threads. While we wait, a clean block could become changed + if that operation started before the resize operation started. To + be safe we must restart at phase 1. + */ + do + { + found= 0; + /* Step over the whole file_blocks hash array. */ + for (idx= 0; idx < CHANGED_BLOCKS_HASH; idx++) + { + /* + If an array element is non-empty, use the first block from its + chain to find a file for flush. All blocks for this file are + freed. So the same block will not appear at this place again + with the next iteration. If multiple files share the + same hash bucket, one of them will be flushed per iteration + of the outer loop of phase 2. + */ + if ((block= keycache->file_blocks[idx])) + { + total_found++; + found++; + if (flush_key_blocks_int(keycache, block->hash_link->file, + FLUSH_RELEASE)) + DBUG_RETURN(1); + } + } + + } while (found); + + /* + If any clean block has been found, we may have waited for it to + become free. In this case it could be possible that another clean + block became dirty. This is possible if the write request existed + before the resize started (BLOCK_FOR_UPDATE). Re-check the hashes. + */ + } while (total_found); + +#ifndef DBUG_OFF + /* Now there should not exist any block any more. */ + for (idx= 0; idx < CHANGED_BLOCKS_HASH; idx++) + { + DBUG_ASSERT(!keycache->changed_blocks[idx]); + DBUG_ASSERT(!keycache->file_blocks[idx]); } - return 0; +#endif + + DBUG_RETURN(0); } @@ -2838,8 +4460,8 @@ static void keycache_debug_print(const char * fmt,...) va_start(args,fmt); if (keycache_debug_log) { - VOID(vfprintf(keycache_debug_log, fmt, args)); - VOID(fputc('\n',keycache_debug_log)); + (void) vfprintf(keycache_debug_log, fmt, args); + (void) fputc('\n',keycache_debug_log); } va_end(args); } @@ -2856,3 +4478,70 @@ void keycache_debug_log_close(void) #endif /* defined(KEYCACHE_DEBUG_LOG) */ #endif /* defined(KEYCACHE_DEBUG) */ + +#if !defined(DBUG_OFF) +#define F_B_PRT(_f_, _v_) DBUG_PRINT("assert_fail", (_f_, _v_)) + +static int fail_block(BLOCK_LINK *block) +{ + F_B_PRT("block->next_used: %lx\n", (ulong) block->next_used); + F_B_PRT("block->prev_used: %lx\n", (ulong) block->prev_used); + F_B_PRT("block->next_changed: %lx\n", (ulong) block->next_changed); + F_B_PRT("block->prev_changed: %lx\n", (ulong) block->prev_changed); + F_B_PRT("block->hash_link: %lx\n", (ulong) block->hash_link); + F_B_PRT("block->status: %u\n", block->status); + F_B_PRT("block->length: %u\n", block->length); + F_B_PRT("block->offset: %u\n", block->offset); + F_B_PRT("block->requests: %u\n", block->requests); + F_B_PRT("block->temperature: %u\n", block->temperature); + return 0; /* Let the assert fail. */ +} + +static int fail_hlink(HASH_LINK *hlink) +{ + F_B_PRT("hlink->next: %lx\n", (ulong) hlink->next); + F_B_PRT("hlink->prev: %lx\n", (ulong) hlink->prev); + F_B_PRT("hlink->block: %lx\n", (ulong) hlink->block); + F_B_PRT("hlink->diskpos: %lu\n", (ulong) hlink->diskpos); + F_B_PRT("hlink->file: %d\n", hlink->file); + return 0; /* Let the assert fail. */ +} + +static int cache_empty(KEY_CACHE *keycache) +{ + int errcnt= 0; + int idx; + if (keycache->disk_blocks <= 0) + return 1; + for (idx= 0; idx < keycache->disk_blocks; idx++) + { + BLOCK_LINK *block= keycache->block_root + idx; + if (block->status || block->requests || block->hash_link) + { + fprintf(stderr, "block index: %u\n", idx); + fail_block(block); + errcnt++; + } + } + for (idx= 0; idx < keycache->hash_links; idx++) + { + HASH_LINK *hash_link= keycache->hash_link_root + idx; + if (hash_link->requests || hash_link->block) + { + fprintf(stderr, "hash_link index: %u\n", idx); + fail_hlink(hash_link); + errcnt++; + } + } + if (errcnt) + { + fprintf(stderr, "blocks: %d used: %lu\n", + keycache->disk_blocks, keycache->blocks_used); + fprintf(stderr, "hash_links: %d used: %d\n", + keycache->hash_links, keycache->hash_links_used); + fprintf(stderr, "\n"); + } + return !errcnt; +} +#endif + diff --git a/mysys/my_static.c b/mysys/my_static.c index 1858d830f41..23e37c53f98 100644 --- a/mysys/my_static.c +++ b/mysys/my_static.c @@ -48,9 +48,6 @@ struct st_remember _my_sig_remember[MAX_SIGNALS]={{0,0}}; sigset_t my_signals; /* signals blocked by mf_brkhant */ #endif - /* from mf_keycache.c */ -my_bool key_cache_inited=0; - /* from mf_reccache.c */ ulong my_default_record_cache_size=RECORD_CACHE_SIZE; diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc index dfd739f6db8..a92e7bbb9fd 100644 --- a/sql/ha_myisam.cc +++ b/sql/ha_myisam.cc @@ -1189,6 +1189,7 @@ int ha_myisam::preload_keys(THD* thd, HA_CHECK_OPT *check_opt) ulonglong map= ~(ulonglong) 0; TABLE_LIST *table_list= table->pos_in_table_list; my_bool ignore_leaves= table_list->ignore_leaves; + char buf[ERRMSGSIZE+20]; DBUG_ENTER("ha_myisam::preload_keys"); @@ -1216,7 +1217,6 @@ int ha_myisam::preload_keys(THD* thd, HA_CHECK_OPT *check_opt) errmsg= "Failed to allocate buffer"; break; default: - char buf[ERRMSGSIZE+20]; my_snprintf(buf, ERRMSGSIZE, "Failed to read from index file (errno: %d)", my_errno); errmsg= buf; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 5a3100685e0..e32c17bc678 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -2741,8 +2741,13 @@ int reassign_keycache_tables(THD *thd, KEY_CACHE *src_cache, bool mysql_preload_keys(THD* thd, TABLE_LIST* tables) { DBUG_ENTER("mysql_preload_keys"); + /* + We cannot allow concurrent inserts. The storage engine reads + directly from the index file, bypassing the cache. It could read + outdated information if parallel inserts into cache blocks happen. + */ DBUG_RETURN(mysql_admin_table(thd, tables, 0, - "preload_keys", TL_READ, 0, 0, 0, 0, + "preload_keys", TL_READ_NO_INSERT, 0, 0, 0, 0, &handler::preload_keys, 0)); } From bd1038fecbe8d7bab304bc5a4c1416be1e31bea0 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 8 Sep 2009 22:56:00 +0200 Subject: [PATCH 45/80] Raise version number after cloning 5.0.86 --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index a70bb3ca27f..523ac01c6f3 100644 --- a/configure.in +++ b/configure.in @@ -7,7 +7,7 @@ AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! # remember to also change ndb version below and update version.c in ndb -AM_INIT_AUTOMAKE(mysql, 5.0.86) +AM_INIT_AUTOMAKE(mysql, 5.0.87) AM_CONFIG_HEADER([include/config.h:config.h.in]) PROTOCOL_VERSION=10 @@ -23,7 +23,7 @@ NDB_SHARED_LIB_VERSION=$NDB_SHARED_LIB_MAJOR_VERSION:0:0 # ndb version NDB_VERSION_MAJOR=5 NDB_VERSION_MINOR=0 -NDB_VERSION_BUILD=86 +NDB_VERSION_BUILD=87 NDB_VERSION_STATUS="" # Set all version vars based on $VERSION. How do we do this more elegant ? From df1660986e207ed0e7bdd4516a147ac83d983d1e Mon Sep 17 00:00:00 2001 From: hery Date: Wed, 9 Sep 2009 20:52:17 +0200 Subject: [PATCH 46/80] change c++ comment to c comment --- client/mysqltest.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/mysqltest.c b/client/mysqltest.c index 79df511641d..4f8e6cdac99 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -1406,7 +1406,7 @@ void show_diff(DYNAMIC_STRING* ds, else diff_name = 0; #else - diff_name = "diff"; // Otherwise always assume it's called diff + diff_name = "diff"; /* Otherwise always assume it's called diff */ #endif if (diff_name) From 19f02facb7e5b11055aa767bdbe50d56e2989666 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Fri, 11 Sep 2009 15:52:08 +0300 Subject: [PATCH 47/80] Bug #45159 : some tests in suite "jp" fail in embedded server (use LOAD DATA) Initialize correctly client flags for the embedded client Test cases in jp updated to work correctly with embedded server. --- libmysqld/libmysqld.c | 1 + mysql-test/suite/jp/r/jp_charset_sjis.result | 12 --------- mysql-test/suite/jp/r/jp_charset_ujis.result | 12 --------- mysql-test/suite/jp/r/jp_charset_utf8.result | 12 --------- mysql-test/suite/jp/r/jp_convert_sjis.result | 12 --------- mysql-test/suite/jp/r/jp_convert_ujis.result | 12 --------- mysql-test/suite/jp/r/jp_convert_utf8.result | 12 --------- mysql-test/suite/jp/r/jp_like_sjis.result | 12 --------- mysql-test/suite/jp/r/jp_like_ujis.result | 12 --------- mysql-test/suite/jp/r/jp_like_utf8.result | 12 --------- mysql-test/suite/jp/r/jp_select_sjis.result | 12 --------- mysql-test/suite/jp/r/jp_select_ujis.result | 12 --------- mysql-test/suite/jp/r/jp_select_utf8.result | 12 --------- mysql-test/suite/jp/r/jp_where_sjis.result | 12 --------- mysql-test/suite/jp/r/jp_where_ujis.result | 12 --------- mysql-test/suite/jp/r/jp_where_utf8.result | 12 --------- mysql-test/suite/jp/t/jp_charset_sjis.test | 26 +++++++++++--------- mysql-test/suite/jp/t/jp_charset_ujis.test | 26 +++++++++++--------- mysql-test/suite/jp/t/jp_charset_utf8.test | 26 +++++++++++--------- mysql-test/suite/jp/t/jp_convert_sjis.test | 26 +++++++++++--------- mysql-test/suite/jp/t/jp_convert_ujis.test | 26 +++++++++++--------- mysql-test/suite/jp/t/jp_convert_utf8.test | 26 +++++++++++--------- mysql-test/suite/jp/t/jp_like_sjis.test | 26 +++++++++++--------- mysql-test/suite/jp/t/jp_like_ujis.test | 26 +++++++++++--------- mysql-test/suite/jp/t/jp_like_utf8.test | 26 +++++++++++--------- mysql-test/suite/jp/t/jp_select_sjis.test | 26 +++++++++++--------- mysql-test/suite/jp/t/jp_select_ujis.test | 26 +++++++++++--------- mysql-test/suite/jp/t/jp_select_utf8.test | 26 +++++++++++--------- mysql-test/suite/jp/t/jp_where_sjis.test | 26 +++++++++++--------- mysql-test/suite/jp/t/jp_where_ujis.test | 26 +++++++++++--------- mysql-test/suite/jp/t/jp_where_utf8.test | 26 +++++++++++--------- 31 files changed, 211 insertions(+), 360 deletions(-) diff --git a/libmysqld/libmysqld.c b/libmysqld/libmysqld.c index eb47a045669..969ea442622 100644 --- a/libmysqld/libmysqld.c +++ b/libmysqld/libmysqld.c @@ -164,6 +164,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, port=0; unix_socket=0; + client_flag|=mysql->options.client_flag; /* Send client information for access check */ client_flag|=CLIENT_CAPABILITIES; if (client_flag & CLIENT_MULTI_STATEMENTS) diff --git a/mysql-test/suite/jp/r/jp_charset_sjis.result b/mysql-test/suite/jp/r/jp_charset_sjis.result index 80ef24a7334..312033be719 100644 --- a/mysql-test/suite/jp/r/jp_charset_sjis.result +++ b/mysql-test/suite/jp/r/jp_charset_sjis.result @@ -24,18 +24,6 @@ CREATE TABLE ` CREATE TABLE `‚s‚P‚O` (`‚b‚P` char(20)) DEFAULT CHARSET = sjis engine = bdb; CREATE TABLE `‚s‚P‚P` (`‚b‚P` char(20)) DEFAULT CHARSET = sjis engine = bdb; CREATE TABLE `‚s‚P‚Q` (`‚b‚P` char(20)) DEFAULT CHARSET = sjis engine = bdb; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚P`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚Q`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚R`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚S`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚T`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚U`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚V`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚W`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚X`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚P‚O`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚P‚P`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚P‚Q`; SELECT DISTINCT CHARSET(`‚b‚P`) FROM `‚s‚P`; CHARSET(`‚b‚P`) sjis diff --git a/mysql-test/suite/jp/r/jp_charset_ujis.result b/mysql-test/suite/jp/r/jp_charset_ujis.result index 964477896bd..4f6e68ba137 100644 --- a/mysql-test/suite/jp/r/jp_charset_ujis.result +++ b/mysql-test/suite/jp/r/jp_charset_ujis.result @@ -24,18 +24,6 @@ CREATE TABLE ` CREATE TABLE `£Ô£±£°` (`£Ã£±` char(20)) DEFAULT CHARSET = ujis engine = bdb; CREATE TABLE `£Ô£±£±` (`£Ã£±` char(20)) DEFAULT CHARSET = ujis engine = bdb; CREATE TABLE `£Ô£±£²` (`£Ã£±` char(20)) DEFAULT CHARSET = ujis engine = bdb; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£±`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£²`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£³`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£´`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£µ`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£¶`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£·`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£¸`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£¹`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£±£°`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£±£±`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£±£²`; SELECT DISTINCT CHARSET(`£Ã£±`) FROM `£Ô£±`; CHARSET(`£Ã£±`) ujis diff --git a/mysql-test/suite/jp/r/jp_charset_utf8.result b/mysql-test/suite/jp/r/jp_charset_utf8.result index 2fdd3fb1a6b..04140828d14 100644 --- a/mysql-test/suite/jp/r/jp_charset_utf8.result +++ b/mysql-test/suite/jp/r/jp_charset_utf8.result @@ -24,18 +24,6 @@ CREATE TABLE `ï¼´ï¼™` (`C1` char(20)) DEFAULT CHARSET = utf8 engine = heap; CREATE TABLE `T1ï¼` (`C1` char(20)) DEFAULT CHARSET = utf8 engine = bdb; CREATE TABLE `T11` (`C1` char(20)) DEFAULT CHARSET = utf8 engine = bdb; CREATE TABLE `T12` (`C1` char(20)) DEFAULT CHARSET = utf8 engine = bdb; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `T1`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `ï¼´ï¼’`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `T3`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `ï¼´ï¼”`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `T5`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `ï¼´ï¼–`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `ï¼´ï¼—`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `T8`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `ï¼´ï¼™`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `T1ï¼`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `T11`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `T12`; SELECT DISTINCT CHARSET(`C1`) FROM `T1`; CHARSET(`C1`) utf8 diff --git a/mysql-test/suite/jp/r/jp_convert_sjis.result b/mysql-test/suite/jp/r/jp_convert_sjis.result index ff8a3fb2cd9..bc581ca56b0 100644 --- a/mysql-test/suite/jp/r/jp_convert_sjis.result +++ b/mysql-test/suite/jp/r/jp_convert_sjis.result @@ -24,18 +24,6 @@ CREATE TABLE ` CREATE TABLE `‚s‚P‚O` (`‚b‚P` char(20), INDEX(`‚b‚P`)) DEFAULT CHARSET = sjis engine = bdb; CREATE TABLE `‚s‚P‚P` (`‚b‚P` char(20), INDEX(`‚b‚P`)) DEFAULT CHARSET = sjis engine = bdb; CREATE TABLE `‚s‚P‚Q` (`‚b‚P` char(20), INDEX(`‚b‚P`)) DEFAULT CHARSET = sjis engine = bdb; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚P`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚Q`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚R`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚S`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚T`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚U`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚V`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚W`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚X`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚P‚O`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚P‚P`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚P‚Q`; SELECT `‚b‚P`, CONVERT(`‚b‚P` using utf8) FROM `‚s‚P`; ‚b‚P CONVERT(`‚b‚P` using utf8) !"#$%&'()*+,-./ !"#$%&'()*+,-./ diff --git a/mysql-test/suite/jp/r/jp_convert_ujis.result b/mysql-test/suite/jp/r/jp_convert_ujis.result index 55f2ab0aea3..f256d8b08b4 100644 --- a/mysql-test/suite/jp/r/jp_convert_ujis.result +++ b/mysql-test/suite/jp/r/jp_convert_ujis.result @@ -24,18 +24,6 @@ CREATE TABLE ` CREATE TABLE `£Ô£±£°` (`£Ã£±` char(20), INDEX(`£Ã£±`)) DEFAULT CHARSET = ujis engine = bdb; CREATE TABLE `£Ô£±£±` (`£Ã£±` char(20), INDEX(`£Ã£±`)) DEFAULT CHARSET = ujis engine = bdb; CREATE TABLE `£Ô£±£²` (`£Ã£±` char(20), INDEX(`£Ã£±`)) DEFAULT CHARSET = ujis engine = bdb; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£±`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£²`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£³`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£´`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£µ`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£¶`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£·`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£¸`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£¹`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£±£°`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£±£±`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£±£²`; SELECT `£Ã£±`, CONVERT(`£Ã£±` using utf8) FROM `£Ô£±`; £Ã£± CONVERT(`£Ã£±` using utf8) !"#$%&'()*+,-./ !"#$%&'()*+,-./ diff --git a/mysql-test/suite/jp/r/jp_convert_utf8.result b/mysql-test/suite/jp/r/jp_convert_utf8.result index 505d6c1cebf..944f1c1068c 100644 --- a/mysql-test/suite/jp/r/jp_convert_utf8.result +++ b/mysql-test/suite/jp/r/jp_convert_utf8.result @@ -24,18 +24,6 @@ CREATE TABLE `ï¼´ï¼™` (`C1` char(20), INDEX(`C1`)) DEFAULT CHARSET = utf CREATE TABLE `T1ï¼` (`C1` char(20), INDEX(`C1`)) DEFAULT CHARSET = utf8 engine = bdb; CREATE TABLE `T11` (`C1` char(20), INDEX(`C1`)) DEFAULT CHARSET = utf8 engine = bdb; CREATE TABLE `T12` (`C1` char(20), INDEX(`C1`)) DEFAULT CHARSET = utf8 engine = bdb; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `T1`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `ï¼´ï¼’`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `T3`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `ï¼´ï¼”`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `T5`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `ï¼´ï¼–`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `ï¼´ï¼—`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `T8`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `ï¼´ï¼™`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `T1ï¼`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `T11`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `T12`; SELECT `C1`, CONVERT(`C1` using ujis) FROM `T1`; C1 CONVERT(`C1` using ujis) !"#$%&'()*+,-./ !"#$%&'()*+,-./ diff --git a/mysql-test/suite/jp/r/jp_like_sjis.result b/mysql-test/suite/jp/r/jp_like_sjis.result index a8145fb08f0..3e52781c7bd 100644 --- a/mysql-test/suite/jp/r/jp_like_sjis.result +++ b/mysql-test/suite/jp/r/jp_like_sjis.result @@ -24,18 +24,6 @@ CREATE TABLE ` CREATE TABLE `‚s‚P‚O` (`‚b‚P` char(20), INDEX(`‚b‚P`)) DEFAULT CHARSET = sjis engine = bdb; CREATE TABLE `‚s‚P‚P` (`‚b‚P` char(20), INDEX(`‚b‚P`)) DEFAULT CHARSET = sjis engine = bdb; CREATE TABLE `‚s‚P‚Q` (`‚b‚P` char(20), INDEX(`‚b‚P`)) DEFAULT CHARSET = sjis engine = bdb; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚P`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚Q`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚R`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚S`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚T`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚U`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚V`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚W`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚X`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚P‚O`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚P‚P`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚P‚Q`; SELECT * FROM `‚s‚P` WHERE `‚b‚P` LIKE ' %'; ‚b‚P !"#$%&'()*+,-./ diff --git a/mysql-test/suite/jp/r/jp_like_ujis.result b/mysql-test/suite/jp/r/jp_like_ujis.result index 5d623df0384..f685d185072 100644 --- a/mysql-test/suite/jp/r/jp_like_ujis.result +++ b/mysql-test/suite/jp/r/jp_like_ujis.result @@ -24,18 +24,6 @@ CREATE TABLE ` CREATE TABLE `£Ô£±£°` (`£Ã£±` char(20), INDEX(`£Ã£±`)) DEFAULT CHARSET = ujis engine = bdb; CREATE TABLE `£Ô£±£±` (`£Ã£±` char(20), INDEX(`£Ã£±`)) DEFAULT CHARSET = ujis engine = bdb; CREATE TABLE `£Ô£±£²` (`£Ã£±` char(20), INDEX(`£Ã£±`)) DEFAULT CHARSET = ujis engine = bdb; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£±`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£²`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£³`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£´`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£µ`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£¶`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£·`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£¸`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£¹`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£±£°`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£±£±`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£±£²`; SELECT * FROM `£Ô£±` WHERE `£Ã£±` LIKE ' %'; £Ã£± !"#$%&'()*+,-./ diff --git a/mysql-test/suite/jp/r/jp_like_utf8.result b/mysql-test/suite/jp/r/jp_like_utf8.result index bf48da79951..90b960ca3a7 100644 --- a/mysql-test/suite/jp/r/jp_like_utf8.result +++ b/mysql-test/suite/jp/r/jp_like_utf8.result @@ -24,18 +24,6 @@ CREATE TABLE `ï¼´ï¼™` (`C1` char(20), INDEX(`C1`)) DEFAULT CHARSET = utf CREATE TABLE `T1ï¼` (`C1` char(20), INDEX(`C1`)) DEFAULT CHARSET = utf8 engine = bdb; CREATE TABLE `T11` (`C1` char(20), INDEX(`C1`)) DEFAULT CHARSET = utf8 engine = bdb; CREATE TABLE `T12` (`C1` char(20), INDEX(`C1`)) DEFAULT CHARSET = utf8 engine = bdb; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `T1`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `ï¼´ï¼’`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `T3`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `ï¼´ï¼”`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `T5`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `ï¼´ï¼–`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `ï¼´ï¼—`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `T8`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `ï¼´ï¼™`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `T1ï¼`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `T11`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `T12`; SELECT * FROM `T1` WHERE `C1` LIKE ' %'; C1 !"#$%&'()*+,-./ diff --git a/mysql-test/suite/jp/r/jp_select_sjis.result b/mysql-test/suite/jp/r/jp_select_sjis.result index 652b538fb88..021b0d29f43 100644 --- a/mysql-test/suite/jp/r/jp_select_sjis.result +++ b/mysql-test/suite/jp/r/jp_select_sjis.result @@ -24,18 +24,6 @@ CREATE TABLE ` CREATE TABLE `‚s‚P‚O` (`‚b‚P` char(20), INDEX(`‚b‚P`)) DEFAULT CHARSET = sjis engine = bdb; CREATE TABLE `‚s‚P‚P` (`‚b‚P` char(20), INDEX(`‚b‚P`)) DEFAULT CHARSET = sjis engine = bdb; CREATE TABLE `‚s‚P‚Q` (`‚b‚P` char(20), INDEX(`‚b‚P`)) DEFAULT CHARSET = sjis engine = bdb; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚P`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚Q`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚R`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚S`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚T`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚U`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚V`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚W`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚X`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚P‚O`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚P‚P`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚P‚Q`; SELECT * FROM `‚s‚P`; ‚b‚P !"#$%&'()*+,-./ diff --git a/mysql-test/suite/jp/r/jp_select_ujis.result b/mysql-test/suite/jp/r/jp_select_ujis.result index 3eea73c8083..d70997b0a01 100644 --- a/mysql-test/suite/jp/r/jp_select_ujis.result +++ b/mysql-test/suite/jp/r/jp_select_ujis.result @@ -24,18 +24,6 @@ CREATE TABLE ` CREATE TABLE `£Ô£±£°` (c1 char(20), INDEX(c1)) DEFAULT CHARSET = ujis engine = bdb; CREATE TABLE `£Ô£±£±` (c1 char(20), INDEX(c1)) DEFAULT CHARSET = ujis engine = bdb; CREATE TABLE `£Ô£±£²` (c1 char(20), INDEX(c1)) DEFAULT CHARSET = ujis engine = bdb; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£±`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£²`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£³`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£´`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£µ`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£¶`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£·`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£¸`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£¹`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£±£°`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£±£±`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£±£²`; SELECT * FROM `£Ô£±`; c1 !"#$%&'()*+,-./ diff --git a/mysql-test/suite/jp/r/jp_select_utf8.result b/mysql-test/suite/jp/r/jp_select_utf8.result index 43704ad2f6e..8bc61b802be 100644 --- a/mysql-test/suite/jp/r/jp_select_utf8.result +++ b/mysql-test/suite/jp/r/jp_select_utf8.result @@ -24,18 +24,6 @@ CREATE TABLE `ï¼´ï¼™` (c1 char(20), INDEX(c1)) DEFAULT CHARSET = utf8 engine = h CREATE TABLE `T1ï¼` (c1 char(20), INDEX(c1)) DEFAULT CHARSET = utf8 engine = bdb; CREATE TABLE `T11` (c1 char(20), INDEX(c1)) DEFAULT CHARSET = utf8 engine = bdb; CREATE TABLE `T12` (c1 char(20), INDEX(c1)) DEFAULT CHARSET = utf8 engine = bdb; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `T1`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `ï¼´ï¼’`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `T3`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `ï¼´ï¼”`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `T5`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `ï¼´ï¼–`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `ï¼´ï¼—`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `T8`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `ï¼´ï¼™`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `T1ï¼`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `T11`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `T12`; SELECT * FROM `T1`; c1 !"#$%&'()*+,-./ diff --git a/mysql-test/suite/jp/r/jp_where_sjis.result b/mysql-test/suite/jp/r/jp_where_sjis.result index a3cbc24c113..e8be6e10850 100644 --- a/mysql-test/suite/jp/r/jp_where_sjis.result +++ b/mysql-test/suite/jp/r/jp_where_sjis.result @@ -24,18 +24,6 @@ CREATE TABLE ` CREATE TABLE `‚s‚P‚O` (`‚b‚P` char(20), INDEX(`‚b‚P`)) DEFAULT CHARSET = sjis engine = bdb; CREATE TABLE `‚s‚P‚P` (`‚b‚P` char(20), INDEX(`‚b‚P`)) DEFAULT CHARSET = sjis engine = bdb; CREATE TABLE `‚s‚P‚Q` (`‚b‚P` char(20), INDEX(`‚b‚P`)) DEFAULT CHARSET = sjis engine = bdb; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚P`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚Q`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚R`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚S`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚T`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚U`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚V`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚W`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚X`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚P‚O`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚P‚P`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚P‚Q`; SELECT * FROM `‚s‚P` WHERE `‚b‚P` = '°±²³´µ¶·¸¹º»¼½¾¿'; ‚b‚P °±²³´µ¶·¸¹º»¼½¾¿ diff --git a/mysql-test/suite/jp/r/jp_where_ujis.result b/mysql-test/suite/jp/r/jp_where_ujis.result index b13b8a10ef8..6b7dc4dde22 100644 --- a/mysql-test/suite/jp/r/jp_where_ujis.result +++ b/mysql-test/suite/jp/r/jp_where_ujis.result @@ -24,18 +24,6 @@ CREATE TABLE ` CREATE TABLE `£Ô£±£°` (`£Ã£±` char(20), INDEX(`£Ã£±`)) DEFAULT CHARSET = ujis engine = bdb; CREATE TABLE `£Ô£±£±` (`£Ã£±` char(20), INDEX(`£Ã£±`)) DEFAULT CHARSET = ujis engine = bdb; CREATE TABLE `£Ô£±£²` (`£Ã£±` char(20), INDEX(`£Ã£±`)) DEFAULT CHARSET = ujis engine = bdb; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£±`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£²`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£³`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£´`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£µ`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£¶`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£·`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£¸`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£¹`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£±£°`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£±£±`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£±£²`; SELECT * FROM `£Ô£±` WHERE `£Ã£±` = 'Ž°Ž±Ž²Ž³Ž´ŽµŽ¶Ž·Ž¸Ž¹ŽºŽ»Ž¼Ž½Ž¾Ž¿'; £Ã£± Ž°Ž±Ž²Ž³Ž´ŽµŽ¶Ž·Ž¸Ž¹ŽºŽ»Ž¼Ž½Ž¾Ž¿ diff --git a/mysql-test/suite/jp/r/jp_where_utf8.result b/mysql-test/suite/jp/r/jp_where_utf8.result index d69aaf8715d..cd7a4c0e500 100644 --- a/mysql-test/suite/jp/r/jp_where_utf8.result +++ b/mysql-test/suite/jp/r/jp_where_utf8.result @@ -24,18 +24,6 @@ CREATE TABLE `ï¼´ï¼™` (`C1` char(20), INDEX(`C1`)) DEFAULT CHARSET = utf CREATE TABLE `T1ï¼` (`C1` char(20), INDEX(`C1`)) DEFAULT CHARSET = utf8 engine = bdb; CREATE TABLE `T11` (`C1` char(20), INDEX(`C1`)) DEFAULT CHARSET = utf8 engine = bdb; CREATE TABLE `T12` (`C1` char(20), INDEX(`C1`)) DEFAULT CHARSET = utf8 engine = bdb; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `T1`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `ï¼´ï¼’`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `T3`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `ï¼´ï¼”`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `T5`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `ï¼´ï¼–`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `ï¼´ï¼—`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `T8`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `ï¼´ï¼™`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `T1ï¼`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `T11`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `T12`; SELECT * FROM `T1` WHERE `C1` = 'ーアイウエオカキクケコサシスセソ'; C1 ーアイウエオカキクケコサシスセソ diff --git a/mysql-test/suite/jp/t/jp_charset_sjis.test b/mysql-test/suite/jp/t/jp_charset_sjis.test index 276be86cd9d..26a56fb61d6 100644 --- a/mysql-test/suite/jp/t/jp_charset_sjis.test +++ b/mysql-test/suite/jp/t/jp_charset_sjis.test @@ -40,18 +40,20 @@ CREATE TABLE ` # jisx0201 hankaku-katakana data # jisx0208 data - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚P`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚Q`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚R`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚S`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚T`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚U`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚V`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚W`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚X`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚P‚O`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚P‚P`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚P‚Q`; +--disable_query_log + --eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚P`; + --eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚Q`; + --eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚R`; + --eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚S`; + --eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚T`; + --eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚U`; + --eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚V`; + --eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚W`; + --eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚X`; + --eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚P‚O`; + --eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚P‚P`; + --eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚P‚Q`; +--enable_query_log #InnoDB SELECT DISTINCT CHARSET(`‚b‚P`) FROM `‚s‚P`; diff --git a/mysql-test/suite/jp/t/jp_charset_ujis.test b/mysql-test/suite/jp/t/jp_charset_ujis.test index a8a6544537a..6308c7124ee 100644 --- a/mysql-test/suite/jp/t/jp_charset_ujis.test +++ b/mysql-test/suite/jp/t/jp_charset_ujis.test @@ -42,18 +42,20 @@ CREATE TABLE ` # jisx0208 data # jisx0212 supplemental character data - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£±`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£²`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£³`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£´`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£µ`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£¶`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£·`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£¸`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£¹`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£±£°`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£±£±`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£±£²`; +--disable_query_log + --eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£±`; + --eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£²`; + --eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£³`; + --eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£´`; + --eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£µ`; + --eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£¶`; + --eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£·`; + --eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£¸`; + --eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£¹`; + --eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£±£°`; + --eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£±£±`; + --eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£±£²`; +--enable_query_log #InnoDB SELECT DISTINCT CHARSET(`£Ã£±`) FROM `£Ô£±`; diff --git a/mysql-test/suite/jp/t/jp_charset_utf8.test b/mysql-test/suite/jp/t/jp_charset_utf8.test index 7d8311c2f72..dcce0477204 100644 --- a/mysql-test/suite/jp/t/jp_charset_utf8.test +++ b/mysql-test/suite/jp/t/jp_charset_utf8.test @@ -40,18 +40,20 @@ CREATE TABLE `T12` (`C1` char(20)) DEFAULT CHARSET = utf8 engine = bdb # jisx0208 data # jisx0212 supplemental character data - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `T1`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `ï¼´ï¼’`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `T3`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `ï¼´ï¼”`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `T5`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `ï¼´ï¼–`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `ï¼´ï¼—`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `T8`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `ï¼´ï¼™`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `T1ï¼`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `T11`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `T12`; +--disable_query_log + --eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `T1`; + --eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `ï¼´ï¼’`; + --eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `T3`; + --eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `ï¼´ï¼”`; + --eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `T5`; + --eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `ï¼´ï¼–`; + --eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `ï¼´ï¼—`; + --eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `T8`; + --eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `ï¼´ï¼™`; + --eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `T1ï¼`; + --eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `T11`; + --eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `T12`; +--enable_query_log #InnoDB SELECT DISTINCT CHARSET(`C1`) FROM `T1`; diff --git a/mysql-test/suite/jp/t/jp_convert_sjis.test b/mysql-test/suite/jp/t/jp_convert_sjis.test index 835328c92eb..4e76b414442 100644 --- a/mysql-test/suite/jp/t/jp_convert_sjis.test +++ b/mysql-test/suite/jp/t/jp_convert_sjis.test @@ -41,18 +41,20 @@ CREATE TABLE ` # jisx0208 data # jisx0212 supplemental character data - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚P`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚Q`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚R`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚S`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚T`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚U`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚V`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚W`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚X`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚P‚O`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚P‚P`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚P‚Q`; +--disable_query_log + --eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚P`; + --eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚Q`; + --eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚R`; + --eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚S`; + --eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚T`; + --eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚U`; + --eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚V`; + --eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚W`; + --eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚X`; + --eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚P‚O`; + --eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚P‚P`; + --eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚P‚Q`; +--enable_query_log #InnoDB SELECT `‚b‚P`, CONVERT(`‚b‚P` using utf8) FROM `‚s‚P`; diff --git a/mysql-test/suite/jp/t/jp_convert_ujis.test b/mysql-test/suite/jp/t/jp_convert_ujis.test index 4409b6cad90..7d53d1853d3 100644 --- a/mysql-test/suite/jp/t/jp_convert_ujis.test +++ b/mysql-test/suite/jp/t/jp_convert_ujis.test @@ -42,18 +42,20 @@ CREATE TABLE ` # jisx0208 data # jisx0212 supplemental character data - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£±`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£²`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£³`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£´`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£µ`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£¶`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£·`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£¸`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£¹`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£±£°`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£±£±`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£±£²`; +--disable_query_log +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£±`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£²`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£³`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£´`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£µ`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£¶`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£·`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£¸`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£¹`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£±£°`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£±£±`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£±£²`; +--enable_query_log #InnoDB SELECT `£Ã£±`, CONVERT(`£Ã£±` using utf8) FROM `£Ô£±`; diff --git a/mysql-test/suite/jp/t/jp_convert_utf8.test b/mysql-test/suite/jp/t/jp_convert_utf8.test index e7c180e72fc..3d81704e87c 100644 --- a/mysql-test/suite/jp/t/jp_convert_utf8.test +++ b/mysql-test/suite/jp/t/jp_convert_utf8.test @@ -40,18 +40,20 @@ CREATE TABLE `T12` (`C1` char(20), INDEX(`C1`)) DEFAULT CHARSET = # jisx0208 data # jisx0212 supplemental character data - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `T1`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `ï¼´ï¼’`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `T3`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `ï¼´ï¼”`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `T5`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `ï¼´ï¼–`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `ï¼´ï¼—`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `T8`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `ï¼´ï¼™`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `T1ï¼`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `T11`; - LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `T12`; +--disable_query_log +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `T1`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `ï¼´ï¼’`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `T3`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `ï¼´ï¼”`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `T5`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `ï¼´ï¼–`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `ï¼´ï¼—`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `T8`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `ï¼´ï¼™`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `T1ï¼`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `T11`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `T12`; +--enable_query_log #InnoDB SELECT `C1`, CONVERT(`C1` using ujis) FROM `T1`; diff --git a/mysql-test/suite/jp/t/jp_like_sjis.test b/mysql-test/suite/jp/t/jp_like_sjis.test index 1cb7aadb876..ad2c5f7b465 100644 --- a/mysql-test/suite/jp/t/jp_like_sjis.test +++ b/mysql-test/suite/jp/t/jp_like_sjis.test @@ -40,18 +40,20 @@ CREATE TABLE ` # jisx0201 hankaku-katakana data # jisx0208 data -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚P`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚Q`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚R`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚S`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚T`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚U`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚V`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚W`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚X`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚P‚O`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚P‚P`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚P‚Q`; +--disable_query_log +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚P`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚Q`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚R`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚S`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚T`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚U`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚V`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚W`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚X`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚P‚O`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚P‚P`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚P‚Q`; +--enable_query_log #InnoDB SELECT * FROM `‚s‚P` WHERE `‚b‚P` LIKE ' %'; diff --git a/mysql-test/suite/jp/t/jp_like_ujis.test b/mysql-test/suite/jp/t/jp_like_ujis.test index 56c4fa8a8b0..c3660e8f88f 100644 --- a/mysql-test/suite/jp/t/jp_like_ujis.test +++ b/mysql-test/suite/jp/t/jp_like_ujis.test @@ -42,18 +42,20 @@ CREATE TABLE ` # jisx0208 data # jisx0212 supplemental character data -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£±`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£²`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£³`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£´`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£µ`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£¶`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£·`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£¸`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£¹`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£±£°`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£±£±`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£±£²`; +--disable_query_log +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£±`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£²`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£³`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£´`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£µ`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£¶`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£·`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£¸`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£¹`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£±£°`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£±£±`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£±£²`; +--enable_query_log #InnoDB SELECT * FROM `£Ô£±` WHERE `£Ã£±` LIKE ' %'; diff --git a/mysql-test/suite/jp/t/jp_like_utf8.test b/mysql-test/suite/jp/t/jp_like_utf8.test index f6cc895d814..57fc1584471 100644 --- a/mysql-test/suite/jp/t/jp_like_utf8.test +++ b/mysql-test/suite/jp/t/jp_like_utf8.test @@ -40,18 +40,20 @@ CREATE TABLE `T12` (`C1` char(20), INDEX(`C1`)) DEFAULT CHARSET = # jisx0208 data # jisx0212 supplemental character data -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `T1`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `ï¼´ï¼’`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `T3`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `ï¼´ï¼”`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `T5`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `ï¼´ï¼–`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `ï¼´ï¼—`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `T8`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `ï¼´ï¼™`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `T1ï¼`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `T11`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `T12`; +--disable_query_log +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `T1`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `ï¼´ï¼’`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `T3`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `ï¼´ï¼”`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `T5`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `ï¼´ï¼–`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `ï¼´ï¼—`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `T8`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `ï¼´ï¼™`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `T1ï¼`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `T11`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `T12`; +--enable_query_log #InnoDB SELECT * FROM `T1` WHERE `C1` LIKE ' %'; diff --git a/mysql-test/suite/jp/t/jp_select_sjis.test b/mysql-test/suite/jp/t/jp_select_sjis.test index fc80ce01471..698d87a6852 100644 --- a/mysql-test/suite/jp/t/jp_select_sjis.test +++ b/mysql-test/suite/jp/t/jp_select_sjis.test @@ -41,18 +41,20 @@ CREATE TABLE ` # jisx0208 data # jisx0212 supplemental character data -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚P`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚Q`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚R`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚S`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚T`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚U`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚V`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚W`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚X`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚P‚O`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚P‚P`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚P‚Q`; +--disable_query_log +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚P`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚Q`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚R`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚S`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚T`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚U`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚V`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚W`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚X`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚P‚O`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚P‚P`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚P‚Q`; +--enable_query_log #InnoDB SELECT * FROM `‚s‚P`; diff --git a/mysql-test/suite/jp/t/jp_select_ujis.test b/mysql-test/suite/jp/t/jp_select_ujis.test index 0e4d1ffc771..7c8ec46d06e 100644 --- a/mysql-test/suite/jp/t/jp_select_ujis.test +++ b/mysql-test/suite/jp/t/jp_select_ujis.test @@ -42,18 +42,20 @@ CREATE TABLE ` # jisx0208 data # jisx0212 supplemental character data -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£±`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£²`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£³`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£´`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£µ`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£¶`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£·`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£¸`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£¹`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£±£°`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£±£±`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£±£²`; +--disable_query_log +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£±`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£²`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£³`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£´`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£µ`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£¶`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£·`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£¸`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£¹`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£±£°`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£±£±`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£±£²`; +--enable_query_log #InnoDB SELECT * FROM `£Ô£±`; diff --git a/mysql-test/suite/jp/t/jp_select_utf8.test b/mysql-test/suite/jp/t/jp_select_utf8.test index 88fd6677f7c..f410333fcfa 100644 --- a/mysql-test/suite/jp/t/jp_select_utf8.test +++ b/mysql-test/suite/jp/t/jp_select_utf8.test @@ -40,18 +40,20 @@ CREATE TABLE `T12` (c1 char(20), INDEX(c1)) DEFAULT CHARSET = utf8 engine # jisx0208 data # jisx0212 supplemental character data -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `T1`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `ï¼´ï¼’`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `T3`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `ï¼´ï¼”`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `T5`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `ï¼´ï¼–`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `ï¼´ï¼—`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `T8`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `ï¼´ï¼™`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `T1ï¼`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `T11`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `T12`; +--disable_query_log +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `T1`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `ï¼´ï¼’`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `T3`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `ï¼´ï¼”`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `T5`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `ï¼´ï¼–`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `ï¼´ï¼—`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `T8`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `ï¼´ï¼™`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `T1ï¼`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `T11`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `T12`; +--enable_query_log #InnoDB SELECT * FROM `T1`; diff --git a/mysql-test/suite/jp/t/jp_where_sjis.test b/mysql-test/suite/jp/t/jp_where_sjis.test index 890a4c28f3c..6fda91a7b4b 100644 --- a/mysql-test/suite/jp/t/jp_where_sjis.test +++ b/mysql-test/suite/jp/t/jp_where_sjis.test @@ -41,18 +41,20 @@ CREATE TABLE ` # jisx0208 data # jisx0212 supplemental character data -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚P`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚Q`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚R`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚S`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚T`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚U`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚V`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚W`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚X`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚P‚O`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚P‚P`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚P‚Q`; +--disable_query_log +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚P`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚Q`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚R`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚S`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚T`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚U`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚V`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚W`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚X`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_sjis.dat' INTO TABLE `‚s‚P‚O`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_sjis.dat' INTO TABLE `‚s‚P‚P`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_sjis2.dat' INTO TABLE `‚s‚P‚Q`; +--enable_query_log #InnoDB SELECT * FROM `‚s‚P` WHERE `‚b‚P` = '°±²³´µ¶·¸¹º»¼½¾¿'; diff --git a/mysql-test/suite/jp/t/jp_where_ujis.test b/mysql-test/suite/jp/t/jp_where_ujis.test index 2f0924e8c8e..6343610306e 100644 --- a/mysql-test/suite/jp/t/jp_where_ujis.test +++ b/mysql-test/suite/jp/t/jp_where_ujis.test @@ -42,18 +42,20 @@ CREATE TABLE ` # jisx0208 data # jisx0212 supplemental character data -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£±`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£²`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£³`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£´`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£µ`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£¶`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£·`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£¸`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£¹`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£±£°`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£±£±`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£±£²`; +--disable_query_log +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£±`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£²`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£³`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£´`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£µ`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£¶`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£·`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£¸`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£¹`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_ujis.dat' INTO TABLE `£Ô£±£°`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_ujis.dat' INTO TABLE `£Ô£±£±`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0212_ujis.dat' INTO TABLE `£Ô£±£²`; +--enable_query_log #InnoDB SELECT * FROM `£Ô£±` WHERE `£Ã£±` = 'Ž°Ž±Ž²Ž³Ž´ŽµŽ¶Ž·Ž¸Ž¹ŽºŽ»Ž¼Ž½Ž¾Ž¿'; diff --git a/mysql-test/suite/jp/t/jp_where_utf8.test b/mysql-test/suite/jp/t/jp_where_utf8.test index 231553e8819..a37b6f1a41a 100644 --- a/mysql-test/suite/jp/t/jp_where_utf8.test +++ b/mysql-test/suite/jp/t/jp_where_utf8.test @@ -40,18 +40,20 @@ CREATE TABLE `T12` (`C1` char(20), INDEX(`C1`)) DEFAULT CHARSET = # jisx0208 data # jisx0212 supplemental character data -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `T1`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `ï¼´ï¼’`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `T3`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `ï¼´ï¼”`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `T5`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `ï¼´ï¼–`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `ï¼´ï¼—`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `T8`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `ï¼´ï¼™`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `T1ï¼`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `T11`; -LOAD DATA LOCAL INFILE 'suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `T12`; +--disable_query_log +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `T1`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `ï¼´ï¼’`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `T3`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `ï¼´ï¼”`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `T5`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `ï¼´ï¼–`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `ï¼´ï¼—`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `T8`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `ï¼´ï¼™`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0201_utf8.dat' INTO TABLE `T1ï¼`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0208_utf8.dat' INTO TABLE `T11`; +--eval LOAD DATA LOCAL INFILE '$MYSQL_TEST_DIR/suite/jp/std_data/jisx0212_utf8.dat' INTO TABLE `T12`; +--enable_query_log #InnoDB SELECT * FROM `T1` WHERE `C1` = 'ーアイウエオカキクケコサシスセソ'; From 7cf8f7a4bb465eca331fb08568127eadb709a4a2 Mon Sep 17 00:00:00 2001 From: Satya B Date: Thu, 17 Sep 2009 11:59:43 +0530 Subject: [PATCH 48/80] Applying InnoDB snapshot 5.1-ss5282, Fixes BUG#44030 1. Fixes BUG#44030 - Error: (1500) Couldn't read the MAX(ID) autoinc value from the index (PRIMARY) 2. Disables the innodb-autoinc test for innodb plugin temporarily. The testcase for this bug has different result file for InnoDB plugin. Should add the testcase to Innodb suite with a different result file. Detailed revision comments: r5243 | sunny | 2009-06-04 03:17:14 +0300 (Thu, 04 Jun 2009) | 14 lines branches/5.1: When the InnoDB and MySQL data dictionaries go out of sync, before the bug fix we would assert on missing autoinc columns. With this fix we allow MySQL to open the table but set the next autoinc value for the column to the MAX value. This effectively disables the next value generation. INSERTs will fail with a generic AUTOINC failure. However, the user should be able to read/dump the table, set the column values explicitly, use ALTER TABLE to set the next autoinc value and/or sync the two data dictionaries to resume normal operations. Fix Bug#44030 Error: (1500) Couldn't read the MAX(ID) autoinc value from the index (PRIMARY) rb://118 r5252 | sunny | 2009-06-04 10:16:24 +0300 (Thu, 04 Jun 2009) | 2 lines branches/5.1: The version of the result file checked in was broken in r5243. r5259 | vasil | 2009-06-05 10:29:16 +0300 (Fri, 05 Jun 2009) | 7 lines branches/5.1: Remove the word "Error" from the printout because the mysqltest suite interprets it as an error and thus the innodb-autoinc test fails. Approved by: Sunny (via IM) r5466 | vasil | 2009-07-02 10:46:45 +0300 (Thu, 02 Jul 2009) | 6 lines branches/5.1: Adjust the failing innodb-autoinc test to conform to the latest behavior of the MySQL code. The idea and the comment in innodb-autoinc.test come from Sunny. --- mysql-test/lib/mtr_cases.pm | 1 + mysql-test/r/innodb-autoinc.result | 22 ++++++++++++++++++++++ mysql-test/t/innodb-autoinc.test | 24 ++++++++++++++++++++++++ storage/innobase/handler/ha_innodb.cc | 27 +++++++++++++++++++++------ 4 files changed, 68 insertions(+), 6 deletions(-) diff --git a/mysql-test/lib/mtr_cases.pm b/mysql-test/lib/mtr_cases.pm index 873339166b3..efd9980eb7a 100644 --- a/mysql-test/lib/mtr_cases.pm +++ b/mysql-test/lib/mtr_cases.pm @@ -495,6 +495,7 @@ sub collect_one_suite($) # Exceptions next if ($test->{'name'} eq 'main.innodb'); # Failed with wrong errno (fk) next if ($test->{'name'} eq 'main.index_merge_innodb'); # Explain diff + next if ($test->{'name'} eq 'main.innodb-autoinc'); # Need dfrnt result file # innodb_file_per_table is rw with innodb_plugin next if ($test->{'name'} eq 'sys_vars.innodb_file_per_table_basic'); # innodb_lock_wait_timeout is rw with innodb_plugin diff --git a/mysql-test/r/innodb-autoinc.result b/mysql-test/r/innodb-autoinc.result index ade4db35ce6..76575ae4160 100644 --- a/mysql-test/r/innodb-autoinc.result +++ b/mysql-test/r/innodb-autoinc.result @@ -867,3 +867,25 @@ INSERT INTO t2 SELECT NULL FROM t1; Got one of the listed errors DROP TABLE t1; DROP TABLE t2; +CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (null); +INSERT INTO t1 VALUES (null); +ALTER TABLE t1 CHANGE c1 d1 INT NOT NULL AUTO_INCREMENT; +SELECT * FROM t1; +d1 +1 +3 +SELECT * FROM t1; +d1 +1 +3 +INSERT INTO t1 VALUES(null); +ALTER TABLE t1 AUTO_INCREMENT = 3; +INSERT INTO t1 VALUES(null); +SELECT * FROM t1; +d1 +1 +3 +4 +5 +DROP TABLE t1; diff --git a/mysql-test/t/innodb-autoinc.test b/mysql-test/t/innodb-autoinc.test index d76b29a7dc8..b51014ef4b3 100644 --- a/mysql-test/t/innodb-autoinc.test +++ b/mysql-test/t/innodb-autoinc.test @@ -478,3 +478,27 @@ INSERT INTO t2 SELECT c1 FROM t1; INSERT INTO t2 SELECT NULL FROM t1; DROP TABLE t1; DROP TABLE t2; +# +# 44030: Error: (1500) Couldn't read the MAX(ID) autoinc value from +# the index (PRIMARY) +# This test requires a restart of the server +CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (null); +INSERT INTO t1 VALUES (null); +ALTER TABLE t1 CHANGE c1 d1 INT NOT NULL AUTO_INCREMENT; +SELECT * FROM t1; +# Restart the server +-- source include/restart_mysqld.inc +# The MySQL and InnoDB data dictionaries should now be out of sync. +# The select should print message to the error log +SELECT * FROM t1; +# MySQL have made a change (http://lists.mysql.com/commits/75268) that no +# longer results in the two data dictionaries being out of sync. If they +# revert their changes then this check for ER_AUTOINC_READ_FAILED will need +# to be enabled. +# -- error ER_AUTOINC_READ_FAILED,1467 +INSERT INTO t1 VALUES(null); +ALTER TABLE t1 AUTO_INCREMENT = 3; +INSERT INTO t1 VALUES(null); +SELECT * FROM t1; +DROP TABLE t1; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index b35f83cce58..207406f8673 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -2515,12 +2515,28 @@ ha_innobase::innobase_initialize_autoinc() dict_table_autoinc_initialize(innodb_table, auto_inc); - } else { + } else if (error == DB_RECORD_NOT_FOUND) { ut_print_timestamp(stderr); - fprintf(stderr, " InnoDB: Error: (%lu) Couldn't read " - "the MAX(%s) autoinc value from the " - "index (%s).\n", error, col_name, index->name); - } + fprintf(stderr, " InnoDB: MySQL and InnoDB data " + "dictionaries are out of sync.\n" + "InnoDB: Unable to find the AUTOINC column %s in the " + "InnoDB table %s.\n" + "InnoDB: We set the next AUTOINC column value to the " + "maximum possible value,\n" + "InnoDB: in effect disabling the AUTOINC next value " + "generation.\n" + "InnoDB: You can either set the next AUTOINC value " + "explicitly using ALTER TABLE\n" + "InnoDB: or fix the data dictionary by recreating " + "the table.\n", + col_name, index->table->name); + + auto_inc = 0xFFFFFFFFFFFFFFFFULL; + + dict_table_autoinc_initialize(innodb_table, auto_inc); + + error = DB_SUCCESS; + } /* else other errors are still fatal */ return(ulong(error)); } @@ -2731,7 +2747,6 @@ retry: if (dict_table_autoinc_read(prebuilt->table) == 0) { error = innobase_initialize_autoinc(); - /* Should always succeed! */ ut_a(error == DB_SUCCESS); } From 31809edc24b2d6ee6b4a9932d5af0b2247ecf8dc Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Thu, 17 Sep 2009 14:25:07 +0300 Subject: [PATCH 49/80] Bug #46917: mysqd-nt installs wrong When parsing the service installation parameter in default_service_handling() make sure the value of the optional parameter doesn't overwrite it's name. --- sql/mysqld.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index afbbf753813..ce1d562d0ca 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4022,7 +4022,7 @@ default_service_handling(char **argv, if (opt_delim= strchr(extra_opt, '=')) { size_t length= ++opt_delim - extra_opt; - strnmov(pos, extra_opt, length); + pos= strnmov(pos, extra_opt, length); } else opt_delim= extra_opt; From 2535ede7138cb4d1e8986d18b4154c377ba37f3f Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Thu, 17 Sep 2009 16:33:23 +0500 Subject: [PATCH 50/80] Bug#42364 SHOW ERRORS returns empty resultset after dropping non existent table additional backport of of bug43138 fix mysql-test/t/myisam-system.test: additional backport of of bug43138 fix sql/sql_db.cc: additional backport of of bug43138 fix --- mysql-test/r/trigger_notembedded.result | 2 -- mysql-test/t/myisam-system.test | 6 +++--- sql/sql_db.cc | 4 ++++ 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/trigger_notembedded.result b/mysql-test/r/trigger_notembedded.result index 335e6910a3a..d66308a9bd7 100644 --- a/mysql-test/r/trigger_notembedded.result +++ b/mysql-test/r/trigger_notembedded.result @@ -180,8 +180,6 @@ NULL mysqltest_db1 trg5 DELETE NULL mysqltest_db1 t1 0 NULL SET @a = 5 ROW BEFOR DROP USER mysqltest_dfn@localhost; DROP USER mysqltest_inv@localhost; DROP DATABASE mysqltest_db1; -Warnings: -Warning 1454 No definer attribute for trigger 'mysqltest_db1'.'trg1'. The trigger will be activated under the authorization of the invoker, which may have insufficient privileges. Please recreate the trigger. DELETE FROM mysql.user WHERE User LIKE 'mysqltest_%'; DELETE FROM mysql.db WHERE User LIKE 'mysqltest_%'; DELETE FROM mysql.tables_priv WHERE User LIKE 'mysqltest_%'; diff --git a/mysql-test/t/myisam-system.test b/mysql-test/t/myisam-system.test index dc5bb58b6a2..d908e639a4e 100644 --- a/mysql-test/t/myisam-system.test +++ b/mysql-test/t/myisam-system.test @@ -12,11 +12,11 @@ let $MYSQLD_DATADIR= `select @@datadir`; drop table if exists t1; create table t1 (a int) engine=myisam; --remove_file $MYSQLD_DATADIR/test/t1.MYI ---error 1051,6 +--error ER_BAD_TABLE_ERROR,6 drop table t1; create table t1 (a int) engine=myisam; --remove_file $MYSQLD_DATADIR/test/t1.MYD ---error 1105,6,29 +--error ER_BAD_TABLE_ERROR,6,29 drop table t1; ---error 1051 +--error ER_BAD_TABLE_ERROR drop table t1; diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 3fca5bd7df6..bcc8fcf54fc 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -907,6 +907,9 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) remove_db_from_cache(db); pthread_mutex_unlock(&LOCK_open); + Drop_table_error_handler err_handler(thd->get_internal_handler()); + thd->push_internal_handler(&err_handler); + error= -1; /* We temporarily disable the binary log while dropping the objects @@ -939,6 +942,7 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) error = 0; reenable_binlog(thd); } + thd->pop_internal_handler(); } if (!silent && deleted>=0) { From 5999113f3323f520213b809e11fb439805bc514f Mon Sep 17 00:00:00 2001 From: Anurag Shekhar Date: Thu, 17 Sep 2009 17:35:43 +0530 Subject: [PATCH 51/80] Bug #45840 read_buffer_size allocated for each partition when "insert into.. select * from" When inserting into a partitioned table using 'insert into select * from ', read_buffer_size bytes of memory are allocated for each partition in the target table. This resulted in large memory consumption when the number of partitions are high. This patch introduces a new method which tries to estimate the buffer size required for each partition and limits the maximum buffer size used to maximum of 10 * read_buffer_size, 11 * read_buffer_size in case of monotonic partition functions. sql/ha_partition.cc: Introduced a method ha_partition::estimate_read_buffer_size to estimate buffer size required for each partition. Method ha_partition::start_part_bulk_insert updated to update the read_buffer_size before calling bulk upload in storage engines. Added thd in ha_partition::start_part_bulk_insert method signature. sql/ha_partition.h: Introduced a method ha_partition::estimate_read_buffer_size. Added thd in ha_partition::start_part_bulk_insert method signature. --- sql/ha_partition.cc | 52 ++++++++++++++++++++++++++++++++++++++++++--- sql/ha_partition.h | 3 ++- 2 files changed, 51 insertions(+), 4 deletions(-) diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 5b053ab9cac..b27f493b80a 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -3037,7 +3037,7 @@ int ha_partition::write_row(uchar * buf) } m_last_part= part_id; DBUG_PRINT("info", ("Insert in partition %d", part_id)); - start_part_bulk_insert(part_id); + start_part_bulk_insert(thd, part_id); tmp_disable_binlog(thd); /* Do not replicate the low-level changes. */ error= m_file[part_id]->ha_write_row(buf); @@ -3101,7 +3101,7 @@ int ha_partition::update_row(const uchar *old_data, uchar *new_data) } m_last_part= new_part_id; - start_part_bulk_insert(new_part_id); + start_part_bulk_insert(thd, new_part_id); if (new_part_id == old_part_id) { DBUG_PRINT("info", ("Update in partition %d", new_part_id)); @@ -3282,17 +3282,63 @@ void ha_partition::start_bulk_insert(ha_rows rows) Check if start_bulk_insert has been called for this partition, if not, call it and mark it called */ -void ha_partition::start_part_bulk_insert(uint part_id) +void ha_partition::start_part_bulk_insert(THD *thd, uint part_id) { + long old_buffer_size; if (!bitmap_is_set(&m_bulk_insert_started, part_id) && bitmap_is_set(&m_bulk_insert_started, m_tot_parts)) { + old_buffer_size= thd->variables.read_buff_size; + /* Update read_buffer_size for this partition */ + thd->variables.read_buff_size= estimate_read_buffer_size(old_buffer_size); m_file[part_id]->ha_start_bulk_insert(guess_bulk_insert_rows()); bitmap_set_bit(&m_bulk_insert_started, part_id); + thd->variables.read_buff_size= old_buffer_size; } m_bulk_inserted_rows++; } +/* + Estimate the read buffer size for each partition. + SYNOPSIS + ha_partition::estimate_read_buffer_size() + original_size read buffer size originally set for the server + RETURN VALUE + estimated buffer size. + DESCRIPTION + If the estimated number of rows to insert is less than 10 (but not 0) + the new buffer size is same as original buffer size. + In case of first partition of when partition function is monotonic + new buffer size is same as the original buffer size. + For rest of the partition total buffer of 10*original_size is divided + equally if number of partition is more than 10 other wise each partition + will be allowed to use original buffer size. +*/ +long ha_partition::estimate_read_buffer_size(long original_size) +{ + /* + If number of rows to insert is less than 10, but not 0, + return original buffer size. + */ + if (estimation_rows_to_insert && (estimation_rows_to_insert < 10)) + return (original_size); + /* + If first insert/partition and monotonic partition function, + allow using buffer size originally set. + */ + if (!m_bulk_inserted_rows && + m_part_func_monotonicity_info != NON_MONOTONIC && + m_tot_parts > 1) + return original_size; + /* + Allow total buffer used in all partition to go up to 10*read_buffer_size. + 11*read_buffer_size in case of monotonic partition function. + */ + + if (m_tot_parts < 10) + return original_size; + return (original_size * 10 / m_tot_parts); +} /* Try to predict the number of inserts into this partition. diff --git a/sql/ha_partition.h b/sql/ha_partition.h index f47dfe8f621..1c863d6c294 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -367,7 +367,8 @@ public: virtual int end_bulk_insert(); private: ha_rows guess_bulk_insert_rows(); - void start_part_bulk_insert(uint part_id); + void start_part_bulk_insert(THD *thd, uint part_id); + long estimate_read_buffer_size(long original_size); public: virtual bool is_fatal_error(int error, uint flags) From e5888b16afcef42e8127a815cc5a95abc283c6d9 Mon Sep 17 00:00:00 2001 From: Staale Smedseng Date: Thu, 17 Sep 2009 17:10:30 +0200 Subject: [PATCH 52/80] Bug #43414 Parenthesis (and other) warnings compiling MySQL with gcc 4.3.2 This is the fifth patch cleaning up more GCC warnings about variables used before initialized using the new macro UNINIT_VAR(). --- heap/hp_write.c | 7 ++----- include/my_global.h | 6 ------ myisam/mi_search.c | 6 ++---- myisam/mi_write.c | 6 ++---- mysys/hash.c | 7 ++----- sql-common/my_time.c | 3 +-- sql/item_func.cc | 6 ++---- sql/item_timefunc.cc | 11 +++-------- sql/sql_handler.cc | 7 ++----- sql/sql_lex.cc | 3 +-- sql/sql_select.cc | 3 +-- sql/udf_example.c | 4 ++-- 12 files changed, 20 insertions(+), 49 deletions(-) diff --git a/heap/hp_write.c b/heap/hp_write.c index 6aa34acf2c3..85551c1cc41 100644 --- a/heap/hp_write.c +++ b/heap/hp_write.c @@ -196,13 +196,10 @@ int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo, HP_SHARE *share = info->s; int flag; ulong halfbuff,hashnr,first_index; - byte *ptr_to_rec,*ptr_to_rec2; - HASH_INFO *empty,*gpos,*gpos2,*pos; + byte *UNINIT_VAR(ptr_to_rec),*UNINIT_VAR(ptr_to_rec2); + HASH_INFO *empty,*UNINIT_VAR(gpos),*UNINIT_VAR(gpos2),*pos; DBUG_ENTER("hp_write_key"); - LINT_INIT(gpos); LINT_INIT(gpos2); - LINT_INIT(ptr_to_rec); LINT_INIT(ptr_to_rec2); - flag=0; if (!(empty= hp_find_free_hash(share,&keyinfo->block,share->records))) DBUG_RETURN(-1); /* No more memory */ diff --git a/include/my_global.h b/include/my_global.h index 0b5458215c6..6910ae092e1 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -458,12 +458,6 @@ int __void__; #define LINT_INIT(var) #endif -#if defined(_lint) || defined(FORCE_INIT_OF_VARS) || defined(HAVE_purify) -#define PURIFY_OR_LINT_INIT(var) var=0 -#else -#define PURIFY_OR_LINT_INIT(var) -#endif - /* Suppress uninitialized variable warning without generating code. diff --git a/myisam/mi_search.c b/myisam/mi_search.c index 3b1cd6158f2..21efaa03744 100644 --- a/myisam/mi_search.c +++ b/myisam/mi_search.c @@ -295,7 +295,8 @@ int _mi_prefix_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page, uchar *end, *kseg, *vseg; uchar *sort_order=keyinfo->seg->charset->sort_order; uchar tt_buff[MI_MAX_KEY_BUFF+2], *t_buff=tt_buff+2; - uchar *saved_from, *saved_to, *saved_vseg; + uchar *UNINIT_VAR(saved_from), *UNINIT_VAR(saved_to); + uchar *UNINIT_VAR(saved_vseg); uint saved_length=0, saved_prefix_len=0; uint length_pack; DBUG_ENTER("_mi_prefix_search"); @@ -303,9 +304,6 @@ int _mi_prefix_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page, LINT_INIT(length); LINT_INIT(prefix_len); LINT_INIT(seg_len_pack); - LINT_INIT(saved_from); - LINT_INIT(saved_to); - LINT_INIT(saved_vseg); t_buff[0]=0; /* Avoid bugs */ end= page+mi_getint(page); diff --git a/myisam/mi_write.c b/myisam/mi_write.c index b4843a748dd..61cea588562 100644 --- a/myisam/mi_write.c +++ b/myisam/mi_write.c @@ -700,8 +700,8 @@ static uchar *_mi_find_last_pos(MI_KEYDEF *keyinfo, uchar *page, uchar *key, uint *return_key_length, uchar **after_key) { - uint keys,length,last_length,key_ref_length; - uchar *end,*lastpos,*prevpos; + uint keys,length,UNINIT_VAR(last_length),key_ref_length; + uchar *end,*lastpos,*UNINIT_VAR(prevpos); uchar key_buff[MI_MAX_KEY_BUFF]; DBUG_ENTER("_mi_find_last_pos"); @@ -720,8 +720,6 @@ static uchar *_mi_find_last_pos(MI_KEYDEF *keyinfo, uchar *page, DBUG_RETURN(end); } - LINT_INIT(prevpos); - LINT_INIT(last_length); end=page+length-key_ref_length; *key='\0'; length=0; diff --git a/mysys/hash.c b/mysys/hash.c index 4aab75609f4..3e7851a886f 100644 --- a/mysys/hash.c +++ b/mysys/hash.c @@ -332,11 +332,8 @@ my_bool my_hash_insert(HASH *info,const byte *record) { int flag; uint halfbuff,hash_nr,first_index,idx; - byte *ptr_to_rec,*ptr_to_rec2; - HASH_LINK *data,*empty,*gpos,*gpos2,*pos; - - LINT_INIT(gpos); LINT_INIT(gpos2); - LINT_INIT(ptr_to_rec); LINT_INIT(ptr_to_rec2); + byte *UNINIT_VAR(ptr_to_rec),*UNINIT_VAR(ptr_to_rec2); + HASH_LINK *data,*empty,*UNINIT_VAR(gpos),*UNINIT_VAR(gpos2),*pos; flag=0; if (!(empty=(HASH_LINK*) alloc_dynamic(&info->array))) diff --git a/sql-common/my_time.c b/sql-common/my_time.c index d2ef9da25f5..ed1279f7afb 100644 --- a/sql-common/my_time.c +++ b/sql-common/my_time.c @@ -165,7 +165,7 @@ str_to_datetime(const char *str, uint length, MYSQL_TIME *l_time, uint add_hours= 0, start_loop; ulong not_zero_date, allow_space; my_bool is_internal_format; - const char *pos, *last_field_pos; + const char *pos, *UNINIT_VAR(last_field_pos); const char *end=str+length; const uchar *format_position; my_bool found_delimitier= 0, found_space= 0; @@ -174,7 +174,6 @@ str_to_datetime(const char *str, uint length, MYSQL_TIME *l_time, DBUG_PRINT("ENTER",("str: %.*s",length,str)); LINT_INIT(field_length); - LINT_INIT(last_field_pos); *was_cut= 0; diff --git a/sql/item_func.cc b/sql/item_func.cc index 3c1e2126008..c6dbdb1d9a7 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -428,8 +428,7 @@ bool Item_func::eq(const Item *item, bool binary_cmp) const Field *Item_func::tmp_table_field(TABLE *t_arg) { - Field *res; - LINT_INIT(res); + Field *res= NULL; switch (result_type()) { case INT_RESULT: @@ -4202,9 +4201,8 @@ void Item_func_set_user_var::save_item_result(Item *item) bool Item_func_set_user_var::update() { - bool res; + bool res= NULL; DBUG_ENTER("Item_func_set_user_var::update"); - LINT_INIT(res); switch (cached_result_type) { case REAL_RESULT: diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 39f869106b6..de76f821795 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -271,9 +271,9 @@ static bool extract_date_time(DATE_TIME_FORMAT *format, int strict_week_number_year= -1; int frac_part; bool usa_time= 0; - bool sunday_first_n_first_week_non_iso; - bool strict_week_number; - bool strict_week_number_year_type; + bool UNINIT_VAR(sunday_first_n_first_week_non_iso); + bool UNINIT_VAR(strict_week_number); + bool UNINIT_VAR(strict_week_number_year_type); const char *val_begin= val; const char *val_end= val + length; const char *ptr= format->format.str; @@ -281,11 +281,6 @@ static bool extract_date_time(DATE_TIME_FORMAT *format, CHARSET_INFO *cs= &my_charset_bin; DBUG_ENTER("extract_date_time"); - LINT_INIT(strict_week_number); - /* Remove valgrind varnings when using gcc 3.3 and -O1 */ - PURIFY_OR_LINT_INIT(strict_week_number_year_type); - PURIFY_OR_LINT_INIT(sunday_first_n_first_week_non_iso); - if (!sub_pattern_end) bzero((char*) l_time, sizeof(*l_time)); diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index 721b365a7b9..5bd28add428 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -385,16 +385,13 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables, String buffer(buff, sizeof(buff), system_charset_info); int error, keyno= -1; uint num_rows; - byte *key; - uint key_len; + byte *UNINIT_VAR(key); + uint UNINIT_VAR(key_len); bool need_reopen; DBUG_ENTER("mysql_ha_read"); DBUG_PRINT("enter",("'%s'.'%s' as '%s'", tables->db, tables->table_name, tables->alias)); - LINT_INIT(key); - LINT_INIT(key_len); - thd->lex->select_lex.context.resolve_in_table_list_only(tables); list.push_front(new Item_field(&thd->lex->select_lex.context, NULL, NULL, "*")); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index b0b4256184c..17ee53d446b 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -530,7 +530,7 @@ static inline uint int_token(const char *str,uint length) int MYSQLlex(void *arg, void *yythd) { - reg1 uchar c; + reg1 uchar UNINIT_VAR(c); bool comment_closed; int tokval, result_state; uint length; @@ -550,7 +550,6 @@ int MYSQLlex(void *arg, void *yythd) lip->tok_start=lip->tok_end=lip->ptr; state=lip->next_state; lip->next_state=MY_LEX_OPERATOR_OR_IDENT; - LINT_INIT(c); for (;;) { switch (state) { diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 9d5e67c9532..84b5b61c941 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -10480,9 +10480,8 @@ do_select(JOIN *join,List *fields,TABLE *table,Procedure *procedure) { int rc= 0; enum_nested_loop_state error= NESTED_LOOP_OK; - JOIN_TAB *join_tab; + JOIN_TAB *UNINIT_VAR(join_tab); DBUG_ENTER("do_select"); - LINT_INIT(join_tab); join->procedure=procedure; join->tmp_table= table; /* Save for easy recursion */ diff --git a/sql/udf_example.c b/sql/udf_example.c index db48984eed8..019d4d834dd 100644 --- a/sql/udf_example.c +++ b/sql/udf_example.c @@ -139,10 +139,10 @@ typedef long long longlong; #include #include -static pthread_mutex_t LOCK_hostname; - #ifdef HAVE_DLOPEN +static pthread_mutex_t LOCK_hostname; + /* These must be right or mysqld will not find the symbol! */ my_bool metaphon_init(UDF_INIT *initid, UDF_ARGS *args, char *message); From 4826b61c33da53ddf2c859934ef00c299cc890f3 Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Fri, 18 Sep 2009 11:19:02 +0400 Subject: [PATCH 53/80] Bug #43606: 4GB Limit on huge_pages shared memory set-up Large pages allocator could not allocate more than 4 GB due to incorrect size alignment. mysys/my_largepage.c: Large pages allocator could not allocate more than 4 GB due to incorrect size alignment. --- mysys/my_largepage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysys/my_largepage.c b/mysys/my_largepage.c index a20111396cb..b50a606c8d8 100644 --- a/mysys/my_largepage.c +++ b/mysys/my_largepage.c @@ -121,7 +121,7 @@ uchar* my_large_malloc_int(size_t size, myf my_flags) DBUG_ENTER("my_large_malloc_int"); /* Align block size to my_large_page_size */ - size = ((size - 1) & ~(my_large_page_size - 1)) + my_large_page_size; + size= MY_ALIGN(size, (size_t) my_large_page_size); shmid = shmget(IPC_PRIVATE, size, SHM_HUGETLB | SHM_R | SHM_W); if (shmid < 0) From 64badb5f269850d0111aec29788aff7e181c195d Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 18 Sep 2009 16:20:29 +0800 Subject: [PATCH 54/80] Bug #42914 Log event that larger than max_allowed_packet results in stop of slave I/O thread, But there is no Last_IO_Error reported. On the master, if a binary log event is larger than max_allowed_packet, ER_MASTER_FATAL_ERROR_READING_BINLOG and the specific reason of this error is sent to a slave when it requests a dump from the master, thus leading the I/O thread to stop. On a slave, the I/O thread stops when receiving a packet larger than max_allowed_packet. In both cases, however, there was no Last_IO_Error reported. This patch adds code to report the Last_IO_Error and exact reason before stopping the I/O thread and also reports the case the out memory pops up while handling packets from the master. sql/sql_repl.cc: The master send the Specific reasons instead of "error reading log entry" to the slave which is requesting a dump. if an fatal error is returned by read_log_event function. --- mysql-test/suite/rpl/r/rpl_packet.result | 15 ++++++++++++ mysql-test/suite/rpl/t/rpl_packet.test | 30 ++++++++++++++++++++++++ sql/share/errmsg.txt | 2 +- sql/slave.cc | 12 ++++++---- sql/sql_repl.cc | 14 ++++------- 5 files changed, 58 insertions(+), 15 deletions(-) diff --git a/mysql-test/suite/rpl/r/rpl_packet.result b/mysql-test/suite/rpl/r/rpl_packet.result index 4c64054e348..cb26d04bea9 100644 --- a/mysql-test/suite/rpl/r/rpl_packet.result +++ b/mysql-test/suite/rpl/r/rpl_packet.result @@ -32,6 +32,21 @@ include/start_slave.inc CREATE TABLE `t1` (`f1` LONGTEXT) ENGINE=MyISAM; INSERT INTO `t1`(`f1`) VALUES ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa2048'); Slave_IO_Running = No (expect No) +SELECT "Got a packet bigger than 'max_allowed_packet' bytes" AS Last_IO_Error; +Last_IO_Error +Got a packet bigger than 'max_allowed_packet' bytes +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +CREATE TABLE t1 (f1 int PRIMARY KEY, f2 LONGTEXT, f3 LONGTEXT) ENGINE=MyISAM; +INSERT INTO t1(f1, f2, f3) VALUES(1, REPEAT('a', @@global.max_allowed_packet), REPEAT('b', @@global.max_allowed_packet)); +Slave_IO_Running = No (expect No) +SELECT "Got fatal error 1236 from master when reading data from binary log: 'log event entry exceeded max_allowed_packet; Increase max_allowed_packet on master'" AS Last_IO_Error; +Last_IO_Error +Got fatal error 1236 from master when reading data from binary log: 'log event entry exceeded max_allowed_packet; Increase max_allowed_packet on master' ==== clean up ==== DROP TABLE t1; SET @@global.max_allowed_packet= 1024; diff --git a/mysql-test/suite/rpl/t/rpl_packet.test b/mysql-test/suite/rpl/t/rpl_packet.test index 79cb2d9d735..b4e04405037 100644 --- a/mysql-test/suite/rpl/t/rpl_packet.test +++ b/mysql-test/suite/rpl/t/rpl_packet.test @@ -5,6 +5,7 @@ # max-out size db name source include/master-slave.inc; +source include/have_binlog_format_row.inc; let $db= DB_NAME_OF_MAX_LENGTH_AKA_NAME_LEN_64_BYTES_____________________; disable_warnings; @@ -86,6 +87,35 @@ connection slave; --source include/wait_for_slave_io_to_stop.inc let $slave_io_running= query_get_value(SHOW SLAVE STATUS, Slave_IO_Running, 1); --echo Slave_IO_Running = $slave_io_running (expect No) +# +# Bug#42914: The slave I/O thread must stop after trying to read the above +# event, However there is no Last_IO_Error report. +# +let $last_io_error= query_get_value(SHOW SLAVE STATUS, Last_IO_Error, 1); +eval SELECT "$last_io_error" AS Last_IO_Error; + +# +# Bug#42914: On the master, if a binary log event is larger than +# max_allowed_packet, the error message ER_MASTER_FATAL_ERROR_READING_BINLOG +# is sent to a slave when it requests a dump from the master, thus leading the +# I/O thread to stop. However, there is no Last_IO_Error reported. +# +source include/master-slave-reset.inc; +connection master; +CREATE TABLE t1 (f1 int PRIMARY KEY, f2 LONGTEXT, f3 LONGTEXT) ENGINE=MyISAM; +sync_slave_with_master; + +connection master; +INSERT INTO t1(f1, f2, f3) VALUES(1, REPEAT('a', @@global.max_allowed_packet), REPEAT('b', @@global.max_allowed_packet)); + +connection slave; +# The slave I/O thread must stop after receiving +# ER_MASTER_FATAL_ERROR_READING_BINLOG error message from master. +--source include/wait_for_slave_io_to_stop.inc +let $slave_io_running= query_get_value(SHOW SLAVE STATUS, Slave_IO_Running, 1); +--echo Slave_IO_Running = $slave_io_running (expect No) +let $last_io_error= query_get_value(SHOW SLAVE STATUS, Last_IO_Error, 1); +eval SELECT "$last_io_error" AS Last_IO_Error; --echo ==== clean up ==== connection master; diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 3aba434b284..fdad2a44b68 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -4702,7 +4702,7 @@ ER_NOT_SUPPORTED_YET 42000 swe "Denna version av MySQL kan ännu inte utföra '%s'" ER_MASTER_FATAL_ERROR_READING_BINLOG nla "Kreeg fatale fout %d: '%-.128s' van master tijdens lezen van data uit binaire log" - eng "Got fatal error %d: '%-.128s' from master when reading data from binary log" + eng "Got fatal error %d from master when reading data from binary log: '%-.128s'" ger "Schwerer Fehler %d: '%-.128s vom Master beim Lesen des binären Logs" ita "Errore fatale %d: '%-.128s' dal master leggendo i dati dal log binario" por "Obteve fatal erro %d: '%-.128s' do master quando lendo dados do binary log" diff --git a/sql/slave.cc b/sql/slave.cc index fac9ee214c5..b489eb3b45f 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -2678,15 +2678,19 @@ Log entry on master is longer than max_allowed_packet (%ld) on \ slave. If the entry is correct, restart the server with a higher value of \ max_allowed_packet", thd->variables.max_allowed_packet); + mi->report(ERROR_LEVEL, ER_NET_PACKET_TOO_LARGE, + ER(ER_NET_PACKET_TOO_LARGE)); goto err; case ER_MASTER_FATAL_ERROR_READING_BINLOG: - sql_print_error(ER(mysql_error_number), mysql_error_number, - mysql_error(mysql)); + mi->report(ERROR_LEVEL, ER_MASTER_FATAL_ERROR_READING_BINLOG, + ER(ER_MASTER_FATAL_ERROR_READING_BINLOG), + mysql_error_number, mysql_error(mysql)); goto err; - case EE_OUTOFMEMORY: - case ER_OUTOFMEMORY: + case ER_OUT_OF_RESOURCES: sql_print_error("\ Stopping slave I/O thread due to out-of-memory error from master"); + mi->report(ERROR_LEVEL, ER_OUT_OF_RESOURCES, + ER(ER_OUT_OF_RESOURCES)); goto err; } if (try_to_reconnect(thd, mysql, mi, &retry_count, suppress_warnings, diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 0ec8d91214c..b8f2e1e39bf 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -623,7 +623,7 @@ impossible position"; */ { log.error=0; - bool read_packet = 0, fatal_error = 0; + bool read_packet = 0; #ifndef DBUG_OFF if (max_binlog_dump_events && !left_events--) @@ -645,7 +645,7 @@ impossible position"; */ pthread_mutex_lock(log_lock); - switch (Log_event::read_log_event(&log, packet, (pthread_mutex_t*)0)) { + switch (error= Log_event::read_log_event(&log, packet, (pthread_mutex_t*) 0)) { case 0: /* we read successfully, so we'll need to send it to the slave */ pthread_mutex_unlock(log_lock); @@ -671,8 +671,8 @@ impossible position"; default: pthread_mutex_unlock(log_lock); - fatal_error = 1; - break; + test_for_non_eof_log_read_errors(error, &errmsg); + goto err; } if (read_packet) @@ -701,12 +701,6 @@ impossible position"; */ } - if (fatal_error) - { - errmsg = "error reading log entry"; - my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG; - goto err; - } log.error=0; } } From 5dda6c18cdb6b549681f76b6158baa3afd2816bb Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Fri, 18 Sep 2009 12:34:08 +0300 Subject: [PATCH 55/80] Bug #47106: Crash / segfault on adding EXPLAIN to a non-crashing query The fix for bug 46749 removed the check for OUTER_REF_TABLE_BIT and substituted it for a check on the presence of Item_ident::depended_from. Removing it altogether was wrong : OUTER_REF_TABLE_BIT should still be checked in addition to depended_from (because it's not set in all cases and doesn't contradict to the check of depended_from). Fixed by returning the old condition back as a compliment to the new one. --- mysql-test/r/subselect4.result | 31 +++++++++++++++++++++++++++++++ mysql-test/t/subselect4.test | 32 ++++++++++++++++++++++++++++++++ sql/sql_select.cc | 8 ++++---- 3 files changed, 67 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/subselect4.result b/mysql-test/r/subselect4.result index 68577cb2a4c..e863cbfb7a8 100644 --- a/mysql-test/r/subselect4.result +++ b/mysql-test/r/subselect4.result @@ -27,4 +27,35 @@ SELECT 1; 1 1 DROP TABLE t1,t2,t3; +# +# Bug #47106: Crash / segfault on adding EXPLAIN to a non-crashing +# query +# +CREATE TABLE t1 ( +a INT, +b INT, +PRIMARY KEY (a), +KEY b (b) +); +INSERT INTO t1 VALUES (1, 1), (2, 1); +CREATE TABLE t2 LIKE t1; +INSERT INTO t2 SELECT * FROM t1; +CREATE TABLE t3 LIKE t1; +INSERT INTO t3 SELECT * FROM t1; +# Should not crash. +# Should have 1 impossible where and 2 dependent subqs. +EXPLAIN +SELECT +(SELECT 1 FROM t1,t2 WHERE t2.b > t3.b) +FROM t3 WHERE 1 = 0 GROUP BY 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +2 DEPENDENT SUBQUERY t1 index NULL PRIMARY 4 NULL 2 Using index +2 DEPENDENT SUBQUERY t2 index b b 5 NULL 2 Using where; Using index +# should return 0 rows +SELECT +(SELECT 1 FROM t1,t2 WHERE t2.b > t3.b) +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. diff --git a/mysql-test/t/subselect4.test b/mysql-test/t/subselect4.test index ff4cdf3c439..440eca22828 100644 --- a/mysql-test/t/subselect4.test +++ b/mysql-test/t/subselect4.test @@ -28,5 +28,37 @@ SELECT 1; DROP TABLE t1,t2,t3; +--echo # +--echo # Bug #47106: Crash / segfault on adding EXPLAIN to a non-crashing +--echo # query +--echo # + +CREATE TABLE t1 ( + a INT, + b INT, + PRIMARY KEY (a), + KEY b (b) +); +INSERT INTO t1 VALUES (1, 1), (2, 1); + +CREATE TABLE t2 LIKE t1; +INSERT INTO t2 SELECT * FROM t1; + +CREATE TABLE t3 LIKE t1; +INSERT INTO t3 SELECT * FROM t1; + +--echo # Should not crash. +--echo # Should have 1 impossible where and 2 dependent subqs. +EXPLAIN +SELECT + (SELECT 1 FROM t1,t2 WHERE t2.b > t3.b) +FROM t3 WHERE 1 = 0 GROUP BY 1; + +--echo # should return 0 rows +SELECT + (SELECT 1 FROM t1,t2 WHERE t2.b > t3.b) +FROM t3 WHERE 1 = 0 GROUP BY 1; + +DROP TABLE t1,t2,t3; --echo End of 5.0 tests. diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 84b5b61c941..76d6833de5c 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -3216,12 +3216,12 @@ add_key_equal_fields(KEY_FIELD **key_fields, uint and_level, @retval FALSE it's something else */ -inline static bool +static bool is_local_field (Item *field) { - field= field->real_item(); - return field->type() == Item::FIELD_ITEM && - !((Item_field *)field)->depended_from; + return field->real_item()->type() == Item::FIELD_ITEM + && !(field->used_tables() & OUTER_REF_TABLE_BIT) + && !((Item_field *)field->real_item())->depended_from; } From 01e5bc703d91e5d39b9f00b8eb31d563a2cf6b40 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Fri, 18 Sep 2009 16:01:18 +0300 Subject: [PATCH 56/80] Bug#46760: Fast ALTER TABLE no longer works for InnoDB Despite copying the value of the old table's row type we don't always have to mark row type as being specified. Innodb uses this to check if it can do fast ALTER TABLE or not. Fixed by correctly flagging the presence of row_type only when it's actually changed. Added a test case for 39200. --- mysql-test/r/bug46760.result | 43 ++++++++++++++++++++++++++++++++ mysql-test/t/bug46760-master.opt | 2 ++ mysql-test/t/bug46760.test | 38 ++++++++++++++++++++++++++++ sql/handler.h | 9 +++++++ sql/sql_table.cc | 10 ++++++++ 5 files changed, 102 insertions(+) create mode 100644 mysql-test/r/bug46760.result create mode 100644 mysql-test/t/bug46760-master.opt create mode 100644 mysql-test/t/bug46760.test diff --git a/mysql-test/r/bug46760.result b/mysql-test/r/bug46760.result new file mode 100644 index 00000000000..413df050b10 --- /dev/null +++ b/mysql-test/r/bug46760.result @@ -0,0 +1,43 @@ +# +# Bug#46760: Fast ALTER TABLE no longer works for InnoDB +# +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +# By using --enable_info and verifying that number of affected +# rows is 0 we check that this ALTER TABLE is really carried +# out as "fast/online" operation, i.e. without full-blown data +# copying. +# +# I.e. info for the below statement should normally look like: +# +# affected rows: 0 +# info: Records: 0 Duplicates: 0 Warnings: 0 +ALTER TABLE t1 ALTER COLUMN a SET DEFAULT 10; +affected rows: 0 +info: Records: 0 Duplicates: 0 Warnings: 0 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT '10' +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t1; +# +# MySQL Bug#39200: optimize table does not recognize +# ROW_FORMAT=COMPRESSED +# +CREATE TABLE t1 (a INT) ROW_FORMAT=compressed; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 ROW_FORMAT=COMPRESSED +OPTIMIZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 optimize status Table is already up to date +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 ROW_FORMAT=COMPRESSED +DROP TABLE t1; +End of 5.1 tests diff --git a/mysql-test/t/bug46760-master.opt b/mysql-test/t/bug46760-master.opt new file mode 100644 index 00000000000..f830d135149 --- /dev/null +++ b/mysql-test/t/bug46760-master.opt @@ -0,0 +1,2 @@ +--innodb-lock-wait-timeout=2 +--innodb-file-per-table diff --git a/mysql-test/t/bug46760.test b/mysql-test/t/bug46760.test new file mode 100644 index 00000000000..f55edbbfa42 --- /dev/null +++ b/mysql-test/t/bug46760.test @@ -0,0 +1,38 @@ +-- source include/have_innodb.inc + +--echo # +--echo # Bug#46760: Fast ALTER TABLE no longer works for InnoDB +--echo # + +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); + +--echo # By using --enable_info and verifying that number of affected +--echo # rows is 0 we check that this ALTER TABLE is really carried +--echo # out as "fast/online" operation, i.e. without full-blown data +--echo # copying. +--echo # +--echo # I.e. info for the below statement should normally look like: +--echo # +--echo # affected rows: 0 +--echo # info: Records: 0 Duplicates: 0 Warnings: 0 + +--enable_info +ALTER TABLE t1 ALTER COLUMN a SET DEFAULT 10; +--disable_info +SHOW CREATE TABLE t1; + +DROP TABLE t1; + +--echo # +--echo # MySQL Bug#39200: optimize table does not recognize +--echo # ROW_FORMAT=COMPRESSED +--echo # + +CREATE TABLE t1 (a INT) ROW_FORMAT=compressed; +SHOW CREATE TABLE t1; +OPTIMIZE TABLE t1; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +--echo End of 5.1 tests diff --git a/sql/handler.h b/sql/handler.h index f759239d66e..fe8f7c437ff 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -913,6 +913,15 @@ typedef struct st_ha_create_information ulong key_block_size; SQL_LIST merge_list; handlerton *db_type; + /** + Row type of the table definition. + + Defaults to ROW_TYPE_DEFAULT for all non-ALTER statements. + For ALTER TABLE defaults to ROW_TYPE_NOT_USED (means "keep the current"). + + Can be changed either explicitly by the parser. + If nothing speficied inherits the value of the original table (if present). + */ enum row_type row_type; uint null_bits; /* NULL bits at start of record */ uint options; /* OR of HA_CREATE_ options */ diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 41e76211dd8..9d929c0d1a3 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -6656,9 +6656,19 @@ view_err: goto err; } + /* + If this is an ALTER TABLE and no explicit row type specified reuse + the table's row type. + Note : this is the same as if the row type was specified explicitly. + */ if (create_info->row_type == ROW_TYPE_NOT_USED) { + /* ALTER TABLE without explicit row type */ create_info->row_type= table->s->row_type; + } + else + { + /* ALTER TABLE with specific row type */ create_info->used_fields |= HA_CREATE_USED_ROW_FORMAT; } From 5ec6043ac37380fac2cbcbc15e4f2e8b76653f15 Mon Sep 17 00:00:00 2001 From: Kristofer Pettersson Date: Mon, 21 Sep 2009 11:58:15 +0200 Subject: [PATCH 57/80] Fix for BUG#35570 "CHECKSUM TABLE unreliable if LINESTRING field (same content/ differen checksum)" The problem was that checksum of GEOMETRY type used memory addresses in the computation, making it un-repeatable thus useless. (This patch is a backport from 6.0 branch) mysql-test/r/myisam.result: test case for bug35570 that same tables give same checksums mysql-test/t/myisam.test: test case for bug35570 that same tables give same checksums sql/sql_table.cc: Type GEOMETRY is implemented on top of type BLOB, so, just like for BLOB, its 'field' contains pointers which it does not make sense to include in the checksum; it rather has to be converted to a string and then we can compute the checksum. --- mysql-test/r/myisam.result | 19 +++++++++++++++++++ mysql-test/t/myisam.test | 15 +++++++++++++++ sql/sql_table.cc | 10 ++++++++-- 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index 732b1b260f8..58e2e451a0d 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -2252,4 +2252,23 @@ h+0 d + 0 e g + 0 1 1 3 0 1 1 4 0 DROP TABLE t1; +# +# Test of BUG#35570 CHECKSUM TABLE unreliable if LINESTRING field +# (same content / differen checksum) +# +CREATE TABLE t1 (line LINESTRING NOT NULL) engine=myisam; +INSERT INTO t1 VALUES (GeomFromText("POINT(0 0)")); +checksum table t1; +Table Checksum +test.t1 326284887 +CREATE TABLE t2 (line LINESTRING NOT NULL) engine=myisam; +INSERT INTO t2 VALUES (GeomFromText("POINT(0 0)")); +checksum table t2; +Table Checksum +test.t2 326284887 +CREATE TABLE t3 select * from t1; +checksum table t3; +Table Checksum +test.t3 326284887 +drop table t1,t2,t3; End of 5.1 tests diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test index ba6bc05cfea..5de7c997a24 100644 --- a/mysql-test/t/myisam.test +++ b/mysql-test/t/myisam.test @@ -1503,5 +1503,20 @@ SELECT h+0, d + 0, e, g + 0 FROM t1; DROP TABLE t1; +--echo # +--echo # Test of BUG#35570 CHECKSUM TABLE unreliable if LINESTRING field +--echo # (same content / differen checksum) +--echo # + +CREATE TABLE t1 (line LINESTRING NOT NULL) engine=myisam; +INSERT INTO t1 VALUES (GeomFromText("POINT(0 0)")); +checksum table t1; +CREATE TABLE t2 (line LINESTRING NOT NULL) engine=myisam; +INSERT INTO t2 VALUES (GeomFromText("POINT(0 0)")); +checksum table t2; +CREATE TABLE t3 select * from t1; +checksum table t3; +drop table t1,t2,t3; + --echo End of 5.1 tests diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 9d929c0d1a3..08f3311be9d 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -7897,8 +7897,14 @@ bool mysql_checksum_table(THD *thd, TABLE_LIST *tables, for (uint i= 0; i < t->s->fields; i++ ) { Field *f= t->field[i]; - if ((f->type() == MYSQL_TYPE_BLOB) || - (f->type() == MYSQL_TYPE_VARCHAR)) + enum_field_types field_type= f->type(); + /* + BLOB and VARCHAR have pointers in their field, we must convert + to string; GEOMETRY is implemented on top of BLOB. + */ + if ((field_type == MYSQL_TYPE_BLOB) || + (field_type == MYSQL_TYPE_VARCHAR) || + (field_type == MYSQL_TYPE_GEOMETRY)) { String tmp; f->val_str(&tmp); From 83bc7980ce8df92efac754923500b59574055ad0 Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Tue, 22 Sep 2009 08:22:07 -0300 Subject: [PATCH 58/80] Bug#45498: Socket variable not available on Windows The "socket" variable is not available on Windows even though the --socket option can be used to specify the pipe name for local connections that use a named pipe. The solution is to ensure that the variable is always defined. mysql-test/r/windows.result: Add test case result for Bug#45498 mysql-test/t/windows.test: Add test case for Bug#45498 sql/set_var.cc: socket variable must always be present. --- mysql-test/r/windows.result | 7 +++++++ mysql-test/t/windows.test | 6 ++++++ sql/set_var.cc | 4 ++-- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/windows.result b/mysql-test/r/windows.result index 4e0d73ea0eb..d0cdd858d4a 100644 --- a/mysql-test/r/windows.result +++ b/mysql-test/r/windows.result @@ -53,3 +53,10 @@ ERROR HY000: No paths allowed for shared library execute abc; ERROR HY000: No paths allowed for shared library deallocate prepare abc; +# +# Bug#45498: Socket variable not available on Windows +# +SELECT VARIABLE_NAME FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES +WHERE VARIABLE_NAME = 'socket'; +VARIABLE_NAME +SOCKET diff --git a/mysql-test/t/windows.test b/mysql-test/t/windows.test index 89cd2ed19e8..b7d31948d23 100755 --- a/mysql-test/t/windows.test +++ b/mysql-test/t/windows.test @@ -92,3 +92,9 @@ execute abc; execute abc; deallocate prepare abc; +--echo # +--echo # Bug#45498: Socket variable not available on Windows +--echo # + +SELECT VARIABLE_NAME FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES + WHERE VARIABLE_NAME = 'socket'; diff --git a/sql/set_var.cc b/sql/set_var.cc index b64b54fdd29..51c6ca219c6 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -529,11 +529,11 @@ static sys_var_const sys_skip_networking(&vars, "skip_networking", static sys_var_const sys_skip_show_database(&vars, "skip_show_database", OPT_GLOBAL, SHOW_BOOL, (uchar*) &opt_skip_show_db); -#ifdef HAVE_SYS_UN_H + static sys_var_const sys_socket(&vars, "socket", OPT_GLOBAL, SHOW_CHAR_PTR, (uchar*) &mysqld_unix_port); -#endif + #ifdef HAVE_THR_SETCONCURRENCY /* purecov: begin tested */ static sys_var_const sys_thread_concurrency(&vars, "thread_concurrency", From beb519e3caa387b715a6093251ec0b7e5ce61da0 Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Wed, 23 Sep 2009 13:40:33 +0500 Subject: [PATCH 59/80] Bug#45989 memory leak after explain encounters an error in the query the fix is reverted from 5.1, mysql-pe as unnecessary(no valgrind warnings there). sql/sql_select.cc: the fix is reverted from 5.1, mysql-pe as unnecessary(no valgrind warnings there). --- sql/sql_select.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 8b1e0ae365b..1ff068c8881 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -2248,7 +2248,7 @@ JOIN::destroy() tab->cleanup(); } tmp_join->tmp_join= 0; - tmp_table_param.cleanup(); + tmp_table_param.copy_field= 0; DBUG_RETURN(tmp_join->destroy()); } cond_equal= 0; From 1eef7665345054b01c0526c368d4f012ac24a75c Mon Sep 17 00:00:00 2001 From: Satya B Date: Wed, 23 Sep 2009 17:42:12 +0530 Subject: [PATCH 60/80] Additional Fix for BUG#44030 - Error: (1500) Couldn't read the MAX(ID) autoinc value from the index (PRIMARY) With the fix for BUG#46760, we correctly flag the presence of row_type only when it's actually changed and enables the FAST ALTER TABLE which was disabled with the BUG#39200. So the changes made by BUG#46760 makes MySQL data dictionaries to be out of sync but they are handled already by InnoDB with this BUG#44030. The test was originally written to handle this but we requested Innodb to update the test as the data dictionaries were in sync after the fix for BUG#39200. Adjusting the innodb-autoinc testcase as mentioned in the comments. mysql-test/lib/mtr_cases.pm: Re-enable the innodb-autoinc test case for plugin as we have a common result file. mysql-test/r/innodb-autoinc.result: Additional Fix for BUG#44030 - Error: (1500) Couldn't read the MAX(ID) autoinc value from the index (PRIMARY) Adjust the innodb-autoinc testcase as the patch for BUG#46760 enables the FAST ALTER TABLE and makes the data dictonaries go out of sync. This is expected in the testcase. mysql-test/t/innodb-autoinc.test: Additional Fix for BUG#44030 - Error: (1500) Couldn't read the MAX(ID) autoinc value from the index (PRIMARY) Adjust the innodb-autoinc testcase as the patch for BUG#46760 enables the FAST ALTER TABLE and makes the data dictonaries go out of sync. This is expected in the testcase. --- mysql-test/lib/mtr_cases.pm | 1 - mysql-test/r/innodb-autoinc.result | 2 +- mysql-test/t/innodb-autoinc.test | 6 +----- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/mysql-test/lib/mtr_cases.pm b/mysql-test/lib/mtr_cases.pm index dff005105f6..224babaaf32 100644 --- a/mysql-test/lib/mtr_cases.pm +++ b/mysql-test/lib/mtr_cases.pm @@ -500,7 +500,6 @@ sub collect_one_suite($) # Exceptions next if ($test->{'name'} eq 'main.innodb'); # Failed with wrong errno (fk) next if ($test->{'name'} eq 'main.index_merge_innodb'); # Explain diff - next if ($test->{'name'} eq 'main.innodb-autoinc'); # Need dfrnt result file # innodb_file_per_table is rw with innodb_plugin next if ($test->{'name'} eq 'sys_vars.innodb_file_per_table_basic'); # innodb_lock_wait_timeout is rw with innodb_plugin diff --git a/mysql-test/r/innodb-autoinc.result b/mysql-test/r/innodb-autoinc.result index 76575ae4160..d2e8eb19e0c 100644 --- a/mysql-test/r/innodb-autoinc.result +++ b/mysql-test/r/innodb-autoinc.result @@ -880,6 +880,7 @@ d1 1 3 INSERT INTO t1 VALUES(null); +Got one of the listed errors ALTER TABLE t1 AUTO_INCREMENT = 3; INSERT INTO t1 VALUES(null); SELECT * FROM t1; @@ -887,5 +888,4 @@ d1 1 3 4 -5 DROP TABLE t1; diff --git a/mysql-test/t/innodb-autoinc.test b/mysql-test/t/innodb-autoinc.test index b51014ef4b3..61c42f45733 100644 --- a/mysql-test/t/innodb-autoinc.test +++ b/mysql-test/t/innodb-autoinc.test @@ -492,11 +492,7 @@ SELECT * FROM t1; # The MySQL and InnoDB data dictionaries should now be out of sync. # The select should print message to the error log SELECT * FROM t1; -# MySQL have made a change (http://lists.mysql.com/commits/75268) that no -# longer results in the two data dictionaries being out of sync. If they -# revert their changes then this check for ER_AUTOINC_READ_FAILED will need -# to be enabled. -# -- error ER_AUTOINC_READ_FAILED,1467 +-- error ER_AUTOINC_READ_FAILED,1467 INSERT INTO t1 VALUES(null); ALTER TABLE t1 AUTO_INCREMENT = 3; INSERT INTO t1 VALUES(null); From d49913877064778d8301c7bbd610238b3f5422cd Mon Sep 17 00:00:00 2001 From: Alexander Nozdrin Date: Wed, 23 Sep 2009 17:10:23 +0400 Subject: [PATCH 61/80] A patch for Bug#47474 (mysqld hits Dbug_violation_helper assert when compiled with Sun Studio compiler). The thing is that Sun Studio compiler calls destructor of stack objects when pthread_exit() is called. That triggered an assertion in DBUG_ENTER()/DBUG_RETURN() validation logic (if DBUG_ENTER() is used in the beginning of function, all returns should be replaced by DBUG_RETURN/DBUG_VOID_RETURN macros). A fix is to explicitly use DBUG_LEAVE macro. --- sql/ha_ndbcluster.cc | 4 +++- sql/ha_ndbcluster_binlog.cc | 9 ++++++--- sql/mysqld.cc | 23 ++++++++++++++++++----- sql/repl_failsafe.cc | 4 +++- sql/slave.cc | 9 ++++++--- 5 files changed, 36 insertions(+), 13 deletions(-) diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index ddb90427fdc..dfd7ddc4d6c 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -9426,9 +9426,11 @@ ndb_util_thread_fail: pthread_cond_signal(&COND_ndb_util_ready); pthread_mutex_unlock(&LOCK_ndb_util_thread); DBUG_PRINT("exit", ("ndb_util_thread")); + + DBUG_LEAVE; // Must match DBUG_ENTER() my_thread_end(); pthread_exit(0); - DBUG_RETURN(NULL); + return NULL; // Avoid compiler warnings } /* diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc index d9a9738ce72..2a87697c7fa 100644 --- a/sql/ha_ndbcluster_binlog.cc +++ b/sql/ha_ndbcluster_binlog.cc @@ -3663,9 +3663,11 @@ pthread_handler_t ndb_binlog_thread_func(void *arg) ndb_binlog_thread_running= -1; pthread_mutex_unlock(&injector_mutex); pthread_cond_signal(&injector_cond); + + DBUG_LEAVE; // Must match DBUG_ENTER() my_thread_end(); pthread_exit(0); - DBUG_RETURN(NULL); + return NULL; // Avoid compiler warnings } lex_start(thd); @@ -4376,10 +4378,11 @@ err: (void) pthread_cond_signal(&injector_cond); DBUG_PRINT("exit", ("ndb_binlog_thread")); - my_thread_end(); + DBUG_LEAVE; // Must match DBUG_ENTER() + my_thread_end(); pthread_exit(0); - DBUG_RETURN(NULL); + return NULL; // Avoid compiler warnings } bool diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 430592e7688..5778e6ab4aa 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1107,13 +1107,13 @@ void kill_mysql(void) #if defined(__NETWARE__) extern "C" void kill_server(int sig_ptr) -#define RETURN_FROM_KILL_SERVER DBUG_VOID_RETURN +#define RETURN_FROM_KILL_SERVER return #elif !defined(__WIN__) static void *kill_server(void *sig_ptr) -#define RETURN_FROM_KILL_SERVER DBUG_RETURN(0) +#define RETURN_FROM_KILL_SERVER return 0 #else static void __cdecl kill_server(int sig_ptr) -#define RETURN_FROM_KILL_SERVER DBUG_VOID_RETURN +#define RETURN_FROM_KILL_SERVER return #endif { DBUG_ENTER("kill_server"); @@ -1121,7 +1121,10 @@ static void __cdecl kill_server(int sig_ptr) int sig=(int) (long) sig_ptr; // This is passed a int // if there is a signal during the kill in progress, ignore the other if (kill_in_progress) // Safety + { + DBUG_LEAVE; RETURN_FROM_KILL_SERVER; + } kill_in_progress=TRUE; abort_loop=1; // This should be set if (sig != 0) // 0 is not a valid signal number @@ -1156,12 +1159,19 @@ static void __cdecl kill_server(int sig_ptr) pthread_join(select_thread, NULL); // wait for main thread #endif /* __NETWARE__ */ + DBUG_LEAVE; // Must match DBUG_ENTER() my_thread_end(); pthread_exit(0); /* purecov: end */ -#endif /* EMBEDDED_LIBRARY */ + RETURN_FROM_KILL_SERVER; // Avoid compiler warnings + +#else /* EMBEDDED_LIBRARY*/ + + DBUG_LEAVE; RETURN_FROM_KILL_SERVER; + +#endif /* EMBEDDED_LIBRARY */ } @@ -1935,8 +1945,9 @@ bool one_thread_per_connection_end(THD *thd, bool put_in_cache) my_thread_end(); (void) pthread_cond_broadcast(&COND_thread_count); + DBUG_LEAVE; // Must match DBUG_ENTER() pthread_exit(0); - DBUG_RETURN(0); // Impossible + return 0; // Avoid compiler warnings } @@ -2756,7 +2767,9 @@ pthread_handler_t signal_hand(void *arg __attribute__((unused))) DBUG_PRINT("quit",("signal_handler: calling my_thread_end()")); my_thread_end(); signal_thread_in_use= 0; + DBUG_LEAVE; // Must match DBUG_ENTER() pthread_exit(0); // Safety + return 0; // Avoid compiler warnings } switch (sig) { case SIGTERM: diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc index 582348608de..312499bb4ee 100644 --- a/sql/repl_failsafe.cc +++ b/sql/repl_failsafe.cc @@ -638,9 +638,11 @@ err: if (recovery_captain) mysql_close(recovery_captain); delete thd; + + DBUG_LEAVE; // Must match DBUG_ENTER() my_thread_end(); pthread_exit(0); - DBUG_RETURN(0); + return 0; // Avoid compiler warnings } #endif diff --git a/sql/slave.cc b/sql/slave.cc index b489eb3b45f..8bf126ce2c2 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -2799,9 +2799,11 @@ err: pthread_cond_broadcast(&mi->stop_cond); // tell the world we are done DBUG_EXECUTE_IF("simulate_slave_delay_at_terminate_bug38694", sleep(5);); pthread_mutex_unlock(&mi->run_lock); + + DBUG_LEAVE; // Must match DBUG_ENTER() my_thread_end(); pthread_exit(0); - DBUG_RETURN(0); // Can't return anything here + return 0; // Avoid compiler warnings } /* @@ -3157,10 +3159,11 @@ the slave SQL thread with \"SLAVE START\". We stopped at log \ pthread_cond_broadcast(&rli->stop_cond); DBUG_EXECUTE_IF("simulate_slave_delay_at_terminate_bug38694", sleep(5);); pthread_mutex_unlock(&rli->run_lock); // tell the world we are done - + + DBUG_LEAVE; // Must match DBUG_ENTER() my_thread_end(); pthread_exit(0); - DBUG_RETURN(0); // Can't return anything here + return 0; // Avoid compiler warnings } From 6a89842e3642729fbac20a92a1655452f4d45487 Mon Sep 17 00:00:00 2001 From: Staale Smedseng Date: Wed, 23 Sep 2009 15:21:29 +0200 Subject: [PATCH 62/80] Bug #43414 Parenthesis (and other) warnings compiling MySQL with gcc 4.3.2 Cleaning up warnings not present in 5.0. --- client/mysql.cc | 2 +- client/mysqlslap.c | 9 +++++++-- cmd-line-utils/readline/display.c | 6 +++--- extra/yassl/include/yassl_int.hpp | 2 +- extra/yassl/src/yassl_int.cpp | 2 +- include/my_dbug.h | 6 +++--- sql/event_db_repository.cc | 2 +- sql/ha_partition.cc | 2 +- sql/ha_partition.h | 8 ++++---- sql/handler.cc | 12 ++++-------- sql/item_timefunc.cc | 10 +++------- sql/item_xmlfunc.cc | 6 +++--- sql/log_event_old.cc | 6 +++--- sql/mysqld.cc | 3 ++- sql/partition_info.cc | 6 ++---- sql/rpl_rli.cc | 4 ++-- sql/set_var.cc | 9 ++++++--- sql/set_var.h | 3 ++- sql/slave.cc | 14 +++++++------- sql/sql_cache.cc | 2 +- sql/sql_connect.cc | 2 +- sql/sql_db.cc | 6 +++--- sql/sql_partition.cc | 4 ++-- sql/sql_plugin.cc | 2 +- sql/sql_show.cc | 2 ++ sql/strfunc.cc | 2 +- storage/archive/ha_archive.cc | 10 ++++------ storage/csv/ha_tina.cc | 4 ++-- storage/myisammrg/myrg_open.c | 3 +-- unittest/mysys/base64-t.c | 2 +- 30 files changed, 75 insertions(+), 76 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index bafd173343e..28da6d75c1b 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -3561,7 +3561,7 @@ static void print_warnings() messages. To be safe, skip printing the duplicate only if it is the only warning. */ - if (!cur || num_rows == 1 && error == (uint) strtoul(cur[1], NULL, 10)) + if (!cur || (num_rows == 1 && error == (uint) strtoul(cur[1], NULL, 10))) goto end; /* Print the warnings */ diff --git a/client/mysqlslap.c b/client/mysqlslap.c index 70abfbb7136..28c5e8df79d 100644 --- a/client/mysqlslap.c +++ b/client/mysqlslap.c @@ -423,6 +423,7 @@ void concurrency_loop(MYSQL *mysql, uint current, option_string *eptr) stats *sptr; conclusions conclusion; unsigned long long client_limit; + int sysret; head_sptr= (stats *)my_malloc(sizeof(stats) * iterations, MYF(MY_ZEROFILL|MY_FAE|MY_WME)); @@ -463,7 +464,9 @@ void concurrency_loop(MYSQL *mysql, uint current, option_string *eptr) run_query(mysql, "SET AUTOCOMMIT=0", strlen("SET AUTOCOMMIT=0")); if (pre_system) - system(pre_system); + if ((sysret= system(pre_system)) != 0) + fprintf(stderr, "Warning: Execution of pre_system option returned %d.\n", + sysret); /* Pre statements are always run after all other logic so they can @@ -478,7 +481,9 @@ void concurrency_loop(MYSQL *mysql, uint current, option_string *eptr) run_statements(mysql, post_statements); if (post_system) - system(post_system); + if ((sysret= system(post_system)) != 0) + fprintf(stderr, "Warning: Execution of post_system option returned %d.\n", + sysret); /* We are finished with this run */ if (auto_generate_sql_autoincrement || auto_generate_sql_guid_primary) diff --git a/cmd-line-utils/readline/display.c b/cmd-line-utils/readline/display.c index f9b88f0006c..4a9dd466b2f 100644 --- a/cmd-line-utils/readline/display.c +++ b/cmd-line-utils/readline/display.c @@ -465,10 +465,10 @@ rl_redisplay () int newlines, lpos, temp, modmark; const char *prompt_this_line; #if defined (HANDLE_MULTIBYTE) - int num, n0; + int num, n0= 0; wchar_t wc; size_t wc_bytes; - int wc_width; + int wc_width= 0; mbstate_t ps; int _rl_wrapped_multicolumn = 0; #endif @@ -828,7 +828,7 @@ rl_redisplay () cpos_buffer_position = out; lb_linenum = newlines; } - for (i = in; i < in+wc_bytes; i++) + for (i = in; i < in+(int)wc_bytes; i++) line[out++] = rl_line_buffer[i]; for (i = 0; i < wc_width; i++) CHECK_LPOS(); diff --git a/extra/yassl/include/yassl_int.hpp b/extra/yassl/include/yassl_int.hpp index d18dc41860c..1e761f559e2 100644 --- a/extra/yassl/include/yassl_int.hpp +++ b/extra/yassl/include/yassl_int.hpp @@ -441,7 +441,7 @@ public: const Ciphers& GetCiphers() const; const DH_Parms& GetDH_Parms() const; const Stats& GetStats() const; - const VerifyCallback getVerifyCallback() const; + VerifyCallback getVerifyCallback() const; pem_password_cb GetPasswordCb() const; void* GetUserData() const; bool GetSessionCacheOff() const; diff --git a/extra/yassl/src/yassl_int.cpp b/extra/yassl/src/yassl_int.cpp index b7f91d72166..8e4a9aa95ec 100644 --- a/extra/yassl/src/yassl_int.cpp +++ b/extra/yassl/src/yassl_int.cpp @@ -1833,7 +1833,7 @@ SSL_CTX::GetCA_List() const } -const VerifyCallback SSL_CTX::getVerifyCallback() const +VerifyCallback SSL_CTX::getVerifyCallback() const { return verifyCallback_; } diff --git a/include/my_dbug.h b/include/my_dbug.h index 474a46f29dd..0ba72b2210d 100644 --- a/include/my_dbug.h +++ b/include/my_dbug.h @@ -137,13 +137,13 @@ extern FILE *_db_fp_(void); #define DBUG_EVALUATE_IF(keyword,a1,a2) (a2) #define DBUG_PRINT(keyword,arglist) do { } while(0) #define DBUG_PUSH(a1) -#define DBUG_SET(a1) -#define DBUG_SET_INITIAL(a1) +#define DBUG_SET(a1) do { } while(0) +#define DBUG_SET_INITIAL(a1) do { } while(0) #define DBUG_POP() #define DBUG_PROCESS(a1) #define DBUG_SETJMP(a1) setjmp(a1) #define DBUG_LONGJMP(a1) longjmp(a1) -#define DBUG_DUMP(keyword,a1,a2) +#define DBUG_DUMP(keyword,a1,a2) do { } while(0) #define DBUG_END() #define DBUG_ASSERT(A) do { } while(0) #define DBUG_LOCK_FILE diff --git a/sql/event_db_repository.cc b/sql/event_db_repository.cc index 9a253d74546..8faab5023da 100644 --- a/sql/event_db_repository.cc +++ b/sql/event_db_repository.cc @@ -711,7 +711,7 @@ Event_db_repository::update_event(THD *thd, Event_parse_data *parse_data, DBUG_ENTER("Event_db_repository::update_event"); /* None or both must be set */ - DBUG_ASSERT(new_dbname && new_name || new_dbname == new_name); + DBUG_ASSERT((new_dbname && new_name) || new_dbname == new_name); /* Reset sql_mode during data dictionary operations. */ thd->variables.sql_mode= 0; diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index b27f493b80a..df5badccb1e 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -1001,7 +1001,7 @@ static bool print_admin_msg(THD* thd, const char* msg_type, if (!thd->vio_ok()) { - sql_print_error(msgbuf); + sql_print_error("%s", msgbuf); return TRUE; } diff --git a/sql/ha_partition.h b/sql/ha_partition.h index 1c863d6c294..c08b1f77eca 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -773,10 +773,10 @@ public: if (m_handler_status < handler_initialized || m_handler_status >= handler_closed) DBUG_RETURN(PARTITION_ENABLED_TABLE_FLAGS); - else - DBUG_RETURN((m_file[0]->ha_table_flags() & - ~(PARTITION_DISABLED_TABLE_FLAGS)) | - (PARTITION_ENABLED_TABLE_FLAGS)); + + DBUG_RETURN((m_file[0]->ha_table_flags() & + ~(PARTITION_DISABLED_TABLE_FLAGS)) | + (PARTITION_ENABLED_TABLE_FLAGS)); } /* diff --git a/sql/handler.cc b/sql/handler.cc index a4d88e84f4c..d07ebed8ab9 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -3501,14 +3501,10 @@ int handler::index_next_same(uchar *buf, const uchar *key, uint keylen) if (!(error=index_next(buf))) { my_ptrdiff_t ptrdiff= buf - table->record[0]; - uchar *save_record_0; - KEY *key_info; - KEY_PART_INFO *key_part; - KEY_PART_INFO *key_part_end; - LINT_INIT(save_record_0); - LINT_INIT(key_info); - LINT_INIT(key_part); - LINT_INIT(key_part_end); + uchar *UNINIT_VAR(save_record_0); + KEY *UNINIT_VAR(key_info); + KEY_PART_INFO *UNINIT_VAR(key_part); + KEY_PART_INFO *UNINIT_VAR(key_part_end); /* key_cmp_if_same() compares table->record[0] against 'key'. diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index cf38a294e55..b5037c08b3c 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -1344,15 +1344,11 @@ bool get_interval_value(Item *args,interval_type int_type, String *str_value, INTERVAL *interval) { ulonglong array[5]; - longlong value; - const char *str; - size_t length; + longlong UNINIT_VAR(value); + const char *UNINIT_VAR(str); + size_t UNINIT_VAR(length); CHARSET_INFO *cs=str_value->charset(); - LINT_INIT(value); - LINT_INIT(str); - LINT_INIT(length); - bzero((char*) interval,sizeof(*interval)); if ((int) int_type <= INTERVAL_MICROSECOND) { diff --git a/sql/item_xmlfunc.cc b/sql/item_xmlfunc.cc index 6320873e4d3..1eff00027f2 100644 --- a/sql/item_xmlfunc.cc +++ b/sql/item_xmlfunc.cc @@ -1354,7 +1354,7 @@ my_xpath_lex_scan(MY_XPATH *xpath, MY_XPATH_LEX *lex, const char *beg, const char *end) { int ch, ctype, length; - for ( ; beg < end && *beg == ' ' ; beg++); // skip leading spaces + for ( ; beg < end && *beg == ' ' ; beg++) ; // skip leading spaces lex->beg= beg; if (beg >= end) @@ -1423,7 +1423,7 @@ my_xpath_lex_scan(MY_XPATH *xpath, if (my_xdigit(ch)) // a sequence of digits { - for ( ; beg < end && my_xdigit(*beg) ; beg++); + for ( ; beg < end && my_xdigit(*beg) ; beg++) ; lex->end= beg; lex->term= MY_XPATH_LEX_DIGITS; return; @@ -1431,7 +1431,7 @@ my_xpath_lex_scan(MY_XPATH *xpath, if (ch == '"' || ch == '\'') // a string: either '...' or "..." { - for ( ; beg < end && *beg != ch ; beg++); + for ( ; beg < end && *beg != ch ; beg++) ; if (beg < end) { lex->end= beg+1; diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc index 68cd2bf4673..f14ebe49706 100644 --- a/sql/log_event_old.cc +++ b/sql/log_event_old.cc @@ -1245,8 +1245,8 @@ Old_rows_log_event::Old_rows_log_event(THD *thd_arg, TABLE *tbl_arg, ulong tid, solution, to be able to terminate a started statement in the binary log: the extraneous events will be removed in the future. */ - DBUG_ASSERT(tbl_arg && tbl_arg->s && tid != ~0UL || - !tbl_arg && !cols && tid == ~0UL); + DBUG_ASSERT((tbl_arg && tbl_arg->s && tid != ~0UL) || + (!tbl_arg && !cols && tid == ~0UL)); if (thd_arg->options & OPTION_NO_FOREIGN_KEY_CHECKS) set_flags(NO_FOREIGN_KEY_CHECKS_F); @@ -1409,7 +1409,7 @@ int Old_rows_log_event::do_add_row_data(uchar *row_data, size_t length) #endif DBUG_ASSERT(m_rows_buf <= m_rows_cur); - DBUG_ASSERT(!m_rows_buf || m_rows_end && m_rows_buf < m_rows_end); + DBUG_ASSERT(!m_rows_buf || (m_rows_end && m_rows_buf < m_rows_end)); DBUG_ASSERT(m_rows_cur <= m_rows_end); /* The cast will always work since m_rows_cur <= m_rows_end */ diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 5778e6ab4aa..3433b54cb29 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3719,6 +3719,7 @@ static void end_ssl() static int init_server_components() { + FILE* reopen; DBUG_ENTER("init_server_components"); /* We need to call each of these following functions to ensure that @@ -3761,7 +3762,7 @@ static int init_server_components() if (freopen(log_error_file, "a+", stdout)) #endif { - freopen(log_error_file, "a+", stderr); + reopen= freopen(log_error_file, "a+", stderr); setbuf(stderr, NULL); } } diff --git a/sql/partition_info.cc b/sql/partition_info.cc index e2027d3571e..ba9ea0e876e 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -483,10 +483,8 @@ static bool check_engine_condition(partition_element *p_elem, { DBUG_RETURN(TRUE); } - else - { - DBUG_RETURN(FALSE); - } + + DBUG_RETURN(FALSE); } diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index 18fbae9bb9d..0c6cc15297f 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -33,10 +33,10 @@ Relay_log_info::Relay_log_info() :Slave_reporting_capability("SQL"), no_storage(FALSE), replicate_same_server_id(::replicate_same_server_id), info_fd(-1), cur_log_fd(-1), save_temporary_tables(0), + cur_log_old_open_count(0), group_relay_log_pos(0), event_relay_log_pos(0), #if HAVE_purify is_fake(FALSE), #endif - cur_log_old_open_count(0), group_relay_log_pos(0), event_relay_log_pos(0), group_master_log_pos(0), log_space_total(0), ignore_log_space_limit(0), last_master_timestamp(0), slave_skip_counter(0), abort_pos_wait(0), slave_run_id(0), sql_thd(0), @@ -300,7 +300,7 @@ Failed to open the existing relay log info file '%s' (errno %d)", DBUG_RETURN(error); err: - sql_print_error(msg); + sql_print_error("%s", msg); end_io_cache(&rli->info_file); if (info_fd >= 0) my_close(info_fd, MYF(0)); diff --git a/sql/set_var.cc b/sql/set_var.cc index 51c6ca219c6..cd01f6c8624 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -3349,7 +3349,7 @@ int set_var_init() uint count= 0; DBUG_ENTER("set_var_init"); - for (sys_var *var=vars.first; var; var= var->next, count++); + for (sys_var *var=vars.first; var; var= var->next, count++) ; if (hash_init(&system_variable_hash, system_charset_info, count, 0, 0, (hash_get_key) get_sys_var_length, 0, HASH_UNIQUE)) @@ -4184,10 +4184,10 @@ bool sys_var_opt_readonly::update(THD *thd, set_var *var) can cause to wait on a read lock, it's required for the client application to unlock everything, and acceptable for the server to wait on all locks. */ - if (result= close_cached_tables(thd, NULL, FALSE, TRUE, TRUE)) + if ((result= close_cached_tables(thd, NULL, FALSE, TRUE, TRUE))) goto end_with_read_lock; - if (result= make_global_read_lock_block_commit(thd)) + if ((result= make_global_read_lock_block_commit(thd))) goto end_with_read_lock; /* Change the opt_readonly system variable, safe because the lock is held */ @@ -4200,6 +4200,7 @@ end_with_read_lock: } +#ifndef DBUG_OFF /* even session variable here requires SUPER, because of -#o,file */ bool sys_var_thd_dbug::check(THD *thd, set_var *var) { @@ -4226,6 +4227,8 @@ uchar *sys_var_thd_dbug::value_ptr(THD *thd, enum_var_type type, LEX_STRING *b) DBUG_EXPLAIN(buf, sizeof(buf)); return (uchar*) thd->strdup(buf); } +#endif /* DBUG_OFF */ + #ifdef HAVE_EVENT_SCHEDULER bool sys_var_event_scheduler::check(THD *thd, set_var *var) diff --git a/sql/set_var.h b/sql/set_var.h index 10e6e0f9c35..a54591b0fd6 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -621,6 +621,7 @@ public: uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); }; +#ifndef DBUG_OFF class sys_var_thd_dbug :public sys_var_thd { public: @@ -634,7 +635,7 @@ public: void set_default(THD *thd, enum_var_type type) { DBUG_POP(); } uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *b); }; - +#endif /* DBUG_OFF */ /* some variables that require special handling */ diff --git a/sql/slave.cc b/sql/slave.cc index 8bf126ce2c2..66cbef1029a 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1195,7 +1195,7 @@ err: if (master_res) mysql_free_result(master_res); DBUG_ASSERT(err_code != 0); - mi->report(ERROR_LEVEL, err_code, err_buff); + mi->report(ERROR_LEVEL, err_code, "%s", err_buff); DBUG_RETURN(1); } @@ -2386,7 +2386,7 @@ static bool check_io_slave_killed(THD *thd, Master_info *mi, const char *info) if (io_slave_killed(thd, mi)) { if (info && global_system_variables.log_warnings) - sql_print_information(info); + sql_print_information("%s", info); return TRUE; } return FALSE; @@ -2456,13 +2456,13 @@ static int try_to_reconnect(THD *thd, MYSQL *mysql, Master_info *mi, } else { - sql_print_information(buf); + sql_print_information("%s", buf); } } if (safe_reconnect(thd, mysql, mi, 1) || io_slave_killed(thd, mi)) { if (global_system_variables.log_warnings) - sql_print_information(messages[SLAVE_RECON_MSG_KILLED_AFTER]); + sql_print_information("%s", messages[SLAVE_RECON_MSG_KILLED_AFTER]); return 1; } return 0; @@ -2679,7 +2679,7 @@ slave. If the entry is correct, restart the server with a higher value of \ max_allowed_packet", thd->variables.max_allowed_packet); mi->report(ERROR_LEVEL, ER_NET_PACKET_TOO_LARGE, - ER(ER_NET_PACKET_TOO_LARGE)); + "%s", ER(ER_NET_PACKET_TOO_LARGE)); goto err; case ER_MASTER_FATAL_ERROR_READING_BINLOG: mi->report(ERROR_LEVEL, ER_MASTER_FATAL_ERROR_READING_BINLOG, @@ -2690,7 +2690,7 @@ max_allowed_packet", sql_print_error("\ Stopping slave I/O thread due to out-of-memory error from master"); mi->report(ERROR_LEVEL, ER_OUT_OF_RESOURCES, - ER(ER_OUT_OF_RESOURCES)); + "%s", ER(ER_OUT_OF_RESOURCES)); goto err; } if (try_to_reconnect(thd, mysql, mi, &retry_count, suppress_warnings, @@ -3050,7 +3050,7 @@ log '%s' at position %s, relay log '%s' position: %s", RPL_LOG_NAME, This function is reporting an error which was not reported while executing exec_relay_log_event(). */ - rli->report(ERROR_LEVEL, thd->main_da.sql_errno(), errmsg); + rli->report(ERROR_LEVEL, thd->main_da.sql_errno(), "%s", errmsg); } else if (last_errno != thd->main_da.sql_errno()) { diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index df19fd05417..a41b7bd40bb 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -383,7 +383,7 @@ static void debug_wait_for_kill(const char *info) thd= current_thd; prev_info= thd->proc_info; thd->proc_info= info; - sql_print_information(info); + sql_print_information("%s", info); while(!thd->killed) my_sleep(1000); thd->killed= THD::NOT_KILLED; diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index 98574a07a4e..bb4ba2bf21b 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -985,7 +985,7 @@ static void end_connection(THD *thd) if (thd->user_connect) decrease_user_connections(thd->user_connect); - if (thd->killed || net->error && net->vio != 0) + if (thd->killed || (net->error && net->vio != 0)) { statistic_increment(aborted_threads,&LOCK_status); } diff --git a/sql/sql_db.cc b/sql/sql_db.cc index bcc8fcf54fc..c19bfba9fc1 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -1450,11 +1450,11 @@ cmp_db_names(const char *db1_name, { return /* db1 is NULL and db2 is NULL */ - !db1_name && !db2_name || + (!db1_name && !db2_name) || /* db1 is not-NULL, db2 is not-NULL, db1 == db2. */ - db1_name && db2_name && - my_strcasecmp(system_charset_info, db1_name, db2_name) == 0; + (db1_name && db2_name && + my_strcasecmp(system_charset_info, db1_name, db2_name) == 0); } diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 08ff2daacb9..2fb09ab7566 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -7098,9 +7098,9 @@ static uint32 get_next_partition_via_walking(PARTITION_ITERATOR *part_iter) longlong dummy; field->store(part_iter->field_vals.cur++, ((Field_num*)field)->unsigned_flag); - if (part_iter->part_info->is_sub_partitioned() && + if ((part_iter->part_info->is_sub_partitioned() && !part_iter->part_info->get_part_partition_id(part_iter->part_info, - &part_id, &dummy) || + &part_id, &dummy)) || !part_iter->part_info->get_partition_id(part_iter->part_info, &part_id, &dummy)) return part_id; diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 025c8a8248d..b411d5e3095 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -368,7 +368,7 @@ static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report) if (report & REPORT_TO_USER) my_error(ER_UDF_NO_PATHS, MYF(0)); if (report & REPORT_TO_LOG) - sql_print_error(ER(ER_UDF_NO_PATHS)); + sql_print_error("%s", ER(ER_UDF_NO_PATHS)); DBUG_RETURN(0); } /* If this dll is already loaded just increase ref_count. */ diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 5c2c351652b..bb377e676e2 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -3529,7 +3529,9 @@ static int get_schema_tables_record(THD *thd, TABLE_LIST *tables, TABLE_SHARE *share= show_table->s; handler *file= show_table->file; handlerton *tmp_db_type= share->db_type(); +#ifdef WITH_PARTITION_STORAGE_ENGINE bool is_partitioned= FALSE; +#endif if (share->tmp_table == SYSTEM_TMP_TABLE) table->field[3]->store(STRING_WITH_LEN("SYSTEM VIEW"), cs); else if (share->tmp_table) diff --git a/sql/strfunc.cc b/sql/strfunc.cc index 1fb9c1a8451..56fa4a380ea 100644 --- a/sql/strfunc.cc +++ b/sql/strfunc.cc @@ -147,7 +147,7 @@ static uint parse_name(TYPELIB *lib, const char **strpos, const char *end, } } else - for (; pos != end && *pos != '=' && *pos !=',' ; pos++); + for (; pos != end && *pos != '=' && *pos !=',' ; pos++) ; uint var_len= (uint) (pos - start); /* Determine which flag it is */ diff --git a/storage/archive/ha_archive.cc b/storage/archive/ha_archive.cc index 981814628f9..6fa8333c1b7 100644 --- a/storage/archive/ha_archive.cc +++ b/storage/archive/ha_archive.cc @@ -522,8 +522,8 @@ int ha_archive::open(const char *name, int mode, uint open_options) { DBUG_RETURN(0); } - else - DBUG_RETURN(rc); + + DBUG_RETURN(rc); } @@ -1575,10 +1575,8 @@ int ha_archive::check(THD* thd, HA_CHECK_OPT* check_opt) share->crashed= FALSE; DBUG_RETURN(HA_ADMIN_CORRUPT); } - else - { - DBUG_RETURN(HA_ADMIN_OK); - } + + DBUG_RETURN(HA_ADMIN_OK); } /* diff --git a/storage/csv/ha_tina.cc b/storage/csv/ha_tina.cc index e18d4025777..ca9d5215310 100644 --- a/storage/csv/ha_tina.cc +++ b/storage/csv/ha_tina.cc @@ -1598,8 +1598,8 @@ int ha_tina::check(THD* thd, HA_CHECK_OPT* check_opt) share->crashed= TRUE; DBUG_RETURN(HA_ADMIN_CORRUPT); } - else - DBUG_RETURN(HA_ADMIN_OK); + + DBUG_RETURN(HA_ADMIN_OK); } diff --git a/storage/myisammrg/myrg_open.c b/storage/myisammrg/myrg_open.c index b82e3682ebf..7b310dc2eed 100644 --- a/storage/myisammrg/myrg_open.c +++ b/storage/myisammrg/myrg_open.c @@ -392,7 +392,7 @@ int myrg_attach_children(MYRG_INFO *m_info, int handle_locking, int save_errno; uint idx; uint child_nr; - uint key_parts; + uint UNINIT_VAR(key_parts); uint min_keys; my_bool bad_children= FALSE; DBUG_ENTER("myrg_attach_children"); @@ -409,7 +409,6 @@ int myrg_attach_children(MYRG_INFO *m_info, int handle_locking, rc= 1; errpos= 0; file_offset= 0; - LINT_INIT(key_parts); min_keys= 0; child_nr= 0; while ((myisam= (*callback)(callback_param))) diff --git a/unittest/mysys/base64-t.c b/unittest/mysys/base64-t.c index 1622fe22b4d..e1a40f89ff0 100644 --- a/unittest/mysys/base64-t.c +++ b/unittest/mysys/base64-t.c @@ -84,7 +84,7 @@ main(void) unsigned char c= dst[k+l]; sprintf(buf, "%.2x ", (unsigned)c); } - diag(buf); + diag("%s", buf); } diag("src length: %.8x, dst length: %.8x\n", (uint) src_len, (uint) dst_len); From 9eab1cdb9ae94120dd35aeee13c13295ba59ee3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20Bl=C3=A5udd?= Date: Thu, 24 Sep 2009 08:30:31 +0200 Subject: [PATCH 63/80] Bug#42850 race condition in my_thr_init.c - Create the "dummy" thread joinable and wait for it to exit before continuing in 'my_thread_global_init' - This way we know that the pthread library is initialized by one thread only --- mysys/my_thr_init.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/mysys/my_thr_init.c b/mysys/my_thr_init.c index c446808c7da..64fc99952e9 100644 --- a/mysys/my_thr_init.c +++ b/mysys/my_thr_init.c @@ -107,10 +107,11 @@ my_bool my_thread_global_init(void) pthread_attr_t dummy_thread_attr; pthread_attr_init(&dummy_thread_attr); - pthread_attr_setdetachstate(&dummy_thread_attr, PTHREAD_CREATE_DETACHED); + pthread_attr_setdetachstate(&dummy_thread_attr, PTHREAD_CREATE_JOINABLE); - pthread_create(&dummy_thread,&dummy_thread_attr, - nptl_pthread_exit_hack_handler, NULL); + if (pthread_create(&dummy_thread,&dummy_thread_attr, + nptl_pthread_exit_hack_handler, NULL) == 0) + (void)pthread_join(dummy_thread, NULL); } #endif /* TARGET_OS_LINUX */ From c6ca40fb86555f8e19734ecb4735e562107ed001 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Thu, 24 Sep 2009 16:19:06 +0300 Subject: [PATCH 64/80] added suppressions for existing warnings in the result file. --- mysql-test/include/mtr_warnings.sql | 1 + mysql-test/suite/rpl/r/rpl_get_master_version_and_clock.result | 2 ++ mysql-test/suite/rpl/r/rpl_log_pos.result | 1 + mysql-test/suite/rpl/r/rpl_packet.result | 2 ++ mysql-test/suite/rpl/t/rpl_get_master_version_and_clock.test | 2 ++ mysql-test/suite/rpl/t/rpl_log_pos.test | 1 + mysql-test/suite/rpl/t/rpl_packet.test | 2 ++ 7 files changed, 11 insertions(+) diff --git a/mysql-test/include/mtr_warnings.sql b/mysql-test/include/mtr_warnings.sql index 2156c37f3e3..134e448953a 100644 --- a/mysql-test/include/mtr_warnings.sql +++ b/mysql-test/include/mtr_warnings.sql @@ -173,6 +173,7 @@ INSERT INTO global_suppressions VALUES this error message. */ ("Can't find file: '.\\\\test\\\\\\?{8}.frm'"), + ("Slave: Unknown table 't1' Error_code: 1051"), ("THE_LAST_SUPPRESSION")|| diff --git a/mysql-test/suite/rpl/r/rpl_get_master_version_and_clock.result b/mysql-test/suite/rpl/r/rpl_get_master_version_and_clock.result index 263896b884a..99a0fd21f66 100644 --- a/mysql-test/suite/rpl/r/rpl_get_master_version_and_clock.result +++ b/mysql-test/suite/rpl/r/rpl_get_master_version_and_clock.result @@ -4,6 +4,8 @@ reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; +call mtr.add_suppression("Slave I/O: .* failed with error: Lost connection to MySQL server at 'reading initial communication packet'"); +call mtr.add_suppression("Slave I/O: Master command COM_REGISTER_SLAVE failed: failed registering on master, reconnecting to try again"); SELECT IS_FREE_LOCK("debug_lock.before_get_UNIX_TIMESTAMP"); IS_FREE_LOCK("debug_lock.before_get_UNIX_TIMESTAMP") 1 diff --git a/mysql-test/suite/rpl/r/rpl_log_pos.result b/mysql-test/suite/rpl/r/rpl_log_pos.result index 7b3ebf62959..85fa4c10eac 100644 --- a/mysql-test/suite/rpl/r/rpl_log_pos.result +++ b/mysql-test/suite/rpl/r/rpl_log_pos.result @@ -4,6 +4,7 @@ reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; +call mtr.add_suppression ("Slave I/O: Got fatal error 1236 from master when reading data from binary"); show master status; File Position Binlog_Do_DB Binlog_Ignore_DB master-bin.000001 # diff --git a/mysql-test/suite/rpl/r/rpl_packet.result b/mysql-test/suite/rpl/r/rpl_packet.result index cb26d04bea9..0a9495751fe 100644 --- a/mysql-test/suite/rpl/r/rpl_packet.result +++ b/mysql-test/suite/rpl/r/rpl_packet.result @@ -4,6 +4,8 @@ reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; +call mtr.add_suppression("Slave I/O: Got a packet bigger than 'max_allowed_packet' bytes, Error_code: 1153"); +call mtr.add_suppression("Slave I/O: Got fatal error 1236 from master when reading data from binary log:"); drop database if exists DB_NAME_OF_MAX_LENGTH_AKA_NAME_LEN_64_BYTES_____________________; create database DB_NAME_OF_MAX_LENGTH_AKA_NAME_LEN_64_BYTES_____________________; SET @@global.max_allowed_packet=1024; diff --git a/mysql-test/suite/rpl/t/rpl_get_master_version_and_clock.test b/mysql-test/suite/rpl/t/rpl_get_master_version_and_clock.test index 40d11f2cec2..a391b1f5344 100644 --- a/mysql-test/suite/rpl/t/rpl_get_master_version_and_clock.test +++ b/mysql-test/suite/rpl/t/rpl_get_master_version_and_clock.test @@ -16,6 +16,8 @@ source include/master-slave.inc; source include/have_debug.inc; +call mtr.add_suppression("Slave I/O: .* failed with error: Lost connection to MySQL server at 'reading initial communication packet'"); +call mtr.add_suppression("Slave I/O: Master command COM_REGISTER_SLAVE failed: failed registering on master, reconnecting to try again"); #Test case 1: Try to get the value of the UNIX_TIMESTAMP from master under network disconnection connection slave; let $debug_saved= `select @@global.debug`; diff --git a/mysql-test/suite/rpl/t/rpl_log_pos.test b/mysql-test/suite/rpl/t/rpl_log_pos.test index 5e8390f97ed..48effa00b64 100644 --- a/mysql-test/suite/rpl/t/rpl_log_pos.test +++ b/mysql-test/suite/rpl/t/rpl_log_pos.test @@ -11,6 +11,7 @@ # Passes with rbr no problem, removed statement include [jbm] source include/master-slave.inc; +call mtr.add_suppression ("Slave I/O: Got fatal error 1236 from master when reading data from binary"); source include/show_master_status.inc; sync_slave_with_master; source include/stop_slave.inc; diff --git a/mysql-test/suite/rpl/t/rpl_packet.test b/mysql-test/suite/rpl/t/rpl_packet.test index b4e04405037..bfc144c759b 100644 --- a/mysql-test/suite/rpl/t/rpl_packet.test +++ b/mysql-test/suite/rpl/t/rpl_packet.test @@ -6,6 +6,8 @@ # max-out size db name source include/master-slave.inc; source include/have_binlog_format_row.inc; +call mtr.add_suppression("Slave I/O: Got a packet bigger than 'max_allowed_packet' bytes, Error_code: 1153"); +call mtr.add_suppression("Slave I/O: Got fatal error 1236 from master when reading data from binary log:"); let $db= DB_NAME_OF_MAX_LENGTH_AKA_NAME_LEN_64_BYTES_____________________; disable_warnings; From 45c70a2ec50e81d3eeb1699fae939e113bf69ba1 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Thu, 24 Sep 2009 16:21:46 +0300 Subject: [PATCH 65/80] fixed compilation warnings --- mysys/mf_keycache.c | 2 +- sql/item_func.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c index f9898e263aa..3c11e6731b7 100644 --- a/mysys/mf_keycache.c +++ b/mysys/mf_keycache.c @@ -3113,7 +3113,7 @@ int key_cache_write(KEY_CACHE *keycache, /* Used in the server. */ keycache->global_cache_write++; keycache_pthread_mutex_unlock(&keycache->cache_lock); - if (my_pwrite(file, (uchar*) buff, read_length, filepos + offset, + if (my_pwrite(file, (byte*) buff, read_length, filepos + offset, MYF(MY_NABP | MY_WAIT_IF_FULL))) error=1; keycache_pthread_mutex_lock(&keycache->cache_lock); diff --git a/sql/item_func.cc b/sql/item_func.cc index c6dbdb1d9a7..d6f315fda50 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -4201,7 +4201,7 @@ void Item_func_set_user_var::save_item_result(Item *item) bool Item_func_set_user_var::update() { - bool res= NULL; + bool res= 0; DBUG_ENTER("Item_func_set_user_var::update"); switch (cached_result_type) { From 40b685cf59868507eb41f9d41d0f92e6d84eb88c Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Thu, 24 Sep 2009 18:29:00 +0300 Subject: [PATCH 66/80] More valgrind suppressions added for libc 2.6.1 64 bit --- mysql-test/valgrind.supp | 84 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/mysql-test/valgrind.supp b/mysql-test/valgrind.supp index 21c6c30abcc..fe3a0334fae 100644 --- a/mysql-test/valgrind.supp +++ b/mysql-test/valgrind.supp @@ -625,3 +625,87 @@ fun:start_thread } +{ + Mem loss within nptl_pthread_exit_hack_handler 6 + Memcheck:Leak + fun:malloc + obj:*/ld-*.so + obj:*/ld-*.so + obj:*/ld-*.so + obj:*/ld-*.so + obj:*/ld-*.so + obj:*/ld-*.so + obj:*/libc-*.so + obj:*/ld-*.so + obj:*/libc-*.so + fun:__libc_dlopen_mode + fun:pthread_cancel_init + fun:_Unwind_ForcedUnwind + fun:__pthread_unwind + fun:pthread_exit + fun:nptl_pthread_exit_hack_handler +} + +{ + Mem loss within nptl_pthread_exit_hack_handler 7 + Memcheck:Leak + fun:malloc + obj:*/ld-*.so + obj:*/ld-*.so + obj:*/ld-*.so + obj:*/ld-*.so + obj:*/libc-*.so + obj:*/ld-*.so + obj:*/libc-*.so + fun:__libc_dlopen_mode + fun:pthread_cancel_init + fun:_Unwind_ForcedUnwind + fun:__pthread_unwind + fun:pthread_exit + fun:nptl_pthread_exit_hack_handler + fun:start_thread + fun:clone +} + +{ + Mem loss within nptl_pthread_exit_hack_handler 8 + Memcheck:Leak + fun:calloc + obj:*/ld-*.so + obj:*/ld-*.so + obj:*/ld-*.so + obj:*/ld-*.so + obj:*/libc-*.so + obj:*/ld-*.so + obj:*/libc-*.so + fun:__libc_dlopen_mode + fun:pthread_cancel_init + fun:_Unwind_ForcedUnwind + fun:__pthread_unwind + fun:pthread_exit + fun:nptl_pthread_exit_hack_handler + fun:start_thread + fun:clone +} + +{ + Mem loss within nptl_pthread_exit_hack_handler 8 + Memcheck:Leak + fun:calloc + obj:*/ld-*.so + obj:*/ld-*.so + obj:*/ld-*.so + obj:*/ld-*.so + obj:*/ld-*.so + obj:*/ld-*.so + obj:*/libc-*.so + obj:*/ld-*.so + obj:*/libc-*.so + fun:__libc_dlopen_mode + fun:pthread_cancel_init + fun:_Unwind_ForcedUnwind + fun:__pthread_unwind + fun:pthread_exit + fun:nptl_pthread_exit_hack_handler +} + From 3787988ca8064fe38e83c554f7e1b8e6ec6aeb8e Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Fri, 25 Sep 2009 11:57:14 +0300 Subject: [PATCH 67/80] added more valgrind suppressions for glibc 2.6.1 --- mysql-test/valgrind.supp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/mysql-test/valgrind.supp b/mysql-test/valgrind.supp index fe3a0334fae..26f0d329a4a 100644 --- a/mysql-test/valgrind.supp +++ b/mysql-test/valgrind.supp @@ -1,5 +1,4 @@ -# -# Suppress some common (not fatal) errors in system libraries found by valgrind +*# Suppress some common (not fatal) errors in system libraries found by valgrind # # @@ -625,6 +624,8 @@ fun:start_thread } +# suppressions for glibc 2.6.1 64 bit + { Mem loss within nptl_pthread_exit_hack_handler 6 Memcheck:Leak @@ -709,3 +710,14 @@ fun:nptl_pthread_exit_hack_handler } +# +# Pthread doesn't free all thread specific memory before program exists +# +{ + pthread allocate_tls memory loss in 2.6.1. + Memcheck:Leak + fun:calloc + obj:*/ld-*.so + fun:_dl_allocate_tls + fun:pthread_create* +} From 43e6919d56561f5d2de89bbd1a6c03003e3dcf8d Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Fri, 25 Sep 2009 11:26:49 +0200 Subject: [PATCH 68/80] Bug#32430: 'show innodb status' causes errors Invalid (old?) table or database name in logs Problem was still not completely fixed, due to qouting. This is the server side only fix (in explain_filename), the change from filename_to_tablename to use explain_filename in the InnoDB code must be done before the bug is fixed. mysql-test/include/have_not_innodb_plugin.inc: Bug#32430: 'show innodb status' causes errors Invalid (old?) table or database name in logs Added include file to allow test for only the 'old' built-in innodb engine mysql-test/r/not_true.require: Bug#32430: 'show innodb status' causes errors Invalid (old?) table or database name in logs Added require to match 'not' TRUE mysql-test/r/partition_innodb_builtin.result: Bug#32430: 'show innodb status' causes errors Invalid (old?) table or database name in logs New result file for partitioning specific to the 'old' built-in innodb engine mysql-test/r/partition_innodb_plugin.result: Bug#32430: 'show innodb status' causes errors Invalid (old?) table or database name in logs New result file for partitioning specific to the new plugin innodb engine mysql-test/t/disabled.def: Bug#32430: 'show innodb status' causes errors Invalid (old?) table or database name in logs Disabling the new test until the fix is included in the InnoDB source too. mysql-test/t/partition_innodb_builtin.test: Bug#32430: 'show innodb status' causes errors Invalid (old?) table or database name in logs New test file for partitioning specific to the 'old' built-in innodb engine mysql-test/t/partition_innodb_plugin.test: Bug#32430: 'show innodb status' causes errors Invalid (old?) table or database name in logs New test file for partitioning specific to the new plugin innodb engine sql/mysql_priv.h: Bug#32430: 'show innodb status' causes errors Invalid (old?) table or database name in logs Added thd as a parameter to explain_filename to be able to use the correct quote character sql/sql_table.cc: Bug#32430: 'show innodb status' causes errors Invalid (old?) table or database name in logs Changed explain_filename, so that it does qouting correctly according to the sessions qoute char. --- mysql-test/include/have_not_innodb_plugin.inc | 4 + mysql-test/r/not_true.require | 2 + mysql-test/r/partition_innodb_builtin.result | 39 ++++++++++ mysql-test/r/partition_innodb_plugin.result | 50 +++++++++++++ mysql-test/t/disabled.def | 3 +- mysql-test/t/partition_innodb_builtin.test | 67 +++++++++++++++++ mysql-test/t/partition_innodb_plugin.test | 75 +++++++++++++++++++ sql/mysql_priv.h | 5 +- sql/sql_table.cc | 58 +++++++------- 9 files changed, 271 insertions(+), 32 deletions(-) create mode 100644 mysql-test/include/have_not_innodb_plugin.inc create mode 100644 mysql-test/r/not_true.require create mode 100644 mysql-test/r/partition_innodb_builtin.result create mode 100644 mysql-test/r/partition_innodb_plugin.result create mode 100644 mysql-test/t/partition_innodb_builtin.test create mode 100644 mysql-test/t/partition_innodb_plugin.test diff --git a/mysql-test/include/have_not_innodb_plugin.inc b/mysql-test/include/have_not_innodb_plugin.inc new file mode 100644 index 00000000000..aaefbaf661c --- /dev/null +++ b/mysql-test/include/have_not_innodb_plugin.inc @@ -0,0 +1,4 @@ +disable_query_log; +--require r/not_true.require +select (PLUGIN_LIBRARY LIKE 'ha_innodb_plugin%') as `TRUE` from information_schema.plugins where PLUGIN_NAME='InnoDB'; +enable_query_log; diff --git a/mysql-test/r/not_true.require b/mysql-test/r/not_true.require new file mode 100644 index 00000000000..0032832f3d1 --- /dev/null +++ b/mysql-test/r/not_true.require @@ -0,0 +1,2 @@ +TRUE +NULL diff --git a/mysql-test/r/partition_innodb_builtin.result b/mysql-test/r/partition_innodb_builtin.result new file mode 100644 index 00000000000..384ce0790a4 --- /dev/null +++ b/mysql-test/r/partition_innodb_builtin.result @@ -0,0 +1,39 @@ +SET NAMES utf8; +CREATE TABLE `t``\""e` (a INT, PRIMARY KEY (a)) +ENGINE=InnoDB +PARTITION BY RANGE (a) +SUBPARTITION BY HASH (a) +(PARTITION `p0``\""e` VALUES LESS THAN (100) +(SUBPARTITION `sp0``\""e`, +SUBPARTITION `sp1``\""e`), +PARTITION `p1``\""e` VALUES LESS THAN (MAXVALUE) +(SUBPARTITION `sp2``\""e`, +SUBPARTITION `sp3``\""e`)); +INSERT INTO `t``\""e` VALUES (0), (2), (6), (10), (14), (18), (22); +START TRANSACTION; +# con1 +SET NAMES utf8; +START TRANSACTION; +# default connection +UPDATE `t``\""e` SET a = 16 WHERE a = 0; +# con1 +UPDATE `t``\""e` SET a = 8 WHERE a = 22; +UPDATE `t``\""e` SET a = 12 WHERE a = 0; +# default connection +UPDATE `t``\""e` SET a = 4 WHERE a = 22; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +# First table reported in 'SHOW ENGINE InnoDB STATUS' +SHOW ENGINE InnoDB STATUS; +Type Name Status +InnoDB index `PRIMARY` of table `test`.`t``\""e` /* Partition `p0``\""e`, Subpartition `sp0``\""e` */ +set @old_sql_mode = @@sql_mode; +set sql_mode = 'ANSI_QUOTES'; +SHOW ENGINE InnoDB STATUS; +Type Name Status +InnoDB index `PRIMARY` of table `test`.`t``\""e` /* Partition `p0``\""e`, Subpartition `sp0``\""e` */ +set @@sql_mode = @old_sql_mode; +# con1 +ROLLBACK; +# default connection +DROP TABLE `t``\""e`; +SET NAMES DEFAULT; diff --git a/mysql-test/r/partition_innodb_plugin.result b/mysql-test/r/partition_innodb_plugin.result new file mode 100644 index 00000000000..dd91eee316a --- /dev/null +++ b/mysql-test/r/partition_innodb_plugin.result @@ -0,0 +1,50 @@ +SET NAMES utf8; +CREATE TABLE `t``\""e` (a INT, PRIMARY KEY (a)) +ENGINE=InnoDB +PARTITION BY RANGE (a) +SUBPARTITION BY HASH (a) +(PARTITION `p0``\""e` VALUES LESS THAN (100) +(SUBPARTITION `sp0``\""e`, +SUBPARTITION `sp1``\""e`), +PARTITION `p1``\""e` VALUES LESS THAN (MAXVALUE) +(SUBPARTITION `sp2``\""e`, +SUBPARTITION `sp3``\""e`)); +INSERT INTO `t``\""e` VALUES (0), (2), (6), (10), (14), (18), (22); +START TRANSACTION; +# con1 +SET NAMES utf8; +START TRANSACTION; +# default connection +UPDATE `t``\""e` SET a = 16 WHERE a = 0; +# con1 +UPDATE `t``\""e` SET a = 8 WHERE a = 22; +UPDATE `t``\""e` SET a = 12 WHERE a = 0; +# default connection +SELECT lock_table, COUNT(*) FROM INFORMATION_SCHEMA.INNODB_LOCKS +GROUP BY lock_table; +lock_table COUNT(*) +`test`.`t``\""e` /* Partition `p0``\""e`, Subpartition `sp0``\""e` */ 2 +set @old_sql_mode = @@sql_mode; +set sql_mode = 'ANSI_QUOTES'; +SELECT lock_table, COUNT(*) FROM INFORMATION_SCHEMA.INNODB_LOCKS +GROUP BY lock_table; +lock_table COUNT(*) +"test"."t`\""""e" /* Partition "p0`\""""e", Subpartition "sp0`\""""e" */ 2 +set @@sql_mode = @old_sql_mode; +UPDATE `t``\""e` SET a = 4 WHERE a = 22; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +# First table reported in 'SHOW ENGINE InnoDB STATUS' +SHOW ENGINE InnoDB STATUS; +Type Name Status +InnoDB index `PRIMARY` of table `test`.`t``\""e` /* Partition `p0``\""e`, Subpartition `sp0``\""e` */ +set @old_sql_mode = @@sql_mode; +set sql_mode = 'ANSI_QUOTES'; +SHOW ENGINE InnoDB STATUS; +Type Name Status +InnoDB index `PRIMARY` of table `test`.`t``\""e` /* Partition `p0``\""e`, Subpartition `sp0``\""e` */ +set @@sql_mode = @old_sql_mode; +# con1 +ROLLBACK; +# default connection +DROP TABLE `t``\""e`; +SET NAMES DEFAULT; diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index 5436b7166f4..6613b6da415 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -13,4 +13,5 @@ kill : Bug#37780 2008-12-03 HHunger need some changes to be innodb_bug39438 : Bug#42383 2009-01-28 lsoares "This fails in embedded and on windows. Note that this test is not run on windows and on embedded in PB for main trees currently" query_cache_28249 : Bug#43861 2009-03-25 main.query_cache_28249 fails sporadically init_connect : Bug#44920 2009-07-06 pcrews MTR not processing master.opt input properly on Windows. *Must be done this way due to the nature of the bug* - +partition_innodb_builtin : Bug#32430 2009-09-25 mattiasj Waiting for push of Innodb changes +partition_innodb_plugin : Bug#32430 2009-09-25 mattiasj Waiting for push of Innodb changes diff --git a/mysql-test/t/partition_innodb_builtin.test b/mysql-test/t/partition_innodb_builtin.test new file mode 100644 index 00000000000..a9be41c7455 --- /dev/null +++ b/mysql-test/t/partition_innodb_builtin.test @@ -0,0 +1,67 @@ +--source include/have_partition.inc +--source include/have_innodb.inc +--source include/have_not_innodb_plugin.inc + +# +# Bug#32430 - show engine innodb status causes errors +# +SET NAMES utf8; +CREATE TABLE `t``\""e` (a INT, PRIMARY KEY (a)) +ENGINE=InnoDB +PARTITION BY RANGE (a) +SUBPARTITION BY HASH (a) +(PARTITION `p0``\""e` VALUES LESS THAN (100) + (SUBPARTITION `sp0``\""e`, + SUBPARTITION `sp1``\""e`), + PARTITION `p1``\""e` VALUES LESS THAN (MAXVALUE) + (SUBPARTITION `sp2``\""e`, + SUBPARTITION `sp3``\""e`)); +INSERT INTO `t``\""e` VALUES (0), (2), (6), (10), (14), (18), (22); +START TRANSACTION; +--echo # con1 +connect(con1,localhost,root,,); +SET NAMES utf8; +START TRANSACTION; +--echo # default connection +connection default; +UPDATE `t``\""e` SET a = 16 WHERE a = 0; +--echo # con1 +connection con1; +UPDATE `t``\""e` SET a = 8 WHERE a = 22; +let $id_1= `SELECT CONNECTION_ID()`; +SEND; +UPDATE `t``\""e` SET a = 12 WHERE a = 0; +--echo # default connection +connection default; +let $wait_timeout= 2; +let $wait_condition= SELECT 1 FROM INFORMATION_SCHEMA.PROCESSLIST +WHERE ID = $id_1 AND STATE = 'Searching rows for update'; +--source include/wait_condition.inc +#--echo # tested wait condition $wait_condition_reps times +--error ER_LOCK_DEADLOCK +UPDATE `t``\""e` SET a = 4 WHERE a = 22; +--echo # First table reported in 'SHOW ENGINE InnoDB STATUS' +# RECORD LOCKS space id 0 page no 50 n bits 80 index `PRIMARY` in \ +# Database `test`, Table `t1`, Partition `p0`, Subpartition `sp0` \ +# trx id 0 775 +# NOTE: replace_regex is very slow on match copy/past '(.*)' regex's +# on big texts, removing a lot of text before + after makes it much faster. +#/.*in (.*) trx.*/\1/ +--replace_regex /.*RECORD LOCKS space id [0-9]* page no [0-9]* n bits [0-9]* // / trx id .*// /.*index .* in // +SHOW ENGINE InnoDB STATUS; +set @old_sql_mode = @@sql_mode; +set sql_mode = 'ANSI_QUOTES'; +# INNODB_LOCKS only exists in innodb_plugin +#SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS; +--replace_regex /.*RECORD LOCKS space id [0-9]* page no [0-9]* n bits [0-9]* // / trx id .*// /.*index .* in // +SHOW ENGINE InnoDB STATUS; +set @@sql_mode = @old_sql_mode; +--echo # con1 +connection con1; +REAP; +ROLLBACK; +disconnect con1; +--echo # default connection +connection default; +DROP TABLE `t``\""e`; +SET NAMES DEFAULT; diff --git a/mysql-test/t/partition_innodb_plugin.test b/mysql-test/t/partition_innodb_plugin.test new file mode 100644 index 00000000000..fed8c96424a --- /dev/null +++ b/mysql-test/t/partition_innodb_plugin.test @@ -0,0 +1,75 @@ +--source include/have_partition.inc +--source include/have_innodb.inc +--source suite/innodb/include/have_innodb_plugin.inc + +# +# Bug#32430 - show engine innodb status causes errors +# +SET NAMES utf8; +CREATE TABLE `t``\""e` (a INT, PRIMARY KEY (a)) +ENGINE=InnoDB +PARTITION BY RANGE (a) +SUBPARTITION BY HASH (a) +(PARTITION `p0``\""e` VALUES LESS THAN (100) + (SUBPARTITION `sp0``\""e`, + SUBPARTITION `sp1``\""e`), + PARTITION `p1``\""e` VALUES LESS THAN (MAXVALUE) + (SUBPARTITION `sp2``\""e`, + SUBPARTITION `sp3``\""e`)); +INSERT INTO `t``\""e` VALUES (0), (2), (6), (10), (14), (18), (22); +START TRANSACTION; +--echo # con1 +connect(con1,localhost,root,,); +SET NAMES utf8; +START TRANSACTION; +--echo # default connection +connection default; +UPDATE `t``\""e` SET a = 16 WHERE a = 0; +--echo # con1 +connection con1; +UPDATE `t``\""e` SET a = 8 WHERE a = 22; +let $id_1= `SELECT CONNECTION_ID()`; +SEND; +UPDATE `t``\""e` SET a = 12 WHERE a = 0; +--echo # default connection +connection default; +let $wait_timeout= 2; +let $wait_condition= SELECT 1 FROM INFORMATION_SCHEMA.PROCESSLIST +WHERE ID = $id_1 AND STATE = 'Searching rows for update'; +--source include/wait_condition.inc +#--echo # tested wait condition $wait_condition_reps times +# INNODB_LOCKS only exists in innodb_plugin +--sorted_result +SELECT lock_table, COUNT(*) FROM INFORMATION_SCHEMA.INNODB_LOCKS +GROUP BY lock_table; +set @old_sql_mode = @@sql_mode; +set sql_mode = 'ANSI_QUOTES'; +--sorted_result +SELECT lock_table, COUNT(*) FROM INFORMATION_SCHEMA.INNODB_LOCKS +GROUP BY lock_table; +set @@sql_mode = @old_sql_mode; +--error ER_LOCK_DEADLOCK +UPDATE `t``\""e` SET a = 4 WHERE a = 22; +--echo # First table reported in 'SHOW ENGINE InnoDB STATUS' +# RECORD LOCKS space id 0 page no 50 n bits 80 index `PRIMARY` in \ +# Database `test`, Table `t1`, Partition `p0`, Subpartition `sp0` \ +# trx id 0 775 +# NOTE: replace_regex is very slow on match copy/past '(.*)' regex's +# on big texts, removing a lot of text before + after makes it much faster. +#/.*in (.*) trx.*/\1/ +--replace_regex /.*RECORD LOCKS space id [0-9]* page no [0-9]* n bits [0-9]* // / trx id .*// /.*index .* in // +SHOW ENGINE InnoDB STATUS; +set @old_sql_mode = @@sql_mode; +set sql_mode = 'ANSI_QUOTES'; +--replace_regex /.*RECORD LOCKS space id [0-9]* page no [0-9]* n bits [0-9]* // / trx id .*// /.*index .* in // +SHOW ENGINE InnoDB STATUS; +set @@sql_mode = @old_sql_mode; +--echo # con1 +connection con1; +REAP; +ROLLBACK; +disconnect con1; +--echo # default connection +connection default; +DROP TABLE `t``\""e`; +SET NAMES DEFAULT; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 381a0313add..6fde16d3049 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -2277,10 +2277,9 @@ enum enum_explain_filename_mode { EXPLAIN_ALL_VERBOSE= 0, EXPLAIN_PARTITIONS_VERBOSE, - EXPLAIN_PARTITIONS_AS_COMMENT, - EXPLAIN_PARTITIONS_AS_COMMENT_NO_QUOTING + EXPLAIN_PARTITIONS_AS_COMMENT }; -uint explain_filename(const char *from, char *to, uint to_length, +uint explain_filename(THD* thd, const char *from, char *to, uint to_length, enum_explain_filename_mode explain_mode); uint filename_to_tablename(const char *from, char *to, uint to_length); uint tablename_to_filename(const char *from, char *to, uint to_length); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 41e76211dd8..5f718b25d60 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -70,15 +70,21 @@ static void wait_for_kill_signal(THD *thd) /** @brief Helper function for explain_filename + @param thd Thread handle + @param to_p Explained name in system_charset_info + @param end_p End of the to_p buffer + @param name Name to be converted + @param name_len Length of the name, in bytes */ -static char* add_identifier(char *to_p, const char * end_p, - const char* name, uint name_len, bool add_quotes) +static char* add_identifier(THD* thd, char *to_p, const char * end_p, + const char* name, uint name_len) { uint res; uint errors; const char *conv_name; char tmp_name[FN_REFLEN]; char conv_string[FN_REFLEN]; + int quote; DBUG_ENTER("add_identifier"); if (!name[name_len]) @@ -102,19 +108,21 @@ static char* add_identifier(char *to_p, const char * end_p, conv_name= conv_string; } - if (add_quotes && (end_p - to_p > 2)) + quote = thd ? get_quote_char_for_identifier(thd, conv_name, res - 1) : '"'; + + if (quote != EOF && (end_p - to_p > 2)) { - *(to_p++)= '`'; + *(to_p++)= (char) quote; while (*conv_name && (end_p - to_p - 1) > 0) { uint length= my_mbcharlen(system_charset_info, *conv_name); if (!length) length= 1; - if (length == 1 && *conv_name == '`') + if (length == 1 && *conv_name == (char) quote) { if ((end_p - to_p) < 3) break; - *(to_p++)= '`'; + *(to_p++)= (char) quote; *(to_p++)= *(conv_name++); } else if (((long) length) < (end_p - to_p)) @@ -125,7 +133,11 @@ static char* add_identifier(char *to_p, const char * end_p, else break; /* string already filled */ } - to_p= strnmov(to_p, "`", end_p - to_p); + if (end_p > to_p) { + *(to_p++)= (char) quote; + if (end_p > to_p) + *to_p= 0; /* terminate by NUL, but do not include it in the count */ + } } else to_p= strnmov(to_p, conv_name, end_p - to_p); @@ -145,6 +157,7 @@ static char* add_identifier(char *to_p, const char * end_p, diagnostic, error etc. when it would be useful to know what a particular file [and directory] means. Such as SHOW ENGINE STATUS, error messages etc. + @param thd Thread handle @param from Path name in my_charset_filename Null terminated in my_charset_filename, normalized to use '/' as directory separation character. @@ -161,13 +174,12 @@ static char* add_identifier(char *to_p, const char * end_p, [,[ Temporary| Renamed] Partition `p` [, Subpartition `sp`]] *| (| is really a /, and it is all in one line) - EXPLAIN_PARTITIONS_AS_COMMENT_NO_QUOTING -> - same as above but no quotes are added. @retval Length of returned string */ -uint explain_filename(const char *from, +uint explain_filename(THD* thd, + const char *from, char *to, uint to_length, enum_explain_filename_mode explain_mode) @@ -281,14 +293,12 @@ uint explain_filename(const char *from, { to_p= strnmov(to_p, ER(ER_DATABASE_NAME), end_p - to_p); *(to_p++)= ' '; - to_p= add_identifier(to_p, end_p, db_name, db_name_len, 1); + to_p= add_identifier(thd, to_p, end_p, db_name, db_name_len); to_p= strnmov(to_p, ", ", end_p - to_p); } else { - to_p= add_identifier(to_p, end_p, db_name, db_name_len, - (explain_mode != - EXPLAIN_PARTITIONS_AS_COMMENT_NO_QUOTING)); + to_p= add_identifier(thd, to_p, end_p, db_name, db_name_len); to_p= strnmov(to_p, ".", end_p - to_p); } } @@ -296,16 +306,13 @@ uint explain_filename(const char *from, { to_p= strnmov(to_p, ER(ER_TABLE_NAME), end_p - to_p); *(to_p++)= ' '; - to_p= add_identifier(to_p, end_p, table_name, table_name_len, 1); + to_p= add_identifier(thd, to_p, end_p, table_name, table_name_len); } else - to_p= add_identifier(to_p, end_p, table_name, table_name_len, - (explain_mode != - EXPLAIN_PARTITIONS_AS_COMMENT_NO_QUOTING)); + to_p= add_identifier(thd, to_p, end_p, table_name, table_name_len); if (part_name) { - if (explain_mode == EXPLAIN_PARTITIONS_AS_COMMENT || - explain_mode == EXPLAIN_PARTITIONS_AS_COMMENT_NO_QUOTING) + if (explain_mode == EXPLAIN_PARTITIONS_AS_COMMENT) to_p= strnmov(to_p, " /* ", end_p - to_p); else if (explain_mode == EXPLAIN_PARTITIONS_VERBOSE) to_p= strnmov(to_p, " ", end_p - to_p); @@ -321,20 +328,15 @@ uint explain_filename(const char *from, } to_p= strnmov(to_p, ER(ER_PARTITION_NAME), end_p - to_p); *(to_p++)= ' '; - to_p= add_identifier(to_p, end_p, part_name, part_name_len, - (explain_mode != - EXPLAIN_PARTITIONS_AS_COMMENT_NO_QUOTING)); + to_p= add_identifier(thd, to_p, end_p, part_name, part_name_len); if (subpart_name) { to_p= strnmov(to_p, ", ", end_p - to_p); to_p= strnmov(to_p, ER(ER_SUBPARTITION_NAME), end_p - to_p); *(to_p++)= ' '; - to_p= add_identifier(to_p, end_p, subpart_name, subpart_name_len, - (explain_mode != - EXPLAIN_PARTITIONS_AS_COMMENT_NO_QUOTING)); + to_p= add_identifier(thd, to_p, end_p, subpart_name, subpart_name_len); } - if (explain_mode == EXPLAIN_PARTITIONS_AS_COMMENT || - explain_mode == EXPLAIN_PARTITIONS_AS_COMMENT_NO_QUOTING) + if (explain_mode == EXPLAIN_PARTITIONS_AS_COMMENT) to_p= strnmov(to_p, " */", end_p - to_p); } DBUG_PRINT("exit", ("to '%s'", to)); From 5dc38584761072638fd8730ebdb8b721772e5f7a Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Fri, 25 Sep 2009 14:52:41 +0300 Subject: [PATCH 69/80] fixed a typo in valgrind.supp --- mysql-test/valgrind.supp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mysql-test/valgrind.supp b/mysql-test/valgrind.supp index 26f0d329a4a..6b10e4cb544 100644 --- a/mysql-test/valgrind.supp +++ b/mysql-test/valgrind.supp @@ -1,4 +1,4 @@ -*# Suppress some common (not fatal) errors in system libraries found by valgrind +# Suppress some common (not fatal) errors in system libraries found by valgrind # # @@ -721,3 +721,4 @@ fun:_dl_allocate_tls fun:pthread_create* } + From 78b3f82434aac3081431e9785c7b6dbcaaf450f1 Mon Sep 17 00:00:00 2001 From: Omer BarNir Date: Fri, 25 Sep 2009 08:27:55 -0700 Subject: [PATCH 70/80] Checking in new version of 'mysql-stress-test.pl that was used for the last few month from test-extra tree. Changes include improvements to error handling and are based on WL#4685 --- mysql-test/mysql-stress-test.pl | 133 ++++++++++++++++++++++++-------- 1 file changed, 101 insertions(+), 32 deletions(-) diff --git a/mysql-test/mysql-stress-test.pl b/mysql-test/mysql-stress-test.pl index 3061506da51..c80706d9f25 100755 --- a/mysql-test/mysql-stress-test.pl +++ b/mysql-test/mysql-stress-test.pl @@ -14,17 +14,16 @@ # # Design of stress script should allow one: # -# - To stress test the mysqltest binary test engine. -# - To stress test the regular test suite and any additional test suites -# (such as mysql-test-extra-5.0). -# - To specify files with lists of tests both for initialization of -# stress db and for further testing itself. -# - To define the number of threads to be concurrently used in testing. -# - To define limitations for the test run. such as the number of tests or -# loops for execution or duration of testing, delay between test -# executions, and so forth. -# - To get a readable log file that can be used for identification of -# errors that occur during testing. +# - to use for stress testing mysqltest binary as test engine +# - to use for stress testing both regular test suite and any +# additional test suites (e.g. mysql-test-extra-5.0) +# - to specify files with lists of tests both for initialization of +# stress db and for further testing itself +# - to define number of threads that will be concurrently used in testing +# - to define limitations for test run. e.g. number of tests or loops +# for execution or duration of testing, delay between test executions, etc. +# - to get readable log file which can be used for identification of +# errors arose during testing # # Basic scenarios: # @@ -58,6 +57,8 @@ # to reproduce and debug errors that was found in continued stress # testing # +# 2009-01-28 OBN Additions and modifications per WL#4685 +# ######################################################################## use Config; @@ -114,13 +115,15 @@ $opt_stress_mode="random"; $opt_loop_count=0; $opt_test_count=0; $opt_test_duration=0; -$opt_abort_on_error=0; +# OBN: Changing abort-on-error default to -1 (for WL-4626/4685): -1 means no abort +$opt_abort_on_error=-1; $opt_sleep_time = 0; $opt_threads=1; $pid_file="mysql_stress_test.pid"; $opt_mysqltest= ($^O =~ /mswin32/i) ? "mysqltest.exe" : "mysqltest"; $opt_check_tests_file=""; -@mysqltest_args=("--silent", "-v", "--skip-safemalloc"); +# OBM adding a setting for 'max-connect-retries=7' the default of 500 is to high +@mysqltest_args=("--silent", "-v", "--skip-safemalloc", "--max-connect-retries=7"); # Client ip address $client_ip=inet_ntoa((gethostbyname(hostname()))[4]); @@ -133,24 +136,31 @@ $client_ip=~ s/\.//g; # # S1 - Critical errors - cause immediately abort of testing. These errors # could be caused by server crash or impossibility -# of test execution +# of test execution. # # S2 - Serious errors - these errors are bugs for sure as it knowns that # they shouldn't appear during stress testing # -# S3 - Non-seriuos errros - these errors could be caused by fact that +# S3 - Unknown errors - Errors were returned but we don't know what they are +# so script can't determine if they are OK or not +# +# S4 - Non-seriuos errros - these errors could be caused by fact that # we execute simultaneously statements that # affect tests executed by other threads %error_strings = ( 'Failed in mysql_real_connect()' => S1, + 'Can\'t connect' => S1, 'not found (Errcode: 2)' => S1 ); %error_codes = ( 1012 => S2, 1015 => S2, 1021 => S2, 1027 => S2, 1037 => S2, 1038 => S2, 1039 => S2, 1040 => S2, 1046 => S2, - 1180 => S2, 1181 => S2, 1203 => S2, - 1205 => S2, 1206 => S2, 1207 => S2, - 1223 => S2, 2013 => S1); + 1053 => S2, 1180 => S2, 1181 => S2, + 1203 => S2, 1205 => S4, 1206 => S2, + 1207 => S2, 1213 => S4, 1223 => S2, + 2002 => S1, 2003 => S1, 2006 => S1, + 2013 => S1 + ); share(%test_counters); %test_counters=( loop_count => 0, test_count=>0); @@ -158,6 +168,35 @@ share(%test_counters); share($exiting); $exiting=0; +# OBN Code and 'set_exit_code' function added by ES to set an exit code based on the error category returned +# in combination with the --abort-on-error value see WL#4685) +use constant ABORT_MAKEWEIGHT => 20; +share($gExitCode); +$gExitCode = 0; # global exit code +sub set_exit_code { + my $severity = shift; + my $code = 0; + if ( $severity =~ /^S(\d+)/ ) { + $severity = $1; + $code = 11 - $severity; # S1=10, S2=9, ... -- as per WL + } + else { + # we know how we call the sub: severity should be S; so, we should never be here... + print STDERR "Unknown severity format: $severity; setting to S1\n"; + $severity = 1; + } + $abort = 0; + if ( $severity <= $opt_abort_on_error ) { + # the test finished with a failure severe enough to abort. We are adding the 'abort flag' to the exit code + $code += ABORT_MAKEWEIGHT; + # but are not exiting just yet -- we need to update global exit code first + $abort = 1; + } + lock $gExitCode; # we can use lock here because the script uses threads anyway + $gExitCode = $code if $code > $gExitCode; + kill INT, $$ if $abort; # this is just a way to call sig_INT_handler: it will set exiting flag, which should do the rest +} + share($test_counters_lock); $test_counters_lock=0; share($log_file_lock); @@ -176,7 +215,8 @@ GetOptions("server-host=s", "server-logs-dir=s", "server-port=s", "threads=s", "sleep-time=s", "loop-count=i", "test-count=i", "test-duration=i", "test-suffix=s", "check-tests-file", "verbose", "log-error-details", "cleanup", "mysqltest=s", - "abort-on-error", "help") || usage(); + # OBN: (changing 'abort-on-error' to numberic for WL-4626/4685) + "abort-on-error=i" => \$opt_abort_on_error, "help") || usage(); usage() if ($opt_help); @@ -563,7 +603,15 @@ EOF if ($opt_test_duration) { - sleep($opt_test_duration); + # OBN - At this point we need to wait for the duration of the test, hoever + # we need to be able to quit if an 'abort-on-error' condition has happend + # with one of the children (WL#4685). Using solution by ES and replacing + # the 'sleep' command with a loop checking the abort condition every second + + foreach ( 1..$opt_test_duration ) { + last if $exiting; + sleep 1; + } kill INT, $$; #Interrupt child threads } @@ -580,6 +628,8 @@ EOF print "EXIT\n"; } +exit $gExitCode; # ES WL#4685: script should return a meaningful exit code + sub test_init { my ($env)=@_; @@ -681,7 +731,9 @@ sub test_execute { if (!exists($error_codes{$err_code})) { - $severity="S3"; + # OBN Changing severity level to S4 from S3 as S3 now reserved + # for the case where the error is unknown (for WL#4626/4685 + $severity="S4"; $err_code=0; } else @@ -734,6 +786,7 @@ sub test_execute { push @{$env->{test_status}}, "Severity $severity: $total"; $env->{errors}->{total}=+$total; + set_exit_code($severity); } } @@ -748,18 +801,20 @@ sub test_execute log_session_errors($env, $test_file); - if (!$exiting && ($signal_num == 2 || $signal_num == 15 || - ($opt_abort_on_error && $env->{errors}->{S1} > 0))) + #OBN Removing the case of S1 and abort-on-error as that is now set + # inside the set_exit_code function (for WL#4626/4685) + #if (!$exiting && ($signal_num == 2 || $signal_num == 15 || + # ($opt_abort_on_error && $env->{errors}->{S1} > 0))) + if (!$exiting && ($signal_num == 2 || $signal_num == 15)) { - #mysqltest was interrupted with INT or TERM signals or test was - #ran with --abort-on-error option and we got errors with severity S1 + #mysqltest was interrupted with INT or TERM signals #so we assume that we should cancel testing and exit $exiting=1; + # OBN - Adjusted text to exclude case of S1 and abort-on-error that + # was mentioned (for WL#4626/4685) print STDERR< --stress-suite-basedir= --serve --cleanup Force to clean up working directory (specified with --stress-basedir) +--abort-on-error= + Causes the script to abort if an error with severity <= number was encounterd + --log-error-details Enable errors details in the global error log file. (Default: off) From 09efe92a4554c140006bb1ce7b92fe99f5461e2b Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 27 Sep 2009 17:00:29 +0800 Subject: [PATCH 71/80] Bug #46931 rpl.rpl_get_master_version_and_clock fails on hpux11.31 Network error happened here, but it can be caused by CR_CONNECTION_ERROR, CR_CONN_HOST_ERROR, CR_SERVER_GONE_ERROR, CR_SERVER_LOST, ER_CON_COUNT_ERROR, and ER_SERVER_SHUTDOWN. We just check CR_SERVER_LOST here, so the test fails. To fix the problem, check all errors that can be cause by the master shutdown. mysql-test/extra/rpl_tests/rpl_get_master_version_and_clock.test: Added a 'if' sentence to check all errors that can be cause by the master shutdown. mysql-test/suite/rpl/r/rpl_get_master_version_and_clock.result: Test result is updated duo to the patch of bug#46931 --- .../rpl_tests/rpl_get_master_version_and_clock.test | 12 +++++++++++- .../rpl/r/rpl_get_master_version_and_clock.result | 6 ++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/mysql-test/extra/rpl_tests/rpl_get_master_version_and_clock.test b/mysql-test/extra/rpl_tests/rpl_get_master_version_and_clock.test index c79ccdd044f..89c136d8893 100644 --- a/mysql-test/extra/rpl_tests/rpl_get_master_version_and_clock.test +++ b/mysql-test/extra/rpl_tests/rpl_get_master_version_and_clock.test @@ -41,7 +41,17 @@ eval SELECT RELEASE_LOCK($debug_lock); connection slave; source include/wait_for_slave_io_error.inc; let $last_io_errno= query_get_value("show slave status", Last_IO_Errno, 1); -echo Slave_IO_Errno= $last_io_errno; +--echo Check network error happened here +if (`SELECT '$last_io_errno' = '2013' || # CR_SERVER_LOST + '$last_io_errno' = '2003' || # CR_CONN_HOST_ERROR + '$last_io_errno' = '2002' || # CR_CONNECTION_ERROR + '$last_io_errno' = '2006' || # CR_SERVER_GONE_ERROR + '$last_io_errno' = '1040' || # ER_CON_COUNT_ERROR + '$last_io_errno' = '1053' # ER_SERVER_SHUTDOWN + `) +{ + --echo NETWORK ERROR +} # Write file to make mysql-test-run.pl start up the server again --append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect diff --git a/mysql-test/suite/rpl/r/rpl_get_master_version_and_clock.result b/mysql-test/suite/rpl/r/rpl_get_master_version_and_clock.result index 99a0fd21f66..ae3554a5420 100644 --- a/mysql-test/suite/rpl/r/rpl_get_master_version_and_clock.result +++ b/mysql-test/suite/rpl/r/rpl_get_master_version_and_clock.result @@ -18,7 +18,8 @@ start slave; SELECT RELEASE_LOCK("debug_lock.before_get_UNIX_TIMESTAMP"); RELEASE_LOCK("debug_lock.before_get_UNIX_TIMESTAMP") 1 -Slave_IO_Errno= 2013 +Check network error happened here +NETWORK ERROR SELECT IS_FREE_LOCK("debug_lock.before_get_SERVER_ID"); IS_FREE_LOCK("debug_lock.before_get_SERVER_ID") 1 @@ -31,7 +32,8 @@ start slave; SELECT RELEASE_LOCK("debug_lock.before_get_SERVER_ID"); RELEASE_LOCK("debug_lock.before_get_SERVER_ID") 1 -Slave_IO_Errno= 2013 +Check network error happened here +NETWORK ERROR set global debug= ''; reset master; include/stop_slave.inc From 6368919f54cea96c4176b8a98d572ae3eab06b18 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 27 Sep 2009 18:12:58 +0800 Subject: [PATCH 72/80] Bug #43913 rpl_cross_version can't pass on conflicts complainig clash with --slave-load-tm The failure is not reproduced on 5.1, so enable the 'rpl_cross_version' test. mysql-test/suite/rpl/t/disabled.def: Got rid of the line for enabling 'rpl_cross_version' test. --- mysql-test/suite/rpl/t/disabled.def | 1 - 1 file changed, 1 deletion(-) diff --git a/mysql-test/suite/rpl/t/disabled.def b/mysql-test/suite/rpl/t/disabled.def index 38fc9e21322..8cae44a3607 100644 --- a/mysql-test/suite/rpl/t/disabled.def +++ b/mysql-test/suite/rpl/t/disabled.def @@ -10,4 +10,3 @@ # ############################################################################## -rpl_cross_version : Bug#42311 2009-03-27 joro rpl_cross_version fails on macosx From 3d211f39819db045c4992dcf1aab1c2473b56c66 Mon Sep 17 00:00:00 2001 From: Luis Soares Date: Sun, 27 Sep 2009 22:02:47 +0100 Subject: [PATCH 73/80] BUG#47312: RBR: Disabling key on slave breaks replication: HA_ERR_WRONG_INDEX In RBR, disabling keys on slave table will break replication when updating or deleting a record. When the slave thread tries to find the row, by searching in the storage engine, it checks whether the table has a key or not. If it has one, then the slave thread uses it to search the record. Nonetheless, the slave only checks whether the key exists or not, it does not verify if it is active. Should the key be disabled (eg, DBA has issued an ALTER TABLE ... DISABLE KEYS) then it will result in error: HA_ERR_WRONG_INDEX. This patch addresses this issue by making the slave thread also check whether the key is active or not before actually using it. --- .../rpl/r/rpl_row_disabled_slave_key.result | 26 +++++++ .../rpl/t/rpl_row_disabled_slave_key.test | 73 +++++++++++++++++++ sql/log_event.cc | 4 +- 3 files changed, 101 insertions(+), 2 deletions(-) create mode 100644 mysql-test/suite/rpl/r/rpl_row_disabled_slave_key.result create mode 100644 mysql-test/suite/rpl/t/rpl_row_disabled_slave_key.test diff --git a/mysql-test/suite/rpl/r/rpl_row_disabled_slave_key.result b/mysql-test/suite/rpl/r/rpl_row_disabled_slave_key.result new file mode 100644 index 00000000000..01e3dfd6508 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_row_disabled_slave_key.result @@ -0,0 +1,26 @@ +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +SET SQL_LOG_BIN=0; +CREATE TABLE t (a int, b int, c int, key(b)); +SET SQL_LOG_BIN=1; +CREATE TABLE t (a int, b int, c int); +INSERT INTO t VALUES (1,2,4); +INSERT INTO t VALUES (4,3,4); +DELETE FROM t; +DROP TABLE t; +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +CREATE TABLE t (a int, b int, c int, key(b)); +ALTER TABLE t DISABLE KEYS; +INSERT INTO t VALUES (1,2,4); +INSERT INTO t VALUES (4,3,4); +DELETE FROM t; +DROP TABLE t; diff --git a/mysql-test/suite/rpl/t/rpl_row_disabled_slave_key.test b/mysql-test/suite/rpl/t/rpl_row_disabled_slave_key.test new file mode 100644 index 00000000000..1d7e134f4f4 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_disabled_slave_key.test @@ -0,0 +1,73 @@ +# BUG#47312: RBR: Disabling key on slave breaks replication: +# HA_ERR_WRONG_INDEX +# +# Description +# =========== +# +# This test case checks whether disabling a key on a slave breaks +# replication or not. +# +# Case #1, shows that while not using ALTER TABLE... DISABLE KEYS and +# the slave has no key defined while the master has one, replication +# won't break. +# +# Case #2, shows that before patch for BUG#47312, if defining key on +# slave table, and later disable it, replication would break. This +# has been fixed. +# + +-- source include/master-slave.inc +-- source include/have_binlog_format_row.inc + +# +# Case #1: master has key, but slave has not. +# Replication does not break. +# + +SET SQL_LOG_BIN=0; +CREATE TABLE t (a int, b int, c int, key(b)); +SET SQL_LOG_BIN=1; + +-- connection slave + +CREATE TABLE t (a int, b int, c int); + +-- connection master + +INSERT INTO t VALUES (1,2,4); +INSERT INTO t VALUES (4,3,4); +DELETE FROM t; + +-- sync_slave_with_master + +-- connection master +DROP TABLE t; + +-- sync_slave_with_master + +# +# Case #2: master has key, slave also has one, +# but it gets disabled sometime. +# Replication does not break anymore. +# +-- source include/master-slave-reset.inc +-- connection master + +CREATE TABLE t (a int, b int, c int, key(b)); + +-- sync_slave_with_master + +ALTER TABLE t DISABLE KEYS; + +-- connection master + +INSERT INTO t VALUES (1,2,4); +INSERT INTO t VALUES (4,3,4); +DELETE FROM t; + +-- sync_slave_with_master + +-- connection master +DROP TABLE t; + +-- sync_slave_with_master diff --git a/sql/log_event.cc b/sql/log_event.cc index 08fe3aba8ed..3c584011bfb 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -8835,11 +8835,11 @@ int Rows_log_event::find_row(const Relay_log_info *rli) */ store_record(table,record[1]); - if (table->s->keys > 0) + if (table->s->keys > 0 && table->s->keys_in_use.is_set(0)) { DBUG_PRINT("info",("locating record using primary key (index_read)")); - /* We have a key: search the table using the index */ + /* The 0th key is active: search the table using the index */ if (!table->file->inited && (error= table->file->ha_index_init(0, FALSE))) { DBUG_PRINT("info",("ha_index_init returns error %d",error)); From c6186a2500390f5958d29b8d64a93140b74754a6 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 28 Sep 2009 10:23:06 +0800 Subject: [PATCH 74/80] BUG #46572 DROP TEMPORARY table IF EXISTS does not have a consistent behavior in ROW mode In RBR, 'DROP TEMPORARY TABLE IF EXISTS...' statement is binlogged when the table does not exist. In fact, 'DROP TEMPORARY TABLE ...' statement should never be binlogged in RBR no matter if the table exists or not. This patch addresses this by checking whether we are dropping a temporary table or not, when building the custom drop statement. --- .../extra/binlog_tests/drop_temp_table.test | 57 +++++++++++++++---- .../binlog/r/binlog_row_drop_tmp_tbl.result | 40 ++++++++----- .../binlog/r/binlog_stm_drop_tmp_tbl.result | 54 ++++++++++++------ sql/sql_table.cc | 2 +- 4 files changed, 112 insertions(+), 41 deletions(-) diff --git a/mysql-test/extra/binlog_tests/drop_temp_table.test b/mysql-test/extra/binlog_tests/drop_temp_table.test index 7d37fca2bef..5616fb4a643 100644 --- a/mysql-test/extra/binlog_tests/drop_temp_table.test +++ b/mysql-test/extra/binlog_tests/drop_temp_table.test @@ -1,27 +1,62 @@ --disable_warnings -drop database if exists `drop-temp+table-test`; +DROP DATABASE IF EXISTS `drop-temp+table-test`; --enable_warnings connect (con1,localhost,root,,); connect (con2,localhost,root,,); connection con1; -reset master; -create database `drop-temp+table-test`; -use `drop-temp+table-test`; -create temporary table shortn1 (a int); -create temporary table `table:name` (a int); -create temporary table shortn2 (a int); -select get_lock("a",10); +RESET MASTER; +CREATE DATABASE `drop-temp+table-test`; +USE `drop-temp+table-test`; +CREATE TEMPORARY TABLE shortn1 (a INT); +CREATE TEMPORARY TABLE `table:name` (a INT); +CREATE TEMPORARY TABLE shortn2 (a INT); + +############################################################################## +# BUG#46572 DROP TEMPORARY table IF EXISTS does not have a consistent behavior +# in ROW mode +# +# In RBR, 'DROP TEMPORARY TABLE ...' statement should never be binlogged no +# matter if the tables exist or not. In contrast, both in SBR and MBR, the +# statement should be always binlogged no matter if the tables exist or not. +############################################################################## +CREATE TEMPORARY TABLE tmp(c1 int); +CREATE TEMPORARY TABLE tmp1(c1 int); +CREATE TEMPORARY TABLE tmp2(c1 int); +CREATE TEMPORARY TABLE tmp3(c1 int); +CREATE TABLE t(c1 int); + +DROP TEMPORARY TABLE IF EXISTS tmp; + +--disable_warnings +# Before fixing BUG#46572, 'DROP TEMPORARY TABLE IF EXISTS...' statement was +# binlogged when the table did not exist in RBR. +DROP TEMPORARY TABLE IF EXISTS tmp; + +# In RBR, 'DROP TEMPORARY TABLE ...' statement is never binlogged no matter if +# the tables exist or not. +DROP TEMPORARY TABLE IF EXISTS tmp, tmp1; +DROP TEMPORARY TABLE tmp3; + +#In RBR, tmp2 will NOT be binlogged, because it is a temporary table. +DROP TABLE IF EXISTS tmp2, t; + +#In RBR, tmp2 will be binlogged, because it does not exist and master do not know +# whether it is a temporary table or not. +DROP TABLE IF EXISTS tmp2, t; +--enable_warnings + +SELECT GET_LOCK("a",10); disconnect con1; connection con2; # We want to SHOW BINLOG EVENTS, to know what was logged. But there is no # guarantee that logging of the terminated con1 has been done yet. # To be sure that logging has been done, we use a user lock. -select get_lock("a",10); -let $VERSION=`select version()`; +SELECT GET_LOCK("a",10); +let $VERSION=`SELECT VERSION()`; source include/show_binlog_events.inc; -drop database `drop-temp+table-test`; +DROP DATABASE `drop-temp+table-test`; # End of 4.1 tests diff --git a/mysql-test/suite/binlog/r/binlog_row_drop_tmp_tbl.result b/mysql-test/suite/binlog/r/binlog_row_drop_tmp_tbl.result index 503076d66d9..0a6ff1d4400 100644 --- a/mysql-test/suite/binlog/r/binlog_row_drop_tmp_tbl.result +++ b/mysql-test/suite/binlog/r/binlog_row_drop_tmp_tbl.result @@ -1,17 +1,31 @@ -drop database if exists `drop-temp+table-test`; -reset master; -create database `drop-temp+table-test`; -use `drop-temp+table-test`; -create temporary table shortn1 (a int); -create temporary table `table:name` (a int); -create temporary table shortn2 (a int); -select get_lock("a",10); -get_lock("a",10) +DROP DATABASE IF EXISTS `drop-temp+table-test`; +RESET MASTER; +CREATE DATABASE `drop-temp+table-test`; +USE `drop-temp+table-test`; +CREATE TEMPORARY TABLE shortn1 (a INT); +CREATE TEMPORARY TABLE `table:name` (a INT); +CREATE TEMPORARY TABLE shortn2 (a INT); +CREATE TEMPORARY TABLE tmp(c1 int); +CREATE TEMPORARY TABLE tmp1(c1 int); +CREATE TEMPORARY TABLE tmp2(c1 int); +CREATE TEMPORARY TABLE tmp3(c1 int); +CREATE TABLE t(c1 int); +DROP TEMPORARY TABLE IF EXISTS tmp; +DROP TEMPORARY TABLE IF EXISTS tmp; +DROP TEMPORARY TABLE IF EXISTS tmp, tmp1; +DROP TEMPORARY TABLE tmp3; +DROP TABLE IF EXISTS tmp2, t; +DROP TABLE IF EXISTS tmp2, t; +SELECT GET_LOCK("a",10); +GET_LOCK("a",10) 1 -select get_lock("a",10); -get_lock("a",10) +SELECT GET_LOCK("a",10); +GET_LOCK("a",10) 1 show binlog events from ; Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Query # # create database `drop-temp+table-test` -drop database `drop-temp+table-test`; +master-bin.000001 # Query # # CREATE DATABASE `drop-temp+table-test` +master-bin.000001 # Query # # use `drop-temp+table-test`; CREATE TABLE t(c1 int) +master-bin.000001 # Query # # use `drop-temp+table-test`; DROP TABLE IF EXISTS `t` /* generated by server */ +master-bin.000001 # Query # # use `drop-temp+table-test`; DROP TABLE IF EXISTS tmp2, t +DROP DATABASE `drop-temp+table-test`; diff --git a/mysql-test/suite/binlog/r/binlog_stm_drop_tmp_tbl.result b/mysql-test/suite/binlog/r/binlog_stm_drop_tmp_tbl.result index 4d24b2409b9..8bbf1bccc63 100644 --- a/mysql-test/suite/binlog/r/binlog_stm_drop_tmp_tbl.result +++ b/mysql-test/suite/binlog/r/binlog_stm_drop_tmp_tbl.result @@ -1,21 +1,43 @@ -drop database if exists `drop-temp+table-test`; -reset master; -create database `drop-temp+table-test`; -use `drop-temp+table-test`; -create temporary table shortn1 (a int); -create temporary table `table:name` (a int); -create temporary table shortn2 (a int); -select get_lock("a",10); -get_lock("a",10) +DROP DATABASE IF EXISTS `drop-temp+table-test`; +RESET MASTER; +CREATE DATABASE `drop-temp+table-test`; +USE `drop-temp+table-test`; +CREATE TEMPORARY TABLE shortn1 (a INT); +CREATE TEMPORARY TABLE `table:name` (a INT); +CREATE TEMPORARY TABLE shortn2 (a INT); +CREATE TEMPORARY TABLE tmp(c1 int); +CREATE TEMPORARY TABLE tmp1(c1 int); +CREATE TEMPORARY TABLE tmp2(c1 int); +CREATE TEMPORARY TABLE tmp3(c1 int); +CREATE TABLE t(c1 int); +DROP TEMPORARY TABLE IF EXISTS tmp; +DROP TEMPORARY TABLE IF EXISTS tmp; +DROP TEMPORARY TABLE IF EXISTS tmp, tmp1; +DROP TEMPORARY TABLE tmp3; +DROP TABLE IF EXISTS tmp2, t; +DROP TABLE IF EXISTS tmp2, t; +SELECT GET_LOCK("a",10); +GET_LOCK("a",10) 1 -select get_lock("a",10); -get_lock("a",10) +SELECT GET_LOCK("a",10); +GET_LOCK("a",10) 1 show binlog events from ; Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Query # # create database `drop-temp+table-test` -master-bin.000001 # Query # # use `drop-temp+table-test`; create temporary table shortn1 (a int) -master-bin.000001 # Query # # use `drop-temp+table-test`; create temporary table `table:name` (a int) -master-bin.000001 # Query # # use `drop-temp+table-test`; create temporary table shortn2 (a int) +master-bin.000001 # Query # # CREATE DATABASE `drop-temp+table-test` +master-bin.000001 # Query # # use `drop-temp+table-test`; CREATE TEMPORARY TABLE shortn1 (a INT) +master-bin.000001 # Query # # use `drop-temp+table-test`; CREATE TEMPORARY TABLE `table:name` (a INT) +master-bin.000001 # Query # # use `drop-temp+table-test`; CREATE TEMPORARY TABLE shortn2 (a INT) +master-bin.000001 # Query # # use `drop-temp+table-test`; CREATE TEMPORARY TABLE tmp(c1 int) +master-bin.000001 # Query # # use `drop-temp+table-test`; CREATE TEMPORARY TABLE tmp1(c1 int) +master-bin.000001 # Query # # use `drop-temp+table-test`; CREATE TEMPORARY TABLE tmp2(c1 int) +master-bin.000001 # Query # # use `drop-temp+table-test`; CREATE TEMPORARY TABLE tmp3(c1 int) +master-bin.000001 # Query # # use `drop-temp+table-test`; CREATE TABLE t(c1 int) +master-bin.000001 # Query # # use `drop-temp+table-test`; DROP TEMPORARY TABLE IF EXISTS tmp +master-bin.000001 # Query # # use `drop-temp+table-test`; DROP TEMPORARY TABLE IF EXISTS tmp +master-bin.000001 # Query # # use `drop-temp+table-test`; DROP TEMPORARY TABLE IF EXISTS tmp, tmp1 +master-bin.000001 # Query # # use `drop-temp+table-test`; DROP TEMPORARY TABLE tmp3 +master-bin.000001 # Query # # use `drop-temp+table-test`; DROP TABLE IF EXISTS tmp2, t +master-bin.000001 # Query # # use `drop-temp+table-test`; DROP TABLE IF EXISTS tmp2, t master-bin.000001 # Query # # use `drop-temp+table-test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `shortn2`,`table:name`,`shortn1` -drop database `drop-temp+table-test`; +DROP DATABASE `drop-temp+table-test`; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 08f3311be9d..6dba2f02071 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1949,7 +1949,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, being built. The string always end in a comma and the comma will be chopped off before being written to the binary log. */ - if (thd->current_stmt_binlog_row_based && !dont_log_query) + if (!drop_temporary && thd->current_stmt_binlog_row_based && !dont_log_query) { non_temp_tables_count++; /* From 96665fd9ccda9d9c129c5e421b10d00ccf78e5de Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 28 Sep 2009 14:24:19 +0800 Subject: [PATCH 75/80] BUG#43579 mysql_upgrade tries to alter log tables on replicated database All statements executed by mysql_upgrade are binlogged and then are replicated to slave. This will result in some errors. The report of this bug has demonstrated some examples. Master and slave should be upgraded separately. All statements executed by mysql_upgrade will not be binlogged. --write-binlog and --skip-write-binlog options are added into mysql_upgrade. These options control whether sql statements are binlogged or not. --- client/mysql_upgrade.c | 27 +++++++++ client/mysqlcheck.c | 19 +++++++ mysql-test/include/have_mysql_upgrade.inc | 4 ++ .../suite/rpl/r/rpl_mysql_upgrade.result | 13 +++++ mysql-test/suite/rpl/t/rpl_mysql_upgrade.test | 56 +++++++++++++++++++ 5 files changed, 119 insertions(+) create mode 100644 mysql-test/include/have_mysql_upgrade.inc create mode 100644 mysql-test/suite/rpl/r/rpl_mysql_upgrade.result create mode 100644 mysql-test/suite/rpl/t/rpl_mysql_upgrade.test diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c index cfd7ed4ea56..52c3636219d 100644 --- a/client/mysql_upgrade.c +++ b/client/mysql_upgrade.c @@ -54,6 +54,8 @@ static char **defaults_argv; static my_bool not_used; /* Can't use GET_BOOL without a value pointer */ +static my_bool opt_write_binlog; + #include static struct my_option my_long_options[]= @@ -124,6 +126,11 @@ static struct my_option my_long_options[]= {"verbose", 'v', "Display more output about the process", (uchar**) &opt_verbose, (uchar**) &opt_verbose, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, + {"write-binlog", OPT_WRITE_BINLOG, + "All commands including mysqlcheck are binlogged. Enabled by default;" + "use --skip-write-binlog when commands should not be sent to replication slaves.", + (uchar**) &opt_write_binlog, (uchar**) &opt_write_binlog, 0, GET_BOOL, NO_ARG, + 1, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; @@ -448,6 +455,8 @@ static int run_query(const char *query, DYNAMIC_STRING *ds_res, int ret; File fd; char query_file_path[FN_REFLEN]; + const uchar sql_log_bin[]= "SET SQL_LOG_BIN=0;"; + DBUG_ENTER("run_query"); DBUG_PRINT("enter", ("query: %s", query)); if ((fd= create_temp_file(query_file_path, opt_tmpdir, @@ -455,6 +464,22 @@ static int run_query(const char *query, DYNAMIC_STRING *ds_res, MYF(MY_WME))) < 0) die("Failed to create temporary file for defaults"); + /* + Master and slave should be upgraded separately. All statements executed + by mysql_upgrade will not be binlogged. + 'SET SQL_LOG_BIN=0' is executed before any other statements. + */ + if (!opt_write_binlog) + { + if (my_write(fd, sql_log_bin, sizeof(sql_log_bin)-1, + MYF(MY_FNABP | MY_WME))) + { + my_close(fd, MYF(0)); + my_delete(query_file_path, MYF(0)); + die("Failed to write to '%s'", query_file_path); + } + } + if (my_write(fd, (uchar*) query, strlen(query), MYF(MY_FNABP | MY_WME))) { @@ -648,6 +673,7 @@ static int run_mysqlcheck_upgrade(void) "--check-upgrade", "--all-databases", "--auto-repair", + opt_write_binlog ? "--write-binlog" : "--skip-write-binlog", NULL); } @@ -662,6 +688,7 @@ static int run_mysqlcheck_fixnames(void) "--all-databases", "--fix-db-names", "--fix-table-names", + opt_write_binlog ? "--write-binlog" : "--skip-write-binlog", NULL); } diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c index 82aabd77b24..1533e602639 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -652,6 +652,17 @@ static int use_db(char *database) return 0; } /* use_db */ +static int disable_binlog() +{ + const char *stmt= "SET SQL_LOG_BIN=0"; + if (mysql_query(sock, stmt)) + { + fprintf(stderr, "Failed to %s\n", stmt); + fprintf(stderr, "Error: %s\n", mysql_error(sock)); + return 1; + } + return 0; +} static int handle_request_for_tables(char *tables, uint length) { @@ -844,6 +855,14 @@ int main(int argc, char **argv) if (dbConnect(current_host, current_user, opt_password)) exit(EX_MYSQLERR); + if (!opt_write_binlog) + { + if (disable_binlog()) { + first_error= 1; + goto end; + } + } + if (opt_auto_repair && my_init_dynamic_array(&tables4repair, sizeof(char)*(NAME_LEN*2+2),16,64)) { diff --git a/mysql-test/include/have_mysql_upgrade.inc b/mysql-test/include/have_mysql_upgrade.inc new file mode 100644 index 00000000000..8f486176018 --- /dev/null +++ b/mysql-test/include/have_mysql_upgrade.inc @@ -0,0 +1,4 @@ +--require r/have_mysql_upgrade.result +--disable_query_log +select LENGTH("$MYSQL_UPGRADE")>0 as have_mysql_upgrade; +--enable_query_log diff --git a/mysql-test/suite/rpl/r/rpl_mysql_upgrade.result b/mysql-test/suite/rpl/r/rpl_mysql_upgrade.result new file mode 100644 index 00000000000..09a9121d22c --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_mysql_upgrade.result @@ -0,0 +1,13 @@ +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +DROP DATABASE IF EXISTS `#mysql50#mysqltest-1`; +CREATE DATABASE `#mysql50#mysqltest-1`; +Master position is not changed +STOP SLAVE SQL_THREAD; +Master position has been changed +DROP DATABASE `mysqltest-1`; +DROP DATABASE `#mysql50#mysqltest-1`; diff --git a/mysql-test/suite/rpl/t/rpl_mysql_upgrade.test b/mysql-test/suite/rpl/t/rpl_mysql_upgrade.test new file mode 100644 index 00000000000..bf5c6d2b921 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_mysql_upgrade.test @@ -0,0 +1,56 @@ +############################################################################# +# BUG#43579 mysql_upgrade tries to alter log tables on replicated database +# Master and slave should be upgraded separately. All statements executed by +# mysql_upgrade will not be binlogged. --write-binlog and --skip-write-binlog +# options are added into mysql_upgrade. These options control whether sql +# statements are binlogged or not. +############################################################################# +--source include/master-slave.inc + +# Only run test if "mysql_upgrade" is found +--source include/have_mysql_upgrade.inc + +connection master; +--disable_warnings +DROP DATABASE IF EXISTS `#mysql50#mysqltest-1`; +CREATE DATABASE `#mysql50#mysqltest-1`; +--enable_warnings +sync_slave_with_master; + +connection master; +let $before_position= query_get_value(SHOW MASTER STATUS, Position, 1); + +#With '--force' option, mysql_upgrade always executes all sql statements for upgrading. +#--skip-write-binlog option disables binlog. +--exec $MYSQL_UPGRADE --skip-write-binlog --skip-verbose --force --user=root > $MYSQLTEST_VARDIR/log/mysql_upgrade.log 2>&1 +sync_slave_with_master; + +connection master; +let $after_position= query_get_value(SHOW MASTER STATUS, Position, 1); + +if (`SELECT '$before_position'='$after_position'`) +{ + echo Master position is not changed; +} + +#Some log events of the mysql_upgrade's will cause errors on slave. +connection slave; +STOP SLAVE SQL_THREAD; +source include/wait_for_slave_sql_to_stop.inc; + +connection master; +#With '--force' option, mysql_upgrade always executes all sql statements for upgrading. +--exec $MYSQL_UPGRADE --skip-verbose --force --user=root > $MYSQLTEST_VARDIR/log/mysql_upgrade.log 2>&1 + +connection master; +let $after_file= query_get_value(SHOW MASTER STATUS, File, 1); +let $after_position= query_get_value(SHOW MASTER STATUS, Position, 1); + +if (!`SELECT '$before_position'='$after_position'`) +{ + echo Master position has been changed; +} + +DROP DATABASE `mysqltest-1`; +connection slave; +DROP DATABASE `#mysql50#mysqltest-1`; From 2dbe095c3aec3d77ee759f17e04b2039be3f9b4c Mon Sep 17 00:00:00 2001 From: Martin Hansson Date: Mon, 28 Sep 2009 12:48:52 +0200 Subject: [PATCH 76/80] Bug#46958: Assertion in Diagnostics_area::set_ok_status, trigger, merge table The problem with break statements is that they have very local effects. Hence a break statement within the inner loop of a nested-loops join caused execution to proceed to the next table even though a serious error occurred. The problem was fixed by breaking out the inner loop into its own method. The change empowers all errors to terminate the execution. The errors that will now halt multi-DELETE execution altogether are - triggers returning errors - handler errors - server being killed mysql-test/r/delete.result: Bug#46958: Test result. mysql-test/t/delete.test: Bug#46958: Test case. sql/sql_class.h: Bug#46958: New method declaration. sql/sql_delete.cc: Bug#46958: New method implementation. --- mysql-test/r/delete.result | 45 +++++++++++ mysql-test/t/delete.test | 44 +++++++++++ sql/sql_class.h | 3 +- sql/sql_delete.cc | 156 +++++++++++++++++++++---------------- 4 files changed, 182 insertions(+), 66 deletions(-) diff --git a/mysql-test/r/delete.result b/mysql-test/r/delete.result index eb93c69d960..0124a7da35a 100644 --- a/mysql-test/r/delete.result +++ b/mysql-test/r/delete.result @@ -279,3 +279,48 @@ ERROR 42000: Incorrect number of arguments for FUNCTION test.f1; expected 0, got DROP TABLE t1; DROP FUNCTION f1; End of 5.0 tests +# +# Bug#46958: Assertion in Diagnostics_area::set_ok_status, trigger, +# merge table +# +CREATE TABLE t1 ( a INT ); +CREATE TABLE t2 ( a INT ); +CREATE TABLE t3 ( a INT ); +INSERT INTO t1 VALUES (1), (2); +INSERT INTO t2 VALUES (1), (2); +INSERT INTO t3 VALUES (1), (2); +CREATE TRIGGER tr1 BEFORE DELETE ON t2 +FOR EACH ROW INSERT INTO no_such_table VALUES (1); +DELETE t1, t2, t3 FROM t1, t2, t3; +ERROR 42S02: Table 'test.no_such_table' doesn't exist +SELECT * FROM t1; +a +SELECT * FROM t2; +a +1 +2 +SELECT * FROM t3; +a +1 +2 +DROP TABLE t1, t2, t3; +CREATE TABLE t1 ( a INT ); +CREATE TABLE t2 ( a INT ); +CREATE TABLE t3 ( a INT ); +INSERT INTO t1 VALUES (1), (2); +INSERT INTO t2 VALUES (1), (2); +INSERT INTO t3 VALUES (1), (2); +CREATE TRIGGER tr1 AFTER DELETE ON t2 +FOR EACH ROW INSERT INTO no_such_table VALUES (1); +DELETE t1, t2, t3 FROM t1, t2, t3; +ERROR 42S02: Table 'test.no_such_table' doesn't exist +SELECT * FROM t1; +a +SELECT * FROM t2; +a +2 +SELECT * FROM t3; +a +1 +2 +DROP TABLE t1, t2, t3; diff --git a/mysql-test/t/delete.test b/mysql-test/t/delete.test index 602e30687c8..d77f5eb128b 100644 --- a/mysql-test/t/delete.test +++ b/mysql-test/t/delete.test @@ -292,3 +292,47 @@ DROP TABLE t1; DROP FUNCTION f1; --echo End of 5.0 tests + +--echo # +--echo # Bug#46958: Assertion in Diagnostics_area::set_ok_status, trigger, +--echo # merge table +--echo # +CREATE TABLE t1 ( a INT ); +CREATE TABLE t2 ( a INT ); +CREATE TABLE t3 ( a INT ); + +INSERT INTO t1 VALUES (1), (2); +INSERT INTO t2 VALUES (1), (2); +INSERT INTO t3 VALUES (1), (2); + +CREATE TRIGGER tr1 BEFORE DELETE ON t2 +FOR EACH ROW INSERT INTO no_such_table VALUES (1); + +--error ER_NO_SUCH_TABLE +DELETE t1, t2, t3 FROM t1, t2, t3; + +SELECT * FROM t1; +SELECT * FROM t2; +SELECT * FROM t3; + +DROP TABLE t1, t2, t3; + +CREATE TABLE t1 ( a INT ); +CREATE TABLE t2 ( a INT ); +CREATE TABLE t3 ( a INT ); + +INSERT INTO t1 VALUES (1), (2); +INSERT INTO t2 VALUES (1), (2); +INSERT INTO t3 VALUES (1), (2); + +CREATE TRIGGER tr1 AFTER DELETE ON t2 +FOR EACH ROW INSERT INTO no_such_table VALUES (1); + +--error ER_NO_SUCH_TABLE +DELETE t1, t2, t3 FROM t1, t2, t3; + +SELECT * FROM t1; +SELECT * FROM t2; +SELECT * FROM t3; + +DROP TABLE t1, t2, t3; diff --git a/sql/sql_class.h b/sql/sql_class.h index c38eb17f191..b0128244030 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -2907,7 +2907,8 @@ public: bool send_data(List &items); bool initialize_tables (JOIN *join); void send_error(uint errcode,const char *err); - int do_deletes(); + int do_deletes(); + int do_table_deletes(TABLE *table, bool ignore); bool send_eof(); virtual void abort(); }; diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index d2f90fa9288..a81a5f4641f 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -860,22 +860,19 @@ void multi_delete::abort() -/* +/** Do delete from other tables. - Returns values: - 0 ok - 1 error + + @retval 0 ok + @retval 1 error + + @todo Is there any reason not use the normal nested-loops join? If not, and + there is no documentation supporting it, this method and callee should be + removed and there should be hooks within normal execution. */ int multi_delete::do_deletes() { - int local_error= 0, counter= 0, tmp_error; - bool will_batch; - /* - If the IGNORE option is used all non fatal errors will be translated - to warnings and we should not break the row-by-row iteration - */ - bool ignore= thd->lex->current_select->no_error; DBUG_ENTER("do_deletes"); DBUG_ASSERT(do_delete); @@ -886,79 +883,108 @@ int multi_delete::do_deletes() table_being_deleted= (delete_while_scanning ? delete_tables->next_local : delete_tables); - for (; table_being_deleted; + for (uint counter= 0; table_being_deleted; table_being_deleted= table_being_deleted->next_local, counter++) { - ha_rows last_deleted= deleted; TABLE *table = table_being_deleted->table; if (tempfiles[counter]->get(table)) + DBUG_RETURN(1); + + int local_error= + do_table_deletes(table, thd->lex->current_select->no_error); + + if (thd->killed && !local_error) + DBUG_RETURN(1); + + if (local_error == -1) // End of file + local_error = 0; + + if (local_error) + DBUG_RETURN(local_error); + } + DBUG_RETURN(0); +} + + +/** + Implements the inner loop of nested-loops join within multi-DELETE + execution. + + @param table The table from which to delete. + + @param ignore If used, all non fatal errors will be translated + to warnings and we should not break the row-by-row iteration. + + @return Status code + + @retval 0 All ok. + @retval 1 Triggers or handler reported error. + @retval -1 End of file from handler. +*/ +int multi_delete::do_table_deletes(TABLE *table, bool ignore) +{ + int local_error= 0; + READ_RECORD info; + ha_rows last_deleted= deleted; + DBUG_ENTER("do_deletes_for_table"); + init_read_record(&info, thd, table, NULL, 0, 1, FALSE); + /* + Ignore any rows not found in reference tables as they may already have + been deleted by foreign key handling + */ + info.ignore_not_found_rows= 1; + bool will_batch= !table->file->start_bulk_delete(); + while (!(local_error= info.read_record(&info)) && !thd->killed) + { + if (table->triggers && + table->triggers->process_triggers(thd, TRG_EVENT_DELETE, + TRG_ACTION_BEFORE, FALSE)) { - local_error=1; + local_error= 1; break; } - - READ_RECORD info; - init_read_record(&info, thd, table, NULL, 0, 1, FALSE); - /* - Ignore any rows not found in reference tables as they may already have - been deleted by foreign key handling - */ - info.ignore_not_found_rows= 1; - will_batch= !table->file->start_bulk_delete(); - while (!(local_error=info.read_record(&info)) && !thd->killed) + + local_error= table->file->ha_delete_row(table->record[0]); + if (local_error && !ignore) { + table->file->print_error(local_error, MYF(0)); + break; + } + + /* + Increase the reported number of deleted rows only if no error occurred + during ha_delete_row. + Also, don't execute the AFTER trigger if the row operation failed. + */ + if (!local_error) + { + deleted++; if (table->triggers && table->triggers->process_triggers(thd, TRG_EVENT_DELETE, - TRG_ACTION_BEFORE, FALSE)) + TRG_ACTION_AFTER, FALSE)) { local_error= 1; break; } - - local_error= table->file->ha_delete_row(table->record[0]); - if (local_error && !ignore) - { - table->file->print_error(local_error,MYF(0)); - break; - } - - /* - Increase the reported number of deleted rows only if no error occurred - during ha_delete_row. - Also, don't execute the AFTER trigger if the row operation failed. - */ - if (!local_error) - { - deleted++; - if (table->triggers && - table->triggers->process_triggers(thd, TRG_EVENT_DELETE, - TRG_ACTION_AFTER, FALSE)) - { - local_error= 1; - break; - } - } } - if (will_batch && (tmp_error= table->file->end_bulk_delete())) - { - if (!local_error) - { - local_error= tmp_error; - table->file->print_error(local_error,MYF(0)); - } - } - if (last_deleted != deleted && !table->file->has_transactions()) - thd->transaction.stmt.modified_non_trans_table= TRUE; - end_read_record(&info); - if (thd->killed && !local_error) - local_error= 1; - if (local_error == -1) // End of file - local_error = 0; } + if (will_batch) + { + int tmp_error= table->file->end_bulk_delete(); + if (tmp_error && !local_error) + { + local_error= tmp_error; + table->file->print_error(local_error, MYF(0)); + } + } + if (last_deleted != deleted && !table->file->has_transactions()) + thd->transaction.stmt.modified_non_trans_table= TRUE; + + end_read_record(&info); + DBUG_RETURN(local_error); } - /* Send ok to the client From 134441342e1374e648a8e5266ac666d0d465870a Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Mon, 28 Sep 2009 16:55:01 +0300 Subject: [PATCH 77/80] Fixed Sun Studio 8 compilation failures as suggested by Jorgen and reviewed by Svoj over e-mail. --- storage/myisam/mi_check.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/storage/myisam/mi_check.c b/storage/myisam/mi_check.c index 15eb28e6183..1c33ffa90f5 100644 --- a/storage/myisam/mi_check.c +++ b/storage/myisam/mi_check.c @@ -801,7 +801,7 @@ static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo, { DBUG_DUMP("old",(uchar*) info->lastkey, info->lastkey_length); DBUG_DUMP("new",(uchar*) key, key_length); - DBUG_DUMP("new_in_page",(char*) old_keypos,(uint) (keypos-old_keypos)); + DBUG_DUMP("new_in_page",(uchar*) old_keypos,(uint) (keypos-old_keypos)); if (comp_flag & SEARCH_FIND && flag == 0) mi_check_print_error(param,"Found duplicated key at page %s",llstr(page,llbuff)); @@ -871,7 +871,7 @@ static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo, llstr(page,llbuff),llstr(record,llbuff2), llstr(info->state->data_file_length,llbuff3))); DBUG_DUMP("key",(uchar*) key,key_length); - DBUG_DUMP("new_in_page",(char*) old_keypos,(uint) (keypos-old_keypos)); + DBUG_DUMP("new_in_page",(uchar*) old_keypos,(uint) (keypos-old_keypos)); goto err; } param->record_checksum+=(ha_checksum) record; @@ -1545,6 +1545,8 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info, if (info->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD)) param->testflag|=T_CALC_CHECKSUM; + DBUG_ASSERT(param->use_buffers < SIZE_T_MAX); + if (!param->using_global_keycache) VOID(init_key_cache(dflt_key_cache, param->key_cache_block_size, (size_t) param->use_buffers, 0, 0)); From ea295c233b92fb06c476f0b0a011493d4c827435 Mon Sep 17 00:00:00 2001 From: Jonathan Perkin Date: Mon, 28 Sep 2009 15:14:33 +0100 Subject: [PATCH 78/80] bug#30954: "configure" script in binary distributions considered harmfull Add --help option. --- support-files/binary-configure.sh | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/support-files/binary-configure.sh b/support-files/binary-configure.sh index 884a8363e22..5e6d62f69a0 100644 --- a/support-files/binary-configure.sh +++ b/support-files/binary-configure.sh @@ -1,4 +1,28 @@ #!/bin/sh + +SCRIPT_NAME="`basename $0`" + +usage() +{ + echo "Usage: ${SCRIPT_NAME} [--help|-h]" + echo "" + echo "This script creates the MySQL system tables and starts the server." +} + +for arg do + case "$arg" in + --help|-h) + usage + exit 0 + ;; + *) + echo "${SCRIPT_NAME}: unknown option $arg" + usage + exit 2 + ;; + esac +done + if test ! -x ./scripts/mysql_install_db then echo "I didn't find the script './scripts/mysql_install_db'." From 5f8bb5c507631a56a267f42972c809d51dacd84b Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Tue, 29 Sep 2009 07:23:38 +0500 Subject: [PATCH 79/80] Bug#47150 Assertion in Field_long::val_int() on MERGE + TRIGGER + multi-table UPDATE The bug is not related to MERGE table or TRIGGER. More correct description would be 'assertion on multi-table UPDATE + NATURAL JOIN + MERGEABLE VIEW'. On PREPARE stage(see test case) we call mark_common_columns() func which creates ON condition for NATURAL JOIN and sets appropriate table read_set bitmaps for fields which are used in ON condition. On EXECUTE stage mark_common_columns() is not called, we set necessary read_set bitmaps in setup_conds(). But 'B.f1' field is already processed and related item alredy fixed before setup_conds() as updated field and setup_conds can not set read_set bitmap because of that. The fix is to set read_set bitmap for appropriate table field even if Item_direct_view_ref item which represents a refernce to this field is fixed. mysql-test/r/join.result: test result mysql-test/t/join.test: test case sql/item.cc: The bug is not related to MERGE table or TRIGGER. More correct description would be 'assertion on multi-table UPDATE + NATURAL JOIN + MERGEABLE VIEW'. On PREPARE stage(see test case) we call mark_common_columns() func which creates ON condition for NATURAL JOIN and sets appropriate table read_set bitmaps for fields which are used in ON condition. On EXECUTE stage mark_common_columns() is not called, we set necessary read_set bitmaps in setup_conds(). But 'B.f1' field is already processed and related item alredy fixed before setup_conds() as updated field and setup_conds can not set read_set bitmap because of that. The fix is to set read_set bitmap for appropriate table field even if Item_direct_view_ref item which represents a refernce to this field is fixed. --- mysql-test/r/join.result | 10 ++++++++++ mysql-test/t/join.test | 20 ++++++++++++++++++++ sql/item.cc | 21 +++++++++++++++++++-- 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/join.result b/mysql-test/r/join.result index 736ecf1d90e..77f73532474 100644 --- a/mysql-test/r/join.result +++ b/mysql-test/r/join.result @@ -1064,3 +1064,13 @@ a b c d 128 NULL 128 NULL DROP TABLE IF EXISTS t1,t2; End of 5.0 tests. +CREATE TABLE t1 (f1 int); +CREATE TABLE t2 (f1 int); +INSERT INTO t2 VALUES (1); +CREATE VIEW v1 AS SELECT * FROM t2; +PREPARE stmt FROM 'UPDATE t2 AS A NATURAL JOIN v1 B SET B.f1 = 1'; +EXECUTE stmt; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; +DROP VIEW v1; +DROP TABLE t1, t2; diff --git a/mysql-test/t/join.test b/mysql-test/t/join.test index b5e30e63f54..1cd05c8cb65 100644 --- a/mysql-test/t/join.test +++ b/mysql-test/t/join.test @@ -729,4 +729,24 @@ SELECT * FROM t1 JOIN t2 ON b=c ORDER BY a; SELECT * FROM t1 JOIN t2 ON a=c ORDER BY a; DROP TABLE IF EXISTS t1,t2; + --echo End of 5.0 tests. + + +# +# Bug#47150 Assertion in Field_long::val_int() on MERGE + TRIGGER + multi-table UPDATE +# +CREATE TABLE t1 (f1 int); + +CREATE TABLE t2 (f1 int); +INSERT INTO t2 VALUES (1); +CREATE VIEW v1 AS SELECT * FROM t2; + +PREPARE stmt FROM 'UPDATE t2 AS A NATURAL JOIN v1 B SET B.f1 = 1'; +EXECUTE stmt; +EXECUTE stmt; + +DEALLOCATE PREPARE stmt; + +DROP VIEW v1; +DROP TABLE t1, t2; diff --git a/sql/item.cc b/sql/item.cc index 26df3a45971..86e4551e55b 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -6331,9 +6331,26 @@ bool Item_direct_view_ref::fix_fields(THD *thd, Item **reference) /* view fild reference must be defined */ DBUG_ASSERT(*ref); /* (*ref)->check_cols() will be made in Item_direct_ref::fix_fields */ - if (!(*ref)->fixed && - ((*ref)->fix_fields(thd, ref))) + if ((*ref)->fixed) + { + Item *ref_item= (*ref)->real_item(); + if (ref_item->type() == Item::FIELD_ITEM) + { + /* + In some cases we need to update table read set(see bug#47150). + If ref item is FIELD_ITEM and fixed then field and table + have proper values. So we can use them for update. + */ + Field *fld= ((Item_field*) ref_item)->field; + DBUG_ASSERT(fld && fld->table); + if (thd->mark_used_columns == MARK_COLUMNS_READ) + bitmap_set_bit(fld->table->read_set, fld->field_index); + } + } + else if (!(*ref)->fixed && + ((*ref)->fix_fields(thd, ref))) return TRUE; + return Item_direct_ref::fix_fields(thd, reference); } From 8d3d35ea5715739ac94785b8c9ff1a185699a84a Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Tue, 29 Sep 2009 07:58:42 -0300 Subject: [PATCH 80/80] Bug#45567: Fast ALTER TABLE broken for enum and set The problem was that appending values to the end of an existing ENUM or SET column was being treated as table data modification, preventing a immediately (fast) table alteration that occurs when only table metadata is being modified. The cause was twofold: adding a enumeration or set members to the end of the list of valid member values was not being considered a "compatible" table alteration, and for SET columns, the check was being done upon the max display length and not the underlying (pack) length of the field. The solution is to augment the function that checks wether two ENUM or SET fields are compatible -- by comparing the pack lengths and performing a limited comparison of the member values. mysql-test/r/alter_table.result: Add test case result for Bug#45567 mysql-test/t/alter_table.test: Add test case for Bug#45567 sql/field.cc: Check whether two fields can be considered 'equal' for table alteration purposes. Fields are equal if they retain the same pack length and if new members are added to the end of the list. sql/field.h: Add comment and remove method. --- mysql-test/r/alter_table.result | 62 +++++++++++++++++++++++++++ mysql-test/t/alter_table.test | 46 ++++++++++++++++++++ sql/field.cc | 75 ++++++++++++++++++++++++++------- sql/field.h | 8 +++- 4 files changed, 174 insertions(+), 17 deletions(-) diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result index 5a115e9ea99..db7173d0b47 100644 --- a/mysql-test/r/alter_table.result +++ b/mysql-test/r/alter_table.result @@ -1268,4 +1268,66 @@ a b 4 b 5 a DROP TABLE t1; +# +# Bug#45567: Fast ALTER TABLE broken for enum and set +# +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (a ENUM('a1','a2')); +INSERT INTO t1 VALUES ('a1'),('a2'); +# No copy: No modification +ALTER TABLE t1 MODIFY COLUMN a ENUM('a1','a2'); +affected rows: 0 +info: Records: 0 Duplicates: 0 Warnings: 0 +# No copy: Add new enumeration to the end +ALTER TABLE t1 MODIFY COLUMN a ENUM('a1','a2','a3'); +affected rows: 0 +info: Records: 0 Duplicates: 0 Warnings: 0 +# Copy: Modify and add new to the end +ALTER TABLE t1 MODIFY COLUMN a ENUM('a1','a2','xx','a5'); +affected rows: 2 +info: Records: 2 Duplicates: 0 Warnings: 0 +# Copy: Remove from the end +ALTER TABLE t1 MODIFY COLUMN a ENUM('a1','a2','xx'); +affected rows: 2 +info: Records: 2 Duplicates: 0 Warnings: 0 +# Copy: Add new enumeration +ALTER TABLE t1 MODIFY COLUMN a ENUM('a1','a2','a0','xx'); +affected rows: 2 +info: Records: 2 Duplicates: 0 Warnings: 0 +# No copy: Add new enumerations to the end +ALTER TABLE t1 MODIFY COLUMN a ENUM('a1','a2','a0','xx','a5','a6'); +affected rows: 0 +info: Records: 0 Duplicates: 0 Warnings: 0 +DROP TABLE t1; +CREATE TABLE t1 (a SET('a1','a2')); +INSERT INTO t1 VALUES ('a1'),('a2'); +# No copy: No modification +ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2'); +affected rows: 0 +info: Records: 0 Duplicates: 0 Warnings: 0 +# No copy: Add new to the end +ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2','a3'); +affected rows: 0 +info: Records: 0 Duplicates: 0 Warnings: 0 +# Copy: Modify and add new to the end +ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2','xx','a5'); +affected rows: 2 +info: Records: 2 Duplicates: 0 Warnings: 0 +# Copy: Remove from the end +ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2','xx'); +affected rows: 2 +info: Records: 2 Duplicates: 0 Warnings: 0 +# Copy: Add new member +ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2','a0','xx'); +affected rows: 2 +info: Records: 2 Duplicates: 0 Warnings: 0 +# No copy: Add new to the end +ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2','a0','xx','a5','a6'); +affected rows: 0 +info: Records: 0 Duplicates: 0 Warnings: 0 +# Copy: Numerical incrase (pack lenght) +ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2','a0','xx','a5','a6','a7','a8','a9','a10'); +affected rows: 2 +info: Records: 2 Duplicates: 0 Warnings: 0 +DROP TABLE t1; End of 5.1 tests diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test index ae48d5a8736..17549745203 100644 --- a/mysql-test/t/alter_table.test +++ b/mysql-test/t/alter_table.test @@ -1000,4 +1000,50 @@ ALTER TABLE t1 MODIFY b ENUM('a', 'z', 'b', 'c') NOT NULL; SELECT * FROM t1; DROP TABLE t1; +--echo # +--echo # Bug#45567: Fast ALTER TABLE broken for enum and set +--echo # + +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +CREATE TABLE t1 (a ENUM('a1','a2')); +INSERT INTO t1 VALUES ('a1'),('a2'); +--enable_info +--echo # No copy: No modification +ALTER TABLE t1 MODIFY COLUMN a ENUM('a1','a2'); +--echo # No copy: Add new enumeration to the end +ALTER TABLE t1 MODIFY COLUMN a ENUM('a1','a2','a3'); +--echo # Copy: Modify and add new to the end +ALTER TABLE t1 MODIFY COLUMN a ENUM('a1','a2','xx','a5'); +--echo # Copy: Remove from the end +ALTER TABLE t1 MODIFY COLUMN a ENUM('a1','a2','xx'); +--echo # Copy: Add new enumeration +ALTER TABLE t1 MODIFY COLUMN a ENUM('a1','a2','a0','xx'); +--echo # No copy: Add new enumerations to the end +ALTER TABLE t1 MODIFY COLUMN a ENUM('a1','a2','a0','xx','a5','a6'); +--disable_info +DROP TABLE t1; + +CREATE TABLE t1 (a SET('a1','a2')); +INSERT INTO t1 VALUES ('a1'),('a2'); +--enable_info +--echo # No copy: No modification +ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2'); +--echo # No copy: Add new to the end +ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2','a3'); +--echo # Copy: Modify and add new to the end +ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2','xx','a5'); +--echo # Copy: Remove from the end +ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2','xx'); +--echo # Copy: Add new member +ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2','a0','xx'); +--echo # No copy: Add new to the end +ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2','a0','xx','a5','a6'); +--echo # Copy: Numerical incrase (pack lenght) +ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2','a0','xx','a5','a6','a7','a8','a9','a10'); +--disable_info +DROP TABLE t1; + --echo End of 5.1 tests diff --git a/sql/field.cc b/sql/field.cc index 9f46552d5bd..0df9b0fc2e4 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -8832,6 +8832,24 @@ bool Field::eq_def(Field *field) } +/** + Compare the first t1::count type names. + + @return TRUE if the type names of t1 match those of t2. FALSE otherwise. +*/ + +static bool compare_type_names(CHARSET_INFO *charset, TYPELIB *t1, TYPELIB *t2) +{ + for (uint i= 0; i < t1->count; i++) + if (my_strnncoll(charset, + (const uchar*) t1->type_names[i], + t1->type_lengths[i], + (const uchar*) t2->type_names[i], + t2->type_lengths[i])) + return FALSE; + return TRUE; +} + /** @return returns 1 if the fields are equally defined @@ -8839,32 +8857,57 @@ bool Field::eq_def(Field *field) bool Field_enum::eq_def(Field *field) { + TYPELIB *values; + if (!Field::eq_def(field)) - return 0; - return compare_enum_values(((Field_enum*) field)->typelib); -} + return FALSE; + values= ((Field_enum*) field)->typelib; -bool Field_enum::compare_enum_values(TYPELIB *values) -{ + /* Definition must be strictly equal. */ if (typelib->count != values->count) return FALSE; - for (uint i= 0; i < typelib->count; i++) - if (my_strnncoll(field_charset, - (const uchar*) typelib->type_names[i], - typelib->type_lengths[i], - (const uchar*) values->type_names[i], - values->type_lengths[i])) - return FALSE; - return TRUE; + + return compare_type_names(field_charset, typelib, values); } +/** + Check whether two fields can be considered 'equal' for table + alteration purposes. Fields are equal if they retain the same + pack length and if new members are added to the end of the list. + + @return IS_EQUAL_YES if fields are compatible. + IS_EQUAL_NO otherwise. +*/ + uint Field_enum::is_equal(Create_field *new_field) { - if (!Field_str::is_equal(new_field)) - return 0; - return compare_enum_values(new_field->interval); + TYPELIB *values= new_field->interval; + + /* + The fields are compatible if they have the same flags, + type, charset and have the same underlying length. + */ + if (compare_str_field_flags(new_field, flags) || + new_field->sql_type != real_type() || + new_field->charset != field_charset || + new_field->pack_length != pack_length()) + return IS_EQUAL_NO; + + /* + Changing the definition of an ENUM or SET column by adding a new + enumeration or set members to the end of the list of valid member + values only alters table metadata and not table data. + */ + if (typelib->count > values->count) + return IS_EQUAL_NO; + + /* Check whether there are modification before the end. */ + if (! compare_type_names(field_charset, typelib, new_field->interval)) + return IS_EQUAL_NO; + + return IS_EQUAL_YES; } diff --git a/sql/field.h b/sql/field.h index a9299256f88..7a9b69eff40 100644 --- a/sql/field.h +++ b/sql/field.h @@ -472,6 +472,13 @@ public: /* maximum possible display length */ virtual uint32 max_display_length()= 0; + /** + Whether a field being created is compatible with a existing one. + + Used by the ALTER TABLE code to evaluate whether the new definition + of a table is compatible with the old definition so that it can + determine if data needs to be copied over (table data change). + */ virtual uint is_equal(Create_field *new_field); /* convert decimal to longlong with overflow check */ longlong convert_decimal2longlong(const my_decimal *val, bool unsigned_flag, @@ -1862,7 +1869,6 @@ public: CHARSET_INFO *sort_charset(void) const { return &my_charset_bin; } private: int do_save_field_metadata(uchar *first_byte); - bool compare_enum_values(TYPELIB *values); uint is_equal(Create_field *new_field); };