diff options
author | Georgi Kodinov <joro@sun.com> | 2010-01-15 11:06:46 +0200 |
---|---|---|
committer | Georgi Kodinov <joro@sun.com> | 2010-01-15 11:06:46 +0200 |
commit | 0305aea88a220ff9080432a65d50cb30493f3109 (patch) | |
tree | 2be501ad47ff01efe5af595410e222a3ee873214 | |
parent | a07ca23755affd5ad164323593f13a4fa708b9ad (diff) | |
parent | 32aa612819ff756b284e639de50627b3d6d7fa0d (diff) | |
download | mariadb-git-0305aea88a220ff9080432a65d50cb30493f3109.tar.gz |
merge
-rw-r--r-- | .bzr-mysql/default.conf | 2 | ||||
-rw-r--r-- | mysql-test/suite/rpl/r/rpl_myisam_null_values.result | 24 | ||||
-rw-r--r-- | mysql-test/suite/rpl/r/rpl_row_tbl_metadata.result (renamed from mysql-test/suite/binlog/r/binlog_tbl_metadata.result) | 56 | ||||
-rw-r--r-- | mysql-test/suite/rpl/t/rpl_myisam_null_values.test | 53 | ||||
-rw-r--r-- | mysql-test/suite/rpl/t/rpl_row_tbl_metadata.test (renamed from mysql-test/suite/binlog/t/binlog_tbl_metadata.test) | 171 | ||||
-rw-r--r-- | sql/log_event.cc | 45 | ||||
-rw-r--r-- | sql/log_event_old.cc | 39 | ||||
-rw-r--r-- | sql/sql_acl.cc | 15 | ||||
-rw-r--r-- | sql/sql_parse.cc | 9 | ||||
-rw-r--r-- | sql/sql_servers.cc | 10 |
10 files changed, 390 insertions, 34 deletions
diff --git a/.bzr-mysql/default.conf b/.bzr-mysql/default.conf index f044f8e62da..e613cefc614 100644 --- a/.bzr-mysql/default.conf +++ b/.bzr-mysql/default.conf @@ -1,4 +1,4 @@ [MYSQL] post_commit_to = "commits@lists.mysql.com" post_push_to = "commits@lists.mysql.com" -tree_name = "mysql-5.1" +tree_name = "mysql-5.1-bugteam" diff --git a/mysql-test/suite/rpl/r/rpl_myisam_null_values.result b/mysql-test/suite/rpl/r/rpl_myisam_null_values.result new file mode 100644 index 00000000000..574528a8d79 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_myisam_null_values.result @@ -0,0 +1,24 @@ +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +CREATE TABLE t1 (c1 BIT, c2 INT); +INSERT INTO `t1` VALUES ( 1, 1 ); +UPDATE t1 SET c1=NULL where c2=1; +Comparing tables master:test.t1 and slave:test.t1 +DELETE FROM t1 WHERE c2=1 LIMIT 1; +Comparing tables master:test.t1 and slave:test.t1 +DROP TABLE t1; +CREATE TABLE t1 (c1 CHAR); +INSERT INTO t1 ( c1 ) VALUES ( 'w' ) ; +SELECT * FROM t1; +c1 +w +# should trigger switch to row due to LIMIT +UPDATE t1 SET c1=NULL WHERE c1='w' LIMIT 2; +Comparing tables master:test.t1 and slave:test.t1 +DELETE FROM t1 LIMIT 2; +Comparing tables master:test.t1 and slave:test.t1 +DROP TABLE t1; diff --git a/mysql-test/suite/binlog/r/binlog_tbl_metadata.result b/mysql-test/suite/rpl/r/rpl_row_tbl_metadata.result index a2f185edc85..711d0d063aa 100644 --- a/mysql-test/suite/binlog/r/binlog_tbl_metadata.result +++ b/mysql-test/suite/rpl/r/rpl_row_tbl_metadata.result @@ -1,5 +1,11 @@ -RESET MASTER; +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; DROP TABLE IF EXISTS `t1`; +### TABLE with field_metadata_size == 290 CREATE TABLE `t1` ( `c1` int(11) NOT NULL AUTO_INCREMENT, `c2` varchar(30) NOT NULL, @@ -150,7 +156,51 @@ CREATE TABLE `t1` ( PRIMARY KEY (`c1`) ) ENGINE=InnoDB; LOCK TABLES `t1` WRITE; -INSERT INTO `t1` VALUES ('1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1'); -DROP TABLE `t1`; +INSERT INTO `t1`(c2) VALUES ('1'); FLUSH LOGS; +### assertion: the slave replicated event successfully and tables match +Comparing tables master:test.t1 and slave:test.t1 +DROP TABLE `t1`; === Using mysqlbinlog to detect failure. Before the patch mysqlbinlog would find a corrupted event, thence would fail. +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +### action: generating several tables with different metadata +### sizes (resorting to perl) +### testing table with 249 field metadata size. +### testing table with 250 field metadata size. +### testing table with 251 field metadata size. +### testing table with 252 field metadata size. +### testing table with 253 field metadata size. +### testing table with 254 field metadata size. +### testing table with 255 field metadata size. +### testing table with 256 field metadata size. +### testing table with 257 field metadata size. +### testing table with 258 field metadata size. +FLUSH LOGS; +### assertion: the slave replicated event successfully and tables match for t10 +Comparing tables master:test.t10 and slave:test.t10 +### assertion: the slave replicated event successfully and tables match for t9 +Comparing tables master:test.t9 and slave:test.t9 +### assertion: the slave replicated event successfully and tables match for t8 +Comparing tables master:test.t8 and slave:test.t8 +### assertion: the slave replicated event successfully and tables match for t7 +Comparing tables master:test.t7 and slave:test.t7 +### assertion: the slave replicated event successfully and tables match for t6 +Comparing tables master:test.t6 and slave:test.t6 +### assertion: the slave replicated event successfully and tables match for t5 +Comparing tables master:test.t5 and slave:test.t5 +### assertion: the slave replicated event successfully and tables match for t4 +Comparing tables master:test.t4 and slave:test.t4 +### assertion: the slave replicated event successfully and tables match for t3 +Comparing tables master:test.t3 and slave:test.t3 +### assertion: the slave replicated event successfully and tables match for t2 +Comparing tables master:test.t2 and slave:test.t2 +### assertion: the slave replicated event successfully and tables match for t1 +Comparing tables master:test.t1 and slave:test.t1 +### assertion: check that binlog is not corrupt. Using mysqlbinlog to +### detect failure. Before the patch mysqlbinlog would find +### a corrupted event, thence would fail. diff --git a/mysql-test/suite/rpl/t/rpl_myisam_null_values.test b/mysql-test/suite/rpl/t/rpl_myisam_null_values.test new file mode 100644 index 00000000000..d9ec95fc510 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_myisam_null_values.test @@ -0,0 +1,53 @@ +# BUG#49481: RBR: MyISAM and bit fields may cause slave to stop on delete cant find record +# BUG#49482: RBR: Replication may break on deletes when MyISAM tables + char field are used + +-- source include/master-slave.inc +-- source include/have_binlog_format_mixed_or_row.inc + +-- connection master +CREATE TABLE t1 (c1 BIT, c2 INT); +INSERT INTO `t1` VALUES ( 1, 1 ); +UPDATE t1 SET c1=NULL where c2=1; +-- sync_slave_with_master + +-- let $diff_table_1=master:test.t1 +-- let $diff_table_2=slave:test.t1 +-- source include/diff_tables.inc + +-- connection master +DELETE FROM t1 WHERE c2=1 LIMIT 1; +-- sync_slave_with_master + +-- let $diff_table_1=master:test.t1 +-- let $diff_table_2=slave:test.t1 +-- source include/diff_tables.inc + +-- connection master +DROP TABLE t1; +-- sync_slave_with_master + +-- connection master + +CREATE TABLE t1 (c1 CHAR); + +INSERT INTO t1 ( c1 ) VALUES ( 'w' ) ; +SELECT * FROM t1; +-- echo # should trigger switch to row due to LIMIT +UPDATE t1 SET c1=NULL WHERE c1='w' LIMIT 2; +-- sync_slave_with_master + +-- let $diff_table_1=master:test.t1 +-- let $diff_table_2=slave:test.t1 +-- source include/diff_tables.inc + +-- connection master +DELETE FROM t1 LIMIT 2; +-- sync_slave_with_master + +-- let $diff_table_1=master:test.t1 +-- let $diff_table_2=slave:test.t1 +-- source include/diff_tables.inc + +-- connection master +DROP TABLE t1; +-- sync_slave_with_master diff --git a/mysql-test/suite/binlog/t/binlog_tbl_metadata.test b/mysql-test/suite/rpl/t/rpl_row_tbl_metadata.test index 5e847ab5fbd..be5ebb661ca 100644 --- a/mysql-test/suite/binlog/t/binlog_tbl_metadata.test +++ b/mysql-test/suite/rpl/t/rpl_row_tbl_metadata.test @@ -2,38 +2,39 @@ # BUG#42749: infinite loop writing to row based binlog - processlist shows # "freeing items" # +# # WHY # === -# -# This bug would make table map event to report data_written one byte less -# than what would actually be written in its body. This would cause one byte shorter -# event end_log_pos. The ultimate impact was that it would make fixing the -# position in MYSQL_BIN_LOG::write_cache bogus or end up in an infinite loop. +# +# This bug would make table map event to report data_written one +# byte less than what would actually be written in its body. This +# would cause one byte shorter event end_log_pos. The ultimate +# impact was that it would make fixing the position in +# MYSQL_BIN_LOG::write_cache bogus or end up in an infinite loop. # # HOW # === # # Checking that the patch fixes the problem is done as follows: -# i) a table with several fields is created; +# +# i) one table with m_field_metadata sized at 290 # ii) an insert is performed; # iii) the logs are flushed; # iv) mysqlbinlog is used to check if it succeeds. # -# In step iv), before the bug was fixed, the test case would fail with -# mysqlbinlog reporting that it was unable to succeed in reading the event. -# +# In step iv), before the bug was fixed, the test case would fail +# with mysqlbinlog reporting that it was unable to succeed in +# reading the event. --- source include/have_log_bin.inc +-- source include/master-slave.inc -- source include/have_innodb.inc -- source include/have_binlog_format_row.inc --- connection default - -RESET MASTER; -- disable_warnings DROP TABLE IF EXISTS `t1`; -- enable_warnings +-- echo ### TABLE with field_metadata_size == 290 CREATE TABLE `t1` ( `c1` int(11) NOT NULL AUTO_INCREMENT, `c2` varchar(30) NOT NULL, @@ -185,15 +186,155 @@ CREATE TABLE `t1` ( ) ENGINE=InnoDB; LOCK TABLES `t1` WRITE; +INSERT INTO `t1`(c2) VALUES ('1'); +FLUSH LOGS; + +-- sync_slave_with_master +-- connection master -INSERT INTO `t1` VALUES ('1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1'); +-- echo ### assertion: the slave replicated event successfully and tables match +-- let $diff_table_1=master:test.t1 +-- let $diff_table_2=slave:test.t1 +-- source include/diff_tables.inc DROP TABLE `t1`; -FLUSH LOGS; +-- connection master +-- sync_slave_with_master +-- connection master -- echo === Using mysqlbinlog to detect failure. Before the patch mysqlbinlog would find a corrupted event, thence would fail. -- let $MYSQLD_DATADIR= `SELECT @@datadir`; -- exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug42749.binlog -- remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug42749.binlog + +############################################################# +# BUG#50018: binlog corruption when table has many columns +# +# Same test from BUG#42749, but now we generate some SQL which +# creates and inserts into tables with metadata size from 249 +# to 258. +# +# The test works as follows: +# 1. SQL for several CREATE TABLE and INSERTS are generated +# into a file. +# 2. This file is then "sourced" +# 3. The slave is synchronized with the master +# 4. FLUSH LOGS on master +# 5. Compare tables on master and slave. +# 6. run mysqlbinlog on master's binary log +# +# Steps #5 and #6 assert that binary log is not corrupted +# in both cases: when slave is replaying events and when +# mysqlbinlog is used to read the binary log + +-- source include/master-slave-reset.inc +-- connection master + +# Create several tables with field_metadata_size ranging +# from 249 to 258 (so that we cover 251 and 255 range). +# This should exercise the switch between using 1 or 3 +# bytes to pack m_field_metadata_size. +# +# Each varchar field takes up to 2 metadata bytes, see: +# +# Field_varstring::do_save_field_metadata (field.cc) +# +# The float field takes 1 byte, see: +# +# Field_float::do_save_field_metadata (field.cc) +# + +-- let $generated_sql= $MYSQLTEST_VARDIR/tmp/b50018.sql +-- let B50018_FILE= $generated_sql + +-- echo ### action: generating several tables with different metadata +-- echo ### sizes (resorting to perl) +-- perl +my $file= $ENV{'B50018_FILE'}; +open(FILE, ">", "$file") or die "Unable to open bug 50018 generated SQL file: $!" ; + +my $tables= ""; +my $ntables= 10; +my $base_ncols= 124; + +for my $i (1..$ntables) +{ + my $ncols= $base_ncols + $i; + my $metadata_size= $ncols_variable * 2 + 1; + + print FILE "-- echo ### testing table with " . ($base_ncols*2 + $i) . " field metadata size.\n"; + print FILE "CREATE TABLE t$i (\n"; + for my $n (1..$base_ncols) + { + print FILE "c$n VARCHAR(30) NOT NULL DEFAULT 'BUG#50018',\n"; + } + + for my $n (1..$i) + { + print FILE "c" . ($base_ncols+$n) . " FLOAT NOT NULL DEFAULT 0"; + if ($n < $i) + { + print FILE ",\n"; + } + } + + print FILE ") Engine=InnoDB;\n"; + + $tables.= " t$i WRITE"; + if ($i < $ntables) + { + $tables .=","; + } + + print FILE "LOCK TABLES t$i WRITE;\n"; + print FILE "INSERT INTO t$i(c". ($base_ncols+1) . ") VALUES (50018);\n"; + print FILE "UNLOCK TABLES;"; +} + +close(FILE); + +EOF + +## we don't need this in the result file +## however, for debugging purposes you +## may want to reactivate query logging +-- disable_query_log +-- source $generated_sql +-- enable_query_log + +-- sync_slave_with_master +-- connection master + +FLUSH LOGS; + +-- let $ntables=10 +while($ntables) +{ + -- echo ### assertion: the slave replicated event successfully and tables match for t$ntables + -- let $diff_table_1=master:test.t$ntables + -- let $diff_table_2=slave:test.t$ntables + -- source include/diff_tables.inc + + -- connection master + -- disable_query_log + -- eval DROP TABLE t$ntables + -- enable_query_log + -- sync_slave_with_master + -- connection master + + -- dec $ntables +} + +-- echo ### assertion: check that binlog is not corrupt. Using mysqlbinlog to +-- echo ### detect failure. Before the patch mysqlbinlog would find +-- echo ### a corrupted event, thence would fail. +-- let $MYSQLD_DATADIR= `SELECT @@datadir`; +-- exec $MYSQL_BINLOG -v --hex $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug50018.binlog + +## clean up +## For debugging purposes you might want not to remove these +-- remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug50018.binlog +-- remove_file $generated_sql +-- source include/master-slave-end.inc diff --git a/sql/log_event.cc b/sql/log_event.cc index d7eaa57c23b..61f5e93e29e 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -7926,10 +7926,10 @@ Table_map_log_event::Table_map_log_event(THD *thd, TABLE *tbl, ulong tid, plus one or three bytes (see pack.c:net_store_length) for number of elements in the field metadata array. */ - if (m_field_metadata_size > 255) - m_data_size+= m_field_metadata_size + 3; - else + if (m_field_metadata_size < 251) m_data_size+= m_field_metadata_size + 1; + else + m_data_size+= m_field_metadata_size + 3; bzero(m_null_bits, num_null_bytes); for (unsigned int i= 0 ; i < m_table->s->fields ; ++i) @@ -8724,6 +8724,24 @@ static bool record_compare(TABLE *table) } } + /** + Check if we are using MyISAM. + + If this is a myisam table, then we cannot do a memcmp + right away because some NULL fields can still contain + an old value in the row - they are not shown to the user + because the null bit is set, however, the contents are + not cleared. As such, plain memory comparison cannot be + assured to work. See: BUG#49482 and BUG#49481. + + On top of this, we do not store field contents for null + fields in the binlog, so this is extra important when + comparing records fetched from binlog and from storage + engine. + */ + if (table->file->ht->db_type == DB_TYPE_MYISAM) + goto record_compare_field_by_field; + if (table->s->blob_fields + table->s->varchar_fields == 0) { result= cmp_record(table,record[1]); @@ -8739,14 +8757,33 @@ static bool record_compare(TABLE *table) goto record_compare_exit; } +record_compare_field_by_field: + /* Compare updated fields */ for (Field **ptr=table->field ; *ptr ; ptr++) { - if ((*ptr)->cmp_binary_offset(table->s->rec_buff_length)) + Field *f= *ptr; + + /* if just one of the fields is null then there is no match */ + if ((f->is_null_in_record(table->record[0])) == + !(f->is_null_in_record(table->record[1]))) { result= TRUE; goto record_compare_exit; } + + /* if both fields are not null then we can compare */ + if (!(f->is_null_in_record(table->record[0])) && + !(f->is_null_in_record(table->record[1]))) + { + if (f->cmp_binary_offset(table->s->rec_buff_length)) + { + result= TRUE; + goto record_compare_exit; + } + } + + /* if both fields are null then there is a match. compare next field */ } record_compare_exit: diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc index 357bc78b1cd..72a6e159535 100644 --- a/sql/log_event_old.cc +++ b/sql/log_event_old.cc @@ -351,6 +351,24 @@ static bool record_compare(TABLE *table) } } + /** + Check if we are using MyISAM. + + If this is a myisam table, then we cannot do a memcmp + right away because some NULL fields can still contain + an old value in the row - they are not shown to the user + because the null bit is set, however, the contents are + not cleared. As such, plain memory comparison cannot be + assured to work. See: BUG#49482 and BUG#49481. + + On top of this, we do not store field contents for null + fields in the binlog, so this is extra important when + comparing records fetched from binlog and from storage + engine. + */ + if (table->file->ht->db_type == DB_TYPE_MYISAM) + goto record_compare_field_by_field; + if (table->s->blob_fields + table->s->varchar_fields == 0) { result= cmp_record(table,record[1]); @@ -366,14 +384,33 @@ static bool record_compare(TABLE *table) goto record_compare_exit; } +record_compare_field_by_field: + /* Compare updated fields */ for (Field **ptr=table->field ; *ptr ; ptr++) { - if ((*ptr)->cmp_binary_offset(table->s->rec_buff_length)) + Field *f= *ptr; + + /* if just one of the fields is null then there is no match */ + if ((f->is_null_in_record(table->record[0])) == + !(f->is_null_in_record(table->record[1]))) { result= TRUE; goto record_compare_exit; } + + /* if both fields are not null then we can compare */ + if (!(f->is_null_in_record(table->record[0])) && + !(f->is_null_in_record(table->record[1]))) + { + if (f->cmp_binary_offset(table->s->rec_buff_length)) + { + result= TRUE; + goto record_compare_exit; + } + } + + /* if both fields are null then there is a match. compare next field */ } record_compare_exit: diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 7d8f8ea71b3..7ba1a657578 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -310,7 +310,7 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) { TABLE *table; READ_RECORD read_record_info; - my_bool return_val= 1; + my_bool return_val= TRUE; bool check_no_resolve= specialflag & SPECIAL_NO_RESOLVE; char tmp_name[NAME_LEN+1]; int password_length; @@ -623,7 +623,7 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) init_check_host(); initialized=1; - return_val=0; + return_val= FALSE; end: thd->variables.sql_mode= old_sql_mode; @@ -674,7 +674,7 @@ my_bool acl_reload(THD *thd) DYNAMIC_ARRAY old_acl_hosts,old_acl_users,old_acl_dbs; MEM_ROOT old_mem; bool old_initialized; - my_bool return_val= 1; + my_bool return_val= TRUE; DBUG_ENTER("acl_reload"); if (thd->locked_tables) @@ -701,8 +701,13 @@ my_bool acl_reload(THD *thd) if (simple_open_n_lock_tables(thd, tables)) { - sql_print_error("Fatal error: Can't open and lock privilege tables: %s", - thd->main_da.message()); + /* + Execution might have been interrupted; only print the error message + if an error condition has been raised. + */ + if (thd->main_da.is_error()) + sql_print_error("Fatal error: Can't open and lock privilege tables: %s", + thd->main_da.message()); goto end; } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 48743a2d48f..eaea6e55b09 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -6789,13 +6789,13 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, thd->store_globals(); lex_start(thd); } - + if (thd) { bool reload_acl_failed= acl_reload(thd); bool reload_grants_failed= grant_reload(thd); bool reload_servers_failed= servers_reload(thd); - + if (reload_acl_failed || reload_grants_failed || reload_servers_failed) { result= 1; @@ -6951,7 +6951,10 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, if (options & REFRESH_USER_RESOURCES) reset_mqh((LEX_USER *) NULL, 0); /* purecov: inspected */ *write_to_binlog= tmp_write_to_binlog; - return result; + /* + If the query was killed then this function must fail. + */ + return result || thd->killed; } diff --git a/sql/sql_servers.cc b/sql/sql_servers.cc index f8a8dea18ff..1655426bb4a 100644 --- a/sql/sql_servers.cc +++ b/sql/sql_servers.cc @@ -241,8 +241,14 @@ bool servers_reload(THD *thd) if (simple_open_n_lock_tables(thd, tables)) { - sql_print_error("Can't open and lock privilege tables: %s", - thd->main_da.message()); + /* + Execution might have been interrupted; only print the error message + if an error condition has been raised. + */ + if (thd->main_da.is_error()) + sql_print_error("Can't open and lock privilege tables: %s", + thd->main_da.message()); + return_val= FALSE; goto end; } |