diff options
49 files changed, 1113 insertions, 402 deletions
diff --git a/client/mysqlslap.c b/client/mysqlslap.c index 4e8e4f1aa67..01d96f1f75e 100644 --- a/client/mysqlslap.c +++ b/client/mysqlslap.c @@ -1507,7 +1507,12 @@ generate_primary_key_list(MYSQL *mysql, option_string *engine_stmt) exit(1); } - result= mysql_store_result(mysql); + if (!(result= mysql_store_result(mysql))) + { + fprintf(stderr, "%s: Error when storing result: %d %s\n", + my_progname, mysql_errno(mysql), mysql_error(mysql)); + exit(1); + } primary_keys_number_of= mysql_num_rows(result); /* So why check this? Blackhole :) */ @@ -1879,10 +1884,15 @@ limit_not_met: { if (mysql_field_count(mysql)) { - result= mysql_store_result(mysql); - while ((row = mysql_fetch_row(result))) - counter++; - mysql_free_result(result); + if (!(result= mysql_store_result(mysql))) + fprintf(stderr, "%s: Error when storing result: %d %s\n", + my_progname, mysql_errno(mysql), mysql_error(mysql)); + else + { + while ((row= mysql_fetch_row(result))) + counter++; + mysql_free_result(result); + } } } while(mysql_next_result(mysql) == 0); queries++; diff --git a/client/mysqltest.cc b/client/mysqltest.cc index f266197116b..6d1630ebdaa 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -468,6 +468,8 @@ TYPELIB command_typelib= {array_elements(command_names),"", command_names, 0}; DYNAMIC_STRING ds_res; +/* Points to ds_warning in run_query, so it can be freed */ +DYNAMIC_STRING *ds_warn= 0; char builtin_echo[FN_REFLEN]; @@ -488,7 +490,7 @@ VAR* var_init(VAR* v, const char *name, int name_len, const char *val, VAR* var_get(const char *var_name, const char** var_name_end, my_bool raw, my_bool ignore_not_existing); void eval_expr(VAR* v, const char *p, const char** p_end, - bool open_end=false, bool backtick=true); + bool open_end=false, bool do_eval=true); my_bool match_delimiter(int c, const char *delim, uint length); void dump_result_to_reject_file(char *buf, int size); void dump_warning_messages(); @@ -1275,6 +1277,8 @@ void free_used_memory() my_free(embedded_server_args[--embedded_server_arg_count]); delete_dynamic(&q_lines); dynstr_free(&ds_res); + if (ds_warn) + dynstr_free(ds_warn); free_all_replace(); my_free(opt_pass); free_defaults(default_argv); @@ -1318,6 +1322,17 @@ static void cleanup_and_exit(int exit_code) exit(exit_code); } +void print_file_stack() +{ + for (struct st_test_file* err_file= cur_file; + err_file != file_stack; + err_file--) + { + fprintf(stderr, "included from %s at line %d:\n", + err_file->file_name, err_file->lineno); + } +} + void die(const char *fmt, ...) { static int dying= 0; @@ -1337,8 +1352,12 @@ void die(const char *fmt, ...) /* Print the error message */ fprintf(stderr, "mysqltest: "); if (cur_file && cur_file != file_stack) - fprintf(stderr, "In included file \"%s\": ", + { + fprintf(stderr, "In included file \"%s\": \n", cur_file->file_name); + print_file_stack(); + } + if (start_lineno > 0) fprintf(stderr, "At line %u: ", start_lineno); if (fmt) @@ -1368,20 +1387,14 @@ void die(const char *fmt, ...) void abort_not_supported_test(const char *fmt, ...) { va_list args; - struct st_test_file* err_file= cur_file; DBUG_ENTER("abort_not_supported_test"); /* Print include filestack */ fprintf(stderr, "The test '%s' is not supported by this installation\n", file_stack->file_name); fprintf(stderr, "Detected in file %s at line %d\n", - err_file->file_name, err_file->lineno); - while (err_file != file_stack) - { - err_file--; - fprintf(stderr, "included from %s at line %d\n", - err_file->file_name, err_file->lineno); - } + cur_file->file_name, cur_file->lineno); + print_file_stack(); /* Print error message */ va_start(args, fmt); @@ -2519,7 +2532,7 @@ void var_set_query_get_value(struct st_command *command, VAR *var) break; } } - eval_expr(var, value, 0); + eval_expr(var, value, 0, false, false); } dynstr_free(&ds_query); mysql_free_result(res); @@ -2551,12 +2564,16 @@ void var_copy(VAR *dest, VAR *src) void eval_expr(VAR *v, const char *p, const char **p_end, - bool open_end, bool backtick) + bool open_end, bool do_eval) { DBUG_ENTER("eval_expr"); DBUG_PRINT("enter", ("p: '%s'", p)); + /* Skip to treat as pure string if no evaluation */ + if (! do_eval) + goto NO_EVAL; + if (*p == '$') { VAR *vp; @@ -2576,7 +2593,7 @@ void eval_expr(VAR *v, const char *p, const char **p_end, DBUG_VOID_RETURN; } - if (*p == '`' && backtick) + if (*p == '`') { var_query_set(v, p, p_end); DBUG_VOID_RETURN; @@ -2599,6 +2616,7 @@ void eval_expr(VAR *v, const char *p, const char **p_end, } } + NO_EVAL: { int new_val_len = (p_end && *p_end) ? (int) (*p_end - p) : (int) strlen(p); @@ -7679,6 +7697,8 @@ void run_query(struct st_connection *cn, struct st_command *command, int flags) die ("Cannot reap on a connection without pending send"); init_dynamic_string(&ds_warnings, NULL, 0, 256); + ds_warn= &ds_warnings; + /* Evaluate query if this is an eval command */ @@ -7836,6 +7856,7 @@ void run_query(struct st_connection *cn, struct st_command *command, int flags) ds, &ds_warnings); dynstr_free(&ds_warnings); + ds_warn= 0; if (command->type == Q_EVAL || command->type == Q_SEND_EVAL) dynstr_free(&eval_query); diff --git a/mysql-test/collections/README.experimental b/mysql-test/collections/README.experimental index 2f5ee7b00ab..924e062b76a 100644 --- a/mysql-test/collections/README.experimental +++ b/mysql-test/collections/README.experimental @@ -15,9 +15,13 @@ The syntax is as follows: and any subsequent characters are ignored. 4) The full test case name including the suite and execution mode - must be specified, for example: + may be specified, for example: main.alias 'row' # bug#00000 +4b) Now, combinations will also be covered if only the test name is + specified, for example: + rpl.rpl_ps # Covers 'row', 'mix' and 'stmt' + 5) As an exception to item 4, the last character of the test case specification may be an asterisk (*). In that case, all test cases that start with the same characters up to the last letter before the asterisk diff --git a/mysql-test/collections/default.experimental b/mysql-test/collections/default.experimental index fd02498f39a..22378ebe174 100644 --- a/mysql-test/collections/default.experimental +++ b/mysql-test/collections/default.experimental @@ -21,7 +21,7 @@ main.wait_timeout @solaris # Bug#51244 2010-04-26 alik wait_timeou rpl.rpl_heartbeat_basic # BUG#54820 2010-06-26 alik rpl.rpl_heartbeat_basic fails sporadically again rpl.rpl_heartbeat_2slaves # BUG#43828 2009-10-22 luis fails sporadically -rpl.rpl_innodb_bug28430* # Bug#46029 +rpl.rpl_innodb_bug28430 # Bug#46029 sys_vars.max_sp_recursion_depth_func @solaris # Bug#47791 2010-01-20 alik Several test cases fail on Solaris with error Thread stack overrun sys_vars.plugin_dir_basic # Bug#52223 2010-11-24 alik Test "plugin_dir_basic" does not support RPM build (test) directory structure diff --git a/mysql-test/include/plugin.defs b/mysql-test/include/plugin.defs new file mode 100644 index 00000000000..4da03dc2cc9 --- /dev/null +++ b/mysql-test/include/plugin.defs @@ -0,0 +1,41 @@ +# Definition file for plugins. +# +# <lib name> <directory> <variable> [<plugin name>,...] +# +# The following variables will be set for a plugin, where PLUGVAR +# represents the variable name given as the 3rd item +# +# PLUGVAR: name of plugin file including extension .so or .dll +# PLUGVAR_DIR: name of directory where plugin was found +# PLUGVAR_OPT: mysqld option --plugin_dir=.... +# PLUGVAR_LOAD: option --plugin_load=.... if the 4th element is present +# +# If a listed plugin is not found, the corresponding variables will be +# set to empty, they will not be unset. +# +# The PLUGVAR variable is not quoted, so you must remember to quote it +# when using it in an INSTALL PLUGIN command. +# +# The envorinment variables can be used in tests. If adding a new plugin, +# you are free to pick your variable name, but please keep it upper +# case for consistency. +# +# The _LOAD variable will have a form +# +# --plugin_load=<name1>=<lib_name>;<name2>=<lib_name>..... +# +# with name1, name2 etc from the comma separated list of plugin names +# in the optional 4th argument. + +auth_test_plugin plugin/auth PLUGIN_AUTH test_plugin_server +qa_auth_interface plugin/auth PLUGIN_AUTH_INTERFACE qa_auth_interface +qa_auth_server plugin/auth PLUGIN_AUTH_SERVER qa_auth_server +qa_auth_client plugin/auth PLUGIN_AUTH_CLIENT qa_auth_client +udf_example sql UDF_EXAMPLE_LIB +ha_example storage/example EXAMPLE_PLUGIN EXAMPLE +semisync_master plugin/semisync SEMISYNC_MASTER_PLUGIN +semisync_slave plugin/semisync SEMISYNC_SLAVE_PLUGIN +ha_archive storage/archive ARCHIVE_PLUGIN +ha_blackhole storage/blackhole BLACKHOLE_PLUGIN +ha_federated storage/federated FEDERATED_PLUGIN +mypluglib plugin/fulltext SIMPLE_PARSER diff --git a/mysql-test/include/wait_for_status_var.inc b/mysql-test/include/wait_for_status_var.inc index 9f4962aeaed..5c68254f00e 100644 --- a/mysql-test/include/wait_for_status_var.inc +++ b/mysql-test/include/wait_for_status_var.inc @@ -50,8 +50,23 @@ if (!$_status_var_comparsion) let $_status_var_comparsion= =; } +# Get type of variable +let $_is_number= 0; +if (`SELECT '$status_var_value' REGEXP '^[\+\-]*[0-9]+(\.[0-9]+)*\$'`) +{ + let $_is_number= 1; +} + let $_show_status_value= query_get_value("SHOW $status_type STATUS LIKE '$status_var'", Value, 1); -while (`SELECT NOT('$_show_status_value' $_status_var_comparsion '$status_var_value')`) + +# Set way of comparing +let $_query= SELECT NOT('$_show_status_value' $_status_var_comparsion '$status_var_value'); +if ($is_number) +{ + let $_query= SELECT NOT($_show_status_value $_status_var_comparsion $status_var_value); +} + +while (`$_query`) { if (!$_status_timeout_counter) { @@ -65,4 +80,9 @@ while (`SELECT NOT('$_show_status_value' $_status_var_comparsion '$status_var_va dec $_status_timeout_counter; sleep 0.1; let $_show_status_value= query_get_value("SHOW $status_type STATUS LIKE '$status_var'", Value, 1); + let $_query= SELECT NOT('$_show_status_value' $_status_var_comparsion '$status_var_value'); + if ($is_number) + { + let $_query= SELECT NOT($_show_status_value $_status_var_comparsion $status_var_value); + } } diff --git a/mysql-test/lib/mtr_cases.pm b/mysql-test/lib/mtr_cases.pm index f1f1ac35dcd..856982e98a1 100644 --- a/mysql-test/lib/mtr_cases.pm +++ b/mysql-test/lib/mtr_cases.pm @@ -229,8 +229,11 @@ sub collect_test_cases ($$$$) { sub split_testname { my ($test_name)= @_; - # Get rid of directory part and split name on .'s - my @parts= split(/\./, basename($test_name)); + # If .test file name is used, get rid of directory part + $test_name= basename($test_name) if $test_name =~ /\.test$/; + + # Now split name on .'s + my @parts= split(/\./, $test_name); if (@parts == 1){ # Only testname given, ex: alias diff --git a/mysql-test/lib/mtr_report.pm b/mysql-test/lib/mtr_report.pm index af75178473d..cd3f9ce1041 100644 --- a/mysql-test/lib/mtr_report.pm +++ b/mysql-test/lib/mtr_report.pm @@ -129,7 +129,8 @@ sub mtr_report_test ($) { # Find out if this test case is an experimental one, so we can treat # the failure as an expected failure instead of a regression. for my $exp ( @$::experimental_test_cases ) { - if ( $exp ne $test_name ) { + # Include pattern match for combinations + if ( $exp ne $test_name && $test_name !~ /^$exp / ) { # if the expression is not the name of this test case, but has # an asterisk at the end, determine if the characters up to # but excluding the asterisk are the same @@ -395,7 +396,7 @@ sub mtr_report_stats ($$;$) { ############################################################################## sub mtr_print_line () { - print '-' x 60 . "\n"; + print '-' x 74 . "\n"; } @@ -405,13 +406,18 @@ sub mtr_print_thick_line { } -sub mtr_print_header () { +sub mtr_print_header ($) { + my ($wid) = @_; print "\n"; printf "TEST"; - print " " x 38; + if ($wid) { + print " " x 34 . "WORKER "; + } else { + print " " x 38; + } print "RESULT "; - print "TIME (ms)" if $timer; - print "\n"; + print "TIME (ms) or " if $timer; + print "COMMENT\n"; mtr_print_line(); print "\n"; } diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index a7683b8d807..b786066faf6 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -131,10 +131,6 @@ my $opt_start_dirty; my $opt_start_exit; my $start_only; -my $auth_interface_fn; # the name of qa_auth_interface plugin -my $auth_server_fn; # the name of qa_auth_server plugin -my $auth_client_fn; # the name of qa_auth_client plugin -my $auth_filename; # the name of the authentication test plugin my $auth_plugin; # the path to the authentication test plugin END { @@ -442,7 +438,7 @@ sub main { mtr_report(); mtr_print_thick_line(); - mtr_print_header(); + mtr_print_header($opt_parallel > 1); mark_time_used('init'); @@ -1124,27 +1120,7 @@ sub command_line_setup { "$basedir/sql/share/charsets", "$basedir/share/charsets"); - # Look for auth test plugins - if (IS_WINDOWS) - { - $auth_filename = "auth_test_plugin.dll"; - $auth_interface_fn = "qa_auth_interface.dll"; - $auth_server_fn = "qa_auth_server.dll"; - $auth_client_fn = "qa_auth_client.dll"; - } - else - { - $auth_filename = "auth_test_plugin.so"; - $auth_interface_fn = "qa_auth_interface.so"; - $auth_server_fn = "qa_auth_server.so"; - $auth_client_fn = "qa_auth_client.so"; - } - $auth_plugin= - mtr_file_exists(vs_config_dirs('plugin/auth/',$auth_filename), - "$basedir/plugin/auth/.libs/" . $auth_filename, - "$basedir/lib/mysql/plugin/" . $auth_filename, - "$basedir/lib/plugin/" . $auth_filename); - + ($auth_plugin)= find_plugin("auth_test_plugin", "plugin/auth"); if (using_extern()) { @@ -1983,6 +1959,53 @@ sub find_plugin($$) return $lib_example_plugin; } +# +# Read plugin defintions file +# + +sub read_plugin_defs($) +{ + my ($defs_file)= @_; + + open(PLUGDEF, '<', $defs_file) + or mtr_error("Can't read plugin defintions file $defs_file"); + + while (<PLUGDEF>) { + next if /^#/; + my ($plug_file, $plug_loc, $plug_var, $plug_names)= split; + # Allow empty lines + next unless $plug_file; + mtr_error("Lines in $defs_file must have 3 or 4 items") unless $plug_var; + + my ($plugin)= find_plugin($plug_file, $plug_loc); + + # Set env. variables that tests may use, set to empty if plugin + # listed in def. file but not found. + + if ($plugin) { + $ENV{$plug_var}= basename($plugin); + $ENV{$plug_var.'_DIR'}= dirname($plugin); + $ENV{$plug_var.'_OPT'}= "--plugin-dir=".dirname($plugin); + if ($plug_names) { + my $lib_name= basename($plugin); + my $load_var= "--plugin_load="; + my $semi= ''; + foreach my $plug_name (split (',', $plug_names)) { + $load_var .= $semi . "$plug_name=$lib_name"; + $semi= ';'; + } + $ENV{$plug_var.'_LOAD'}= $load_var; + } + } else { + $ENV{$plug_var}= ""; + $ENV{$plug_var.'_DIR'}= ""; + $ENV{$plug_var.'_OPT'}= ""; + $ENV{$plug_var.'_LOAD'}= "" if $plug_names; + } + } + close PLUGDEF; +} + sub environment_setup { umask(022); @@ -2019,127 +2042,16 @@ sub environment_setup { } # -------------------------------------------------------------------------- - # Add the path where mysqld will find udf_example.so - # -------------------------------------------------------------------------- - my $udf_example_filename; - if (IS_WINDOWS) - { - $udf_example_filename = "udf_example.dll"; - } - else - { - $udf_example_filename = "udf_example.so"; - } - my $lib_udf_example= - mtr_file_exists(vs_config_dirs('sql', $udf_example_filename), - "$basedir/sql/.libs/$udf_example_filename",); - - if ( $lib_udf_example ) - { - push(@ld_library_paths, dirname($lib_udf_example)); - } - - $ENV{'UDF_EXAMPLE_LIB'}= - ($lib_udf_example ? basename($lib_udf_example) : ""); - $ENV{'UDF_EXAMPLE_LIB_OPT'}= "--plugin-dir=". - ($lib_udf_example ? dirname($lib_udf_example) : ""); - - # -------------------------------------------------------------------------- - # Add the path where mysqld will find the auth test plugin (dialog.so/dll) - # -------------------------------------------------------------------------- - if ($auth_plugin) - { - $ENV{'PLUGIN_AUTH'}= basename($auth_plugin); - $ENV{'PLUGIN_AUTH_OPT'}= "--plugin-dir=".dirname($auth_plugin); - - $ENV{'PLUGIN_AUTH_LOAD'}="--plugin_load=test_plugin_server=".$auth_filename; - $ENV{'PLUGIN_AUTH_INTERFACE'}="--plugin_load=qa_auth_interface=".$auth_interface_fn; - $ENV{'PLUGIN_AUTH_SERVER'}="--plugin_load=qa_auth_server=".$auth_server_fn; - $ENV{'PLUGIN_AUTH_CLIENT'}="--plugin_load=qa_auth_client=".$auth_client_fn; - } - else - { - $ENV{'PLUGIN_AUTH'}= ""; - $ENV{'PLUGIN_AUTH_OPT'}="--plugin-dir="; - $ENV{'PLUGIN_AUTH_LOAD'}=""; - $ENV{'PLUGIN_AUTH_INTERFACE'}=""; - $ENV{'PLUGIN_AUTH_SERVER'}=""; - $ENV{'PLUGIN_AUTH_CLIENT'}=""; - } - - - # -------------------------------------------------------------------------- - # Add the path where mysqld will find ha_example.so - # -------------------------------------------------------------------------- - if ($mysql_version_id >= 50100) { - my ($lib_example_plugin) = find_plugin("ha_example", "storage/example"); - - if($lib_example_plugin) - { - $ENV{'EXAMPLE_PLUGIN'}= - ($lib_example_plugin ? basename($lib_example_plugin) : ""); - $ENV{'EXAMPLE_PLUGIN_OPT'}= "--plugin-dir=". - ($lib_example_plugin ? dirname($lib_example_plugin) : ""); - - $ENV{'HA_EXAMPLE_SO'}="'".basename($lib_example_plugin)."'"; - $ENV{'EXAMPLE_PLUGIN_LOAD'}="--plugin_load=EXAMPLE=".basename($lib_example_plugin); - } - else - { - # Some ".opt" files use some of these variables, so they must be defined - $ENV{'EXAMPLE_PLUGIN'}= ""; - $ENV{'EXAMPLE_PLUGIN_OPT'}= ""; - $ENV{'HA_EXAMPLE_SO'}= ""; - $ENV{'EXAMPLE_PLUGIN_LOAD'}= ""; - } - } - - - # -------------------------------------------------------------------------- - # Add the path where mysqld will find semisync plugins + # Read definitions from include/plugin.defs + # + # Plugin settings should no longer be added here, instead + # place definitions in include/plugin.defs. + # See comment in that file for details. # -------------------------------------------------------------------------- - if (!$opt_embedded_server) { - - - my ($lib_semisync_master_plugin) = find_plugin("semisync_master", "plugin/semisync"); - my ($lib_semisync_slave_plugin) = find_plugin("semisync_slave", "plugin/semisync"); - - - if ($lib_semisync_master_plugin && $lib_semisync_slave_plugin) - { - $ENV{'SEMISYNC_MASTER_PLUGIN'}= basename($lib_semisync_master_plugin); - $ENV{'SEMISYNC_SLAVE_PLUGIN'}= basename($lib_semisync_slave_plugin); - $ENV{'SEMISYNC_PLUGIN_OPT'}= "--plugin-dir=".dirname($lib_semisync_master_plugin); - } - else - { - $ENV{'SEMISYNC_MASTER_PLUGIN'}= ""; - $ENV{'SEMISYNC_SLAVE_PLUGIN'}= ""; - $ENV{'SEMISYNC_PLUGIN_OPT'}="--plugin-dir="; - } - } - - # ---------------------------------------------------- - # Add the paths where mysqld will find archive/blackhole/federated plugins. - # ---------------------------------------------------- - $ENV{'ARCHIVE_PLUGIN_DIR'} = - dirname(find_plugin("ha_archive", "storage/archive")); - $ENV{'BLACKHOLE_PLUGIN_DIR'} = - dirname(find_plugin("ha_blackhole", "storage/blackhole")); - $ENV{'FEDERATED_PLUGIN_DIR'} = - dirname(find_plugin("ha_federated", "storage/federated")); - - # ---------------------------------------------------- - # Add the path where mysqld will find mypluglib.so - # ---------------------------------------------------- - - my ($lib_simple_parser) = find_plugin("mypluglib", "plugin/fulltext"); + read_plugin_defs("include/plugin.defs"); - $ENV{'MYPLUGLIB_SO'}="'".basename($lib_simple_parser)."'"; - $ENV{'SIMPLE_PARSER'}= - ($lib_simple_parser ? basename($lib_simple_parser) : ""); - $ENV{'SIMPLE_PARSER_OPT'}= "--plugin-dir=". - ($lib_simple_parser ? dirname($lib_simple_parser) : ""); + # Simplify reference to semisync plugins + $ENV{'SEMISYNC_PLUGIN_OPT'}= $ENV{'SEMISYNC_MASTER_PLUGIN_OPT'}; # -------------------------------------------------------------------------- # Valgrind need to be run with debug libraries otherwise it's almost diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index 41fe9c096b0..81fe2413725 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -2615,6 +2615,22 @@ CONVERT(('' IN (REVERSE(CAST(('') AS DECIMAL)), '')), CHAR(3)) 1 Warnings: Warning 1292 Truncated incorrect DECIMAL value: '' +# +# Bug#58165: "my_empty_string" gets modified and causes LOAD DATA to fail +# and other crashes +# +CREATE TABLE t1 ( a TEXT ); +SELECT 'aaaaaaaaaaaaaa' INTO OUTFILE 'bug58165.txt'; +SELECT insert( substring_index( 'a', 'a', 'b' ), 1, 0, 'x' ); +insert( substring_index( 'a', 'a', 'b' ), 1, 0, 'x' ) +x +Warnings: +Warning 1292 Truncated incorrect INTEGER value: 'b' +LOAD DATA INFILE 'bug58165.txt' INTO TABLE t1; +SELECT * FROM t1; +a +aaaaaaaaaaaaaa +DROP TABLE t1; End of 5.1 tests Start of 5.4 tests SELECT format(12345678901234567890.123, 3); diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result index 5663f167d00..7939d01beff 100644 --- a/mysql-test/r/gis.result +++ b/mysql-test/r/gis.result @@ -1014,6 +1014,14 @@ SET @a=0x00000000030000000100000000000000000000000000144000000000000014400000000 SET @a=POLYFROMWKB(@a); SET @a=0x00000000030000000000000000000000000000000000144000000000000014400000000000001840000000000000184000000000000014400000000000001440; SET @a=POLYFROMWKB(@a); +create table t1(a polygon NOT NULL)engine=myisam; +insert into t1 values (geomfromtext("point(0 1)")); +insert into t1 values (geomfromtext("point(1 0)")); +select * from (select polygon(t1.a) as p from t1 order by t1.a) d; +p +NULL +NULL +drop table t1; End of 5.1 tests CREATE TABLE t1( col0 BINARY NOT NULL, diff --git a/mysql-test/r/join_outer.result b/mysql-test/r/join_outer.result index 99ca9f05535..ecd53003513 100644 --- a/mysql-test/r/join_outer.result +++ b/mysql-test/r/join_outer.result @@ -1432,4 +1432,74 @@ WHERE t1.f1 = 4 AND t2.f1 IS NOT NULL AND t2.f2 IS NOT NULL GROUP BY t2.f1, t2.f2; f1 f1 f2 DROP TABLE t1,t2; +# +# Bug#57034 incorrect OUTER JOIN result when joined on unique key +# +CREATE TABLE t1 (pk INT PRIMARY KEY, +col_int INT, +col_int_unique INT UNIQUE KEY); +INSERT INTO t1 VALUES (1,NULL,2), (2,0,0); +CREATE TABLE t2 (pk INT PRIMARY KEY, +col_int INT, +col_int_unique INT UNIQUE KEY); +INSERT INTO t2 VALUES (1,0,1), (2,0,2); +EXPLAIN +SELECT * FROM t1 LEFT JOIN t2 +ON t1.col_int_unique = t2.col_int_unique AND t1.col_int = t2.col_int +WHERE t1.pk=1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1 +1 SIMPLE t2 const col_int_unique col_int_unique 5 const 1 +SELECT * FROM t1 LEFT JOIN t2 +ON t1.col_int_unique = t2.col_int_unique AND t1.col_int = t2.col_int +WHERE t1.pk=1; +pk col_int col_int_unique pk col_int col_int_unique +1 NULL 2 NULL NULL NULL +DROP TABLE t1,t2; +# +# Bug#48046 Server incorrectly processing JOINs on NULL values +# +CREATE TABLE `BB` ( +`pk` int(11) NOT NULL AUTO_INCREMENT, +`time_key` time DEFAULT NULL, +`varchar_key` varchar(1) DEFAULT NULL, +`varchar_nokey` varchar(1) DEFAULT NULL, +PRIMARY KEY (`pk`), +KEY `time_key` (`time_key`), +KEY `varchar_key` (`varchar_key`) +) ENGINE=MyISAM AUTO_INCREMENT=11 DEFAULT CHARSET=latin1; +INSERT INTO `BB` VALUES (10,'18:27:58',NULL,NULL); +SELECT table1.time_key AS field1, table2.pk +FROM BB table1 LEFT JOIN BB table2 +ON table2.varchar_nokey = table1.varchar_key +HAVING field1; +field1 pk +18:27:58 NULL +DROP TABLE BB; +# +# Bug#49600 Server incorrectly processing RIGHT JOIN with +# constant WHERE clause and no index +# +CREATE TABLE `BB` ( +`col_datetime_key` datetime DEFAULT NULL, +`col_varchar_key` varchar(1) DEFAULT NULL, +`col_varchar_nokey` varchar(1) DEFAULT NULL, +KEY `col_datetime_key` (`col_datetime_key`), +KEY `col_varchar_key` (`col_varchar_key`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +INSERT INTO `BB` VALUES ('1900-01-01 00:00:00',NULL,NULL); +SELECT table1.col_datetime_key +FROM BB table1 RIGHT JOIN BB table2 +ON table2 .col_varchar_nokey = table1.col_varchar_key +WHERE 7; +col_datetime_key +NULL +ALTER TABLE BB DISABLE KEYS; +SELECT table1.col_datetime_key +FROM BB table1 RIGHT JOIN BB table2 +ON table2 .col_varchar_nokey = table1.col_varchar_key +WHERE 7; +col_datetime_key +NULL +DROP TABLE BB; End of 5.1 tests diff --git a/mysql-test/r/mysqlbinlog_row_big.result b/mysql-test/r/mysqlbinlog_row_big.result index 46fa0dc79cd..0bdbfdcee3a 100644 --- a/mysql-test/r/mysqlbinlog_row_big.result +++ b/mysql-test/r/mysqlbinlog_row_big.result @@ -36,8 +36,8 @@ c1 LONGTEXT # # Insert some big rows. # -256MB -INSERT INTO t1 VALUES (REPEAT('ManyMegaByteBlck', 16777216)); +64MB +INSERT INTO t1 VALUES (REPEAT('ManyMegaByteBlck', 4194304)); affected rows: 1 32MB INSERT INTO t1 VALUES (REPEAT('ManyMegaByteBlck', 2097152)); @@ -53,7 +53,7 @@ affected rows: 1 # Do not display the column value itself, just its length. # SELECT LENGTH(c1) FROM t1; -LENGTH(c1) 268435456 +LENGTH(c1) 67108864 LENGTH(c1) 33554432 LENGTH(c1) 4194304 LENGTH(c1) 524288 @@ -69,7 +69,7 @@ info: Rows matched: 4 Changed: 4 Warnings: 0 # Do not display the column value itself, just its length. # SELECT LENGTH(c1) FROM t1; -LENGTH(c1) 536870912 +LENGTH(c1) 134217728 LENGTH(c1) 1048576 LENGTH(c1) 67108864 LENGTH(c1) 8388608 diff --git a/mysql-test/r/mysqltest.result b/mysql-test/r/mysqltest.result index c3b6d22ef38..9c8f49c333b 100644 --- a/mysql-test/r/mysqltest.result +++ b/mysql-test/r/mysqltest.result @@ -311,12 +311,33 @@ failing query in let create table t1 (a varchar(100)); insert into t1 values ('`select 42`'); `select 42` +insert into t1 values ('$dollar'); +$dollar +`select 42` drop table t1; mysqltest: At line 1: Error running query 'failing query': 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'failing query' at line 1 mysqltest: At line 1: Missing required argument 'filename' to command 'source' mysqltest: At line 1: Could not open './non_existingFile' for reading, errno: 2 -mysqltest: In included file "MYSQLTEST_VARDIR/tmp/recursive.sql": At line 1: Source directives are nesting too deep -mysqltest: In included file "MYSQLTEST_VARDIR/tmp/error.sql": At line 1: query 'garbage ' failed: 1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1 +mysqltest: In included file "MYSQLTEST_VARDIR/tmp/recursive.sql": +included from MYSQLTEST_VARDIR/tmp/recursive.sql at line 1: +included from MYSQLTEST_VARDIR/tmp/recursive.sql at line 1: +included from MYSQLTEST_VARDIR/tmp/recursive.sql at line 1: +included from MYSQLTEST_VARDIR/tmp/recursive.sql at line 1: +included from MYSQLTEST_VARDIR/tmp/recursive.sql at line 1: +included from MYSQLTEST_VARDIR/tmp/recursive.sql at line 1: +included from MYSQLTEST_VARDIR/tmp/recursive.sql at line 1: +included from MYSQLTEST_VARDIR/tmp/recursive.sql at line 1: +included from MYSQLTEST_VARDIR/tmp/recursive.sql at line 1: +included from MYSQLTEST_VARDIR/tmp/recursive.sql at line 1: +included from MYSQLTEST_VARDIR/tmp/recursive.sql at line 1: +included from MYSQLTEST_VARDIR/tmp/recursive.sql at line 1: +included from MYSQLTEST_VARDIR/tmp/recursive.sql at line 1: +included from MYSQLTEST_VARDIR/tmp/recursive.sql at line 1: +included from MYSQLTEST_VARDIR/tmp/recursive.sql at line 1: +At line 1: Source directives are nesting too deep +mysqltest: In included file "MYSQLTEST_VARDIR/tmp/error.sql": +included from MYSQLTEST_VARDIR/tmp/error.sql at line 1: +At line 1: query 'garbage ' failed: 1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1 2 = outer loop variable after while here is the sourced script @@ -444,7 +465,9 @@ counter is 6 counter is 7 1 Testing while with not -mysqltest: In included file "MYSQLTEST_VARDIR/tmp/mysqltest_while.inc": At line 64: Nesting too deeply +mysqltest: In included file "MYSQLTEST_VARDIR/tmp/mysqltest_while.inc": +included from MYSQLTEST_VARDIR/tmp/mysqltest_while.inc at line 65: +At line 64: Nesting too deeply mysqltest: At line 1: missing '(' in while mysqltest: At line 1: missing ')' in while mysqltest: At line 1: Missing '{' after while. Found "dec $i" @@ -493,8 +516,12 @@ mysqltest: At line 1: query 'connect con2,localhost,root,,illegal_db' failed: 1 mysqltest: At line 1: Illegal argument for port: 'illegal_port' mysqltest: At line 1: Illegal option to connect: SMTP 200 connects succeeded -mysqltest: In included file "MYSQLTEST_VARDIR/tmp/mysqltest.sql": At line 3: connection 'test_con1' not found in connection pool -mysqltest: In included file "MYSQLTEST_VARDIR/tmp/mysqltest.sql": At line 2: Connection test_con1 already exists +mysqltest: In included file "MYSQLTEST_VARDIR/tmp/mysqltest.sql": +included from MYSQLTEST_VARDIR/tmp/mysqltest.sql at line 3: +At line 3: connection 'test_con1' not found in connection pool +mysqltest: In included file "MYSQLTEST_VARDIR/tmp/mysqltest.sql": +included from MYSQLTEST_VARDIR/tmp/mysqltest.sql at line 2: +At line 2: Connection test_con1 already exists show tables; ERROR 3D000: No database selected connect con1,localhost,root,,; diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index a345a2ae6aa..af0ef29bb53 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -4867,6 +4867,70 @@ SELECT 1 FROM t1 ORDER BY a COLLATE latin1_german2_ci; 1 1 DROP TABLE t1; +# +# Bug #58422: Incorrect result when OUTER JOIN'ing +# with an empty table +# +CREATE TABLE t_empty(pk INT PRIMARY KEY, i INT) ENGINE = MYISAM; +CREATE TABLE t1(pk INT PRIMARY KEY, i INT) ENGINE = MYISAM; +INSERT INTO t1 VALUES (1,1), (2,2), (3,3); +CREATE TABLE t2(pk INT PRIMARY KEY, i INT) ENGINE = MYISAM; +INSERT INTO t2 VALUES (1,1), (2,2), (3,3); +EXPLAIN +SELECT * +FROM +t1 +LEFT OUTER JOIN +(t2 INNER JOIN t_empty ON TRUE) +ON t1.pk=t2.pk +WHERE t2.pk <> 2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +SELECT * +FROM +t1 +LEFT OUTER JOIN +(t2 INNER JOIN t_empty ON TRUE) +ON t1.pk=t2.pk +WHERE t2.pk <> 2; +pk i pk i pk i +EXPLAIN +SELECT * +FROM +t1 +LEFT OUTER JOIN +(t2 CROSS JOIN t_empty) +ON t1.pk=t2.pk +WHERE t2.pk <> 2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +SELECT * +FROM +t1 +LEFT OUTER JOIN +(t2 CROSS JOIN t_empty) +ON t1.pk=t2.pk +WHERE t2.pk <> 2; +pk i pk i pk i +EXPLAIN +SELECT * +FROM +t1 +LEFT OUTER JOIN +(t2 INNER JOIN t_empty ON t_empty.i=t2.i) +ON t1.pk=t2.pk +WHERE t2.pk <> 2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +SELECT * +FROM +t1 +LEFT OUTER JOIN +(t2 INNER JOIN t_empty ON t_empty.i=t2.i) +ON t1.pk=t2.pk +WHERE t2.pk <> 2; +pk i pk i pk i +DROP TABLE t1,t2,t_empty; End of 5.1 tests # # Bug#54515: Crash in opt_range.cc::get_best_group_min_max on diff --git a/mysql-test/r/type_timestamp.result b/mysql-test/r/type_timestamp.result index 10a2b47ba02..d5769bfd59a 100644 --- a/mysql-test/r/type_timestamp.result +++ b/mysql-test/r/type_timestamp.result @@ -540,3 +540,32 @@ a 2010-03-05 11:08:02 DROP TABLE t1; End of Bug#50888 +# +# Bug59330: Incorrect result when comparing an aggregate +# function with TIMESTAMP +# +CREATE TABLE t1 (dt DATETIME, ts TIMESTAMP); +INSERT INTO t1 VALUES('2011-01-06 12:34:30', '2011-01-06 12:34:30'); +SELECT MAX(dt), MAX(ts) FROM t1; +MAX(dt) MAX(ts) +2011-01-06 12:34:30 2011-01-06 12:34:30 +SELECT MAX(ts) < '2010-01-01 00:00:00' FROM t1; +MAX(ts) < '2010-01-01 00:00:00' +0 +SELECT MAX(dt) < '2010-01-01 00:00:00' FROM t1; +MAX(dt) < '2010-01-01 00:00:00' +0 +SELECT MAX(ts) > '2010-01-01 00:00:00' FROM t1; +MAX(ts) > '2010-01-01 00:00:00' +1 +SELECT MAX(dt) > '2010-01-01 00:00:00' FROM t1; +MAX(dt) > '2010-01-01 00:00:00' +1 +SELECT MAX(ts) = '2011-01-06 12:34:30' FROM t1; +MAX(ts) = '2011-01-06 12:34:30' +1 +SELECT MAX(dt) = '2011-01-06 12:34:30' FROM t1; +MAX(dt) = '2011-01-06 12:34:30' +1 +DROP TABLE t1; +End of 5.5 tests diff --git a/mysql-test/r/view_grant.result b/mysql-test/r/view_grant.result index 1412df20012..9a0408bc174 100644 --- a/mysql-test/r/view_grant.result +++ b/mysql-test/r/view_grant.result @@ -1248,3 +1248,129 @@ Note 1449 The user specified as a definer ('unknown'@'unknown') does not exist LOCK TABLES v1 READ; ERROR HY000: The user specified as a definer ('unknown'@'unknown') does not exist DROP VIEW v1; +# +# Bug #58499 "DEFINER-security view selecting from INVOKER-security view +# access check wrong". +# +# Check that we correctly handle privileges for various combinations +# of INVOKER and DEFINER-security views using each other. +DROP DATABASE IF EXISTS mysqltest1; +CREATE DATABASE mysqltest1; +USE mysqltest1; +CREATE TABLE t1 (i INT); +CREATE TABLE t2 (j INT); +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (2); +# +# 1) DEFINER-security view uses INVOKER-security view (covers +# scenario originally described in the bug report). +CREATE SQL SECURITY INVOKER VIEW v1_uses_t1 AS SELECT * FROM t1; +CREATE SQL SECURITY INVOKER VIEW v1_uses_t2 AS SELECT * FROM t2; +CREATE USER 'mysqluser1'@'%'; +GRANT CREATE VIEW ON mysqltest1.* TO 'mysqluser1'@'%'; +GRANT SELECT ON t1 TO 'mysqluser1'@'%'; +# To be able create 'v2_uses_t2' we also need select on t2. +GRANT SELECT ON t2 TO 'mysqluser1'@'%'; +GRANT SELECT ON v1_uses_t1 TO 'mysqluser1'@'%'; +GRANT SELECT ON v1_uses_t2 TO 'mysqluser1'@'%'; +# +# Connection 'mysqluser1'. +CREATE SQL SECURITY DEFINER VIEW v2_uses_t1 AS SELECT * FROM v1_uses_t1; +CREATE SQL SECURITY DEFINER VIEW v2_uses_t2 AS SELECT * FROM v1_uses_t2; +# +# Connection 'default'. +CREATE USER 'mysqluser2'@'%'; +GRANT SELECT ON v2_uses_t1 TO 'mysqluser2'@'%'; +GRANT SELECT ON v2_uses_t2 TO 'mysqluser2'@'%'; +GRANT SELECT ON t2 TO 'mysqluser2'@'%'; +GRANT CREATE VIEW ON mysqltest1.* TO 'mysqluser2'@'%'; +# Make 'mysqluser1' unable to access t2. +REVOKE SELECT ON t2 FROM 'mysqluser1'@'%'; +# +# Connection 'mysqluser2'. +# The below statement should succeed thanks to suid nature of v2_uses_t1. +SELECT * FROM v2_uses_t1; +i +1 +# The below statement should fail due to suid nature of v2_uses_t2. +SELECT * FROM v2_uses_t2; +ERROR HY000: View 'mysqltest1.v2_uses_t2' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +# +# 2) INVOKER-security view uses INVOKER-security view. +# +# Connection 'default'. +DROP VIEW v2_uses_t1, v2_uses_t2; +CREATE SQL SECURITY INVOKER VIEW v2_uses_t1 AS SELECT * FROM v1_uses_t1; +CREATE SQL SECURITY INVOKER VIEW v2_uses_t2 AS SELECT * FROM v1_uses_t2; +GRANT SELECT ON v2_uses_t1 TO 'mysqluser1'@'%'; +GRANT SELECT ON v2_uses_t2 TO 'mysqluser1'@'%'; +GRANT SELECT ON v1_uses_t1 TO 'mysqluser2'@'%'; +GRANT SELECT ON v1_uses_t2 TO 'mysqluser2'@'%'; +# +# Connection 'mysqluser1'. +# For both versions of 'v2' 'mysqluser1' privileges should be used. +SELECT * FROM v2_uses_t1; +i +1 +SELECT * FROM v2_uses_t2; +ERROR HY000: View 'mysqltest1.v2_uses_t2' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +# +# Connection 'mysqluser2'. +# And now for both versions of 'v2' 'mysqluser2' privileges should +# be used. +SELECT * FROM v2_uses_t1; +ERROR HY000: View 'mysqltest1.v2_uses_t1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +SELECT * FROM v2_uses_t2; +j +2 +# +# 3) INVOKER-security view uses DEFINER-security view. +# +# Connection 'default'. +DROP VIEW v1_uses_t1, v1_uses_t2; +# To be able create 'v1_uses_t2' we also need select on t2. +GRANT SELECT ON t2 TO 'mysqluser1'@'%'; +# +# Connection 'mysqluser1'. +CREATE SQL SECURITY DEFINER VIEW v1_uses_t1 AS SELECT * FROM t1; +CREATE SQL SECURITY DEFINER VIEW v1_uses_t2 AS SELECT * FROM t2; +# +# Connection 'default'. +# Make 'mysqluser1' unable to access t2. +REVOKE SELECT ON t2 FROM 'mysqluser1'@'%'; +# +# Connection 'mysqluser2'. +# Due to suid nature of v1_uses_t1 and v1_uses_t2 the first +# select should succeed and the second select should fail. +SELECT * FROM v2_uses_t1; +i +1 +SELECT * FROM v2_uses_t2; +ERROR HY000: View 'mysqltest1.v2_uses_t2' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +# +# 4) DEFINER-security view uses DEFINER-security view. +# +# Connection 'default'. +DROP VIEW v2_uses_t1, v2_uses_t2; +# To be able create 'v2_uses_t2' we also need select on t2. +GRANT SELECT ON t2 TO 'mysqluser1'@'%'; +# +# Connection 'mysqluser2'. +CREATE SQL SECURITY DEFINER VIEW v2_uses_t1 AS SELECT * FROM v1_uses_t1; +CREATE SQL SECURITY DEFINER VIEW v2_uses_t2 AS SELECT * FROM v1_uses_t2; +# +# Connection 'default'. +# Make 'mysqluser1' unable to access t2. +REVOKE SELECT ON t2 FROM 'mysqluser1'@'%'; +# +# Connection 'mysqluser2'. +# Again privileges of creator of innermost views should apply. +SELECT * FROM v2_uses_t1; +i +1 +SELECT * FROM v2_uses_t2; +ERROR HY000: View 'mysqltest1.v2_uses_t2' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +USE test; +DROP DATABASE mysqltest1; +DROP USER 'mysqluser1'@'%'; +DROP USER 'mysqluser2'@'%'; diff --git a/mysql-test/suite/bugs/t/bug57108.test b/mysql-test/suite/bugs/t/bug57108.test index 1006a7b30f1..56acd7fe7bd 100644 --- a/mysql-test/suite/bugs/t/bug57108.test +++ b/mysql-test/suite/bugs/t/bug57108.test @@ -5,7 +5,7 @@ # switched directory after starting the server and am using a relative # --defaults-file. --replace_regex /\.dll/.so/ -eval INSTALL PLUGIN example SONAME $HA_EXAMPLE_SO; +eval INSTALL PLUGIN example SONAME '$EXAMPLE_PLUGIN'; --query_vertical SELECT @@global.connect_timeout AS connect_timeout, @@global.local_infile AS local_infile diff --git a/mysql-test/suite/perfschema/r/server_init.result b/mysql-test/suite/perfschema/r/server_init.result index b6f1d4828c3..26104197686 100644 --- a/mysql-test/suite/perfschema/r/server_init.result +++ b/mysql-test/suite/perfschema/r/server_init.result @@ -31,10 +31,6 @@ select count(name) from mutex_instances where name like "wait/synch/mutex/mysys/THR_LOCK_charset"; count(name) 1 -select count(name) from mutex_instances -where name like "wait/synch/mutex/mysys/THR_LOCK_time"; -count(name) -1 select count(name) from cond_instances where name like "wait/synch/cond/mysys/THR_COND_threads"; count(name) diff --git a/mysql-test/suite/perfschema/t/server_init.test b/mysql-test/suite/perfschema/t/server_init.test index 33eeeb7edb2..95d8be0e864 100644 --- a/mysql-test/suite/perfschema/t/server_init.test +++ b/mysql-test/suite/perfschema/t/server_init.test @@ -52,9 +52,6 @@ select count(name) from mutex_instances select count(name) from mutex_instances where name like "wait/synch/mutex/mysys/THR_LOCK_charset"; -select count(name) from mutex_instances - where name like "wait/synch/mutex/mysys/THR_LOCK_time"; - # There are no global rwlock in mysys # Verify that these global conditions have been properly initilized in mysys diff --git a/mysql-test/suite/rpl/r/rpl_heartbeat_basic.result b/mysql-test/suite/rpl/r/rpl_heartbeat_basic.result index ccef60d6323..ef901476784 100644 --- a/mysql-test/suite/rpl/r/rpl_heartbeat_basic.result +++ b/mysql-test/suite/rpl/r/rpl_heartbeat_basic.result @@ -16,7 +16,7 @@ RESET SLAVE; *** Reset slave affect *** SET @@global.slave_net_timeout=30; -CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD=5; +CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_CONNECT_RETRY=20, MASTER_HEARTBEAT_PERIOD=5; RESET SLAVE; SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period'; Variable_name Value @@ -24,7 +24,7 @@ Slave_heartbeat_period 15.000 *** Default value if slave_net_timeout changed *** SET @@global.slave_net_timeout=50; -CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root'; +CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_CONNECT_RETRY=20; SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period'; Variable_name Value Slave_heartbeat_period 25.000 @@ -39,14 +39,14 @@ SET @@global.slave_net_timeout=@restore_slave_net_timeout; RESET SLAVE; *** Warning if updated slave_heartbeat_timeout > slave_net_timeout *** -CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD=SLAVE_NET_TIMEOUT; +CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_CONNECT_RETRY=20, MASTER_HEARTBEAT_PERIOD=SLAVE_NET_TIMEOUT; Warnings: Warning 1704 The requested value for the heartbeat period exceeds the value of `slave_net_timeout' seconds. A sensible value for the period should be less than the timeout. RESET SLAVE; *** CHANGE MASTER statement only updates slave_heartbeat_period *** SET @@global.slave_net_timeout=20; -CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD=5; +CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_CONNECT_RETRY=20, MASTER_HEARTBEAT_PERIOD=5; SHOW VARIABLES LIKE 'slave_net_timeout'; Variable_name Value slave_net_timeout 20 @@ -67,7 +67,7 @@ RESET SLAVE; SET @@global.slave_net_timeout=500; SET @@global.slave_net_timeout=200; RESET SLAVE; -CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root'; +CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_CONNECT_RETRY=20; include/start_slave.inc SHOW VARIABLES LIKE 'slave_net_timeout'; Variable_name Value @@ -82,7 +82,7 @@ SET @@global.slave_net_timeout=@restore_slave_net_timeout; *** Start/stop slave *** SET @@global.slave_net_timeout=100; -CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD=20; +CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_CONNECT_RETRY=20, MASTER_HEARTBEAT_PERIOD=20; include/start_slave.inc SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period'; Variable_name Value @@ -94,7 +94,7 @@ Slave_heartbeat_period 20.000 *** Reload slave *** SET @@global.slave_net_timeout=50; -CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD=30; +CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_CONNECT_RETRY=20, MASTER_HEARTBEAT_PERIOD=30; include/rpl_restart_server.inc [server_number=2] SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period'; Variable_name Value @@ -102,7 +102,7 @@ Slave_heartbeat_period 30.000 SET @restore_slave_net_timeout=@@global.slave_net_timeout; *** Disable heartbeat *** -CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD=0; +CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_CONNECT_RETRY=20, MASTER_HEARTBEAT_PERIOD=0; SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period'; Variable_name Value Slave_heartbeat_period 0.000 @@ -129,12 +129,12 @@ Result 0 *** Min slave_heartbeat_timeout *** -CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD=0.001; +CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_CONNECT_RETRY=20, MASTER_HEARTBEAT_PERIOD=0.001; SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period'; Variable_name Value Slave_heartbeat_period 0.001 RESET SLAVE; -CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD=0.0009; +CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_CONNECT_RETRY=20, MASTER_HEARTBEAT_PERIOD=0.0009; Warnings: Warning 1703 The requested value for the heartbeat period is less than 1 millisecond. The value is reset to 0, meaning that heartbeating will effectively be disabled. SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period'; @@ -143,36 +143,36 @@ Slave_heartbeat_period 0.000 RESET SLAVE; *** Max slave_heartbeat_timeout *** -CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD=4294967; +CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_CONNECT_RETRY=20, MASTER_HEARTBEAT_PERIOD=4294967; Warnings: Warning 1704 The requested value for the heartbeat period exceeds the value of `slave_net_timeout' seconds. A sensible value for the period should be less than the timeout. SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period'; Variable_name Value Slave_heartbeat_period 4294967.000 RESET SLAVE; -CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD=4294968; +CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_CONNECT_RETRY=20, MASTER_HEARTBEAT_PERIOD=4294968; ERROR HY000: The requested value for the heartbeat period is either negative or exceeds the maximum allowed (4294967 seconds). RESET SLAVE; -CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD=8589935; +CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_CONNECT_RETRY=20, MASTER_HEARTBEAT_PERIOD=8589935; ERROR HY000: The requested value for the heartbeat period is either negative or exceeds the maximum allowed (4294967 seconds). RESET SLAVE; -CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD=4294967296; +CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_CONNECT_RETRY=20, MASTER_HEARTBEAT_PERIOD=4294967296; ERROR HY000: The requested value for the heartbeat period is either negative or exceeds the maximum allowed (4294967 seconds). RESET SLAVE; *** Misc incorrect values *** -CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD='-1'; +CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_CONNECT_RETRY=20, MASTER_HEARTBEAT_PERIOD='-1'; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''-1'' at line 1 RESET SLAVE; -CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD='123abc'; +CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_CONNECT_RETRY=20, MASTER_HEARTBEAT_PERIOD='123abc'; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''123abc'' at line 1 RESET SLAVE; -CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD=''; +CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_CONNECT_RETRY=20, MASTER_HEARTBEAT_PERIOD=''; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '''' at line 1 RESET SLAVE; *** Running slave *** -CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD=0.1; +CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_CONNECT_RETRY=20, MASTER_HEARTBEAT_PERIOD=0.1; include/start_slave.inc Heartbeat event received @@ -218,7 +218,7 @@ BEGIN UPDATE test.t1 SET a = a + 1 WHERE a < 10; END| RESET SLAVE; -CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD=5; +CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_CONNECT_RETRY=20, MASTER_HEARTBEAT_PERIOD=5; include/start_slave.inc SET @@global.event_scheduler=1; Number of received heartbeat events: 0 @@ -231,7 +231,7 @@ RESET SLAVE; DROP TABLE t1; DROP TABLE t1; RESET MASTER; -CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD=0.5; +CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_CONNECT_RETRY=20, MASTER_HEARTBEAT_PERIOD=0.5; include/start_slave.inc Heartbeat events are received while rotation of relay logs (1 means 'yes'): 1 @@ -240,7 +240,7 @@ SET @@global.slave_compressed_protocol=1; include/stop_slave.inc RESET SLAVE; SET @@global.slave_compressed_protocol=1; -CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD=0.1; +CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_CONNECT_RETRY=20, MASTER_HEARTBEAT_PERIOD=0.1; include/start_slave.inc Heartbeat event received SET @@global.slave_compressed_protocol=0; @@ -249,7 +249,7 @@ SET @@global.slave_compressed_protocol=0; *** Reset master *** STOP SLAVE; RESET SLAVE; -CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD=0.1; +CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_CONNECT_RETRY=20, MASTER_HEARTBEAT_PERIOD=0.1; include/start_slave.inc RESET MASTER; Heartbeat events are received after reset of master (1 means 'yes'): 1 @@ -257,7 +257,7 @@ Heartbeat events are received after reset of master (1 means 'yes'): 1 *** Reload master *** STOP SLAVE; RESET SLAVE; -CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD=0.1, MASTER_CONNECT_RETRY = 5; +CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=MASTER_PORT, MASTER_USER='root', MASTER_CONNECT_RETRY=20, MASTER_HEARTBEAT_PERIOD=0.1; include/start_slave.inc Heartbeat event received include/rpl_restart_server.inc [server_number=1] diff --git a/mysql-test/suite/rpl/t/rpl_heartbeat_basic.test b/mysql-test/suite/rpl/t/rpl_heartbeat_basic.test index 94667485dfe..a89a1847bc6 100644 --- a/mysql-test/suite/rpl/t/rpl_heartbeat_basic.test +++ b/mysql-test/suite/rpl/t/rpl_heartbeat_basic.test @@ -18,6 +18,9 @@ --source include/have_binlog_format_mixed.inc --echo +# Set number of retries to connect to master +let $connect_retry= 20; + --echo *** Preparing *** --connection slave --source include/stop_slave.inc @@ -57,7 +60,7 @@ RESET SLAVE; SET @@global.slave_net_timeout=30; --enable_warnings --replace_result $MASTER_MYPORT MASTER_PORT -eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD=5; +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=5; RESET SLAVE; SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period'; --echo @@ -68,7 +71,7 @@ SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period'; SET @@global.slave_net_timeout=50; --enable_warnings --replace_result $MASTER_MYPORT MASTER_PORT -eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root'; +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry; SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period'; SET @@global.slave_net_timeout=@restore_slave_net_timeout; RESET SLAVE; @@ -88,7 +91,7 @@ RESET SLAVE; let $slave_net_timeout= query_get_value(SHOW VARIABLES LIKE 'slave_net_timeout', Value, 1); inc $slave_net_timeout; --replace_result $MASTER_MYPORT MASTER_PORT $slave_net_timeout SLAVE_NET_TIMEOUT -eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD=$slave_net_timeout; +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=$slave_net_timeout; RESET SLAVE; --echo @@ -98,7 +101,7 @@ RESET SLAVE; SET @@global.slave_net_timeout=20; --enable_warnings --replace_result $MASTER_MYPORT MASTER_PORT -eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD=5; +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=5; SHOW VARIABLES LIKE 'slave_net_timeout'; SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period'; SET @@global.slave_net_timeout=2*@@global.slave_net_timeout; @@ -118,7 +121,7 @@ SET @@global.slave_net_timeout=500; SET @@global.slave_net_timeout=200; RESET SLAVE; --replace_result $MASTER_MYPORT MASTER_PORT -eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root'; +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry; --source include/start_slave.inc --connection master --sync_slave_with_master @@ -138,7 +141,7 @@ SET @@global.slave_net_timeout=@restore_slave_net_timeout; SET @@global.slave_net_timeout=100; --enable_warnings --replace_result $MASTER_MYPORT MASTER_PORT -eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD=20; +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=20; --source include/start_slave.inc --connection master --sync_slave_with_master @@ -154,7 +157,7 @@ SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period'; SET @@global.slave_net_timeout=50; --enable_warnings --replace_result $MASTER_MYPORT MASTER_PORT -eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD=30; +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=30; --let $rpl_server_number= 2 --source include/rpl_restart_server.inc SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period'; @@ -164,7 +167,7 @@ SET @restore_slave_net_timeout=@@global.slave_net_timeout; # Disable heartbeat --echo *** Disable heartbeat *** --replace_result $MASTER_MYPORT MASTER_PORT -eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD=0; +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=0; SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period'; SHOW STATUS LIKE 'slave_received_heartbeats'; --source include/start_slave.inc @@ -188,48 +191,48 @@ let $slave_heartbeat_timeout= query_get_value(SHOW GLOBAL STATUS LIKE 'slave_hea --echo *** Min slave_heartbeat_timeout *** --replace_result $MASTER_MYPORT MASTER_PORT -eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD=0.001; +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=0.001; SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period'; RESET SLAVE; --replace_result $MASTER_MYPORT MASTER_PORT -eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD=0.0009; +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=0.0009; SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period'; RESET SLAVE; --echo --echo *** Max slave_heartbeat_timeout *** --replace_result $MASTER_MYPORT MASTER_PORT -eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD=4294967; +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=4294967; SHOW GLOBAL STATUS LIKE 'slave_heartbeat_period'; RESET SLAVE; --replace_result $MASTER_MYPORT MASTER_PORT --error ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE -eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD=4294968; +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=4294968; RESET SLAVE; # Check double size of max allowed value for master_heartbeat_period --replace_result $MASTER_MYPORT MASTER_PORT --error ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE -eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD=8589935; +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=8589935; RESET SLAVE; # Check 2^32 --replace_result $MASTER_MYPORT MASTER_PORT --error ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE -eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD=4294967296; +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=4294967296; RESET SLAVE; --echo --echo *** Misc incorrect values *** --replace_result $MASTER_MYPORT MASTER_PORT --error ER_PARSE_ERROR -eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD='-1'; +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD='-1'; RESET SLAVE; --replace_result $MASTER_MYPORT MASTER_PORT --error ER_PARSE_ERROR -eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD='123abc'; +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD='123abc'; RESET SLAVE; --replace_result $MASTER_MYPORT MASTER_PORT --error ER_PARSE_ERROR -eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD=''; +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=''; RESET SLAVE; --echo @@ -240,7 +243,7 @@ RESET SLAVE; # Check received heartbeat events for running slave --echo *** Running slave *** --replace_result $MASTER_MYPORT MASTER_PORT -eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD=0.1; +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=0.1; --source include/start_slave.inc --connection master --sync_slave_with_master @@ -342,7 +345,7 @@ DELIMITER ;| --connection slave RESET SLAVE; --replace_result $MASTER_MYPORT MASTER_PORT -eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD=5; +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=5; --source include/start_slave.inc --connection master # Enable scheduler @@ -374,7 +377,7 @@ DROP TABLE t1; RESET MASTER; --connection slave --replace_result $MASTER_MYPORT MASTER_PORT -eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD=0.5; +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=0.5; let $slave_param_comparison= =; --source include/start_slave.inc let $rcvd_heartbeats_before= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1); @@ -401,7 +404,7 @@ SET @@global.slave_compressed_protocol=1; RESET SLAVE; SET @@global.slave_compressed_protocol=1; --replace_result $MASTER_MYPORT MASTER_PORT -eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD=0.1; +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=0.1; --source include/start_slave.inc let $status_var_value= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1); let $status_var= slave_received_heartbeats; @@ -420,7 +423,7 @@ SET @@global.slave_compressed_protocol=0; STOP SLAVE; RESET SLAVE; --replace_result $MASTER_MYPORT MASTER_PORT -eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD=0.1; +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=0.1; --source include/start_slave.inc let $rcvd_heartbeats_before= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1); --connection master @@ -439,7 +442,7 @@ let $result= query_get_value(SELECT ($rcvd_heartbeats_after - $rcvd_heartbeats_b STOP SLAVE; RESET SLAVE; --replace_result $MASTER_MYPORT MASTER_PORT -eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD=0.1, MASTER_CONNECT_RETRY = 5; +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=0.1; --source include/start_slave.inc # Wait until slave_received_heartbeats will be incremented let $status_var_value= query_get_value(SHOW STATUS LIKE 'slave_received_heartbeats', Value, 1); @@ -474,7 +477,7 @@ let $status_var_comparsion= >; #let $slave_binlog= query_get_value(SHOW MASTER STATUS, File, 1); --connection master #--replace_result $SLAVE_MYPORT SLAVE_PORT $slave_binlog SLAVE_BINLOG -#eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$SLAVE_MYPORT, MASTER_USER='root', MASTER_HEARTBEAT_PERIOD=1, MASTER_LOG_FILE='$slave_binlog'; +#eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$SLAVE_MYPORT, MASTER_USER='root', MASTER_CONNECT_RETRY=$connect_retry, MASTER_HEARTBEAT_PERIOD=1, MASTER_LOG_FILE='$slave_binlog'; --source include/start_slave.inc # Insert data on master and on slave and make sure that it replicated for both directions diff --git a/mysql-test/t/bug46261.test b/mysql-test/t/bug46261.test index 67bdc995850..e0eae9b86fb 100644 --- a/mysql-test/t/bug46261.test +++ b/mysql-test/t/bug46261.test @@ -7,7 +7,7 @@ --replace_regex /\.dll/.so/ --error ER_OPTION_PREVENTS_STATEMENT -eval INSTALL PLUGIN example SONAME $HA_EXAMPLE_SO; +eval INSTALL PLUGIN example SONAME '$EXAMPLE_PLUGIN'; --replace_regex /\.dll/.so/ --error ER_OPTION_PREVENTS_STATEMENT diff --git a/mysql-test/t/fulltext_plugin.test b/mysql-test/t/fulltext_plugin.test index 25e4302ef0d..b591a7949e5 100644 --- a/mysql-test/t/fulltext_plugin.test +++ b/mysql-test/t/fulltext_plugin.test @@ -4,7 +4,7 @@ # BUG#39746 - Debug flag breaks struct definition (server crash) # --replace_regex /\.dll/.so/ -eval INSTALL PLUGIN simple_parser SONAME $MYPLUGLIB_SO; +eval INSTALL PLUGIN simple_parser SONAME '$SIMPLE_PARSER'; CREATE TABLE t1(a TEXT, b TEXT, FULLTEXT(a) WITH PARSER simple_parser); ALTER TABLE t1 ADD FULLTEXT(b) WITH PARSER simple_parser; DROP TABLE t1; diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index aff99d7e303..9a9a8110a74 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -1370,6 +1370,17 @@ DROP TABLE t1; SELECT '1' IN ('1', SUBSTRING(-9223372036854775809, 1)); SELECT CONVERT(('' IN (REVERSE(CAST(('') AS DECIMAL)), '')), CHAR(3)); +--echo # +--echo # Bug#58165: "my_empty_string" gets modified and causes LOAD DATA to fail +--echo # and other crashes +--echo # +CREATE TABLE t1 ( a TEXT ); +SELECT 'aaaaaaaaaaaaaa' INTO OUTFILE 'bug58165.txt'; +SELECT insert( substring_index( 'a', 'a', 'b' ), 1, 0, 'x' ); +LOAD DATA INFILE 'bug58165.txt' INTO TABLE t1; +SELECT * FROM t1; +DROP TABLE t1; + --echo End of 5.1 tests --echo Start of 5.4 tests diff --git a/mysql-test/t/gis.test b/mysql-test/t/gis.test index 4aad3f80b68..6c0fdda1cea 100644 --- a/mysql-test/t/gis.test +++ b/mysql-test/t/gis.test @@ -747,6 +747,16 @@ SET @a=0x00000000030000000000000000000000000000000000144000000000000014400000000 SET @a=POLYFROMWKB(@a); +# +# Bug #57321 crashes and valgrind errors from spatial types +# + +create table t1(a polygon NOT NULL)engine=myisam; +insert into t1 values (geomfromtext("point(0 1)")); +insert into t1 values (geomfromtext("point(1 0)")); +select * from (select polygon(t1.a) as p from t1 order by t1.a) d; +drop table t1; + --echo End of 5.1 tests # diff --git a/mysql-test/t/join_outer.test b/mysql-test/t/join_outer.test index 3251ff292b6..72d27d3571a 100644 --- a/mysql-test/t/join_outer.test +++ b/mysql-test/t/join_outer.test @@ -1010,4 +1010,86 @@ GROUP BY t2.f1, t2.f2; DROP TABLE t1,t2; +--echo # +--echo # Bug#57034 incorrect OUTER JOIN result when joined on unique key +--echo # + +CREATE TABLE t1 (pk INT PRIMARY KEY, + col_int INT, + col_int_unique INT UNIQUE KEY); +INSERT INTO t1 VALUES (1,NULL,2), (2,0,0); + +CREATE TABLE t2 (pk INT PRIMARY KEY, + col_int INT, + col_int_unique INT UNIQUE KEY); +INSERT INTO t2 VALUES (1,0,1), (2,0,2); + +EXPLAIN +SELECT * FROM t1 LEFT JOIN t2 + ON t1.col_int_unique = t2.col_int_unique AND t1.col_int = t2.col_int + WHERE t1.pk=1; + +SELECT * FROM t1 LEFT JOIN t2 + ON t1.col_int_unique = t2.col_int_unique AND t1.col_int = t2.col_int + WHERE t1.pk=1; + +DROP TABLE t1,t2; + +--echo # +--echo # Bug#48046 Server incorrectly processing JOINs on NULL values +--echo # + +# bug#48046 is a duplicate of bug#57034 + +CREATE TABLE `BB` ( + `pk` int(11) NOT NULL AUTO_INCREMENT, + `time_key` time DEFAULT NULL, + `varchar_key` varchar(1) DEFAULT NULL, + `varchar_nokey` varchar(1) DEFAULT NULL, + PRIMARY KEY (`pk`), + KEY `time_key` (`time_key`), + KEY `varchar_key` (`varchar_key`) +) ENGINE=MyISAM AUTO_INCREMENT=11 DEFAULT CHARSET=latin1; + +INSERT INTO `BB` VALUES (10,'18:27:58',NULL,NULL); + +SELECT table1.time_key AS field1, table2.pk +FROM BB table1 LEFT JOIN BB table2 + ON table2.varchar_nokey = table1.varchar_key + HAVING field1; + +DROP TABLE BB; + +--echo # +--echo # Bug#49600 Server incorrectly processing RIGHT JOIN with +--echo # constant WHERE clause and no index +--echo # + +# bug#49600 is a duplicate of bug#57034 + +CREATE TABLE `BB` ( + `col_datetime_key` datetime DEFAULT NULL, + `col_varchar_key` varchar(1) DEFAULT NULL, + `col_varchar_nokey` varchar(1) DEFAULT NULL, + KEY `col_datetime_key` (`col_datetime_key`), + KEY `col_varchar_key` (`col_varchar_key`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + +INSERT INTO `BB` VALUES ('1900-01-01 00:00:00',NULL,NULL); + +SELECT table1.col_datetime_key +FROM BB table1 RIGHT JOIN BB table2 + ON table2 .col_varchar_nokey = table1.col_varchar_key + WHERE 7; + +# Disable keys, and we get incorrect result for the same query +ALTER TABLE BB DISABLE KEYS; + +SELECT table1.col_datetime_key +FROM BB table1 RIGHT JOIN BB table2 + ON table2 .col_varchar_nokey = table1.col_varchar_key + WHERE 7; + +DROP TABLE BB; + --echo End of 5.1 tests diff --git a/mysql-test/t/mysqlbinlog_row_big.test b/mysql-test/t/mysqlbinlog_row_big.test index 75f3b90269f..ffd1b79af34 100644 --- a/mysql-test/t/mysqlbinlog_row_big.test +++ b/mysql-test/t/mysqlbinlog_row_big.test @@ -79,8 +79,8 @@ eval CREATE TABLE t1 ( --echo # Insert some big rows. --echo # ---echo 256MB -INSERT INTO t1 VALUES (REPEAT('ManyMegaByteBlck', 16777216)); +--echo 64MB +INSERT INTO t1 VALUES (REPEAT('ManyMegaByteBlck', 4194304)); --echo 32MB INSERT INTO t1 VALUES (REPEAT('ManyMegaByteBlck', 2097152)); diff --git a/mysql-test/t/mysqltest.test b/mysql-test/t/mysqltest.test index 7108b9f9878..9ff92496653 100644 --- a/mysql-test/t/mysqltest.test +++ b/mysql-test/t/mysqltest.test @@ -859,6 +859,12 @@ insert into t1 values ('`select 42`'); let $a= `select * from t1`; # This should output `select 42`, not evaluate it again to 42 echo $a; +insert into t1 values ('$dollar'); +# These should also output the string without evaluating it. +let $a= query_get_value(select * from t1 order by a, a, 1); +echo $a; +let $a= query_get_value(select * from t1 order by a, a, 2); +echo $a; drop table t1; --error 1 diff --git a/mysql-test/t/plugin.test b/mysql-test/t/plugin.test index 0bf86b47dd7..117eaf1e19b 100644 --- a/mysql-test/t/plugin.test +++ b/mysql-test/t/plugin.test @@ -5,15 +5,15 @@ CREATE TABLE t1(a int) ENGINE=EXAMPLE; DROP TABLE t1; --replace_regex /\.dll/.so/ -eval INSTALL PLUGIN example SONAME $HA_EXAMPLE_SO; +eval INSTALL PLUGIN example SONAME '$EXAMPLE_PLUGIN'; --replace_regex /\.dll/.so/ --error 1125 -eval INSTALL PLUGIN EXAMPLE SONAME $HA_EXAMPLE_SO; +eval INSTALL PLUGIN EXAMPLE SONAME '$EXAMPLE_PLUGIN'; UNINSTALL PLUGIN example; --replace_regex /\.dll/.so/ -eval INSTALL PLUGIN example SONAME $HA_EXAMPLE_SO; +eval INSTALL PLUGIN example SONAME '$EXAMPLE_PLUGIN'; CREATE TABLE t1(a int) ENGINE=EXAMPLE; @@ -41,7 +41,7 @@ UNINSTALL PLUGIN non_exist; --echo # to impossible int val --echo # --replace_regex /\.dll/.so/ -eval INSTALL PLUGIN example SONAME $HA_EXAMPLE_SO; +eval INSTALL PLUGIN example SONAME '$EXAMPLE_PLUGIN'; SET GLOBAL example_enum_var= e1; SET GLOBAL example_enum_var= e2; @@ -56,7 +56,7 @@ UNINSTALL PLUGIN example; # Bug #32757 hang with sql_mode set when setting some global variables # --replace_regex /\.dll/.so/ -eval INSTALL PLUGIN example SONAME $HA_EXAMPLE_SO; +eval INSTALL PLUGIN example SONAME '$EXAMPLE_PLUGIN'; select @@session.sql_mode into @old_sql_mode; diff --git a/mysql-test/t/plugin_auth_qa_2-master.opt b/mysql-test/t/plugin_auth_qa_2-master.opt index c29153ac95b..354907b9366 100644 --- a/mysql-test/t/plugin_auth_qa_2-master.opt +++ b/mysql-test/t/plugin_auth_qa_2-master.opt @@ -1,2 +1,2 @@ -$PLUGIN_AUTH_OPT -$PLUGIN_AUTH_INTERFACE +$PLUGIN_AUTH_INTERFACE_OPT +$PLUGIN_AUTH_INTERFACE_LOAD diff --git a/mysql-test/t/plugin_auth_qa_3-master.opt b/mysql-test/t/plugin_auth_qa_3-master.opt index 5cc2af0a358..e1754862a4d 100644 --- a/mysql-test/t/plugin_auth_qa_3-master.opt +++ b/mysql-test/t/plugin_auth_qa_3-master.opt @@ -1,2 +1,2 @@ -$PLUGIN_AUTH_OPT -$PLUGIN_AUTH_SERVER +$PLUGIN_AUTH_SERVER_OPT +$PLUGIN_AUTH_SERVER_LOAD diff --git a/mysql-test/t/plugin_not_embedded.test b/mysql-test/t/plugin_not_embedded.test index 40024efcaad..a2b7b8a0fe4 100644 --- a/mysql-test/t/plugin_not_embedded.test +++ b/mysql-test/t/plugin_not_embedded.test @@ -8,7 +8,7 @@ GRANT INSERT ON mysql.plugin TO bug51770@localhost; connect(con1,localhost,bug51770,,); --replace_regex /\.dll/.so/ -eval INSTALL PLUGIN example SONAME $HA_EXAMPLE_SO; +eval INSTALL PLUGIN example SONAME '$EXAMPLE_PLUGIN'; --error ER_TABLEACCESS_DENIED_ERROR UNINSTALL PLUGIN example; connection default; @@ -25,7 +25,7 @@ DROP USER bug51770@localhost; # The bug consisted of not recognizing / on Windows, so checking / on # all platforms should cover this case. -let $path = `select CONCAT_WS('/', '..', $HA_EXAMPLE_SO)`; +let $path = `select CONCAT_WS('/', '..', '$EXAMPLE_PLUGIN')`; --replace_regex /\.dll/.so/ --error ER_UDF_NO_PATHS eval INSTALL PLUGIN example SONAME '$path'; diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index 3ed7213e8d7..043b03e4686 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -4123,6 +4123,76 @@ SELECT 1 FROM t1 ORDER BY a COLLATE latin1_german2_ci; DROP TABLE t1; + +--echo # +--echo # Bug #58422: Incorrect result when OUTER JOIN'ing +--echo # with an empty table +--echo # + +CREATE TABLE t_empty(pk INT PRIMARY KEY, i INT) ENGINE = MYISAM; +CREATE TABLE t1(pk INT PRIMARY KEY, i INT) ENGINE = MYISAM; +INSERT INTO t1 VALUES (1,1), (2,2), (3,3); +CREATE TABLE t2(pk INT PRIMARY KEY, i INT) ENGINE = MYISAM; +INSERT INTO t2 VALUES (1,1), (2,2), (3,3); + +EXPLAIN +SELECT * + FROM + t1 + LEFT OUTER JOIN + (t2 INNER JOIN t_empty ON TRUE) + ON t1.pk=t2.pk + WHERE t2.pk <> 2; + +SELECT * + FROM + t1 + LEFT OUTER JOIN + (t2 INNER JOIN t_empty ON TRUE) + ON t1.pk=t2.pk + WHERE t2.pk <> 2; + + +EXPLAIN +SELECT * + FROM + t1 + LEFT OUTER JOIN + (t2 CROSS JOIN t_empty) + ON t1.pk=t2.pk + WHERE t2.pk <> 2; + +SELECT * + FROM + t1 + LEFT OUTER JOIN + (t2 CROSS JOIN t_empty) + ON t1.pk=t2.pk + WHERE t2.pk <> 2; + + +EXPLAIN +SELECT * + FROM + t1 + LEFT OUTER JOIN + (t2 INNER JOIN t_empty ON t_empty.i=t2.i) + ON t1.pk=t2.pk + WHERE t2.pk <> 2; + +SELECT * + FROM + t1 + LEFT OUTER JOIN + (t2 INNER JOIN t_empty ON t_empty.i=t2.i) + ON t1.pk=t2.pk + WHERE t2.pk <> 2; + + + +DROP TABLE t1,t2,t_empty; + + --echo End of 5.1 tests --echo # diff --git a/mysql-test/t/type_timestamp.test b/mysql-test/t/type_timestamp.test index dfac6f93b7d..76423b11b99 100644 --- a/mysql-test/t/type_timestamp.test +++ b/mysql-test/t/type_timestamp.test @@ -377,3 +377,21 @@ SELECT a FROM t1; DROP TABLE t1; --echo End of Bug#50888 + +--echo # +--echo # Bug59330: Incorrect result when comparing an aggregate +--echo # function with TIMESTAMP +--echo # +CREATE TABLE t1 (dt DATETIME, ts TIMESTAMP); +INSERT INTO t1 VALUES('2011-01-06 12:34:30', '2011-01-06 12:34:30'); +SELECT MAX(dt), MAX(ts) FROM t1; +SELECT MAX(ts) < '2010-01-01 00:00:00' FROM t1; +SELECT MAX(dt) < '2010-01-01 00:00:00' FROM t1; +SELECT MAX(ts) > '2010-01-01 00:00:00' FROM t1; +SELECT MAX(dt) > '2010-01-01 00:00:00' FROM t1; +SELECT MAX(ts) = '2011-01-06 12:34:30' FROM t1; +SELECT MAX(dt) = '2011-01-06 12:34:30' FROM t1; +DROP TABLE t1; + +--echo End of 5.5 tests + diff --git a/mysql-test/t/view_grant.test b/mysql-test/t/view_grant.test index 3ccef94d7ea..5896e25feda 100644 --- a/mysql-test/t/view_grant.test +++ b/mysql-test/t/view_grant.test @@ -1503,8 +1503,6 @@ SHOW CREATE VIEW v1; DROP TABLE t1; DROP VIEW v1; -# Wait till we reached the initial number of concurrent sessions ---source include/wait_until_count_sessions.inc --echo # --echo # Bug #46019: ERROR 1356 When selecting from within another @@ -1546,3 +1544,145 @@ CREATE DEFINER=`unknown`@`unknown` SQL SECURITY DEFINER VIEW v1 AS SELECT 1; --error ER_NO_SUCH_USER LOCK TABLES v1 READ; DROP VIEW v1; + + +--echo # +--echo # Bug #58499 "DEFINER-security view selecting from INVOKER-security view +--echo # access check wrong". +--echo # +--echo # Check that we correctly handle privileges for various combinations +--echo # of INVOKER and DEFINER-security views using each other. +--disable_warnings +DROP DATABASE IF EXISTS mysqltest1; +--enable_warnings +CREATE DATABASE mysqltest1; +USE mysqltest1; +CREATE TABLE t1 (i INT); +CREATE TABLE t2 (j INT); +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (2); +--echo # +--echo # 1) DEFINER-security view uses INVOKER-security view (covers +--echo # scenario originally described in the bug report). +CREATE SQL SECURITY INVOKER VIEW v1_uses_t1 AS SELECT * FROM t1; +CREATE SQL SECURITY INVOKER VIEW v1_uses_t2 AS SELECT * FROM t2; +CREATE USER 'mysqluser1'@'%'; +GRANT CREATE VIEW ON mysqltest1.* TO 'mysqluser1'@'%'; +GRANT SELECT ON t1 TO 'mysqluser1'@'%'; +--echo # To be able create 'v2_uses_t2' we also need select on t2. +GRANT SELECT ON t2 TO 'mysqluser1'@'%'; +GRANT SELECT ON v1_uses_t1 TO 'mysqluser1'@'%'; +GRANT SELECT ON v1_uses_t2 TO 'mysqluser1'@'%'; +--echo # +--echo # Connection 'mysqluser1'. +--connect (mysqluser1, localhost, mysqluser1,,mysqltest1) +CREATE SQL SECURITY DEFINER VIEW v2_uses_t1 AS SELECT * FROM v1_uses_t1; +CREATE SQL SECURITY DEFINER VIEW v2_uses_t2 AS SELECT * FROM v1_uses_t2; +--echo # +--echo # Connection 'default'. +--connection default +CREATE USER 'mysqluser2'@'%'; +GRANT SELECT ON v2_uses_t1 TO 'mysqluser2'@'%'; +GRANT SELECT ON v2_uses_t2 TO 'mysqluser2'@'%'; +GRANT SELECT ON t2 TO 'mysqluser2'@'%'; +GRANT CREATE VIEW ON mysqltest1.* TO 'mysqluser2'@'%'; +--echo # Make 'mysqluser1' unable to access t2. +REVOKE SELECT ON t2 FROM 'mysqluser1'@'%'; +--echo # +--echo # Connection 'mysqluser2'. +--connect (mysqluser2, localhost, mysqluser2,,mysqltest1) +--echo # The below statement should succeed thanks to suid nature of v2_uses_t1. +SELECT * FROM v2_uses_t1; +--echo # The below statement should fail due to suid nature of v2_uses_t2. +--error ER_VIEW_INVALID +SELECT * FROM v2_uses_t2; +--echo # +--echo # 2) INVOKER-security view uses INVOKER-security view. +--echo # +--echo # Connection 'default'. +--connection default +DROP VIEW v2_uses_t1, v2_uses_t2; +CREATE SQL SECURITY INVOKER VIEW v2_uses_t1 AS SELECT * FROM v1_uses_t1; +CREATE SQL SECURITY INVOKER VIEW v2_uses_t2 AS SELECT * FROM v1_uses_t2; +GRANT SELECT ON v2_uses_t1 TO 'mysqluser1'@'%'; +GRANT SELECT ON v2_uses_t2 TO 'mysqluser1'@'%'; +GRANT SELECT ON v1_uses_t1 TO 'mysqluser2'@'%'; +GRANT SELECT ON v1_uses_t2 TO 'mysqluser2'@'%'; +--echo # +--echo # Connection 'mysqluser1'. +--connection mysqluser1 +--echo # For both versions of 'v2' 'mysqluser1' privileges should be used. +SELECT * FROM v2_uses_t1; +--error ER_VIEW_INVALID +SELECT * FROM v2_uses_t2; +--echo # +--echo # Connection 'mysqluser2'. +--connection mysqluser2 +--echo # And now for both versions of 'v2' 'mysqluser2' privileges should +--echo # be used. +--error ER_VIEW_INVALID +SELECT * FROM v2_uses_t1; +SELECT * FROM v2_uses_t2; +--echo # +--echo # 3) INVOKER-security view uses DEFINER-security view. +--echo # +--echo # Connection 'default'. +--connection default +DROP VIEW v1_uses_t1, v1_uses_t2; +--echo # To be able create 'v1_uses_t2' we also need select on t2. +GRANT SELECT ON t2 TO 'mysqluser1'@'%'; +--echo # +--echo # Connection 'mysqluser1'. +--connection mysqluser1 +CREATE SQL SECURITY DEFINER VIEW v1_uses_t1 AS SELECT * FROM t1; +CREATE SQL SECURITY DEFINER VIEW v1_uses_t2 AS SELECT * FROM t2; +--echo # +--echo # Connection 'default'. +--connection default +--echo # Make 'mysqluser1' unable to access t2. +REVOKE SELECT ON t2 FROM 'mysqluser1'@'%'; +--echo # +--echo # Connection 'mysqluser2'. +--connection mysqluser2 +--echo # Due to suid nature of v1_uses_t1 and v1_uses_t2 the first +--echo # select should succeed and the second select should fail. +SELECT * FROM v2_uses_t1; +--error ER_VIEW_INVALID +SELECT * FROM v2_uses_t2; +--echo # +--echo # 4) DEFINER-security view uses DEFINER-security view. +--echo # +--echo # Connection 'default'. +--connection default +DROP VIEW v2_uses_t1, v2_uses_t2; +--echo # To be able create 'v2_uses_t2' we also need select on t2. +GRANT SELECT ON t2 TO 'mysqluser1'@'%'; +--echo # +--echo # Connection 'mysqluser2'. +--connection mysqluser2 +CREATE SQL SECURITY DEFINER VIEW v2_uses_t1 AS SELECT * FROM v1_uses_t1; +CREATE SQL SECURITY DEFINER VIEW v2_uses_t2 AS SELECT * FROM v1_uses_t2; +--echo # +--echo # Connection 'default'. +--connection default +--echo # Make 'mysqluser1' unable to access t2. +REVOKE SELECT ON t2 FROM 'mysqluser1'@'%'; +--echo # +--echo # Connection 'mysqluser2'. +--connection mysqluser2 +--echo # Again privileges of creator of innermost views should apply. +SELECT * FROM v2_uses_t1; +--error ER_VIEW_INVALID +SELECT * FROM v2_uses_t2; + +--disconnect mysqluser1 +--disconnect mysqluser2 +--connection default +USE test; +DROP DATABASE mysqltest1; +DROP USER 'mysqluser1'@'%'; +DROP USER 'mysqluser2'@'%'; + + +# Wait till we reached the initial number of concurrent sessions +--source include/wait_until_count_sessions.inc diff --git a/mysys/my_getsystime.c b/mysys/my_getsystime.c index 614f49fc425..01b3b912aae 100644 --- a/mysys/my_getsystime.c +++ b/mysys/my_getsystime.c @@ -25,13 +25,25 @@ #include "mysys_priv.h" #include "my_static.h" +/** + Get high-resolution time. + + @remark For windows platforms we need the frequency value of + the CPU. This is initialized in my_init.c through + QueryPerformanceFrequency(). If the Windows platform + doesn't support QueryPerformanceFrequency(), zero is + returned. + + @retval current high-resolution time. +*/ + ulonglong my_getsystime() { #ifdef HAVE_CLOCK_GETTIME struct timespec tp; clock_gettime(CLOCK_REALTIME, &tp); return (ulonglong)tp.tv_sec*10000000+(ulonglong)tp.tv_nsec/100; -#elif defined(__WIN__) +#elif defined(_WIN32) LARGE_INTEGER t_cnt; if (query_performance_frequency) { @@ -50,22 +62,17 @@ ulonglong my_getsystime() } -/* - Return current time +/** + Return current time. - SYNOPSIS - my_time() - flags If MY_WME is set, write error if time call fails + @param flags If MY_WME is set, write error if time call fails. + @retval current time. */ -time_t my_time(myf flags __attribute__((unused))) +time_t my_time(myf flags) { time_t t; -#ifdef HAVE_GETHRTIME - (void) my_micro_time_and_time(&t); - return t; -#else /* The following loop is here beacuse time() may fail on some systems */ while ((t= time(0)) == (time_t) -1) { @@ -73,39 +80,26 @@ time_t my_time(myf flags __attribute__((unused))) fprintf(stderr, "%s: Warning: time() call failed\n", my_progname); } return t; -#endif } -/* - Return time in micro seconds - - SYNOPSIS - my_micro_time() - - NOTES - This function is to be used to measure performance in micro seconds. - As it's not defined whats the start time for the clock, this function - us only useful to measure time between two moments. +/** + Return time in microseconds. - For windows platforms we need the frequency value of the CUP. This is - initalized in my_init.c through QueryPerformanceFrequency(). + @remark This function is to be used to measure performance in + micro seconds. As it's not defined whats the start time + for the clock, this function us only useful to measure + time between two moments. - If Windows platform doesn't support QueryPerformanceFrequency() we will - obtain the time via GetClockCount, which only supports milliseconds. - - RETURN - Value in microseconds from some undefined point in time + @retval Value in microseconds from some undefined point in time. */ ulonglong my_micro_time() { -#if defined(__WIN__) +#ifdef _WIN32 ulonglong newtime; GetSystemTimeAsFileTime((FILETIME*)&newtime); return (newtime/10); -#elif defined(HAVE_GETHRTIME) - return gethrtime()/1000; #else ulonglong newtime; struct timeval t; @@ -116,69 +110,37 @@ ulonglong my_micro_time() {} newtime= (ulonglong)t.tv_sec * 1000000 + t.tv_usec; return newtime; -#endif /* defined(__WIN__) */ +#endif } -/* +/** Return time in seconds and timer in microseconds (not different start!) - SYNOPSIS - my_micro_time_and_time() - time_arg Will be set to seconds since epoch (00:00:00 UTC, - January 1, 1970) + @param time_arg Will be set to seconds since epoch. - NOTES - This function is to be useful when we need both the time and microtime. - For example in MySQL this is used to get the query time start of a query - and to measure the time of a query (for the slow query log) + @remark This function is to be useful when we need both the time and + microtime. For example in MySQL this is used to get the query + time start of a query and to measure the time of a query (for + the slow query log) - IMPLEMENTATION - Value of time is as in time() call. - Value of microtime is same as my_micro_time(), which may be totally - unrealated to time() + @remark The time source is the same as for my_micro_time(), meaning + that time values returned by both functions can be intermixed + in meaningful ways (i.e. for comparison purposes). - RETURN - Value in microseconds from some undefined point in time + @retval Value in microseconds from some undefined point in time. */ -#define DELTA_FOR_SECONDS 500000000LL /* Half a second */ - /* Difference between GetSystemTimeAsFileTime() and now() */ #define OFFSET_TO_EPOCH 116444736000000000ULL ulonglong my_micro_time_and_time(time_t *time_arg) { -#if defined(__WIN__) +#ifdef _WIN32 ulonglong newtime; GetSystemTimeAsFileTime((FILETIME*)&newtime); *time_arg= (time_t) ((newtime - OFFSET_TO_EPOCH) / 10000000); return (newtime/10); -#elif defined(HAVE_GETHRTIME) - /* - Solaris has a very slow time() call. We optimize this by using the very - fast gethrtime() call and only calling time() every 1/2 second - */ - static hrtime_t prev_gethrtime= 0; - static time_t cur_time= 0; - hrtime_t cur_gethrtime; - - mysql_mutex_lock(&THR_LOCK_time); - cur_gethrtime= gethrtime(); - /* - Due to bugs in the Solaris (x86) implementation of gethrtime(), - the time returned by it might not be monotonic. Don't use the - cached time(2) value if this is a case. - */ - if ((prev_gethrtime > cur_gethrtime) || - ((cur_gethrtime - prev_gethrtime) > DELTA_FOR_SECONDS)) - { - cur_time= time(0); - prev_gethrtime= cur_gethrtime; - } - *time_arg= cur_time; - mysql_mutex_unlock(&THR_LOCK_time); - return cur_gethrtime/1000; #else ulonglong newtime; struct timeval t; @@ -190,37 +152,31 @@ ulonglong my_micro_time_and_time(time_t *time_arg) *time_arg= t.tv_sec; newtime= (ulonglong)t.tv_sec * 1000000 + t.tv_usec; return newtime; -#endif /* defined(__WIN__) */ +#endif } -/* - Returns current time +/** + Returns current time. - SYNOPSIS - my_time_possible_from_micro() - microtime Value from very recent my_micro_time() + @param microtime Value from very recent my_micro_time(). - NOTES - This function returns the current time. The microtime argument is only used - if my_micro_time() uses a function that can safely be converted to the - current time. + @remark This function returns the current time. The microtime argument + is only used if my_micro_time() uses a function that can safely + be converted to the current time. - RETURN - current time + @retval current time. */ time_t my_time_possible_from_micro(ulonglong microtime __attribute__((unused))) { -#if defined(__WIN__) +#ifdef _WIN32 time_t t; while ((t= time(0)) == (time_t) -1) {} return t; -#elif defined(HAVE_GETHRTIME) - return my_time(0); /* Cached time */ #else return (time_t) (microtime / 1000000); -#endif /* defined(__WIN__) */ +#endif } diff --git a/mysys/my_init.c b/mysys/my_init.c index f5a2d9ac4bd..9a17d0d6916 100644 --- a/mysys/my_init.c +++ b/mysys/my_init.c @@ -510,7 +510,7 @@ PSI_mutex_key key_BITMAP_mutex, key_IO_CACHE_append_buffer_lock, key_my_thread_var_mutex, key_THR_LOCK_charset, key_THR_LOCK_heap, key_THR_LOCK_isam, key_THR_LOCK_lock, key_THR_LOCK_malloc, key_THR_LOCK_mutex, key_THR_LOCK_myisam, key_THR_LOCK_net, - key_THR_LOCK_open, key_THR_LOCK_threads, key_THR_LOCK_time, + key_THR_LOCK_open, key_THR_LOCK_threads, key_TMPDIR_mutex, key_THR_LOCK_myisam_mmap; static PSI_mutex_info all_mysys_mutexes[]= @@ -540,7 +540,6 @@ static PSI_mutex_info all_mysys_mutexes[]= { &key_THR_LOCK_net, "THR_LOCK_net", PSI_FLAG_GLOBAL}, { &key_THR_LOCK_open, "THR_LOCK_open", PSI_FLAG_GLOBAL}, { &key_THR_LOCK_threads, "THR_LOCK_threads", PSI_FLAG_GLOBAL}, - { &key_THR_LOCK_time, "THR_LOCK_time", PSI_FLAG_GLOBAL}, { &key_TMPDIR_mutex, "TMPDIR_mutex", PSI_FLAG_GLOBAL}, { &key_THR_LOCK_myisam_mmap, "THR_LOCK_myisam_mmap", PSI_FLAG_GLOBAL} }; diff --git a/mysys/my_thr_init.c b/mysys/my_thr_init.c index c4b56cde850..a672d8af818 100644 --- a/mysys/my_thr_init.c +++ b/mysys/my_thr_init.c @@ -25,7 +25,7 @@ pthread_key(struct st_my_thread_var*, THR_KEY_mysys); mysql_mutex_t THR_LOCK_malloc, THR_LOCK_open, THR_LOCK_lock, THR_LOCK_isam, THR_LOCK_myisam, THR_LOCK_heap, - THR_LOCK_net, THR_LOCK_charset, THR_LOCK_threads, THR_LOCK_time, + THR_LOCK_net, THR_LOCK_charset, THR_LOCK_threads, THR_LOCK_myisam_mmap; mysql_cond_t THR_COND_threads; @@ -219,7 +219,6 @@ my_bool my_thread_global_init(void) mysql_mutex_init(key_THR_LOCK_myisam_mmap, &THR_LOCK_myisam_mmap, MY_MUTEX_INIT_FAST); mysql_mutex_init(key_THR_LOCK_heap, &THR_LOCK_heap, MY_MUTEX_INIT_FAST); mysql_mutex_init(key_THR_LOCK_net, &THR_LOCK_net, MY_MUTEX_INIT_FAST); - mysql_mutex_init(key_THR_LOCK_time, &THR_LOCK_time, MY_MUTEX_INIT_FAST); mysql_cond_init(key_THR_COND_threads, &THR_COND_threads, NULL); #if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R) @@ -288,7 +287,6 @@ void my_thread_global_end(void) mysql_mutex_destroy(&THR_LOCK_myisam_mmap); mysql_mutex_destroy(&THR_LOCK_heap); mysql_mutex_destroy(&THR_LOCK_net); - mysql_mutex_destroy(&THR_LOCK_time); mysql_mutex_destroy(&THR_LOCK_charset); if (all_threads_killed) { diff --git a/mysys/mysys_priv.h b/mysys/mysys_priv.h index 4e642b7e3d3..e760ea808b7 100644 --- a/mysys/mysys_priv.h +++ b/mysys/mysys_priv.h @@ -45,7 +45,7 @@ extern PSI_mutex_key key_BITMAP_mutex, key_IO_CACHE_append_buffer_lock, key_my_thread_var_mutex, key_THR_LOCK_charset, key_THR_LOCK_heap, key_THR_LOCK_isam, key_THR_LOCK_lock, key_THR_LOCK_malloc, key_THR_LOCK_mutex, key_THR_LOCK_myisam, key_THR_LOCK_net, - key_THR_LOCK_open, key_THR_LOCK_threads, key_THR_LOCK_time, + key_THR_LOCK_open, key_THR_LOCK_threads, key_TMPDIR_mutex, key_THR_LOCK_myisam_mmap; extern PSI_cond_key key_COND_alarm, key_IO_CACHE_SHARE_cond, @@ -60,7 +60,7 @@ extern PSI_thread_key key_thread_alarm; extern mysql_mutex_t THR_LOCK_malloc, THR_LOCK_open, THR_LOCK_keycache; extern mysql_mutex_t THR_LOCK_lock, THR_LOCK_isam, THR_LOCK_net; -extern mysql_mutex_t THR_LOCK_charset, THR_LOCK_time; +extern mysql_mutex_t THR_LOCK_charset; #include <mysql/psi/mysql_file.h> diff --git a/sql/item.cc b/sql/item.cc index 18a88d64470..c7787d65c22 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -7370,8 +7370,7 @@ Item_cache* Item_cache::get_cache(const Item *item, const Item_result type) return new Item_cache_decimal(); case STRING_RESULT: /* Not all functions that return DATE/TIME are actually DATE/TIME funcs. */ - if ((item->field_type() == MYSQL_TYPE_DATE || - item->field_type() == MYSQL_TYPE_DATETIME || + if ((item->is_datetime() || item->field_type() == MYSQL_TYPE_TIME) && (const_cast<Item*>(item))->result_as_longlong()) return new Item_cache_datetime(item->field_type()); diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index fe8ff3a74d0..ac13ca8a8c5 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -5643,15 +5643,15 @@ longlong Item_equal::val_int() return 0; List_iterator_fast<Item_field> it(fields); Item *item= const_item ? const_item : it++; + eval_item->store_value(item); if ((null_value= item->null_value)) return 0; - eval_item->store_value(item); while ((item_field= it++)) { /* Skip fields of non-const tables. They haven't been read yet */ if (item_field->field->table->const_table) { - if ((null_value= item_field->null_value) || eval_item->cmp(item_field)) + if (eval_item->cmp(item_field) || (null_value= item_field->null_value)) return 0; } } diff --git a/sql/item_geofunc.h b/sql/item_geofunc.h index 84034841ad5..6145f72b665 100644 --- a/sql/item_geofunc.h +++ b/sql/item_geofunc.h @@ -181,6 +181,7 @@ public: String *val_str(String *); void fix_length_and_dec() { + Item_geometry_func::fix_length_and_dec(); for (unsigned int i= 0; i < arg_count; ++i) { if (args[i]->fixed && args[i]->field_type() != MYSQL_TYPE_GEOMETRY) diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 2a93bcd0153..65eb2bb527b 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -56,6 +56,9 @@ C_MODE_START #include "../mysys/my_static.h" // For soundex_map C_MODE_END +/** + @todo Remove this. It is not safe to use a shared String object. + */ String my_empty_string("",default_charset_info); /* @@ -642,7 +645,7 @@ String *Item_func_des_encrypt::val_str(String *str) if ((null_value= args[0]->null_value)) return 0; // ENCRYPT(NULL) == NULL if ((res_length=res->length()) == 0) - return &my_empty_string; + return make_empty_result(); if (arg_count == 1) { /* Protect against someone doing FLUSH DES_KEY_FILE */ @@ -832,7 +835,7 @@ String *Item_func_concat_ws::val_str(String *str) } if (i == arg_count) - return &my_empty_string; + return make_empty_result(); for (i++; i < arg_count ; i++) { @@ -978,7 +981,7 @@ String *Item_func_reverse::val_str(String *str) return 0; /* An empty string is a special case as the string pointer may be null */ if (!res->length()) - return &my_empty_string; + return make_empty_result(); if (tmp_value.alloced_length() < res->length() && tmp_value.realloc(res->length())) { @@ -1311,8 +1314,7 @@ String *Item_func_left::val_str(String *str) /* if "unsigned_flag" is set, we have a *huge* positive number. */ if ((length <= 0) && (!args[1]->unsigned_flag)) - return &my_empty_string; - + return make_empty_result(); if ((res->length() <= (ulonglong) length) || (res->length() <= (char_pos= res->charpos((int) length)))) return res; @@ -1357,7 +1359,7 @@ String *Item_func_right::val_str(String *str) /* if "unsigned_flag" is set, we have a *huge* positive number. */ if ((length <= 0) && (!args[1]->unsigned_flag)) - return &my_empty_string; /* purecov: inspected */ + return make_empty_result(); /* purecov: inspected */ if (res->length() <= (ulonglong) length) return res; /* purecov: inspected */ @@ -1397,7 +1399,7 @@ String *Item_func_substr::val_str(String *str) /* Negative or zero length, will return empty string. */ if ((arg_count == 3) && (length <= 0) && (length == 0 || !args[2]->unsigned_flag)) - return &my_empty_string; + return make_empty_result(); /* Assumes that the maximum length of a String is < INT_MAX32. */ /* Set here so that rest of code sees out-of-bound value as such. */ @@ -1408,12 +1410,12 @@ String *Item_func_substr::val_str(String *str) /* Assumes that the maximum length of a String is < INT_MAX32. */ if ((!args[1]->unsigned_flag && (start < INT_MIN32 || start > INT_MAX32)) || (args[1]->unsigned_flag && ((ulonglong) start > INT_MAX32))) - return &my_empty_string; + return make_empty_result(); start= ((start < 0) ? res->numchars() + start : start - 1); start= res->charpos((int) start); if ((start < 0) || ((uint) start + 1 > res->length())) - return &my_empty_string; + return make_empty_result(); length= res->charpos((int) length, (uint32) start); tmp_length= res->length() - start; @@ -1476,7 +1478,7 @@ String *Item_func_substr_index::val_str(String *str) null_value=0; uint delimiter_length= delimiter->length(); if (!res->length() || !delimiter_length || !count) - return &my_empty_string; // Wrong parameters + return make_empty_result(); // Wrong parameters res->set_charset(collation.collation); @@ -1826,7 +1828,7 @@ String *Item_func_password::val_str_ascii(String *str) if ((null_value=args[0]->null_value)) return 0; if (res->length() == 0) - return &my_empty_string; + return make_empty_result(); my_make_scrambled_password(tmp_value, res->ptr(), res->length()); str->set(tmp_value, SCRAMBLED_PASSWORD_CHAR_LENGTH, &my_charset_latin1); return str; @@ -1850,7 +1852,7 @@ String *Item_func_old_password::val_str_ascii(String *str) if ((null_value=args[0]->null_value)) return 0; if (res->length() == 0) - return &my_empty_string; + return make_empty_result(); my_make_scrambled_password_323(tmp_value, res->ptr(), res->length()); str->set(tmp_value, SCRAMBLED_PASSWORD_CHAR_LENGTH_323, &my_charset_latin1); return str; @@ -1878,8 +1880,7 @@ String *Item_func_encrypt::val_str(String *str) if ((null_value=args[0]->null_value)) return 0; if (res->length() == 0) - return &my_empty_string; - + return make_empty_result(); if (arg_count == 1) { // generate random salt time_t timestamp=current_thd->query_start(); @@ -2141,7 +2142,7 @@ String *Item_func_soundex::val_str(String *str) for ( ; ; ) /* Skip pre-space */ { if ((rc= cs->cset->mb_wc(cs, &wc, (uchar*) from, (uchar*) end)) <= 0) - return &my_empty_string; /* EOL or invalid byte sequence */ + return make_empty_result(); /* EOL or invalid byte sequence */ if (rc == 1 && cs->ctype) { @@ -2166,7 +2167,7 @@ String *Item_func_soundex::val_str(String *str) { /* Extra safety - should not really happen */ DBUG_ASSERT(false); - return &my_empty_string; + return make_empty_result(); } to+= rc; break; @@ -2507,7 +2508,7 @@ String *Item_func_make_set::val_str(String *str) else { if (tmp_str.copy(*res)) // Don't use 'str' - return &my_empty_string; + return make_empty_result(); result= &tmp_str; } } @@ -2517,11 +2518,11 @@ String *Item_func_make_set::val_str(String *str) { // Copy data to tmp_str if (tmp_str.alloc(result->length()+res->length()+1) || tmp_str.copy(*result)) - return &my_empty_string; + return make_empty_result(); result= &tmp_str; } if (tmp_str.append(STRING_WITH_LEN(","), &my_charset_bin) || tmp_str.append(*res)) - return &my_empty_string; + return make_empty_result(); } } } @@ -2666,7 +2667,7 @@ String *Item_func_repeat::val_str(String *str) null_value= 0; if (count <= 0 && (count == 0 || !args[1]->unsigned_flag)) - return &my_empty_string; + return make_empty_result(); /* Assumes that the maximum length of a String is < INT_MAX32. */ /* Bounds check on count: If this is triggered, we will error. */ @@ -2948,7 +2949,7 @@ String *Item_func_conv::val_str(String *str) ptr= longlong2str(dec, ans, to_base); if (str->copy(ans, (uint32) (ptr-ans), default_charset())) - return &my_empty_string; + return make_empty_result(); return str; } @@ -3115,7 +3116,7 @@ String *Item_func_hex::val_str_ascii(String *str) return 0; ptr= longlong2str(dec,ans,16); if (str->copy(ans,(uint32) (ptr-ans), &my_charset_numeric)) - return &my_empty_string; // End of memory + return make_empty_result(); // End of memory return str; } diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index d76e139883c..626926213e6 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -27,6 +27,16 @@ class MY_LOCALE; class Item_str_func :public Item_func { +protected: + /** + Sets the result value of the function an empty string, using the current + character set. No memory is allocated. + @retval A pointer to the str_value member. + */ + String *make_empty_result() { + str_value.set("", 0, collation.collation); + return &str_value; + } public: Item_str_func() :Item_func() { decimals=NOT_FIXED_DEC; } Item_str_func(Item *a) :Item_func(a) {decimals=NOT_FIXED_DEC; } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 91ce31636b4..fdce2510df4 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -6480,7 +6480,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) OPTIMIZER_SWITCH_ENGINE_CONDITION_PUSHDOWN) { COND *push_cond= - make_cond_for_table(tmp, current_map, current_map); + make_cond_for_table(tmp, tab->table->map, tab->table->map); if (push_cond) { /* Push condition to handler */ @@ -12040,7 +12040,7 @@ join_read_const_table(JOIN_TAB *tab, POSITION *pos) /* Mark for EXPLAIN that the row was not found */ pos->records_read=0.0; pos->ref_depend_map= 0; - if (!table->maybe_null || error > 0) + if (!table->pos_in_table_list->outer_join || error > 0) DBUG_RETURN(error); } } @@ -12061,7 +12061,7 @@ join_read_const_table(JOIN_TAB *tab, POSITION *pos) /* Mark for EXPLAIN that the row was not found */ pos->records_read=0.0; pos->ref_depend_map= 0; - if (!table->maybe_null || error > 0) + if (!table->pos_in_table_list->outer_join || error > 0) DBUG_RETURN(error); } } @@ -13099,7 +13099,7 @@ make_cond_for_table(COND *cond, table_map tables, table_map used_table) new_cond->argument_list()->push_back(fix); } /* - Item_cond_and do not need fix_fields for execution, its parameters + Item_cond_or do not need fix_fields for execution, its parameters are fixed or do not need fix_fields, too */ new_cond->quick_fix_field(); diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 4b7dab243d2..d19b876a82f 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -51,11 +51,33 @@ bool String::real_alloc(uint32 length) } -/* -** Check that string is big enough. Set string[alloc_length] to 0 -** (for C functions) -*/ +/** + Allocates a new buffer on the heap for this String. + + - If the String's internal buffer is privately owned and heap allocated, + one of the following is performed. + + - If the requested length is greater than what fits in the buffer, a new + buffer is allocated, data moved and the old buffer freed. + + - If the requested length is less or equal to what fits in the buffer, a + null character is inserted at the appropriate position. + - If the String does not keep a private buffer on the heap, such a buffer + will be allocated and the string copied accoring to its length, as found + in String::length(). + + For C compatibility, the new string buffer is null terminated. + + @param alloc_length The requested string size in characters, excluding any + null terminator. + + @retval false Either the copy operation is complete or, if the size of the + new buffer is smaller than the currently allocated buffer (if one exists), + no allocation occured. + + @retval true An error occured when attempting to allocate memory. +*/ bool String::realloc(uint32 alloc_length) { uint32 len=ALIGN_SIZE(alloc_length+1); @@ -128,6 +150,17 @@ bool String::copy() return FALSE; } +/** + Copies the internal buffer from str. If this String has a private heap + allocated buffer where new data does not fit, a new buffer is allocated + before copying and the old buffer freed. Character set information is also + copied. + + @param str The string whose internal buffer is to be copied. + + @retval false Success. + @retval true Memory allocation failed. +*/ bool String::copy(const String &str) { if (alloc(str.str_length)) diff --git a/sql/sql_string.h b/sql/sql_string.h index 3642a96de35..dcd9975f399 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -148,6 +148,16 @@ public: Alloced_length=0; str_charset=str.str_charset; } + + + /** + Points the internal buffer to the supplied one. The old buffer is freed. + @param str Pointer to the new buffer. + @param arg_length Length of the new buffer in characters, excluding any + null character. + @param cs Character set to use for interpreting string data. + @note The new buffer will not be null terminated. + */ inline void set(char *str,uint32 arg_length, CHARSET_INFO *cs) { free(); diff --git a/sql/sql_view.cc b/sql/sql_view.cc index f569c679776..9b4543bf636 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -1270,6 +1270,7 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table, TABLE_LIST *view_tables= lex->query_tables; TABLE_LIST *view_tables_tail= 0; TABLE_LIST *tbl; + Security_context *security_ctx; /* Check rights to run commands (EXPLAIN SELECT & SHOW CREATE) which show @@ -1416,26 +1417,39 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table, if (table->view_suid) { /* - Prepare a security context to check underlying objects of the view + For suid views prepare a security context for checking underlying + objects of the view. */ if (!(table->view_sctx= (Security_context *) thd->stmt_arena->alloc(sizeof(Security_context)))) goto err; - /* Assign the context to the tables referenced in the view */ - if (view_tables) - { - DBUG_ASSERT(view_tables_tail); - for (tbl= view_tables; tbl != view_tables_tail->next_global; - tbl= tbl->next_global) - tbl->security_ctx= table->view_sctx; - } - /* assign security context to SELECT name resolution contexts of view */ - for(SELECT_LEX *sl= lex->all_selects_list; - sl; - sl= sl->next_select_in_list()) - sl->context.security_ctx= table->view_sctx; + security_ctx= table->view_sctx; + } + else + { + /* + For non-suid views inherit security context from view's table list. + This allows properly handle situation when non-suid view is used + from within suid view. + */ + security_ctx= table->security_ctx; + } + + /* Assign the context to the tables referenced in the view */ + if (view_tables) + { + DBUG_ASSERT(view_tables_tail); + for (tbl= view_tables; tbl != view_tables_tail->next_global; + tbl= tbl->next_global) + tbl->security_ctx= security_ctx; } + /* assign security context to SELECT name resolution contexts of view */ + for(SELECT_LEX *sl= lex->all_selects_list; + sl; + sl= sl->next_select_in_list()) + sl->context.security_ctx= security_ctx; + /* Setup an error processor to hide error messages issued by stored routines referenced in the view |