From 5babac539d03b4bb9aff2f74965b98c8506726e5 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 26 Jul 2007 11:31:10 +0300 Subject: [PATCH 01/26] Bug #29571: INSERT DELAYED IGNORE written to binary log on the master but on the slave MySQL can decide to "downgrade" a INSERT DELAYED statement to normal insert in certain situations. One such situation is when the slave is replaying a replication feed. However INSERT DELAYED is logged even if there're no updates whereas the NORMAL INSERT is not logged in such cases. Fixed by always logging a "downgraded" INSERT DELAYED: even if there were no updates. mysql-test/r/rpl_insert_delayed.result: Bug #29571: test case mysql-test/t/rpl_insert_delayed.test: Bug #29571: test case sql/sql_insert.cc: Bug #29571: log INSERT DELAYED even if it was "downgraded" to INSERT (and there were no updates) --- mysql-test/r/rpl_insert_delayed.result | 20 ++++++++++++++++++ mysql-test/t/rpl_insert_delayed.test | 29 ++++++++++++++++++++++++++ sql/sql_insert.cc | 9 +++++--- 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/rpl_insert_delayed.result b/mysql-test/r/rpl_insert_delayed.result index 38e2cddd650..ddf6e9c2165 100644 --- a/mysql-test/r/rpl_insert_delayed.result +++ b/mysql-test/r/rpl_insert_delayed.result @@ -29,3 +29,23 @@ id name 10 my name 20 is Bond drop table t1; +CREATE TABLE t1(a int, UNIQUE(a)); +INSERT DELAYED IGNORE INTO t1 VALUES(1); +INSERT DELAYED IGNORE INTO t1 VALUES(1); +show binlog events limit 11,100; +Log_name Pos Event_type Server_id End_log_pos Info +x x x x x use `test`; INSERT DELAYED IGNORE INTO t1 VALUES(1) +x x x x x use `test`; INSERT DELAYED IGNORE INTO t1 VALUES(1) +select * from t1; +a +1 +On slave +show binlog events limit 12,100; +Log_name Pos Event_type Server_id End_log_pos Info +x x x x x use `test`; INSERT DELAYED IGNORE INTO t1 VALUES(1) +x x x x x use `test`; INSERT DELAYED IGNORE INTO t1 VALUES(1) +select * from t1; +a +1 +drop table t1; +End of 5.0 tests diff --git a/mysql-test/t/rpl_insert_delayed.test b/mysql-test/t/rpl_insert_delayed.test index 3f72f3a3625..141f36a694a 100644 --- a/mysql-test/t/rpl_insert_delayed.test +++ b/mysql-test/t/rpl_insert_delayed.test @@ -65,3 +65,32 @@ connection master; drop table t1; sync_slave_with_master; connection master; + +# +# Bug #29571: INSERT DELAYED IGNORE written to binary log on the master but +# on the slave +# +CREATE TABLE t1(a int, UNIQUE(a)); +INSERT DELAYED IGNORE INTO t1 VALUES(1); +INSERT DELAYED IGNORE INTO t1 VALUES(1); + +#must show two INSERT DELAYED +--replace_column 1 x 2 x 3 x 4 x 5 x +show binlog events limit 11,100; +select * from t1; + +sync_slave_with_master; +echo On slave; +#must show two INSERT DELAYED +--replace_column 1 x 2 x 3 x 4 x 5 x +show binlog events limit 12,100; +select * from t1; + + +# clean up +connection master; +drop table t1; +sync_slave_with_master; +connection master; + +--echo End of 5.0 tests diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 73f8c5e4418..618ba62ef19 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -560,6 +560,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, int error, res; bool transactional_table, joins_freed= FALSE; bool changed; + bool was_insert_delayed= (table_list->lock_type == TL_WRITE_DELAYED); uint value_count; ulong counter = 1; ulonglong id; @@ -859,14 +860,16 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, transactional_table= table->file->has_transactions(); - if ((changed= (info.copied || info.deleted || info.updated))) + if ((changed= (info.copied || info.deleted || info.updated)) || + was_insert_delayed) { /* Invalidate the table in the query cache if something changed. For the transactional algorithm to work the invalidation must be before binlog writing and ha_autocommit_or_rollback */ - query_cache_invalidate3(thd, table_list, 1); + if (changed) + query_cache_invalidate3(thd, table_list, 1); if (error <= 0 || !transactional_table) { if (mysql_bin_log.is_open()) @@ -904,7 +907,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, if (mysql_bin_log.write(&qinfo) && transactional_table) error=1; } - if (!transactional_table) + if (!transactional_table && changed) thd->no_trans_update.all= TRUE; } } From f2a91e55c8c522877c1af0dd99b6300b3f4d5f01 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 26 Jul 2007 16:59:21 +0300 Subject: [PATCH 02/26] Addendum to bug 29571: wait for INSERT DELAYED to finish on master --- mysql-test/r/rpl_insert_delayed.result | 3 +++ mysql-test/t/rpl_insert_delayed.test | 1 + 2 files changed, 4 insertions(+) diff --git a/mysql-test/r/rpl_insert_delayed.result b/mysql-test/r/rpl_insert_delayed.result index ddf6e9c2165..6815a727fd7 100644 --- a/mysql-test/r/rpl_insert_delayed.result +++ b/mysql-test/r/rpl_insert_delayed.result @@ -32,10 +32,12 @@ drop table t1; CREATE TABLE t1(a int, UNIQUE(a)); INSERT DELAYED IGNORE INTO t1 VALUES(1); INSERT DELAYED IGNORE INTO t1 VALUES(1); +flush table t1; show binlog events limit 11,100; Log_name Pos Event_type Server_id End_log_pos Info x x x x x use `test`; INSERT DELAYED IGNORE INTO t1 VALUES(1) x x x x x use `test`; INSERT DELAYED IGNORE INTO t1 VALUES(1) +x x x x x use `test`; flush table t1 select * from t1; a 1 @@ -44,6 +46,7 @@ show binlog events limit 12,100; Log_name Pos Event_type Server_id End_log_pos Info x x x x x use `test`; INSERT DELAYED IGNORE INTO t1 VALUES(1) x x x x x use `test`; INSERT DELAYED IGNORE INTO t1 VALUES(1) +x x x x x use `test`; flush table t1 select * from t1; a 1 diff --git a/mysql-test/t/rpl_insert_delayed.test b/mysql-test/t/rpl_insert_delayed.test index 141f36a694a..09e0c5cc2e9 100644 --- a/mysql-test/t/rpl_insert_delayed.test +++ b/mysql-test/t/rpl_insert_delayed.test @@ -73,6 +73,7 @@ connection master; CREATE TABLE t1(a int, UNIQUE(a)); INSERT DELAYED IGNORE INTO t1 VALUES(1); INSERT DELAYED IGNORE INTO t1 VALUES(1); +flush table t1; # to wait for INSERT DELAYED to be done #must show two INSERT DELAYED --replace_column 1 x 2 x 3 x 4 x 5 x From c7150fd814603bb12a686ea0857296b92282de1b Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 26 Jul 2007 18:33:05 +0300 Subject: [PATCH 03/26] Bug #30036: SHOW TABLE TYPES causes the debug client to crash SHOW TABLE TYPES is a (to be deprecated) synonym for SHOW STORAGE ENGINES. Fixed to use the right schema table in addition to issuing a warning. mysql-test/r/show_check.result: Bug #30036: test case mysql-test/t/show_check.test: Bug #30036: test case sql/sql_yacc.yy: Bug #30036: use the right schema table --- mysql-test/r/show_check.result | 1 + mysql-test/t/show_check.test | 8 ++++++++ sql/sql_yacc.yy | 2 ++ 3 files changed, 11 insertions(+) diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result index 2bdd29602fb..83881be8ad4 100644 --- a/mysql-test/r/show_check.result +++ b/mysql-test/r/show_check.result @@ -1351,4 +1351,5 @@ DROP PROCEDURE p1; DROP FUNCTION f1; DROP TABLE t1; DROP EVENT ev1; +SHOW TABLE TYPES; End of 5.1 tests diff --git a/mysql-test/t/show_check.test b/mysql-test/t/show_check.test index 09c0b08a3cd..f2dba49f455 100644 --- a/mysql-test/t/show_check.test +++ b/mysql-test/t/show_check.test @@ -977,4 +977,12 @@ DROP FUNCTION f1; DROP TABLE t1; DROP EVENT ev1; +# +# Bug #30036: SHOW TABLE TYPES causes the debug client to crash +# +--disable_result_log +SHOW TABLE TYPES; +--enable_result_log + + --echo End of 5.1 tests diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index d9a808bf8f7..468c3305c57 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -8729,6 +8729,8 @@ show_param: LEX *lex=Lex; lex->sql_command= SQLCOM_SHOW_STORAGE_ENGINES; WARN_DEPRECATED(yythd, "5.2", "SHOW TABLE TYPES", "'SHOW [STORAGE] ENGINES'"); + if (prepare_schema_table(YYTHD, lex, 0, SCH_ENGINES)) + MYSQL_YYABORT; } | opt_storage ENGINES_SYM { From 9206f6847742a208500da660a2e76306e3fadae3 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 26 Jul 2007 20:52:53 +0400 Subject: [PATCH 04/26] BUG#28591: make the fix work for BDB tables too: - make ha_berkeley::cmp_ref() take into account that auto-generated PKs are stored in LSB-first order. - Remove the temporary code that made the bugfix work for innodb only mysql-test/r/bdb.result: Adjust test-results. sql/ha_berkeley.cc: BUG#28591: make the fix work for BDB tables too: - make ha_berkeley::cmp_ref() take into account that auto-generated PKs are stored in LSB-first order. sql/sql_select.cc: BUG#28591: Remove "innodb only" clause as the fix now works for BDB too sql/table.cc: BUG#28591: Remove "innodb only" clause as the fix now works for BDB too --- mysql-test/r/bdb.result | 2 +- sql/ha_berkeley.cc | 6 +++++- sql/sql_select.cc | 1 - sql/table.cc | 3 +-- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/bdb.result b/mysql-test/r/bdb.result index 91c385112b4..3356d23053f 100644 --- a/mysql-test/r/bdb.result +++ b/mysql-test/r/bdb.result @@ -136,8 +136,8 @@ update ignore t1 set id=1023 where id=1010; select * from t1 where parent_id=102 order by parent_id,id; id parent_id level 1008 102 2 -1010 102 2 1015 102 2 +1010 102 2 explain select level from t1 where level=1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ref level level 1 const X Using index diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc index 2a5fe775ca6..fbfd5031656 100644 --- a/sql/ha_berkeley.cc +++ b/sql/ha_berkeley.cc @@ -2646,7 +2646,11 @@ ha_rows ha_berkeley::estimate_rows_upper_bound() int ha_berkeley::cmp_ref(const byte *ref1, const byte *ref2) { if (hidden_primary_key) - return memcmp(ref1, ref2, BDB_HIDDEN_PRIMARY_KEY_LENGTH); + { + ulonglong a=uint5korr((char*) ref1); + ulonglong b=uint5korr((char*) ref2); + return a < b ? -1 : (a > b ? 1 : 0); + } int result; Field *field; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 2d9d261bb31..d82a0fdcf41 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -12033,7 +12033,6 @@ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx, */ if (!on_primary_key && (table->file->table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX) && - table->s->db_type == DB_TYPE_INNODB && table->s->primary_key != MAX_KEY) { on_primary_key= TRUE; diff --git a/sql/table.cc b/sql/table.cc index ce894e6910f..18a395d69af 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -782,8 +782,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat, if (ha_option & HA_PRIMARY_KEY_IN_READ_INDEX) { field->part_of_key= share->keys_in_use; - if (share->db_type == DB_TYPE_INNODB && - field->part_of_sortkey.is_set(key)) + if (field->part_of_sortkey.is_set(key)) field->part_of_sortkey= share->keys_in_use; } } From 13c679124f2f0e6ebe23aa0cd484e1bcc4896619 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 27 Jul 2007 14:28:36 +0300 Subject: [PATCH 05/26] 5.0-opt -> 5.1-opt merge of the test case for bug 29571: - reset the logs before and after the test. - cleanup from the previous tests : use the correct schema. mysql-test/extra/rpl_tests/rpl_insert_delayed.test: 5.0-opt -> 5.1-opt merge of the test case for bug 29571. mysql-test/suite/rpl/r/rpl_stm_insert_delayed.result: 5.0-opt -> 5.1-opt merge of the test case for bug 29571. --- .../extra/rpl_tests/rpl_insert_delayed.test | 15 +++++- .../suite/rpl/r/rpl_stm_insert_delayed.result | 52 +++++++++++++++++++ 2 files changed, 65 insertions(+), 2 deletions(-) diff --git a/mysql-test/extra/rpl_tests/rpl_insert_delayed.test b/mysql-test/extra/rpl_tests/rpl_insert_delayed.test index 9364bcbec48..1dc14748688 100644 --- a/mysql-test/extra/rpl_tests/rpl_insert_delayed.test +++ b/mysql-test/extra/rpl_tests/rpl_insert_delayed.test @@ -83,12 +83,19 @@ connection master; USE test; DROP SCHEMA mysqlslap; sync_slave_with_master; +use test; connection master; # # Bug #29571: INSERT DELAYED IGNORE written to binary log on the master but # on the slave # +#flush the logs before the test +connection slave; +FLUSH LOGS; +connection master; +FLUSH LOGS; + CREATE TABLE t1(a int, UNIQUE(a)); INSERT DELAYED IGNORE INTO t1 VALUES(1); INSERT DELAYED IGNORE INTO t1 VALUES(1); @@ -96,14 +103,14 @@ flush table t1; # to wait for INSERT DELAYED to be done #must show two INSERT DELAYED --replace_column 1 x 2 x 3 x 4 x 5 x -show binlog events limit 11,100; +show binlog events in 'master-bin.000002' LIMIT 2,2; select * from t1; sync_slave_with_master; echo On slave; #must show two INSERT DELAYED --replace_column 1 x 2 x 3 x 4 x 5 x -show binlog events limit 12,100; +show binlog events in 'slave-bin.000002' LIMIT 2,2; select * from t1; @@ -111,6 +118,10 @@ select * from t1; connection master; drop table t1; sync_slave_with_master; +#flush the logs after the test +FLUSH LOGS; connection master; +FLUSH LOGS; + --echo End of 5.0 tests diff --git a/mysql-test/suite/rpl/r/rpl_stm_insert_delayed.result b/mysql-test/suite/rpl/r/rpl_stm_insert_delayed.result index 1c003856eb9..5ca0ea2b780 100644 --- a/mysql-test/suite/rpl/r/rpl_stm_insert_delayed.result +++ b/mysql-test/suite/rpl/r/rpl_stm_insert_delayed.result @@ -45,6 +45,32 @@ id name 20 is Bond USE test; DROP SCHEMA mysqlslap; +use test; +FLUSH LOGS; +FLUSH LOGS; +CREATE TABLE t1(a int, UNIQUE(a)); +INSERT DELAYED IGNORE INTO t1 VALUES(1); +INSERT DELAYED IGNORE INTO t1 VALUES(1); +flush table t1; +show binlog events in 'master-bin.000002' LIMIT 2,2; +Log_name Pos Event_type Server_id End_log_pos Info +x x x x x use `test`; INSERT DELAYED IGNORE INTO t1 VALUES(1) +x x x x x use `test`; INSERT DELAYED IGNORE INTO t1 VALUES(1) +select * from t1; +a +1 +On slave +show binlog events in 'slave-bin.000002' LIMIT 2,2; +Log_name Pos Event_type Server_id End_log_pos Info +x x x x x use `test`; INSERT DELAYED IGNORE INTO t1 VALUES(1) +x x x x x use `test`; INSERT DELAYED IGNORE INTO t1 VALUES(1) +select * from t1; +a +1 +drop table t1; +FLUSH LOGS; +FLUSH LOGS; +End of 5.0 tests set @@global.binlog_format = mixed; CREATE SCHEMA IF NOT EXISTS mysqlslap; USE mysqlslap; @@ -85,4 +111,30 @@ id name 20 is Bond USE test; DROP SCHEMA mysqlslap; +use test; +FLUSH LOGS; +FLUSH LOGS; +CREATE TABLE t1(a int, UNIQUE(a)); +INSERT DELAYED IGNORE INTO t1 VALUES(1); +INSERT DELAYED IGNORE INTO t1 VALUES(1); +flush table t1; +show binlog events in 'master-bin.000002' LIMIT 2,2; +Log_name Pos Event_type Server_id End_log_pos Info +x x x x x use `test`; INSERT DELAYED IGNORE INTO t1 VALUES(1) +x x x x x use `test`; INSERT DELAYED IGNORE INTO t1 VALUES(1) +select * from t1; +a +1 +On slave +show binlog events in 'slave-bin.000002' LIMIT 2,2; +Log_name Pos Event_type Server_id End_log_pos Info +x x x x x use `test`; INSERT DELAYED IGNORE INTO t1 VALUES(1) +x x x x x use `test`; INSERT DELAYED IGNORE INTO t1 VALUES(1) +select * from t1; +a +1 +drop table t1; +FLUSH LOGS; +FLUSH LOGS; +End of 5.0 tests set @@global.binlog_format = @old_global_binlog_format; From 78587a08acfc4d9f34ffaf09672ded531eb4c38a Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 27 Jul 2007 15:36:10 +0300 Subject: [PATCH 06/26] portation of the test case for bug 29571 to cover row replication --- .../suite/rpl/r/rpl_row_insert_delayed.result | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/mysql-test/suite/rpl/r/rpl_row_insert_delayed.result b/mysql-test/suite/rpl/r/rpl_row_insert_delayed.result index 2044672f49d..87b375bf653 100644 --- a/mysql-test/suite/rpl/r/rpl_row_insert_delayed.result +++ b/mysql-test/suite/rpl/r/rpl_row_insert_delayed.result @@ -45,4 +45,30 @@ id name 20 is Bond USE test; DROP SCHEMA mysqlslap; +use test; +FLUSH LOGS; +FLUSH LOGS; +CREATE TABLE t1(a int, UNIQUE(a)); +INSERT DELAYED IGNORE INTO t1 VALUES(1); +INSERT DELAYED IGNORE INTO t1 VALUES(1); +flush table t1; +show binlog events in 'master-bin.000002' LIMIT 2,2; +Log_name Pos Event_type Server_id End_log_pos Info +x x x x x table_id: 23 (test.t1) +x x x x x table_id: 23 flags: STMT_END_F +select * from t1; +a +1 +On slave +show binlog events in 'slave-bin.000002' LIMIT 2,2; +Log_name Pos Event_type Server_id End_log_pos Info +x x x x x table_id: 23 (test.t1) +x x x x x table_id: 23 flags: STMT_END_F +select * from t1; +a +1 +drop table t1; +FLUSH LOGS; +FLUSH LOGS; +End of 5.0 tests set @@global.binlog_format = @old_global_binlog_format; From d27bf14ed7aab39b8b83d0eed34cb3ba4417de35 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 27 Jul 2007 18:42:25 +0500 Subject: [PATCH 07/26] Bug #29878 Garbage data generation when executing SESSION_USER() on a slave. Item_func_user doesn't calculate anything in it's val_str() method, just returns saved str_value. Though Item::save_in_field method can destroy str_value, relying on val_str() return. As a result we get the garbage stored in field. We cannot use Item::save_in_field implementation for Item_func_user, reimplement it in simpler way. mysql-test/r/rpl_session_var.result: Bug #29878 Garbage data generation when executing SESSION_USER() on a slave. test result mysql-test/t/rpl_session_var.test: Bug #29878 Garbage data generation when executing SESSION_USER() on a slave. test case sql/item.cc: Bug #29878 Garbage data generation when executing SESSION_USER() on a slave. duplicating code moved to Item::save_str_in_field sql/item.h: Bug #29878 Garbage data generation when executing SESSION_USER() on a slave. duplicating code moved to Item::save_str_in_field sql/item_strfunc.h: Bug #29878 Garbage data generation when executing SESSION_USER() on a slave. Item_func_user::save_in_field implemented as simple storing str_value --- mysql-test/r/rpl_session_var.result | 10 ++++++ mysql-test/t/rpl_session_var.test | 22 ++++++++++++ sql/item.cc | 52 +++++++++++++++++++++-------- sql/item.h | 6 +++- sql/item_strfunc.h | 4 +++ 5 files changed, 79 insertions(+), 15 deletions(-) diff --git a/mysql-test/r/rpl_session_var.result b/mysql-test/r/rpl_session_var.result index b5b4b815ade..787899932d6 100644 --- a/mysql-test/r/rpl_session_var.result +++ b/mysql-test/r/rpl_session_var.result @@ -41,3 +41,13 @@ select * from t2 order by b; b a 1 1 drop table t1,t2; +CREATE TABLE t1 ( +`id` int(11) NOT NULL auto_increment, +`data` varchar(100), +PRIMARY KEY (`id`) +) ENGINE=MyISAM; +INSERT INTO t1(data) VALUES(SESSION_USER()); +SELECT * FROM t1; +id data +1 +drop table t1; diff --git a/mysql-test/t/rpl_session_var.test b/mysql-test/t/rpl_session_var.test index a6f4b496a23..8231a0dbefd 100644 --- a/mysql-test/t/rpl_session_var.test +++ b/mysql-test/t/rpl_session_var.test @@ -40,3 +40,25 @@ drop table t1,t2; save_master_pos; connection slave; sync_with_master; + +# +# Bug #29878 Garbage data generation when executing SESSION_USER() on a slave. +# + +connection master; +CREATE TABLE t1 ( + `id` int(11) NOT NULL auto_increment, + `data` varchar(100), + PRIMARY KEY (`id`) + ) ENGINE=MyISAM; + +INSERT INTO t1(data) VALUES(SESSION_USER()); +save_master_pos; +connection slave; +sync_with_master; +SELECT * FROM t1; +connection master; +drop table t1; +save_master_pos; +connection slave; +sync_with_master; diff --git a/sql/item.cc b/sql/item.cc index 2fc58eebe75..bd47fb706a6 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -336,6 +336,37 @@ int Item::save_date_in_field(Field *field) } +/* + Store the string value in field directly + + SYNOPSIS + Item::save_str_value_in_field() + field a pointer to field where to store + result the pointer to the string value to be stored + + DESCRIPTION + The method is used by Item_*::save_in_field implementations + when we don't need to calculate the value to store + See Item_string::save_in_field() implementation for example + + IMPLEMENTATION + Check if the Item is null and stores the NULL or the + result value in the field accordingly. + + RETURN + Nonzero value if error +*/ + +int Item::save_str_value_in_field(Field *field, String *result) +{ + if (null_value) + return set_field_to_null(field); + field->set_notnull(); + return field->store(result->ptr(), result->length(), + collation.collation); +} + + Item::Item(): rsize(0), name(0), orig_name(0), name_length(0), fixed(0), is_autogenerated_name(TRUE), @@ -3009,16 +3040,6 @@ my_decimal *Item_copy_string::val_decimal(my_decimal *decimal_value) } - -int Item_copy_string::save_in_field(Field *field, bool no_conversions) -{ - if (null_value) - return set_field_to_null(field); - field->set_notnull(); - return field->store(str_value.ptr(),str_value.length(), - collation.collation); -} - /* Functions to convert item to field (for send_fields) */ @@ -4417,6 +4438,12 @@ int Item_null::save_safe_in_field(Field *field) } +/* + This implementation can lose str_value content, so if the + Item uses str_value to store something, it should + reimplement it's ::save_in_field() as Item_string, for example, does +*/ + int Item::save_in_field(Field *field, bool no_conversions) { int error; @@ -4474,10 +4501,7 @@ int Item_string::save_in_field(Field *field, bool no_conversions) { String *result; result=val_str(&str_value); - if (null_value) - return set_field_to_null(field); - field->set_notnull(); - return field->store(result->ptr(),result->length(),collation.collation); + return save_str_value_in_field(field, result); } diff --git a/sql/item.h b/sql/item.h index 5b1a80a5f03..72236cb5e63 100644 --- a/sql/item.h +++ b/sql/item.h @@ -612,6 +612,7 @@ public: int save_time_in_field(Field *field); int save_date_in_field(Field *field); + int save_str_value_in_field(Field *field, String *result); virtual Field *get_tmp_table_field() { return 0; } /* This is also used to create fields in CREATE ... SELECT: */ @@ -2166,7 +2167,10 @@ public: my_decimal *val_decimal(my_decimal *); void make_field(Send_field *field) { item->make_field(field); } void copy(); - int save_in_field(Field *field, bool no_conversions); + int save_in_field(Field *field, bool no_conversions) + { + return save_str_value_in_field(field, &str_value); + } table_map used_tables() const { return (table_map) 1L; } bool const_item() const { return 0; } bool is_null() { return null_value; } diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index d7c4a3eddef..6ca0b89a22b 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -434,6 +434,10 @@ public: } const char *func_name() const { return "user"; } const char *fully_qualified_func_name() const { return "user()"; } + int save_in_field(Field *field, bool no_conversions) + { + return save_str_value_in_field(field, &str_value); + } }; From d47763406d40cf429696e77ec5ef34720c6e9b5f Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 27 Jul 2007 17:29:48 +0300 Subject: [PATCH 08/26] fixing the 5.1-opt merge of the fix for bug 29571: cannot check the statments in the binlog for row based replication. --- .../extra/rpl_tests/rpl_insert_delayed.test | 41 ++++++++++++------- .../suite/rpl/r/rpl_row_insert_delayed.result | 12 ------ 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/mysql-test/extra/rpl_tests/rpl_insert_delayed.test b/mysql-test/extra/rpl_tests/rpl_insert_delayed.test index 1dc14748688..e492903afad 100644 --- a/mysql-test/extra/rpl_tests/rpl_insert_delayed.test +++ b/mysql-test/extra/rpl_tests/rpl_insert_delayed.test @@ -90,27 +90,36 @@ connection master; # Bug #29571: INSERT DELAYED IGNORE written to binary log on the master but # on the slave # -#flush the logs before the test -connection slave; -FLUSH LOGS; -connection master; -FLUSH LOGS; +if (`SELECT @@global.binlog_format != 'ROW'`) +{ + #flush the logs before the test + connection slave; + FLUSH LOGS; + connection master; + FLUSH LOGS; +} CREATE TABLE t1(a int, UNIQUE(a)); INSERT DELAYED IGNORE INTO t1 VALUES(1); INSERT DELAYED IGNORE INTO t1 VALUES(1); flush table t1; # to wait for INSERT DELAYED to be done -#must show two INSERT DELAYED ---replace_column 1 x 2 x 3 x 4 x 5 x -show binlog events in 'master-bin.000002' LIMIT 2,2; +if (`SELECT @@global.binlog_format != 'ROW'`) +{ + #must show two INSERT DELAYED + --replace_column 1 x 2 x 3 x 4 x 5 x + show binlog events in 'master-bin.000002' LIMIT 2,2; +} select * from t1; sync_slave_with_master; echo On slave; -#must show two INSERT DELAYED ---replace_column 1 x 2 x 3 x 4 x 5 x -show binlog events in 'slave-bin.000002' LIMIT 2,2; +if (`SELECT @@global.binlog_format != 'ROW'`) +{ + #must show two INSERT DELAYED + --replace_column 1 x 2 x 3 x 4 x 5 x + show binlog events in 'slave-bin.000002' LIMIT 2,2; +} select * from t1; @@ -118,10 +127,14 @@ select * from t1; connection master; drop table t1; sync_slave_with_master; -#flush the logs after the test -FLUSH LOGS; +if (`SELECT @@global.binlog_format != 'ROW'`) +{ + #flush the logs after the test + FLUSH LOGS; + connection master; + FLUSH LOGS; +} connection master; -FLUSH LOGS; --echo End of 5.0 tests diff --git a/mysql-test/suite/rpl/r/rpl_row_insert_delayed.result b/mysql-test/suite/rpl/r/rpl_row_insert_delayed.result index 87b375bf653..1551d83266d 100644 --- a/mysql-test/suite/rpl/r/rpl_row_insert_delayed.result +++ b/mysql-test/suite/rpl/r/rpl_row_insert_delayed.result @@ -46,29 +46,17 @@ id name USE test; DROP SCHEMA mysqlslap; use test; -FLUSH LOGS; -FLUSH LOGS; CREATE TABLE t1(a int, UNIQUE(a)); INSERT DELAYED IGNORE INTO t1 VALUES(1); INSERT DELAYED IGNORE INTO t1 VALUES(1); flush table t1; -show binlog events in 'master-bin.000002' LIMIT 2,2; -Log_name Pos Event_type Server_id End_log_pos Info -x x x x x table_id: 23 (test.t1) -x x x x x table_id: 23 flags: STMT_END_F select * from t1; a 1 On slave -show binlog events in 'slave-bin.000002' LIMIT 2,2; -Log_name Pos Event_type Server_id End_log_pos Info -x x x x x table_id: 23 (test.t1) -x x x x x table_id: 23 flags: STMT_END_F select * from t1; a 1 drop table t1; -FLUSH LOGS; -FLUSH LOGS; End of 5.0 tests set @@global.binlog_format = @old_global_binlog_format; From 82c87c0a44d17ff2ae723c1ac38ad103bf6949f5 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 27 Jul 2007 17:55:39 +0300 Subject: [PATCH 09/26] Bug #30000: SHOW commands once again ends up in the slow query log Disable the SHOW commands to appear in the show query log. Update the commands type array. mysql-test/r/show_check.result: Bug #30000: test case mysql-test/t/show_check.test: Bug #30000: test case sql/sql_parse.cc: Bug #30000: skip SHOW commands from the slow query log. --- mysql-test/r/show_check.result | 70 +++++++++++++++++++++++++++++++--- mysql-test/t/show_check.test | 64 +++++++++++++++++++++++++++++++ sql/sql_parse.cc | 36 ++++++++++++++--- 3 files changed, 160 insertions(+), 10 deletions(-) diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result index 83881be8ad4..f84d4f3882c 100644 --- a/mysql-test/r/show_check.result +++ b/mysql-test/r/show_check.result @@ -790,13 +790,73 @@ show tables; Tables_in_test show status like 'slow_queries'; Variable_name Value -Slow_queries 1 +Slow_queries 0 select 1 from information_schema.tables limit 1; 1 1 show status like 'slow_queries'; Variable_name Value -Slow_queries 2 +Slow_queries 1 +create table t1 (a int); +create trigger tr1 before insert on t1 for each row +begin +end; +create view v1 as select a from t1; +create procedure p1() +begin +end; +create function f1() +returns int +return 0; +create event e1 on schedule every 1 year starts now() +ends date_add(now(), interval 5 hour) do +begin +end; +flush status; +show databases; +show tables; +show events; +show table status; +show open tables; +show plugins; +show columns in t1; +show slave hosts; +show keys in t1; +show column types; +show table types; +show storage engines; +show authors; +show contributors; +show privileges; +show count(*) warnings; +show count(*) errors; +show warnings; +show status; +show processlist; +show variables; +show charset; +show collation; +show grants; +show create database test; +show create table t1; +show create view v1; +show master status; +show slave status; +show create procedure p1; +show create function f1; +show create trigger tr1; +show procedure status; +show procedure code p1; +show function code f1; +show create event e1; +show status like 'slow_queries'; +Variable_name Value +Slow_queries 0 +drop view v1; +drop table t1; +drop procedure p1; +drop function f1; +drop event e1; DROP DATABASE IF EXISTS mysqltest1; DROP TABLE IF EXISTS t1; DROP VIEW IF EXISTS v1; @@ -1157,7 +1217,7 @@ select 1 from information_schema.tables limit 1; 1 show status like 'slow_queries'; Variable_name Value -Slow_queries 2 +Slow_queries 1 set global log_queries_not_using_indexes=OFF; show variables like "log_queries_not_using_indexes"; Variable_name Value @@ -1167,7 +1227,7 @@ select 1 from information_schema.tables limit 1; 1 show status like 'slow_queries'; Variable_name Value -Slow_queries 2 +Slow_queries 1 set global log_queries_not_using_indexes=ON; show variables like "log_queries_not_using_indexes"; Variable_name Value @@ -1177,7 +1237,7 @@ select 1 from information_schema.tables limit 1; 1 show status like 'slow_queries'; Variable_name Value -Slow_queries 4 +Slow_queries 2 End of 5.0 tests SHOW AUTHORS; create database mysqltest; diff --git a/mysql-test/t/show_check.test b/mysql-test/t/show_check.test index f2dba49f455..89eac15ccfc 100644 --- a/mysql-test/t/show_check.test +++ b/mysql-test/t/show_check.test @@ -549,6 +549,70 @@ show status like 'slow_queries'; # (mysqld is started with --log-queries-not-using-indexes) select 1 from information_schema.tables limit 1; show status like 'slow_queries'; + +create table t1 (a int); +create trigger tr1 before insert on t1 for each row +begin +end; +create view v1 as select a from t1; +create procedure p1() +begin +end; +create function f1() +returns int +return 0; +create event e1 on schedule every 1 year starts now() + ends date_add(now(), interval 5 hour) do +begin +end; + +--disable_result_log +flush status; +show databases; +show tables; +show events; +show table status; +show open tables; +show plugins; +show columns in t1; +show slave hosts; +show keys in t1; +show column types; +show table types; +show storage engines; +show authors; +show contributors; +show privileges; +show count(*) warnings; +show count(*) errors; +show warnings; +show status; +show processlist; +show variables; +show charset; +show collation; +show grants; +show create database test; +show create table t1; +show create view v1; +show master status; +show slave status; +show create procedure p1; +show create function f1; +show create trigger tr1; +show procedure status; +show procedure code p1; +show function code f1; +show create event e1; +--enable_result_log + +show status like 'slow_queries'; + +drop view v1; +drop table t1; +drop procedure p1; +drop function f1; +drop event e1; # # BUG#10491: Server returns data as charset binary SHOW CREATE TABLE or SELECT # FROM I_S. diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 93887db88e1..63971609794 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -223,7 +223,6 @@ void init_update_queries(void) sql_command_flags[SQLCOM_REPLACE_SELECT]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT; sql_command_flags[SQLCOM_SHOW_STATUS_PROC]= CF_STATUS_COMMAND; - sql_command_flags[SQLCOM_SHOW_STATUS_FUNC]= CF_STATUS_COMMAND; sql_command_flags[SQLCOM_SHOW_STATUS]= CF_STATUS_COMMAND; sql_command_flags[SQLCOM_SHOW_DATABASES]= CF_STATUS_COMMAND; sql_command_flags[SQLCOM_SHOW_TRIGGERS]= CF_STATUS_COMMAND; @@ -235,10 +234,36 @@ void init_update_queries(void) sql_command_flags[SQLCOM_SHOW_VARIABLES]= CF_STATUS_COMMAND; sql_command_flags[SQLCOM_SHOW_CHARSETS]= CF_STATUS_COMMAND; sql_command_flags[SQLCOM_SHOW_COLLATIONS]= CF_STATUS_COMMAND; - sql_command_flags[SQLCOM_SHOW_STATUS_PROC]= CF_STATUS_COMMAND; + sql_command_flags[SQLCOM_SHOW_NEW_MASTER]= CF_STATUS_COMMAND; + sql_command_flags[SQLCOM_SHOW_BINLOGS]= CF_STATUS_COMMAND; + sql_command_flags[SQLCOM_SHOW_SLAVE_HOSTS]= CF_STATUS_COMMAND; + sql_command_flags[SQLCOM_SHOW_BINLOG_EVENTS]= CF_STATUS_COMMAND; + sql_command_flags[SQLCOM_SHOW_COLUMN_TYPES]= CF_STATUS_COMMAND; + sql_command_flags[SQLCOM_SHOW_STORAGE_ENGINES]= CF_STATUS_COMMAND; + sql_command_flags[SQLCOM_SHOW_AUTHORS]= CF_STATUS_COMMAND; + sql_command_flags[SQLCOM_SHOW_CONTRIBUTORS]= CF_STATUS_COMMAND; + sql_command_flags[SQLCOM_SHOW_PRIVILEGES]= CF_STATUS_COMMAND; + sql_command_flags[SQLCOM_SHOW_WARNS]= CF_STATUS_COMMAND; + sql_command_flags[SQLCOM_SHOW_ERRORS]= CF_STATUS_COMMAND; + sql_command_flags[SQLCOM_SHOW_ENGINE_STATUS]= CF_STATUS_COMMAND; + sql_command_flags[SQLCOM_SHOW_ENGINE_MUTEX]= CF_STATUS_COMMAND; + sql_command_flags[SQLCOM_SHOW_ENGINE_LOGS]= CF_STATUS_COMMAND; + sql_command_flags[SQLCOM_SHOW_PROCESSLIST]= CF_STATUS_COMMAND; + sql_command_flags[SQLCOM_SHOW_GRANTS]= CF_STATUS_COMMAND; + sql_command_flags[SQLCOM_SHOW_CREATE_DB]= CF_STATUS_COMMAND; + sql_command_flags[SQLCOM_SHOW_CREATE]= CF_STATUS_COMMAND; + sql_command_flags[SQLCOM_SHOW_MASTER_STAT]= CF_STATUS_COMMAND; + sql_command_flags[SQLCOM_SHOW_SLAVE_STAT]= CF_STATUS_COMMAND; + sql_command_flags[SQLCOM_SHOW_CREATE_PROC]= CF_STATUS_COMMAND; + sql_command_flags[SQLCOM_SHOW_CREATE_FUNC]= CF_STATUS_COMMAND; + sql_command_flags[SQLCOM_SHOW_CREATE_TRIGGER]= CF_STATUS_COMMAND; + sql_command_flags[SQLCOM_SHOW_STATUS_FUNC]= CF_STATUS_COMMAND; + sql_command_flags[SQLCOM_SHOW_PROC_CODE]= CF_STATUS_COMMAND; + sql_command_flags[SQLCOM_SHOW_FUNC_CODE]= CF_STATUS_COMMAND; + sql_command_flags[SQLCOM_SHOW_CREATE_EVENT]= CF_STATUS_COMMAND; - sql_command_flags[SQLCOM_SHOW_TABLES]= (CF_STATUS_COMMAND | - CF_SHOW_TABLE_COMMAND); + sql_command_flags[SQLCOM_SHOW_TABLES]= (CF_STATUS_COMMAND | + CF_SHOW_TABLE_COMMAND); sql_command_flags[SQLCOM_SHOW_TABLE_STATUS]= (CF_STATUS_COMMAND | CF_SHOW_TABLE_COMMAND); @@ -1323,7 +1348,8 @@ void log_slow_statement(THD *thd) thd->variables.long_query_time || ((thd->server_status & (SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED)) && - opt_log_queries_not_using_indexes)) + opt_log_queries_not_using_indexes && + !(sql_command_flags[thd->lex->sql_command] & CF_STATUS_COMMAND))) { thd->status_var.long_query_count++; slow_log_print(thd, thd->query, thd->query_length, start_of_query); From 9c79db318c689e97186170207f315b8accb296d9 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 28 Jul 2007 08:42:43 +0300 Subject: [PATCH 10/26] show_check.result: Addendum to thr fix for bug 30000: show procedure/function code defined only in debug builds show_check.test: Addendum to thr fix for bug 30000: show procedure/function code defined only in debug builds mysql-test/t/show_check.test: Addendum to thr fix for bug 30000: show procedure/function code defined only in debug builds mysql-test/r/show_check.result: Addendum to thr fix for bug 30000: show procedure/function code defined only in debug builds --- mysql-test/r/show_check.result | 2 -- mysql-test/t/show_check.test | 2 -- 2 files changed, 4 deletions(-) diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result index f84d4f3882c..f4b5f2689f6 100644 --- a/mysql-test/r/show_check.result +++ b/mysql-test/r/show_check.result @@ -846,8 +846,6 @@ show create procedure p1; show create function f1; show create trigger tr1; show procedure status; -show procedure code p1; -show function code f1; show create event e1; show status like 'slow_queries'; Variable_name Value diff --git a/mysql-test/t/show_check.test b/mysql-test/t/show_check.test index 89eac15ccfc..5856803d390 100644 --- a/mysql-test/t/show_check.test +++ b/mysql-test/t/show_check.test @@ -601,8 +601,6 @@ show create procedure p1; show create function f1; show create trigger tr1; show procedure status; -show procedure code p1; -show function code f1; show create event e1; --enable_result_log From 5fb351ae072416d2ffa0209277cf9bafe10cd9e7 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 28 Jul 2007 14:10:56 +0500 Subject: [PATCH 11/26] rpl_session_var.test fixed to not depend on mysql_test_run parameters mysql-test/suite/rpl/r/rpl_session_var.result: result fixed mysql-test/suite/rpl/t/rpl_session_var.test: test fixed --- mysql-test/suite/rpl/r/rpl_session_var.result | 6 +++--- mysql-test/suite/rpl/t/rpl_session_var.test | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mysql-test/suite/rpl/r/rpl_session_var.result b/mysql-test/suite/rpl/r/rpl_session_var.result index 787899932d6..297a18a5931 100644 --- a/mysql-test/suite/rpl/r/rpl_session_var.result +++ b/mysql-test/suite/rpl/r/rpl_session_var.result @@ -47,7 +47,7 @@ CREATE TABLE t1 ( PRIMARY KEY (`id`) ) ENGINE=MyISAM; INSERT INTO t1(data) VALUES(SESSION_USER()); -SELECT * FROM t1; -id data -1 +SELECT length(data) < 100 FROM t1; +length(data) < 100 +1 drop table t1; diff --git a/mysql-test/suite/rpl/t/rpl_session_var.test b/mysql-test/suite/rpl/t/rpl_session_var.test index 8231a0dbefd..2491611e23d 100644 --- a/mysql-test/suite/rpl/t/rpl_session_var.test +++ b/mysql-test/suite/rpl/t/rpl_session_var.test @@ -56,7 +56,7 @@ INSERT INTO t1(data) VALUES(SESSION_USER()); save_master_pos; connection slave; sync_with_master; -SELECT * FROM t1; +SELECT length(data) < 100 FROM t1; connection master; drop table t1; save_master_pos; From 40d596c200bd03b5fb01ba5b9af5912d65cc586d Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 28 Jul 2007 15:01:29 +0400 Subject: [PATCH 12/26] Bug#29856: Insufficient buffer space led to a server crash. The subst_spvars function is used to create query string with SP variables substituted with their values. This string is used later for the binary log and for the query cache. The problem is that the query_cache_send_result_to_client function requires some additional space after the query to store database name and query cache flags. This space wasn't reserved by the subst_spvars function which led to a memory corruption and crash. Now the subst_spvars function reserves additional space for the query cache. mysql-test/t/query_cache.test: Added a test case for the bug#29856: Insufficient buffer space led to a server crash. mysql-test/r/query_cache.result: Added a test case for the bug#29856: Insufficient buffer space led to a server crash. sql/sp_head.cc: Bug#29856: Insufficient buffer space led to a server crash. Now the subst_spvars function reserves additional space for the query cache. --- mysql-test/r/query_cache.result | 119 ++++++++++++++++++++++++ mysql-test/t/query_cache.test | 124 +++++++++++++++++++++++++ sql/sp_head.cc | 156 +++++++++++++++++--------------- 3 files changed, 327 insertions(+), 72 deletions(-) diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result index b0f3fb77c0e..327d9531bc6 100644 --- a/mysql-test/r/query_cache.result +++ b/mysql-test/r/query_cache.result @@ -1467,3 +1467,122 @@ insert into t1 values ('c'); a drop table t1; set GLOBAL query_cache_size= default; +SET GLOBAL query_cache_size=64*1024*1024; +CREATE TABLE t1 (id INT); +CREATE PROCEDURE proc29856(IN theUPC TEXT) +BEGIN +SET @stmtStr := ''; +SELECT CONCAT("SELECT id FROM t1 WHERE id IN (",theUPC,")") INTO @stmtStr; +PREPARE stmt FROM @stmtStr; +EXECUTE stmt; +END | +CALL proc29856('1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24, +25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50, +51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76, +77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101, +102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120, +121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139, +140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158, +159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177, +178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196, +197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215, +216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234, +235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253, +254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272, +273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291, +292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310, +311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329, +330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348, +349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367, +368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386, +387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405, +406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424, +425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443, +444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462, +463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481, +482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500, +501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519, +520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538, +539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557, +558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576, +577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595, +596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614, +615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633, +634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652, +653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671, +672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690, +691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709, +710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728, +729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747, +748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766, +767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785, +786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804, +805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823, +824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842, +843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861, +862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880, +881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899, +900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918, +919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937, +938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956, +957,958,959,960,961,962,963,964,965,966,967,968,969,970,971,972,973,974,975, +976,977,978,979,980,981,982,983,984,985,986,987,988,989,990,991,992,993,994, +995,996,997,998,999,1000,1001,1002,1003,1004,1005,1006,1007,1008,1009,1010, +1011,1012,1013,1014,1015,1016,1017,1018,1019,1020,1021,1022,1023,1024,1025, +1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,1040, +1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055, +1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070, +1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085, +1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100, +1101,1102,1103,1104,1105,1106,1107,1108,1109,1110,1111,1112,1113,1114,1115, +1116,1117,1118,1119,1120,1121,1122,1123,1124,1125,1126,1127,1128,1129,1130, +1131,1132,1133,1134,1135,1136,1137,1138,1139,1140,1141,1142,1143,1144,1145, +1146,1147,1148,1149,1150,1151,1152,1153,1154,1155,1156,1157,1158,1159,1160, +1161,1162,1163,1164,1165,1166,1167,1168,1169,1170,1171,1172,1173,1174,1175, +1176,1177,1178,1179,1180,1181,1182,1183,1184,1185,1186,1187,1188,1189,1190, +1191,1192,1193,1194,1195,1196,1197,1198,1199,1200,1201,1202,1203,1204,1205, +1206,1207,1208,1209,1210,1211,1212,1213,1214,1215,1216,1217,1218,1219,1220, +1221,1222,1223,1224,1225,1226,1227,1228,1229,1230,1231,1232,1233,1234,1235, +1236,1237,1238,1239,1240,1241,1242,1243,1244,1245,1246,1247,1248,1249,1250, +1251,1252,1253,1254,1255,1256,1257,1258,1259,1260,1261,1262,1263,1264,1265, +1266,1267,1268,1269,1270,1271,1272,1273,1274,1275,1276,1277,1278,1279,1280, +1281,1282,1283,1284,1285,1286,1287,1288,1289,1290,1291,1292,1293,1294,1295, +1296,1297,1298,1299,1300,1301,1302,1303,1304,1305,1306,1307,1308,1309,1310, +1311,1312,1313,1314,1315,1316,1317,1318,1319,1320,1321,1322,1323,1324,1325, +1326,1327,1328,1329,1330,1331,1332,1333,1334,1335,1336,1337,1338,1339,1340, +1341,1342,1343,1344,1345,1346,1347,1348,1349,1350,1351,1352,1353,1354,1355, +1356,1357,1358,1359,1360,1361,1362,1363,1364,1365,1366,1367,1368,1369,1370, +1371,1372,1373,1374,1375,1376,1377,1378,1379,1380,1381,1382,1383,1384,1385, +1386,1387,1388,1389,1390,1391,1392,1393,1394,1395,1396,1397,1398,1399,1400, +1401,1402,1403,1404,1405,1406,1407,1408,1409,1410,1411,1412,1413,1414,1415, +1416,1417,1418,1419,1420,1421,1422,1423,1424,1425,1426,1427,1428,1429,1430, +1431,1432,1433,1434,1435,1436,1437,1438,1439,1440,1441,1442,1443,1444,1445, +1446,1447,1448,1449,1450,1451,1452,1453,1454,1455,1456,1457,1458,1459,1460, +1461,1462,1463,1464,1465,1466,1467,1468,1469,1470,1471,1472,1473,1474,1475, +1476,1477,1478,1479,1480,1481,1482,1483,1484,1485,1486,1487,1488,1489,1490, +1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505, +1506,1507,1508,1509,1510,1511,1512,1513,1514,1515,1516,1517,1518,1519,1520, +1521,1522,1523,1524,1525,1526,1527,1528,1529,1530,1531,1532,1533,1534,1535, +1536,1537,1538,1539,1540,1541,1542,1543,1544,1545,1546,1547,1548,1549,1550, +1551,1552,1553,1554,1555,1556,1557,1558,1559,1560,1561,1562,1563,1564,1565, +1566,1567,1568,1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580, +1581,1582,1583,1584,1585,1586,1587,1588,1589,1590,1591,1592,1593,1594,1595, +1596,1597,1598,1599,1600,1601,1602,1603,1604,1605,1606,1607,1608,1609,1610, +1611,1612,1613,1614,1615,1616,1617,1618,1619,1620,1621,1622,1623,1624,1625, +1626,1627,1628,1629,1630,1631,1632,1633,1634,1635,1636,1637,1638,1639,1640, +1641,1642,1643,1644,1645,1646,1647,1648,1649,1650,1651,1652,1653,1654,1655, +1656,1657,1658,1659,1660,1661,1662,1663,1664,1665,1666,1667,1668,1669,1670, +1671,1672,1673,1674,1675,1676,1677,1678,1679,1680,1681,1682,1683,1684,1685, +1686,1687,1688,1689,1690,1691,1692,1693,1694,1695,1696,1697,1698,1699,1700, +1701,1702,1703,1704,1705,1706,1707,1708,1709,1710,1711,1712,1713,1714,1715, +1716,1717,1718,1719,1720,1721,1722,1723,1724,1725,1726,1727,1728,1729,1730, +1731,1732,1733,1734,1735,1736,1737,1738,1739,1740,1741,1742,1743,1744,1745, +1746,1747,1748,1749,1750,1751,1752,1753,1754,1755,1756,1757,1758,1759,1760, +1761,1762,1763,1764,1765,1766,1767,1768,1769,1770,1771,1772,1773,1774,1775, +1776,1777,1778,1779,1780,1781,1782,1783,1784,1785,1786,1787,1788,1789,1790, +1791,1792,1793,1794,1795,1796,1797,1798,1799,1800,1801,1802,1803,1804,1805, +1806,1807,1808,1809,1810,1811'); +id +DROP PROCEDURE proc29856; +DROP TABLE t1; +SET GLOBAL query_cache_size= default; diff --git a/mysql-test/t/query_cache.test b/mysql-test/t/query_cache.test index 965ebf5df62..2f4896513f5 100644 --- a/mysql-test/t/query_cache.test +++ b/mysql-test/t/query_cache.test @@ -1028,4 +1028,128 @@ drop table t1; set GLOBAL query_cache_size= default; +# +# Bug#29856: Insufficient buffer space led to a server crash. +# +SET GLOBAL query_cache_size=64*1024*1024; +CREATE TABLE t1 (id INT); +DELIMITER |; +CREATE PROCEDURE proc29856(IN theUPC TEXT) +BEGIN + SET @stmtStr := ''; + SELECT CONCAT("SELECT id FROM t1 WHERE id IN (",theUPC,")") INTO @stmtStr; + PREPARE stmt FROM @stmtStr; + EXECUTE stmt; +END | +DELIMITER ;| +CALL proc29856('1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24, +25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50, +51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76, +77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101, +102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120, +121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139, +140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158, +159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177, +178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196, +197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215, +216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234, +235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253, +254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272, +273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291, +292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310, +311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329, +330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348, +349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367, +368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386, +387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405, +406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424, +425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443, +444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462, +463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481, +482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500, +501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519, +520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538, +539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557, +558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576, +577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595, +596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614, +615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633, +634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652, +653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671, +672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690, +691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709, +710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728, +729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747, +748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766, +767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785, +786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804, +805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823, +824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842, +843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861, +862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880, +881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899, +900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918, +919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937, +938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956, +957,958,959,960,961,962,963,964,965,966,967,968,969,970,971,972,973,974,975, +976,977,978,979,980,981,982,983,984,985,986,987,988,989,990,991,992,993,994, +995,996,997,998,999,1000,1001,1002,1003,1004,1005,1006,1007,1008,1009,1010, +1011,1012,1013,1014,1015,1016,1017,1018,1019,1020,1021,1022,1023,1024,1025, +1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,1040, +1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055, +1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070, +1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085, +1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100, +1101,1102,1103,1104,1105,1106,1107,1108,1109,1110,1111,1112,1113,1114,1115, +1116,1117,1118,1119,1120,1121,1122,1123,1124,1125,1126,1127,1128,1129,1130, +1131,1132,1133,1134,1135,1136,1137,1138,1139,1140,1141,1142,1143,1144,1145, +1146,1147,1148,1149,1150,1151,1152,1153,1154,1155,1156,1157,1158,1159,1160, +1161,1162,1163,1164,1165,1166,1167,1168,1169,1170,1171,1172,1173,1174,1175, +1176,1177,1178,1179,1180,1181,1182,1183,1184,1185,1186,1187,1188,1189,1190, +1191,1192,1193,1194,1195,1196,1197,1198,1199,1200,1201,1202,1203,1204,1205, +1206,1207,1208,1209,1210,1211,1212,1213,1214,1215,1216,1217,1218,1219,1220, +1221,1222,1223,1224,1225,1226,1227,1228,1229,1230,1231,1232,1233,1234,1235, +1236,1237,1238,1239,1240,1241,1242,1243,1244,1245,1246,1247,1248,1249,1250, +1251,1252,1253,1254,1255,1256,1257,1258,1259,1260,1261,1262,1263,1264,1265, +1266,1267,1268,1269,1270,1271,1272,1273,1274,1275,1276,1277,1278,1279,1280, +1281,1282,1283,1284,1285,1286,1287,1288,1289,1290,1291,1292,1293,1294,1295, +1296,1297,1298,1299,1300,1301,1302,1303,1304,1305,1306,1307,1308,1309,1310, +1311,1312,1313,1314,1315,1316,1317,1318,1319,1320,1321,1322,1323,1324,1325, +1326,1327,1328,1329,1330,1331,1332,1333,1334,1335,1336,1337,1338,1339,1340, +1341,1342,1343,1344,1345,1346,1347,1348,1349,1350,1351,1352,1353,1354,1355, +1356,1357,1358,1359,1360,1361,1362,1363,1364,1365,1366,1367,1368,1369,1370, +1371,1372,1373,1374,1375,1376,1377,1378,1379,1380,1381,1382,1383,1384,1385, +1386,1387,1388,1389,1390,1391,1392,1393,1394,1395,1396,1397,1398,1399,1400, +1401,1402,1403,1404,1405,1406,1407,1408,1409,1410,1411,1412,1413,1414,1415, +1416,1417,1418,1419,1420,1421,1422,1423,1424,1425,1426,1427,1428,1429,1430, +1431,1432,1433,1434,1435,1436,1437,1438,1439,1440,1441,1442,1443,1444,1445, +1446,1447,1448,1449,1450,1451,1452,1453,1454,1455,1456,1457,1458,1459,1460, +1461,1462,1463,1464,1465,1466,1467,1468,1469,1470,1471,1472,1473,1474,1475, +1476,1477,1478,1479,1480,1481,1482,1483,1484,1485,1486,1487,1488,1489,1490, +1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505, +1506,1507,1508,1509,1510,1511,1512,1513,1514,1515,1516,1517,1518,1519,1520, +1521,1522,1523,1524,1525,1526,1527,1528,1529,1530,1531,1532,1533,1534,1535, +1536,1537,1538,1539,1540,1541,1542,1543,1544,1545,1546,1547,1548,1549,1550, +1551,1552,1553,1554,1555,1556,1557,1558,1559,1560,1561,1562,1563,1564,1565, +1566,1567,1568,1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580, +1581,1582,1583,1584,1585,1586,1587,1588,1589,1590,1591,1592,1593,1594,1595, +1596,1597,1598,1599,1600,1601,1602,1603,1604,1605,1606,1607,1608,1609,1610, +1611,1612,1613,1614,1615,1616,1617,1618,1619,1620,1621,1622,1623,1624,1625, +1626,1627,1628,1629,1630,1631,1632,1633,1634,1635,1636,1637,1638,1639,1640, +1641,1642,1643,1644,1645,1646,1647,1648,1649,1650,1651,1652,1653,1654,1655, +1656,1657,1658,1659,1660,1661,1662,1663,1664,1665,1666,1667,1668,1669,1670, +1671,1672,1673,1674,1675,1676,1677,1678,1679,1680,1681,1682,1683,1684,1685, +1686,1687,1688,1689,1690,1691,1692,1693,1694,1695,1696,1697,1698,1699,1700, +1701,1702,1703,1704,1705,1706,1707,1708,1709,1710,1711,1712,1713,1714,1715, +1716,1717,1718,1719,1720,1721,1722,1723,1724,1725,1726,1727,1728,1729,1730, +1731,1732,1733,1734,1735,1736,1737,1738,1739,1740,1741,1742,1743,1744,1745, +1746,1747,1748,1749,1750,1751,1752,1753,1754,1755,1756,1757,1758,1759,1760, +1761,1762,1763,1764,1765,1766,1767,1768,1769,1770,1771,1772,1773,1774,1775, +1776,1777,1778,1779,1780,1781,1782,1783,1784,1785,1786,1787,1788,1789,1790, +1791,1792,1793,1794,1795,1796,1797,1798,1799,1800,1801,1802,1803,1804,1805, +1806,1807,1808,1809,1810,1811'); +DROP PROCEDURE proc29856; +DROP TABLE t1; +SET GLOBAL query_cache_size= default; + # End of 5.0 tests diff --git a/sql/sp_head.cc b/sql/sp_head.cc index d939fd20b9b..94d3a967b8c 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -767,7 +767,8 @@ int cmp_splocal_locations(Item_splocal * const *a, Item_splocal * const *b) /* - Replace thd->query{_length} with a string that one can write to the binlog. + Replace thd->query{_length} with a string that one can write to the binlog + or the query cache. SYNOPSIS subst_spvars() @@ -779,7 +780,9 @@ int cmp_splocal_locations(Item_splocal * const *a, Item_splocal * const *b) DESCRIPTION The binlog-suitable string is produced by replacing references to SP local - variables with NAME_CONST('sp_var_name', value) calls. + variables with NAME_CONST('sp_var_name', value) calls. To make this string + suitable for the query cache this function allocates some additional space + for the query cache flags. RETURN FALSE on success @@ -792,80 +795,89 @@ static bool subst_spvars(THD *thd, sp_instr *instr, LEX_STRING *query_str) { DBUG_ENTER("subst_spvars"); - if (thd->prelocked_mode == NON_PRELOCKED && mysql_bin_log.is_open()) + + Dynamic_array sp_vars_uses; + char *pbuf, *cur, buffer[512]; + String qbuf(buffer, sizeof(buffer), &my_charset_bin); + int prev_pos, res, buf_len; + + /* Find all instances of Item_splocal used in this statement */ + for (Item *item= instr->free_list; item; item= item->next) { - Dynamic_array sp_vars_uses; - char *pbuf, *cur, buffer[512]; - String qbuf(buffer, sizeof(buffer), &my_charset_bin); - int prev_pos, res; - - /* Find all instances of Item_splocal used in this statement */ - for (Item *item= instr->free_list; item; item= item->next) + if (item->is_splocal()) { - if (item->is_splocal()) - { - Item_splocal *item_spl= (Item_splocal*)item; - if (item_spl->pos_in_query) - sp_vars_uses.append(item_spl); - } + Item_splocal *item_spl= (Item_splocal*)item; + if (item_spl->pos_in_query) + sp_vars_uses.append(item_spl); } - if (!sp_vars_uses.elements()) - DBUG_RETURN(FALSE); - - /* Sort SP var refs by their occurences in the query */ - sp_vars_uses.sort(cmp_splocal_locations); - - /* - Construct a statement string where SP local var refs are replaced - with "NAME_CONST(name, value)" - */ - qbuf.length(0); - cur= query_str->str; - prev_pos= res= 0; - for (Item_splocal **splocal= sp_vars_uses.front(); - splocal < sp_vars_uses.back(); splocal++) - { - Item *val; - - char str_buffer[STRING_BUFFER_USUAL_SIZE]; - String str_value_holder(str_buffer, sizeof(str_buffer), - &my_charset_latin1); - String *str_value; - - /* append the text between sp ref occurences */ - res|= qbuf.append(cur + prev_pos, (*splocal)->pos_in_query - prev_pos); - prev_pos= (*splocal)->pos_in_query + (*splocal)->m_name.length; - - /* append the spvar substitute */ - res|= qbuf.append(STRING_WITH_LEN(" NAME_CONST('")); - res|= qbuf.append((*splocal)->m_name.str, (*splocal)->m_name.length); - res|= qbuf.append(STRING_WITH_LEN("',")); - res|= (*splocal)->fix_fields(thd, (Item **) splocal); - - if (res) - break; - - val= (*splocal)->this_item(); - DBUG_PRINT("info", ("print %p", val)); - str_value= sp_get_item_value(thd, val, &str_value_holder); - if (str_value) - res|= qbuf.append(*str_value); - else - res|= qbuf.append(STRING_WITH_LEN("NULL")); - res|= qbuf.append(')'); - if (res) - break; - } - res|= qbuf.append(cur + prev_pos, query_str->length - prev_pos); - if (res) - DBUG_RETURN(TRUE); - - if (!(pbuf= thd->strmake(qbuf.ptr(), qbuf.length()))) - DBUG_RETURN(TRUE); - - thd->query= pbuf; - thd->query_length= qbuf.length(); } + if (!sp_vars_uses.elements()) + DBUG_RETURN(FALSE); + + /* Sort SP var refs by their occurences in the query */ + sp_vars_uses.sort(cmp_splocal_locations); + + /* + Construct a statement string where SP local var refs are replaced + with "NAME_CONST(name, value)" + */ + qbuf.length(0); + cur= query_str->str; + prev_pos= res= 0; + for (Item_splocal **splocal= sp_vars_uses.front(); + splocal < sp_vars_uses.back(); splocal++) + { + Item *val; + + char str_buffer[STRING_BUFFER_USUAL_SIZE]; + String str_value_holder(str_buffer, sizeof(str_buffer), + &my_charset_latin1); + String *str_value; + + /* append the text between sp ref occurences */ + res|= qbuf.append(cur + prev_pos, (*splocal)->pos_in_query - prev_pos); + prev_pos= (*splocal)->pos_in_query + (*splocal)->m_name.length; + + /* append the spvar substitute */ + res|= qbuf.append(STRING_WITH_LEN(" NAME_CONST('")); + res|= qbuf.append((*splocal)->m_name.str, (*splocal)->m_name.length); + res|= qbuf.append(STRING_WITH_LEN("',")); + res|= (*splocal)->fix_fields(thd, (Item **) splocal); + + if (res) + break; + + val= (*splocal)->this_item(); + DBUG_PRINT("info", ("print %p", val)); + str_value= sp_get_item_value(thd, val, &str_value_holder); + if (str_value) + res|= qbuf.append(*str_value); + else + res|= qbuf.append(STRING_WITH_LEN("NULL")); + res|= qbuf.append(')'); + if (res) + break; + } + res|= qbuf.append(cur + prev_pos, query_str->length - prev_pos); + if (res) + DBUG_RETURN(TRUE); + + /* + Allocate additional space at the end of the new query string for the + query_cache_send_result_to_client function. + */ + buf_len= qbuf.length() + thd->db_length + 1 + QUERY_CACHE_FLAGS_SIZE + 1; + if ((pbuf= alloc_root(thd->mem_root, buf_len))) + { + memcpy(pbuf, qbuf.ptr(), qbuf.length()); + pbuf[qbuf.length()]= 0; + } + else + DBUG_RETURN(TRUE); + + thd->query= pbuf; + thd->query_length= qbuf.length(); + DBUG_RETURN(FALSE); } From aa4a3c9ad0a1d1c7e1ac036c7ac160a80a051219 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 28 Jul 2007 16:02:29 +0400 Subject: [PATCH 13/26] Bug#30020: Insufficient check led to a wrong info provided by the information schema table. The get_schema_views_record() function fills records in the view table of the informations schema with data about given views. Among other info the is_updatable flag is set. But the check whether the view is updatable or not wasn't covering all cases thus sometimes providing wrong info. This might led to a user confusion. Now the get_schema_views_record function additionally calls to the view->can_be_merge() function to find out whether the view can be updated or not. mysql-test/t/view.test: Added a test case for the bug#30020: Insufficient check led to a wrong info provided by the information schema table. mysql-test/r/view.result: Added a test case for the bug#30020: Insufficient check led to a wrong info provided by the information schema table. sql/sql_show.cc: Bug#30020: Insufficient check led to a wrong info provided by the information schema table. Now the get_schema_views_record function additionally calls to the view->can_be_merge() function to find out whether the view can be updated or not. --- mysql-test/r/view.result | 15 +++++++++++++++ mysql-test/t/view.test | 13 +++++++++++++ sql/sql_show.cc | 4 +++- 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index c51a4c30960..c5c6b675146 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -3547,4 +3547,19 @@ a b 6 6 DROP VIEW v1; DROP TABLE t1,t2,t3; +create table t1 (i int); +insert into t1 values (1), (2), (1), (3), (2), (4); +create view v1 as select distinct i from t1; +select * from v1; +i +1 +2 +3 +4 +select table_name, is_updatable from information_schema.views +where table_name = 'v1'; +table_name is_updatable +v1 NO +drop view v1; +drop table t1; End of 5.0 tests. diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index c7f722a18a5..fc3fdc932ba 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -3402,5 +3402,18 @@ SELECT t.person_id AS a, t.person_id AS b FROM v1 t WHERE t.person_id=6; DROP VIEW v1; DROP TABLE t1,t2,t3; +# +# Bug#30020: Insufficient check led to a wrong info provided by the +# information schema table. +# +create table t1 (i int); +insert into t1 values (1), (2), (1), (3), (2), (4); +create view v1 as select distinct i from t1; +select * from v1; +select table_name, is_updatable from information_schema.views + where table_name = 'v1'; +drop view v1; +drop table t1; + --echo End of 5.0 tests. diff --git a/sql/sql_show.cc b/sql/sql_show.cc index b91412390bc..05a847b3830 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -3211,7 +3211,7 @@ static int get_schema_views_record(THD *thd, TABLE_LIST *tables, Item *item; Item_field *field; /* - chech that at least one coulmn in view is updatable + check that at least one column in view is updatable */ while ((item= it++)) { @@ -3222,6 +3222,8 @@ static int get_schema_views_record(THD *thd, TABLE_LIST *tables, break; } } + if (updatable_view && !tables->view->can_be_merged()) + updatable_view= 0; } if (updatable_view) table->field[5]->store(STRING_WITH_LEN("YES"), cs); From 90c5621d6c22ce86354ffe8ccd244007a5e4d846 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 28 Jul 2007 23:10:38 +0500 Subject: [PATCH 14/26] Fixed bug #29834. Using view columns by their names during an execution of a prepared SELECT statement or a SELECT statement inside a SP caused a memory leak. sql/sql_base.cc: Fixed bug #29834. The find_field_in_view function has been modified to use the execution memory root for the Item_direct_view_ref objects allocation at non-first executions of a PS/SP instead of the statement memory. mysql-test/t/sp.test: Updated test case for bug #29834. mysql-test/r/sp.result: Updated test case for bug #29834. --- mysql-test/r/sp.result | 71 ++++++++++++++++++++++++++++++++++++++++ mysql-test/t/sp.test | 74 ++++++++++++++++++++++++++++++++++++++++++ sql/sql_base.cc | 6 ++-- 3 files changed, 148 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index b411c65faee..313fdca7f82 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -1,5 +1,9 @@ use test; drop table if exists t1,t2,t3,t4; +drop view if exists v1; +drop procedure if exists p1; +drop procedure if exists p2; +drop function if exists f1; create table t1 ( id char(16) not null default '', data int not null @@ -6176,4 +6180,71 @@ v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VI DROP VIEW v1; DROP FUNCTION metered; DROP TABLE t1; +SET @p1_p2_cnt= 2; +CREATE TABLE t1 (c1 INT); +CREATE VIEW v1 AS SELECT * FROM t1; +PREPARE s1 FROM 'SELECT c1 FROM v1'; +EXECUTE s1; +c1 +EXECUTE s1; +c1 +CREATE PROCEDURE p1(IN loops BIGINT(19) UNSIGNED) +BEGIN +WHILE loops > 0 DO +SELECT c1 FROM v1; +SET loops = loops - 1; +END WHILE; +END| +CREATE PROCEDURE p2(IN loops BIGINT(19) UNSIGNED) +BEGIN +WHILE loops > 0 DO +SELECT c1 FROM v1; +CALL p1(@p1_p2_cnt); +SET loops = loops - 1; +END WHILE; +END| +CREATE FUNCTION f1(loops INT UNSIGNED) +RETURNS INT +BEGIN +DECLARE tmp INT; +WHILE loops > 0 DO +SELECT c1 INTO tmp FROM v1; +SET loops = loops - 1; +END WHILE; +RETURN loops; +END| +CALL p1(2); +c1 +c1 +CALL p2(2); +c1 +c1 +c1 +c1 +c1 +c1 +SELECT f1(2); +f1(2) +0 +Warnings: +Warning 1329 No data - zero rows fetched, selected, or processed +Warning 1329 No data - zero rows fetched, selected, or processed +PREPARE s1 FROM 'SELECT f1(2)'; +EXECUTE s1; +f1(2) +0 +Warnings: +Warning 1329 No data - zero rows fetched, selected, or processed +Warning 1329 No data - zero rows fetched, selected, or processed +EXECUTE s1; +f1(2) +0 +Warnings: +Warning 1329 No data - zero rows fetched, selected, or processed +Warning 1329 No data - zero rows fetched, selected, or processed +DROP PROCEDURE p1; +DROP PROCEDURE p2; +DROP FUNCTION f1; +DROP VIEW v1; +DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 2f82482bdf7..088ce9b72ff 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -23,6 +23,10 @@ use test; # --disable_warnings drop table if exists t1,t2,t3,t4; +drop view if exists v1; +drop procedure if exists p1; +drop procedure if exists p2; +drop function if exists f1; --enable_warnings create table t1 ( id char(16) not null default '', @@ -7134,5 +7138,75 @@ DROP VIEW v1; DROP FUNCTION metered; DROP TABLE t1; +# +# Bug#29834: Accessing a view column by name in SP/PS causes a memory leak. +# +# This is leak test. Run with large number assigned to $execute_cnt, +# $p1_cnt, $p2_cnt, @p1_p2_cnt, $f1_normal_cnt or $f1_prep_cnt variables. +# + +let $execute_cnt= 2; +let $p1_cnt= 2; +let $p2_cnt= 2; +SET @p1_p2_cnt= 2; +let $f1_normal_cnt= 2; +let $f1_prep_cnt= 2; + +CREATE TABLE t1 (c1 INT); +CREATE VIEW v1 AS SELECT * FROM t1; + +PREPARE s1 FROM 'SELECT c1 FROM v1'; +while ($execute_cnt) +{ + EXECUTE s1; + dec $execute_cnt; +} + +DELIMITER |; + +CREATE PROCEDURE p1(IN loops BIGINT(19) UNSIGNED) +BEGIN + WHILE loops > 0 DO + SELECT c1 FROM v1; + SET loops = loops - 1; + END WHILE; +END| + +CREATE PROCEDURE p2(IN loops BIGINT(19) UNSIGNED) +BEGIN + WHILE loops > 0 DO + SELECT c1 FROM v1; + CALL p1(@p1_p2_cnt); + SET loops = loops - 1; + END WHILE; +END| + +CREATE FUNCTION f1(loops INT UNSIGNED) + RETURNS INT +BEGIN + DECLARE tmp INT; + WHILE loops > 0 DO + SELECT c1 INTO tmp FROM v1; + SET loops = loops - 1; + END WHILE; + RETURN loops; +END| + +DELIMITER ;| + +eval CALL p1($p1_cnt); +eval CALL p2($p2_cnt); + +eval SELECT f1($f1_normal_cnt); + +eval PREPARE s1 FROM 'SELECT f1($f1_prep_cnt)'; +EXECUTE s1; +EXECUTE s1; + +DROP PROCEDURE p1; +DROP PROCEDURE p2; +DROP FUNCTION f1; +DROP VIEW v1; +DROP TABLE t1; --echo End of 5.0 tests diff --git a/sql/sql_base.cc b/sql/sql_base.cc index ed006714143..deb46f0d932 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -3435,7 +3435,7 @@ find_field_in_view(THD *thd, TABLE_LIST *table_list, table_list->alias, name, item_name, (ulong) ref)); Field_iterator_view field_it; field_it.set(table_list); - Query_arena *arena, backup; + Query_arena *arena= 0, backup; DBUG_ASSERT(table_list->schema_table_reformed || (ref != 0 && table_list->view != 0)); @@ -3444,14 +3444,14 @@ find_field_in_view(THD *thd, TABLE_LIST *table_list, if (!my_strcasecmp(system_charset_info, field_it.name(), name)) { // in PS use own arena or data will be freed after prepare - if (register_tree_change) + if (register_tree_change && thd->stmt_arena->is_stmt_prepare_or_first_sp_execute()) arena= thd->activate_stmt_arena_if_needed(&backup); /* create_item() may, or may not create a new Item, depending on the column reference. See create_view_field() for details. */ Item *item= field_it.create_item(thd); - if (register_tree_change && arena) + if (arena) thd->restore_active_arena(arena, &backup); if (!item) From 11816452bc097c3e5273137a1d012a321e12a9c1 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 29 Jul 2007 21:12:54 +0500 Subject: [PATCH 15/26] sp_head.cc: Post-merge fix. sql/sp_head.cc: Post-merge fix. --- sql/sp_head.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sp_head.cc b/sql/sp_head.cc index d08d1dd3930..74714a42591 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -958,7 +958,7 @@ subst_spvars(THD *thd, sp_instr *instr, LEX_STRING *query_str) query_cache_send_result_to_client function. */ buf_len= qbuf.length() + thd->db_length + 1 + QUERY_CACHE_FLAGS_SIZE + 1; - if ((pbuf= alloc_root(thd->mem_root, buf_len))) + if ((pbuf= (char *) alloc_root(thd->mem_root, buf_len))) { memcpy(pbuf, qbuf.ptr(), qbuf.length()); pbuf[qbuf.length()]= 0; From c0b65fb77dcb7010056dff7e476b7397dd912c89 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 30 Jul 2007 03:20:45 +0500 Subject: [PATCH 16/26] disabled.def: ddl_i18n_koi8r.test has been disabled to ignore bug #30120. mysql-test/t/disabled.def: ddl_i18n_koi8r.test has been disabled to ignore bug #30120. --- mysql-test/t/disabled.def | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index 368a659d939..fff651e54c9 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -25,3 +25,4 @@ ctype_big5 : BUG#26711 2007-06-21 Lars Test has never worked on Do mysql_upgrade : Bug#28560 test links to /usr/local/mysql/lib libraries, causes non-determinism and failures on ABI breakage federated_transactions : Bug#29523 Transactions do not work +ddl_i18n_koi8r : Bug #30120 SP with local variables with non-ASCII names crashes server From 33fc4ad4e124413ef617a1a073bb50135f6a12af Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 30 Jul 2007 04:35:16 +0500 Subject: [PATCH 17/26] Fixed bug #30120. SP with local variables with non-ASCII names crashed the server. The server replaces SP local variable names with NAME_CONST calls when putting statements into the binary log. It used UTF8-encoded item names as variable names for the replacement inside NAME_CONST calls. However, statement string may be encoded by any known character set by the SET NAMES statement. The server used byte length of UTF8-encoded names to increment the position in the query string that led to array index overrun. sql/item.cc: Fixed bug #30120. The Item_splocal class constructor has been modified to accept new parameter `len_in_q': the byte length of variable name in the query string. sql/item.h: Fixed bug #30120. The Item_splocal class has been modified to keep new field `len_in_query': the byte length of variable name in the query string. sql/sp_head.cc: Fixed bug #30120. The subst_spvars function has been modified to increment position in the query string by the lengths of not encoded variable names instead of byte length of names encoded to UTF-8. sql/sql_yacc.yy: Fixed bug #30120. The simple_ident rule action has been modified to pass the byte length of the local variable name token to the Item_splocal object constructor. mysql-test/t/sp.test: Updated test case for bug #30120. mysql-test/r/sp.result: Updated test case for bug #30120. --- mysql-test/r/sp.result | 11 +++++++++++ mysql-test/t/sp.test | 21 +++++++++++++++++++++ sql/item.cc | 4 ++-- sql/item.h | 11 ++++++++++- sql/sp_head.cc | 2 +- sql/sql_yacc.yy | 3 ++- 6 files changed, 47 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index a7b6d8aa3fd..4a278cd4aec 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -6303,4 +6303,15 @@ DROP VIEW v1; DROP FUNCTION f1; DROP FUNCTION f2; DROP TABLE t1; +SET NAMES latin1; +CREATE PROCEDURE p1() +BEGIN +DECLARE áâä INT; +SELECT áâä; +END| +CALL p1(); +áâä +NULL +SET NAMES default; +DROP PROCEDURE p1; End of 5.0 tests diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index ddf33b285f5..46a1b1dc740 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -7278,4 +7278,25 @@ DROP FUNCTION f1; DROP FUNCTION f2; DROP TABLE t1; +# +# Bug #30120 SP with local variables with non-ASCII names crashes server. +# + +SET NAMES latin1; + +DELIMITER |; + +CREATE PROCEDURE p1() +BEGIN + DECLARE áâä INT; + SELECT áâä; +END| + +DELIMITER ;| + +CALL p1(); + +SET NAMES default; +DROP PROCEDURE p1; + --echo End of 5.0 tests diff --git a/sql/item.cc b/sql/item.cc index bd47fb706a6..9612fbc5243 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1053,9 +1053,9 @@ bool Item_sp_variable::is_null() Item_splocal::Item_splocal(const LEX_STRING &sp_var_name, uint sp_var_idx, enum_field_types sp_var_type, - uint pos_in_q) + uint pos_in_q, uint len_in_q) :Item_sp_variable(sp_var_name.str, sp_var_name.length), - m_var_idx(sp_var_idx), pos_in_query(pos_in_q) + m_var_idx(sp_var_idx), pos_in_query(pos_in_q), len_in_query(len_in_q) { maybe_null= TRUE; diff --git a/sql/item.h b/sql/item.h index 72236cb5e63..23f6977a0f8 100644 --- a/sql/item.h +++ b/sql/item.h @@ -960,9 +960,18 @@ public: SP variable in query text. */ uint pos_in_query; + /* + Byte length of SP variable name in the statement (see pos_in_query). + The value of this field may differ from the name_length value because + name_length contains byte length of UTF8-encoded item name, but + the query string (see sp_instr_stmt::m_query) is currently stored with + a charset from the SET NAMES statement. + */ + uint len_in_query; Item_splocal(const LEX_STRING &sp_var_name, uint sp_var_idx, - enum_field_types sp_var_type, uint pos_in_q= 0); + enum_field_types sp_var_type, + uint pos_in_q= 0, uint len_in_q= 0); bool is_splocal() { return 1; } /* Needed for error checking */ diff --git a/sql/sp_head.cc b/sql/sp_head.cc index fd8724b2171..8f4d407a5b0 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -864,7 +864,7 @@ subst_spvars(THD *thd, sp_instr *instr, LEX_STRING *query_str) /* append the text between sp ref occurences */ res|= qbuf.append(cur + prev_pos, (*splocal)->pos_in_query - prev_pos); - prev_pos= (*splocal)->pos_in_query + (*splocal)->m_name.length; + prev_pos= (*splocal)->pos_in_query + (*splocal)->len_in_query; /* append the spvar substitute */ res|= qbuf.append(STRING_WITH_LEN(" NAME_CONST('")); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 6fbd521e302..b0e59d0f8dc 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -7708,7 +7708,8 @@ simple_ident: Item_splocal *splocal; splocal= new Item_splocal($1, spv->offset, spv->type, lip->tok_start_prev - - lex->sphead->m_tmp_query); + lex->sphead->m_tmp_query, + lip->tok_end - lip->tok_start_prev); #ifndef DBUG_OFF if (splocal) splocal->m_sp= lex->sphead; From b9097abf00983f479f8e4b9f0ee82ac7fde74adc Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 30 Jul 2007 16:03:52 +0300 Subject: [PATCH 18/26] Moved the DBUG_ASSERT from bug 28983 to a place where it would not obstruct correct multithreading. --- sql/log.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/sql/log.cc b/sql/log.cc index 744d2a3ca65..6992f6c10ef 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1833,6 +1833,7 @@ bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache, Log_event *commit_event) /* NULL would represent nothing to replicate after ROLLBACK */ DBUG_ASSERT(commit_event != NULL); + DBUG_ASSERT(is_open()); if (likely(is_open())) // Should always be true { uint length, group, carry, hdr_offs, val; From 1307d3b8033985d842b900ec8ebe7be9f0a4e092 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 30 Jul 2007 18:27:36 +0300 Subject: [PATCH 19/26] (pushing for Andrei) Bug #27417 thd->no_trans_update.stmt lost value inside of SF-exec-stack Once had been set the flag might later got reset inside of a stored routine execution stack. The reason was in that there was no check if a new statement started at time of resetting. The artifact affects most of binlogable DML queries. Notice, that multi-update is wrapped up within bug@27716 fix, multi-delete bug@29136. Fixed with saving parent's statement flag of whether the statement modified non-transactional table, and unioning (merging) the value with that was gained in mysql_execute_command. Resettling thd->no_trans_update members into thd->transaction.`member`; Asserting code; Effectively the following properties are held. 1. At the end of a substatement thd->transaction.stmt.modified_non_trans_table reflects the fact if such a table got modified by the substatement. That also respects THD::really_abort_on_warnin() requirements. 2. Eventually thd->transaction.stmt.modified_non_trans_table will be computed as the union of the values of all invoked sub-statements. That fixes this bug#27417; Computing of thd->transaction.all.modified_non_trans_table is refined to base to the stmt's value for all the case including insert .. select statement which before the patch had an extra issue bug@28960. Minor issues are covered with mysql_load, mysql_delete, and binloggin of insert in to temp_table select. The supplied test verifies limitely, mostly asserts. The ultimate testing is defered for bug@13270, bug@23333. mysql-test/r/mix_innodb_myisam_binlog.result: results changed mysql-test/t/mix_innodb_myisam_binlog.test: regression test incl the related bug#28960. sql/ha_ndbcluster.cc: thd->transaction.{all,stmt}.modified_non_trans_table instead of thd->no_trans_update.{all,stmt} sql/handler.cc: thd->transaction.{all,stmt}.modified_non_trans_table instead of thd->no_trans_update.{all,stmt} sql/handler.h: new member added sql/log.cc: thd->transaction.{all,stmt}.modified_non_trans_table instead of thd->no_trans_update.{all,stmt} sql/set_var.cc: thd->transaction.{all,stmt}.modified_non_trans_table instead of thd->no_trans_update.{all,stmt} sql/sp_head.cc: thd->transaction.{all,stmt}.modified_non_trans_table instead of thd->no_trans_update.{all,stmt} and saving and merging stmt's flag at the end of a substatement. sql/sql_class.cc: thd->transaction.{all,stmt}.modified_non_trans_table instead of thd->no_trans_update.{all,stmt} sql/sql_class.h: thd->transaction.{all,stmt}.modified_non_trans_table instead of thd->no_trans_update.{all,stmt} sql/sql_delete.cc: correcting basic delete incl truncate branch and multi-delete queries to set stmt.modified_non_trans_table; optimization to set the flag at the end of per-row loop; multi-delete still has an extra issue similar to bug#27716 of multi-update - to be address with bug_29136 fix. sql/sql_insert.cc: thd->transaction.{all,stmt}.modified_non_trans_table instead of thd->no_trans_update.{all,stmt} sql/sql_load.cc: eliminating a separate issue where the stmt flag was saved and re-stored after write_record that actually could change it and the change would be lost but should remain permanent; thd->transaction.{all,stmt}.modified_non_trans_table instead of thd->no_trans_update.{all,stmt} sql/sql_parse.cc: initialization to transaction.stmt.modified_non_trans_table at the common part of all types of statements processing - mysql_execute_command(). sql/sql_table.cc: moving the reset up to the mysql_execute_command() caller sql/sql_update.cc: correcting update query case (multi-update part of the issues covered by other bug#27716 fix) thd->transaction.{all,stmt}.modified_non_trans_table instead of thd->no_trans_update.{all,stmt} --- mysql-test/r/mix_innodb_myisam_binlog.result | 113 +++++++++++++++++ mysql-test/t/mix_innodb_myisam_binlog.test | 122 ++++++++++++++++++- sql/ha_ndbcluster.cc | 2 +- sql/handler.cc | 2 +- sql/handler.h | 29 +++++ sql/log.cc | 4 +- sql/set_var.cc | 4 +- sql/sp_head.cc | 20 ++- sql/sql_class.cc | 2 +- sql/sql_class.h | 6 +- sql/sql_delete.cc | 31 +++-- sql/sql_insert.cc | 43 ++++--- sql/sql_load.cc | 16 +-- sql/sql_parse.cc | 22 ++-- sql/sql_table.cc | 1 - sql/sql_update.cc | 41 +++---- 16 files changed, 368 insertions(+), 90 deletions(-) diff --git a/mysql-test/r/mix_innodb_myisam_binlog.result b/mysql-test/r/mix_innodb_myisam_binlog.result index 8fc5bfca3ef..5777bd890b2 100644 --- a/mysql-test/r/mix_innodb_myisam_binlog.result +++ b/mysql-test/r/mix_innodb_myisam_binlog.result @@ -280,3 +280,116 @@ select @a like "%#%error_code=0%ROLLBACK/*!*/;%ROLLBACK /* added by mysqlbinlog */;%" @a not like "%#%error_code=%error_code=%" 1 1 drop table t1, t2; +create temporary table tt (a int unique); +create table ti (a int) engine=innodb; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 98 +begin; +insert into ti values (1); +insert into ti values (2) ; +insert into tt select * from ti; +rollback; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +select count(*) from tt /* 2 */; +count(*) +2 +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 507 +show binlog events from 98; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query 1 # use `test`; BEGIN +master-bin.000001 # Query 1 # use `test`; insert into ti values (1) +master-bin.000001 # Query 1 # use `test`; insert into ti values (2) +master-bin.000001 # Query 1 # use `test`; insert into tt select * from ti +master-bin.000001 # Query 1 # use `test`; ROLLBACK +select count(*) from ti /* zero */; +count(*) +0 +insert into ti select * from tt; +select * from ti /* that is what slave would miss - a bug */; +a +1 +2 +delete from ti; +delete from tt where a=1; +reset master; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 98 +begin; +insert into ti values (1); +insert into ti values (2) /* to make the dup error in the following */; +insert into tt select * from ti /* one affected and error */; +ERROR 23000: Duplicate entry '2' for key 1 +rollback; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 581 +show binlog events from 98; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query 1 # use `test`; BEGIN +master-bin.000001 # Query 1 # use `test`; insert into ti values (1) +master-bin.000001 # Query 1 # use `test`; insert into ti values (2) /* to make the dup error in the following */ +master-bin.000001 # Query 1 # use `test`; insert into tt select * from ti /* one affected and error */ +master-bin.000001 # Query 1 # use `test`; ROLLBACK +select count(*) from ti /* zero */; +count(*) +0 +insert into ti select * from tt; +select * from tt /* that is what otherwise slave missed - the bug */; +a +1 +2 +drop table ti; +drop function if exists bug27417; +drop table if exists t1,t2; +CREATE TABLE t1 (a int NOT NULL auto_increment primary key) ENGINE=MyISAM; +CREATE TABLE t2 (a int NOT NULL auto_increment, PRIMARY KEY (a)); +create function bug27417(n int) +RETURNS int(11) +begin +insert into t1 values (null); +return n; +end| +reset master; +insert into t2 values (bug27417(1)); +insert into t2 select bug27417(2); +reset master; +insert into t2 values (bug27417(2)); +ERROR 23000: Duplicate entry '2' for key 1 +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 98 +/* only (!) with fixes for #23333 will show there is the query */; +select count(*) from t1 /* must be 3 */; +count(*) +3 +reset master; +select count(*) from t2; +count(*) +2 +delete from t2 where a=bug27417(3); +select count(*) from t2 /* nothing got deleted */; +count(*) +2 +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 195 +/* the query must be in regardless of #23333 */; +select count(*) from t1 /* must be 5 */; +count(*) +5 +delete t2 from t2 where t2.a=bug27417(100) /* must not affect t2 */; +affected rows: 0 +select count(*) from t1 /* must be 7 */; +count(*) +7 +drop function bug27417; +drop table t1,t2; +end of tests diff --git a/mysql-test/t/mix_innodb_myisam_binlog.test b/mysql-test/t/mix_innodb_myisam_binlog.test index 428aba92342..f9d7235ff84 100644 --- a/mysql-test/t/mix_innodb_myisam_binlog.test +++ b/mysql-test/t/mix_innodb_myisam_binlog.test @@ -233,8 +233,6 @@ source include/show_binlog_events.inc; do release_lock("lock1"); drop table t0,t2; -# End of 4.1 tests - # Test for BUG#16559 (ROLLBACK should always have a zero error code in # binlog). Has to be here and not earlier, as the SELECTs influence # XIDs differently between normal and ps-protocol (and SHOW BINLOG @@ -267,3 +265,123 @@ eval select @a like "%#%error_code=0%ROLLBACK/*!*/;%ROLLBACK /* added by mysqlbinlog */;%", @a not like "%#%error_code=%error_code=%"; drop table t1, t2; + +# +# Bug #27417 thd->no_trans_update.stmt lost value inside of SF-exec-stack +# bug #28960 non-trans temp table changes with insert .. select +# not binlogged after rollback +# +# testing appearence of insert into temp_table in binlog. +# There are two branches of execution that require different setup. + +## send_eof() branch + +# prepare + +create temporary table tt (a int unique); +create table ti (a int) engine=innodb; +reset master; +show master status; + +# action + +begin; +insert into ti values (1); +insert into ti values (2) ; +insert into tt select * from ti; +rollback; + +# check + +select count(*) from tt /* 2 */; +show master status; +--replace_column 2 # 5 # +show binlog events from 98; +select count(*) from ti /* zero */; +insert into ti select * from tt; +select * from ti /* that is what slave would miss - a bug */; + + +## send_error() branch +delete from ti; +delete from tt where a=1; +reset master; +show master status; + +# action + +begin; +insert into ti values (1); +insert into ti values (2) /* to make the dup error in the following */; +--error ER_DUP_ENTRY +insert into tt select * from ti /* one affected and error */; +rollback; + +# check + +show master status; +--replace_column 2 # 5 # +show binlog events from 98; +select count(*) from ti /* zero */; +insert into ti select * from tt; +select * from tt /* that is what otherwise slave missed - the bug */; + +drop table ti; + + +# +# Bug #27417 thd->no_trans_update.stmt lost value inside of SF-exec-stack +# +# Testing asserts: if there is a side effect of modifying non-transactional +# table thd->no_trans_update.stmt must be TRUE; +# the assert is active with debug build +# + +--disable_warnings +drop function if exists bug27417; +drop table if exists t1,t2; +--enable_warnings +# side effect table +CREATE TABLE t1 (a int NOT NULL auto_increment primary key) ENGINE=MyISAM; +# target tables +CREATE TABLE t2 (a int NOT NULL auto_increment, PRIMARY KEY (a)); + +delimiter |; +create function bug27417(n int) +RETURNS int(11) +begin + insert into t1 values (null); + return n; +end| +delimiter ;| + +reset master; + +# execute + +insert into t2 values (bug27417(1)); +insert into t2 select bug27417(2); +reset master; + +--error ER_DUP_ENTRY +insert into t2 values (bug27417(2)); +show master status; /* only (!) with fixes for #23333 will show there is the query */; +select count(*) from t1 /* must be 3 */; + +reset master; +select count(*) from t2; +delete from t2 where a=bug27417(3); +select count(*) from t2 /* nothing got deleted */; +show master status; /* the query must be in regardless of #23333 */; +select count(*) from t1 /* must be 5 */; + +--enable_info +delete t2 from t2 where t2.a=bug27417(100) /* must not affect t2 */; +--disable_info +select count(*) from t1 /* must be 7 */; + +drop function bug27417; +drop table t1,t2; + +--echo end of tests + diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 357b797ec75..a00dd6c505c 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -3732,7 +3732,7 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type) { m_transaction_on= FALSE; /* Would be simpler if has_transactions() didn't always say "yes" */ - thd->no_trans_update.all= thd->no_trans_update.stmt= TRUE; + thd->transaction.all.modified_non_trans_table= thd->transaction.stmt.modified_non_trans_table= TRUE; } else if (!thd->transaction.on) m_transaction_on= FALSE; diff --git a/sql/handler.cc b/sql/handler.cc index dcc9fde8b76..7b8625f6b3a 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -830,7 +830,7 @@ int ha_rollback_trans(THD *thd, bool all) the error log; but we don't want users to wonder why they have this message in the error log, so we don't send it. */ - if (is_real_trans && thd->no_trans_update.all && + if (is_real_trans && thd->transaction.all.modified_non_trans_table && !thd->slave_thread) push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARNING_NOT_COMPLETE_ROLLBACK, diff --git a/sql/handler.h b/sql/handler.h index a3767573178..c44d7c7f846 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -420,6 +420,35 @@ typedef struct st_thd_trans bool no_2pc; /* storage engines that registered themselves for this transaction */ handlerton *ht[MAX_HA]; + /* + The purpose of this flag is to keep track of non-transactional + tables that were modified in scope of: + - transaction, when the variable is a member of + THD::transaction.all + - top-level statement or sub-statement, when the variable is a + member of THD::transaction.stmt + This member has the following life cycle: + * stmt.modified_non_trans_table is used to keep track of + modified non-transactional tables of top-level statements. At + the end of the previous statement and at the beginning of the session, + it is reset to FALSE. If such functions + as mysql_insert, mysql_update, mysql_delete etc modify a + non-transactional table, they set this flag to TRUE. At the + end of the statement, the value of stmt.modified_non_trans_table + is merged with all.modified_non_trans_table and gets reset. + * all.modified_non_trans_table is reset at the end of transaction + + * Since we do not have a dedicated context for execution of a + sub-statement, to keep track of non-transactional changes in a + sub-statement, we re-use stmt.modified_non_trans_table. + At entrance into a sub-statement, a copy of the value of + stmt.modified_non_trans_table (containing the changes of the + outer statement) is saved on stack. Then + stmt.modified_non_trans_table is reset to FALSE and the + substatement is executed. Then the new value is merged with the + saved value. + */ + bool modified_non_trans_table; } THD_TRANS; enum enum_tx_isolation { ISO_READ_UNCOMMITTED, ISO_READ_COMMITTED, diff --git a/sql/log.cc b/sql/log.cc index 6992f6c10ef..e9aa273676a 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -162,7 +162,7 @@ static int binlog_rollback(THD *thd, bool all) table. Such cases should be rare (updating a non-transactional table inside a transaction...) */ - if (unlikely(thd->no_trans_update.all)) + if (unlikely(thd->transaction.all.modified_non_trans_table)) { Query_log_event qev(thd, STRING_WITH_LEN("ROLLBACK"), TRUE, FALSE); qev.error_code= 0; // see comment in MYSQL_LOG::write(THD, IO_CACHE) @@ -217,7 +217,7 @@ static int binlog_savepoint_rollback(THD *thd, void *sv) non-transactional table. Otherwise, truncate the binlog cache starting from the SAVEPOINT command. */ - if (unlikely(thd->no_trans_update.all)) + if (unlikely(thd->transaction.all.modified_non_trans_table)) { Query_log_event qinfo(thd, thd->query, thd->query_length, TRUE, FALSE); DBUG_RETURN(mysql_bin_log.write(&qinfo)); diff --git a/sql/set_var.cc b/sql/set_var.cc index b30aa008366..e1246617d84 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -2901,14 +2901,14 @@ static bool set_option_autocommit(THD *thd, set_var *var) { /* We changed to auto_commit mode */ thd->options&= ~(ulong) OPTION_BEGIN; - thd->no_trans_update.all= FALSE; + thd->transaction.all.modified_non_trans_table= FALSE; thd->server_status|= SERVER_STATUS_AUTOCOMMIT; if (ha_commit(thd)) return 1; } else { - thd->no_trans_update.all= FALSE; + thd->transaction.all.modified_non_trans_table= FALSE; thd->server_status&= ~SERVER_STATUS_AUTOCOMMIT; } } diff --git a/sql/sp_head.cc b/sql/sp_head.cc index fd8724b2171..589e59faca4 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -337,13 +337,13 @@ sp_eval_expr(THD *thd, Field *result_field, Item **expr_item_ptr) enum_check_fields save_count_cuted_fields= thd->count_cuted_fields; bool save_abort_on_warning= thd->abort_on_warning; - bool save_no_trans_update_stmt= thd->no_trans_update.stmt; + bool save_stmt_modified_non_trans_table= thd->transaction.stmt.modified_non_trans_table; thd->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL; thd->abort_on_warning= thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES); - thd->no_trans_update.stmt= FALSE; + thd->transaction.stmt.modified_non_trans_table= FALSE; /* Save the value in the field. Convert the value if needed. */ @@ -351,7 +351,7 @@ sp_eval_expr(THD *thd, Field *result_field, Item **expr_item_ptr) thd->count_cuted_fields= save_count_cuted_fields; thd->abort_on_warning= save_abort_on_warning; - thd->no_trans_update.stmt= save_no_trans_update_stmt; + thd->transaction.stmt.modified_non_trans_table= save_stmt_modified_non_trans_table; if (thd->net.report_error) { @@ -2400,7 +2400,13 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp, bool open_tables, sp_instr* instr) { int res= 0; - + /* + The flag is saved at the entry to the following substatement. + It's reset further in the common code part. + It's merged with the saved parent's value at the exit of this func. + */ + bool parent_modified_non_trans_table= thd->transaction.stmt.modified_non_trans_table; + thd->transaction.stmt.modified_non_trans_table= FALSE; DBUG_ASSERT(!thd->derived_tables); DBUG_ASSERT(thd->change_list.is_empty()); /* @@ -2467,7 +2473,11 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp, /* Update the state of the active arena. */ thd->stmt_arena->state= Query_arena::EXECUTED; - + /* + Merge here with the saved parent's values + what is needed from the substatement gained + */ + thd->transaction.stmt.modified_non_trans_table |= parent_modified_non_trans_table; /* Unlike for PS we should not call Item's destructors for newly created items after execution of each instruction in stored routine. This is diff --git a/sql/sql_class.cc b/sql/sql_class.cc index ee4e1ea149c..1866576aa3a 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -339,7 +339,7 @@ void THD::init(void) if (variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES) server_status|= SERVER_STATUS_NO_BACKSLASH_ESCAPES; options= thd_startup_options; - no_trans_update.stmt= no_trans_update.all= FALSE; + transaction.all.modified_non_trans_table= transaction.stmt.modified_non_trans_table= FALSE; open_options=ha_open_options; update_lock_default= (variables.low_priority_updates ? TL_WRITE_LOW_PRIORITY : diff --git a/sql/sql_class.h b/sql/sql_class.h index 058f130d4e7..1c84fd32965 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1460,10 +1460,6 @@ public: bool charset_is_system_charset, charset_is_collation_connection; bool charset_is_character_set_filesystem; bool enable_slow_log; /* enable slow log for current statement */ - struct { - bool all:1; - bool stmt:1; - } no_trans_update; bool abort_on_warning; bool got_warning; /* Set on call to push_warning() */ bool no_warnings_for_error; /* no warnings on call to my_error() */ @@ -1714,7 +1710,7 @@ public: inline bool really_abort_on_warning() { return (abort_on_warning && - (!no_trans_update.stmt || + (!transaction.stmt.modified_non_trans_table || (variables.sql_mode & MODE_STRICT_ALL_TABLES))); } void set_status_var_init(); diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index bccd4d4cafe..56edfa6c5b2 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -315,6 +315,9 @@ cleanup: delete select; transactional_table= table->file->has_transactions(); + if (!transactional_table && deleted > 0) + thd->transaction.stmt.modified_non_trans_table= TRUE; + /* See similar binlogging code in sql_update.cc, for comments */ if ((error < 0) || (deleted && !transactional_table)) { @@ -327,9 +330,10 @@ cleanup: if (mysql_bin_log.write(&qinfo) && transactional_table) error=1; } - if (!transactional_table) - thd->no_trans_update.all= TRUE; + if (thd->transaction.stmt.modified_non_trans_table) + thd->transaction.all.modified_non_trans_table= TRUE; } + DBUG_ASSERT(transactional_table || !deleted || thd->transaction.stmt.modified_non_trans_table); free_underlaid_joins(thd, select_lex); if (transactional_table) { @@ -642,20 +646,22 @@ bool multi_delete::send_data(List &values) if (table->triggers && table->triggers->process_triggers(thd, TRG_EVENT_DELETE, TRG_ACTION_BEFORE, FALSE)) - DBUG_RETURN(1); + DBUG_RETURN(1); table->status|= STATUS_DELETED; if (!(error=table->file->delete_row(table->record[0]))) { - deleted++; + deleted++; + if (!table->file->has_transactions()) + thd->transaction.stmt.modified_non_trans_table= TRUE; if (table->triggers && table->triggers->process_triggers(thd, TRG_EVENT_DELETE, TRG_ACTION_AFTER, FALSE)) - DBUG_RETURN(1); + DBUG_RETURN(1); } else { - table->file->print_error(error,MYF(0)); - DBUG_RETURN(1); + table->file->print_error(error,MYF(0)); + DBUG_RETURN(1); } } else @@ -705,6 +711,7 @@ void multi_delete::send_error(uint errcode,const char *err) error= 1; send_eof(); } + DBUG_ASSERT(!normal_tables || !deleted || thd->transaction.stmt.modified_non_trans_table); DBUG_VOID_RETURN; } @@ -732,6 +739,7 @@ int multi_delete::do_deletes() for (; table_being_deleted; table_being_deleted= table_being_deleted->next_local, counter++) { + ha_rows last_deleted= deleted; TABLE *table = table_being_deleted->table; if (tempfiles[counter]->get(table)) { @@ -769,6 +777,8 @@ int multi_delete::do_deletes() break; } } + if (last_deleted != deleted && !table->file->has_transactions()) + thd->transaction.stmt.modified_non_trans_table= TRUE; end_read_record(&info); if (thd->killed && !local_error) local_error= 1; @@ -807,7 +817,6 @@ bool multi_delete::send_eof() { query_cache_invalidate3(thd, delete_tables, 1); } - if ((local_error == 0) || (deleted && normal_tables)) { if (mysql_bin_log.is_open()) @@ -819,9 +828,11 @@ bool multi_delete::send_eof() if (mysql_bin_log.write(&qinfo) && !normal_tables) local_error=1; // Log write failed: roll back the SQL statement } - if (!transactional_tables) - thd->no_trans_update.all= TRUE; + if (thd->transaction.stmt.modified_non_trans_table) + thd->transaction.all.modified_non_trans_table= TRUE; } + DBUG_ASSERT(!normal_tables || !deleted || thd->transaction.stmt.modified_non_trans_table); + /* Commit or rollback the current SQL statement */ if (transactional_tables) if (ha_autocommit_or_rollback(thd,local_error > 0)) diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 5ba1e766947..5edce08e481 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -733,7 +733,6 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, if (lock_type != TL_WRITE_DELAYED && !thd->prelocked_mode) table->file->start_bulk_insert(values_list.elements); - thd->no_trans_update.stmt= FALSE; thd->abort_on_warning= (!ignore && (thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES))); @@ -907,10 +906,12 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, if (mysql_bin_log.write(&qinfo) && transactional_table) error=1; } - if (!transactional_table && changed) - thd->no_trans_update.all= TRUE; + if (thd->transaction.stmt.modified_non_trans_table) + thd->transaction.all.modified_non_trans_table= TRUE; } } + DBUG_ASSERT(transactional_table || !changed || + thd->transaction.stmt.modified_non_trans_table); if (transactional_table) error=ha_autocommit_or_rollback(thd,error); @@ -1311,7 +1312,7 @@ static int last_uniq_key(TABLE *table,uint keynr) then both on update triggers will work instead. Similarly both on delete triggers will be invoked if we will delete conflicting records. - Sets thd->no_trans_update.stmt to TRUE if table which is updated didn't have + Sets thd->transaction.stmt.modified_non_trans_table to TRUE if table which is updated didn't have transactions. RETURN VALUE @@ -1478,7 +1479,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) goto err; info->deleted++; if (!table->file->has_transactions()) - thd->no_trans_update.stmt= TRUE; + thd->transaction.stmt.modified_non_trans_table= TRUE; if (table->triggers && table->triggers->process_triggers(thd, TRG_EVENT_DELETE, TRG_ACTION_AFTER, TRUE)) @@ -1510,7 +1511,7 @@ ok_or_after_trg_err: if (key) my_safe_afree(key,table->s->max_unique_length,MAX_KEY_LENGTH); if (!table->file->has_transactions()) - thd->no_trans_update.stmt= TRUE; + thd->transaction.stmt.modified_non_trans_table= TRUE; DBUG_RETURN(trg_error); err: @@ -2790,7 +2791,6 @@ select_insert::prepare(List &values, SELECT_LEX_UNIT *u) } if (info.handle_duplicates == DUP_UPDATE) table->file->extra(HA_EXTRA_INSERT_WITH_UPDATE); - thd->no_trans_update.stmt= FALSE; thd->abort_on_warning= (!info.ignore && (thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES | @@ -2927,7 +2927,8 @@ void select_insert::send_error(uint errcode,const char *err) bool select_insert::send_eof() { - int error,error2; + int error, error2; + bool changed, transactional_table= table->file->has_transactions(); DBUG_ENTER("select_insert::send_eof"); error= (!thd->prelocked_mode) ? table->file->end_bulk_insert():0; @@ -2939,12 +2940,14 @@ bool select_insert::send_eof() and ha_autocommit_or_rollback */ - if (info.copied || info.deleted || info.updated) + if (changed= (info.copied || info.deleted || info.updated)) { query_cache_invalidate3(thd, table, 1); - if (!(table->file->has_transactions() || table->s->tmp_table)) - thd->no_trans_update.all= TRUE; + if (thd->transaction.stmt.modified_non_trans_table) + thd->transaction.all.modified_non_trans_table= TRUE; } + DBUG_ASSERT(transactional_table || !changed || + thd->transaction.stmt.modified_non_trans_table); if (last_insert_id) thd->insert_id(info.copied ? last_insert_id : 0); // For binary log @@ -2954,7 +2957,7 @@ bool select_insert::send_eof() if (!error) thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, - table->file->has_transactions(), FALSE); + transactional_table, FALSE); mysql_bin_log.write(&qinfo); } if ((error2=ha_autocommit_or_rollback(thd,error)) && ! error) @@ -2980,6 +2983,7 @@ bool select_insert::send_eof() void select_insert::abort() { + bool changed, transactional_table; DBUG_ENTER("select_insert::abort"); if (!table) @@ -2990,6 +2994,7 @@ void select_insert::abort() */ DBUG_VOID_RETURN; } + transactional_table= table->file->has_transactions(); if (!thd->prelocked_mode) table->file->end_bulk_insert(); /* @@ -2998,21 +3003,22 @@ void select_insert::abort() error while inserting into a MyISAM table) we must write to the binlog (and the error code will make the slave stop). */ - if ((info.copied || info.deleted || info.updated) && - !table->file->has_transactions()) + if ((changed= info.copied || info.deleted || info.updated) && + !transactional_table) { if (last_insert_id) thd->insert_id(last_insert_id); // For binary log if (mysql_bin_log.is_open()) { Query_log_event qinfo(thd, thd->query, thd->query_length, - table->file->has_transactions(), FALSE); + transactional_table, FALSE); mysql_bin_log.write(&qinfo); } - if (!table->s->tmp_table) - thd->no_trans_update.all= TRUE; + if (thd->transaction.stmt.modified_non_trans_table) + thd->transaction.all.modified_non_trans_table= TRUE; } - if (info.copied || info.deleted || info.updated) + DBUG_ASSERT(transactional_table || !changed || thd->transaction.stmt.modified_non_trans_table); + if (changed) { query_cache_invalidate3(thd, table, 1); } @@ -3259,7 +3265,6 @@ select_create::prepare(List &values, SELECT_LEX_UNIT *u) table->file->extra(HA_EXTRA_INSERT_WITH_UPDATE); if (!thd->prelocked_mode) table->file->start_bulk_insert((ha_rows) 0); - thd->no_trans_update.stmt= FALSE; thd->abort_on_warning= (!info.ignore && (thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES | diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 7b1799baaad..55cbbf1c540 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -377,7 +377,6 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, table->file->start_bulk_insert((ha_rows) 0); table->copy_blobs=1; - thd->no_trans_update.stmt= FALSE; thd->abort_on_warning= (!ignore && (thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES | @@ -411,7 +410,6 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, ha_autocommit_... */ query_cache_invalidate3(thd, table_list, 0); - if (error) { if (read_file_from_client) @@ -466,8 +464,8 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, sprintf(name, ER(ER_LOAD_INFO), (ulong) info.records, (ulong) info.deleted, (ulong) (info.records - info.copied), (ulong) thd->cuted_fields); - if (!transactional_table) - thd->no_trans_update.all= TRUE; + if (thd->transaction.stmt.modified_non_trans_table) + thd->transaction.all.modified_non_trans_table= TRUE; #ifndef EMBEDDED_LIBRARY if (mysql_bin_log.is_open()) { @@ -488,6 +486,8 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, /* ok to client sent only after binlog write and engine commit */ send_ok(thd, info.copied + info.deleted, 0L, name); err: + DBUG_ASSERT(transactional_table || !(info.copied || info.deleted) || + thd->transaction.stmt.modified_non_trans_table); if (thd->lock) { mysql_unlock_tables(thd, thd->lock); @@ -532,7 +532,7 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, Item_field *sql_field; TABLE *table= table_list->table; ulonglong id; - bool no_trans_update_stmt, err; + bool err; DBUG_ENTER("read_fixed_length"); id= 0; @@ -560,7 +560,6 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, #ifdef HAVE_purify read_info.row_end[0]=0; #endif - no_trans_update_stmt= !table->file->has_transactions(); restore_record(table, s->default_values); /* @@ -630,7 +629,6 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, table->auto_increment_field_not_null= FALSE; if (err) DBUG_RETURN(1); - thd->no_trans_update.stmt= no_trans_update_stmt; /* If auto_increment values are used, save the first one for @@ -673,12 +671,11 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, TABLE *table= table_list->table; uint enclosed_length; ulonglong id; - bool no_trans_update_stmt, err; + bool err; DBUG_ENTER("read_sep_field"); enclosed_length=enclosed.length(); id= 0; - no_trans_update_stmt= !table->file->has_transactions(); for (;;it.rewind()) { @@ -821,7 +818,6 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, We don't need to reset auto-increment field since we are restoring its default value at the beginning of each loop iteration. */ - thd->no_trans_update.stmt= no_trans_update_stmt; if (read_info.next_line()) // Skip to next line break; if (read_info.line_cuted) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index ae3bc0f5597..7d723d3cd5b 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -149,7 +149,7 @@ static bool end_active_trans(THD *thd) if (ha_commit(thd)) error=1; thd->options&= ~(ulong) OPTION_BEGIN; - thd->no_trans_update.all= FALSE; + thd->transaction.all.modified_non_trans_table= FALSE; } DBUG_RETURN(error); } @@ -173,7 +173,7 @@ static bool begin_trans(THD *thd) else { LEX *lex= thd->lex; - thd->no_trans_update.all= FALSE; + thd->transaction.all.modified_non_trans_table= FALSE; thd->options|= (ulong) OPTION_BEGIN; thd->server_status|= SERVER_STATUS_IN_TRANS; if (lex->start_transaction_opt & MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT) @@ -1471,7 +1471,7 @@ int end_trans(THD *thd, enum enum_mysql_completiontype completion) thd->server_status&= ~SERVER_STATUS_IN_TRANS; res= ha_commit(thd); thd->options&= ~(ulong) OPTION_BEGIN; - thd->no_trans_update.all= FALSE; + thd->transaction.all.modified_non_trans_table= FALSE; break; case COMMIT_RELEASE: do_release= 1; /* fall through */ @@ -1489,7 +1489,7 @@ int end_trans(THD *thd, enum enum_mysql_completiontype completion) if (ha_rollback(thd)) res= -1; thd->options&= ~(ulong) OPTION_BEGIN; - thd->no_trans_update.all= FALSE; + thd->transaction.all.modified_non_trans_table= FALSE; if (!res && (completion == ROLLBACK_AND_CHAIN)) res= begin_trans(thd); break; @@ -2600,6 +2600,8 @@ mysql_execute_command(THD *thd) statistic_increment(thd->status_var.com_stat[lex->sql_command], &LOCK_status); + DBUG_ASSERT(thd->transaction.stmt.modified_non_trans_table == FALSE); + switch (lex->sql_command) { case SQLCOM_SELECT: { @@ -2937,7 +2939,7 @@ mysql_execute_command(THD *thd) else { /* So that CREATE TEMPORARY TABLE gets to binlog at commit/rollback */ - thd->no_trans_update.all= TRUE; + thd->transaction.all.modified_non_trans_table= TRUE; } DBUG_ASSERT(first_table == all_tables && first_table != 0); bool link_to_local; @@ -3720,7 +3722,7 @@ end_with_restore_list: lex->drop_if_exists= 1; /* So that DROP TEMPORARY TABLE gets to binlog at commit/rollback */ - thd->no_trans_update.all= TRUE; + thd->transaction.all.modified_non_trans_table= TRUE; } /* DDL and binlog write order protected by LOCK_open */ res= mysql_rm_table(thd, first_table, lex->drop_if_exists, @@ -4322,7 +4324,7 @@ end_with_restore_list: res= TRUE; // cannot happen else { - if (thd->no_trans_update.all && + if (thd->transaction.all.modified_non_trans_table && !thd->slave_thread) push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARNING_NOT_COMPLETE_ROLLBACK, @@ -4969,7 +4971,7 @@ create_sp_error: thd->transaction.xid_state.xa_state=XA_ACTIVE; thd->transaction.xid_state.xid.set(thd->lex->xid); xid_cache_insert(&thd->transaction.xid_state); - thd->no_trans_update.all= FALSE; + thd->transaction.all.modified_non_trans_table= FALSE; thd->options|= (ulong) OPTION_BEGIN; thd->server_status|= SERVER_STATUS_IN_TRANS; send_ok(thd); @@ -5064,7 +5066,7 @@ create_sp_error: break; } thd->options&= ~(ulong) OPTION_BEGIN; - thd->no_trans_update.all= FALSE; + thd->transaction.all.modified_non_trans_table= FALSE; thd->server_status&= ~SERVER_STATUS_IN_TRANS; xid_cache_delete(&thd->transaction.xid_state); thd->transaction.xid_state.xa_state=XA_NOTR; @@ -5095,7 +5097,7 @@ create_sp_error: else send_ok(thd); thd->options&= ~(ulong) OPTION_BEGIN; - thd->no_trans_update.all= FALSE; + thd->transaction.all.modified_non_trans_table= FALSE; thd->server_status&= ~SERVER_STATUS_IN_TRANS; xid_cache_delete(&thd->transaction.xid_state); thd->transaction.xid_state.xa_state=XA_NOTR; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 7db79543016..d83100aa439 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -4091,7 +4091,6 @@ copy_data_between_tables(TABLE *from,TABLE *to, alter_table_manage_keys(to, from->file->indexes_are_disabled(), keys_onoff); /* We can abort alter table for any table type */ - thd->no_trans_update.stmt= FALSE; thd->abort_on_warning= !ignore && test(thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES)); diff --git a/sql/sql_update.cc b/sql/sql_update.cc index f4239afc4cd..e20647dc808 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -430,7 +430,6 @@ int mysql_update(THD *thd, query_id=thd->query_id; transactional_table= table->file->has_transactions(); - thd->no_trans_update.stmt= FALSE; thd->abort_on_warning= test(!ignore && (thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES | @@ -487,7 +486,6 @@ int mysql_update(THD *thd, (byte*) table->record[0]))) { updated++; - thd->no_trans_update.stmt= !transactional_table; if (table->triggers && table->triggers->process_triggers(thd, TRG_EVENT_UPDATE, @@ -522,6 +520,10 @@ int mysql_update(THD *thd, thd->row_count++; } + if (!transactional_table && updated > 0) + thd->transaction.stmt.modified_non_trans_table= TRUE; + + /* todo bug#27571: to avoid asynchronization of `error' and `error_code' of binlog event constructor @@ -589,9 +591,10 @@ int mysql_update(THD *thd, if (mysql_bin_log.write(&qinfo) && transactional_table) error=1; // Rollback update } - if (!transactional_table) - thd->no_trans_update.all= TRUE; + if (thd->transaction.stmt.modified_non_trans_table) + thd->transaction.all.modified_non_trans_table= TRUE; } + DBUG_ASSERT(transactional_table || !updated || thd->transaction.stmt.modified_non_trans_table); free_underlaid_joins(thd, select_lex); if (transactional_table) { @@ -955,7 +958,6 @@ bool mysql_multi_update(THD *thd, handle_duplicates, ignore))) DBUG_RETURN(TRUE); - thd->no_trans_update.stmt= FALSE; thd->abort_on_warning= test(thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES)); @@ -1331,9 +1333,7 @@ multi_update::~multi_update() if (copy_field) delete [] copy_field; thd->count_cuted_fields= CHECK_FIELD_IGNORE; // Restore this setting - if (!trans_safe) // todo: remove since redundant - thd->no_trans_update.all= TRUE; - DBUG_ASSERT(trans_safe || thd->no_trans_update.all); + DBUG_ASSERT(trans_safe || thd->transaction.all.modified_non_trans_table); } @@ -1426,7 +1426,7 @@ bool multi_update::send_data(List ¬_used_values) else { trans_safe= 0; - thd->no_trans_update.stmt= TRUE; + thd->transaction.stmt.modified_non_trans_table= TRUE; } if (table->triggers && table->triggers->process_triggers(thd, TRG_EVENT_UPDATE, @@ -1489,7 +1489,6 @@ void multi_update::send_error(uint errcode,const char *err) /* Something already updated so we have to invalidate cache */ query_cache_invalidate3(thd, update_tables, 1); - /* If all tables that has been updated are trans safe then just do rollback. If not attempt to do remaining updates. @@ -1502,7 +1501,7 @@ void multi_update::send_error(uint errcode,const char *err) } else { - DBUG_ASSERT(thd->no_trans_update.stmt); + DBUG_ASSERT(thd->transaction.stmt.modified_non_trans_table); if (do_update && table_count > 1) { /* Add warning here */ @@ -1513,7 +1512,7 @@ void multi_update::send_error(uint errcode,const char *err) VOID(do_updates(0)); } } - if (thd->no_trans_update.stmt) + if (thd->transaction.stmt.modified_non_trans_table) { /* The query has to binlog because there's a modified non-transactional table @@ -1526,9 +1525,9 @@ void multi_update::send_error(uint errcode,const char *err) mysql_bin_log.write(&qinfo); } if (!trans_safe) - thd->no_trans_update.all= TRUE; + thd->transaction.all.modified_non_trans_table= TRUE; } - DBUG_ASSERT(trans_safe || !updated || thd->no_trans_update.stmt); + DBUG_ASSERT(trans_safe || !updated || thd->transaction.stmt.modified_non_trans_table); if (transactional_tables) { @@ -1664,7 +1663,7 @@ int multi_update::do_updates(bool from_send_error) else { trans_safe= 0; // Can't do safe rollback - thd->no_trans_update.stmt= TRUE; + thd->transaction.stmt.modified_non_trans_table= TRUE; } } (void) table->file->ha_rnd_end(); @@ -1697,7 +1696,7 @@ err2: else { trans_safe= 0; - thd->no_trans_update.stmt= TRUE; + thd->transaction.stmt.modified_non_trans_table= TRUE; } } DBUG_RETURN(1); @@ -1722,7 +1721,6 @@ bool multi_update::send_eof() { query_cache_invalidate3(thd, update_tables, 1); } - /* Write the SQL statement to the binlog if we updated rows and we succeeded or if we updated some non @@ -1732,8 +1730,9 @@ bool multi_update::send_eof() either from the query's list or via a stored routine: bug#13270,23333 */ - DBUG_ASSERT(trans_safe || !updated || thd->no_trans_update.stmt); - if (local_error == 0 || thd->no_trans_update.stmt) + DBUG_ASSERT(trans_safe || !updated || + thd->transaction.stmt.modified_non_trans_table); + if (local_error == 0 || thd->transaction.stmt.modified_non_trans_table) { if (mysql_bin_log.is_open()) { @@ -1746,8 +1745,8 @@ bool multi_update::send_eof() if (mysql_bin_log.write(&qinfo) && trans_safe) local_error= 1; // Rollback update } - if (!trans_safe) - thd->no_trans_update.all= TRUE; + if (thd->transaction.stmt.modified_non_trans_table) + thd->transaction.all.modified_non_trans_table= TRUE; } if (transactional_tables) From 77edfb16e8a699d87694a7b3aff95118c5104d83 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 30 Jul 2007 21:05:56 +0500 Subject: [PATCH 20/26] bigint.test: Fixing a typo in the test case. mysql-test/t/bigint.test: Fixing a typo in the test case. --- mysql-test/t/bigint.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/t/bigint.test b/mysql-test/t/bigint.test index 4aef7395184..002dfad9981 100644 --- a/mysql-test/t/bigint.test +++ b/mysql-test/t/bigint.test @@ -307,6 +307,6 @@ select -(9223372036854775808); select -((9223372036854775808)); select -(-(9223372036854775808)); --disable_metadata ---endble_ps_protocol +--enable_ps_protocol select --9223372036854775808, ---9223372036854775808, ----9223372036854775808; select -(-9223372036854775808), -(-(-9223372036854775808)); From 791584ae0d57ce1f31b4652c1dd9cb4edee8526e Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 31 Jul 2007 10:46:04 +0500 Subject: [PATCH 21/26] Bug #29717 INSERT INTO SELECT inserts values even if SELECT statement itself returns empty. As a result of this bug 'SELECT AGGREGATE_FUNCTION(fld) ... GROUP BY' can return one row instead of an empty result set. When GROUP BY only has fields of constant tables (with a single row), the optimizer deletes the group_list. After that we lose the information about whether we had an GROUP BY statement. Though it's important as SELECT min(x) from empty_table; and SELECT min(x) from empty_table GROUP BY y; have to return different results - the first query should return one row, second - an empty result set. So here we add the 'group_optimized_away' flag to remember this case when GROUP BY exists in the query and is removed by the optimizer, and check this flag in end_send_group() mysql-test/r/group_by.result: Bug #29717 INSERT INTO SELECT inserts values even if SELECT statement itself returns empty. test result mysql-test/r/insert_select.result: Bug #29717 INSERT INTO SELECT inserts values even if SELECT statement itself returns empty. test result mysql-test/t/group_by.test: Bug #29717 INSERT INTO SELECT inserts values even if SELECT statement itself returns empty. This is additional testcase that is more basic than the original bug's testcase and has the same reason. mysql-test/t/insert_select.test: Bug #29717 INSERT INTO SELECT inserts values even if SELECT statement itself returns empty. test case sql/sql_select.cc: Bug #29717 INSERT INTO SELECT inserts values even if SELECT statement itself returns empty. Remember the 'GROUP BY was optimized away' case in the JOIN::group_optimized and check this in the end_send_group() sql/sql_select.h: Bug #29717 INSERT INTO SELECT inserts values even if SELECT statement itself returns empty. JOIN::group_optimized member added to remember the 'GROUP BY optimied away' case --- mysql-test/r/group_by.result | 17 +++++++++++++++++ mysql-test/r/insert_select.result | 26 ++++++++++++++++++++++++++ mysql-test/t/group_by.test | 23 +++++++++++++++++++++++ mysql-test/t/insert_select.test | 28 ++++++++++++++++++++++++++++ sql/sql_select.cc | 4 +++- sql/sql_select.h | 9 +++++++++ 6 files changed, 106 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result index 61b73dc7005..f717c16742f 100644 --- a/mysql-test/r/group_by.result +++ b/mysql-test/r/group_by.result @@ -818,3 +818,20 @@ a 2 1 DROP TABLE t1; +CREATE TABLE t1 ( +f1 int(10) unsigned NOT NULL auto_increment primary key, +f2 varchar(100) NOT NULL default '' +); +CREATE TABLE t2 ( +f1 varchar(10) NOT NULL default '', +f2 char(3) NOT NULL default '', +PRIMARY KEY (`f1`), +KEY `k1` (`f2`,`f1`) +); +INSERT INTO t1 values(NULL, ''); +INSERT INTO `t2` VALUES ('486878','WDT'),('486910','WDT'); +SELECT SQL_BUFFER_RESULT avg(t2.f1) FROM t1, t2 where t2.f2 = 'SIR' GROUP BY t1.f1; +avg(t2.f1) +SELECT avg(t2.f1) FROM t1, t2 where t2.f2 = 'SIR' GROUP BY t1.f1; +avg(t2.f1) +DROP TABLE t1, t2; diff --git a/mysql-test/r/insert_select.result b/mysql-test/r/insert_select.result index 1d7aef256e1..601eb2aa0bc 100644 --- a/mysql-test/r/insert_select.result +++ b/mysql-test/r/insert_select.result @@ -690,3 +690,29 @@ CREATE TABLE t1 (a int PRIMARY KEY); INSERT INTO t1 values (1), (2); INSERT INTO t1 SELECT a + 2 FROM t1 LIMIT 1; DROP TABLE t1; +CREATE TABLE t1 ( +f1 int(10) unsigned NOT NULL auto_increment PRIMARY KEY, +f2 varchar(100) NOT NULL default '' +); +CREATE TABLE t2 ( +f1 varchar(10) NOT NULL default '', +f2 char(3) NOT NULL default '', +PRIMARY KEY (`f1`), +KEY `k1` (`f2`, `f1`) +); +INSERT INTO t1 values(NULL, ''); +INSERT INTO `t2` VALUES ('486878','WDT'),('486910','WDT'); +SELECT COUNT(*) FROM t1; +COUNT(*) +1 +SELECT min(t2.f1) FROM t1, t2 where t2.f2 = 'SIR' GROUP BY t1.f1; +min(t2.f1) +INSERT INTO t1 (f2) +SELECT min(t2.f1) FROM t1, t2 where t2.f2 = 'SIR' GROUP BY t1.f1; +SELECT COUNT(*) FROM t1; +COUNT(*) +1 +SELECT * FROM t1; +f1 f2 +1 +DROP TABLE t1, t2; diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test index 064d46aa0c0..180299f7f4a 100644 --- a/mysql-test/t/group_by.test +++ b/mysql-test/t/group_by.test @@ -633,4 +633,27 @@ SELECT a FROM t1 ORDER BY 'a' DESC; SELECT a FROM t1 ORDER BY "a" DESC; SELECT a FROM t1 ORDER BY `a` DESC; DROP TABLE t1; + + +# +# Bug #29717 INSERT INTO SELECT inserts values even if SELECT statement itself +# returns empty +# +CREATE TABLE t1 ( + f1 int(10) unsigned NOT NULL auto_increment primary key, + f2 varchar(100) NOT NULL default '' +); +CREATE TABLE t2 ( + f1 varchar(10) NOT NULL default '', + f2 char(3) NOT NULL default '', + PRIMARY KEY (`f1`), + KEY `k1` (`f2`,`f1`) +); + +INSERT INTO t1 values(NULL, ''); +INSERT INTO `t2` VALUES ('486878','WDT'),('486910','WDT'); +SELECT SQL_BUFFER_RESULT avg(t2.f1) FROM t1, t2 where t2.f2 = 'SIR' GROUP BY t1.f1; +SELECT avg(t2.f1) FROM t1, t2 where t2.f2 = 'SIR' GROUP BY t1.f1; +DROP TABLE t1, t2; + # End of 4.1 tests diff --git a/mysql-test/t/insert_select.test b/mysql-test/t/insert_select.test index fcea489fcff..dfb313706dd 100644 --- a/mysql-test/t/insert_select.test +++ b/mysql-test/t/insert_select.test @@ -239,4 +239,32 @@ INSERT INTO t1 SELECT a + 2 FROM t1 LIMIT 1; DROP TABLE t1; +# +# Bug #29717 INSERT INTO SELECT inserts values even if SELECT statement itself returns empty +# + +CREATE TABLE t1 ( + f1 int(10) unsigned NOT NULL auto_increment PRIMARY KEY, + f2 varchar(100) NOT NULL default '' +); +CREATE TABLE t2 ( + f1 varchar(10) NOT NULL default '', + f2 char(3) NOT NULL default '', + PRIMARY KEY (`f1`), + KEY `k1` (`f2`, `f1`) +); + +INSERT INTO t1 values(NULL, ''); +INSERT INTO `t2` VALUES ('486878','WDT'),('486910','WDT'); +SELECT COUNT(*) FROM t1; + +SELECT min(t2.f1) FROM t1, t2 where t2.f2 = 'SIR' GROUP BY t1.f1; + +INSERT INTO t1 (f2) + SELECT min(t2.f1) FROM t1, t2 where t2.f2 = 'SIR' GROUP BY t1.f1; + +SELECT COUNT(*) FROM t1; +SELECT * FROM t1; +DROP TABLE t1, t2; + # End of 4.1 tests diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 8b5664a7f96..8f0ad359f43 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -777,6 +777,7 @@ JOIN::optimize() order=0; // The output has only one row simple_order=1; select_distinct= 0; // No need in distinct for 1 row + group_optimized_away= 1; } calc_group_buffer(this, group_list); @@ -6896,7 +6897,8 @@ end_send_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), if (!join->first_record || end_of_records || (idx=test_if_group_changed(join->group_fields)) >= 0) { - if (join->first_record || (end_of_records && !join->group)) + if (join->first_record || + (end_of_records && !join->group && !join->group_optimized_away)) { if (join->procedure) join->procedure->end_group(); diff --git a/sql/sql_select.h b/sql/sql_select.h index c61ef4fb92b..6227d6d2cc5 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -180,6 +180,14 @@ class JOIN :public Sql_alloc ROLLUP rollup; // Used with rollup bool select_distinct; // Set if SELECT DISTINCT + /* + If we have the GROUP BY statement in the query, + but the group_list was emptied by optimizer, this + flag is TRUE. + It happens when fields in the GROUP BY are from + constant table + */ + bool group_optimized_away; /* simple_xxxxx is set if ORDER/GROUP BY doesn't include any references @@ -276,6 +284,7 @@ class JOIN :public Sql_alloc ref_pointer_array_size= 0; zero_result_cause= 0; optimized= 0; + group_optimized_away= 0; fields_list= fields_arg; bzero((char*) &keyuse,sizeof(keyuse)); From 210243480cf0506809d28dd7502f73628483cd8b Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 31 Jul 2007 11:10:03 +0500 Subject: [PATCH 22/26] merging --- mysql-test/r/group_by.result | 17 +++++++++++++++++ mysql-test/r/insert_select.result | 26 ++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result index 88f635595d6..d4ffbe43a91 100644 --- a/mysql-test/r/group_by.result +++ b/mysql-test/r/group_by.result @@ -824,6 +824,23 @@ a 2 1 DROP TABLE t1; +CREATE TABLE t1 ( +f1 int(10) unsigned NOT NULL auto_increment primary key, +f2 varchar(100) NOT NULL default '' +); +CREATE TABLE t2 ( +f1 varchar(10) NOT NULL default '', +f2 char(3) NOT NULL default '', +PRIMARY KEY (`f1`), +KEY `k1` (`f2`,`f1`) +); +INSERT INTO t1 values(NULL, ''); +INSERT INTO `t2` VALUES ('486878','WDT'),('486910','WDT'); +SELECT SQL_BUFFER_RESULT avg(t2.f1) FROM t1, t2 where t2.f2 = 'SIR' GROUP BY t1.f1; +avg(t2.f1) +SELECT avg(t2.f1) FROM t1, t2 where t2.f2 = 'SIR' GROUP BY t1.f1; +avg(t2.f1) +DROP TABLE t1, t2; create table t1 (c1 char(3), c2 char(3)); create table t2 (c3 char(3), c4 char(3)); insert into t1 values ('aaa', 'bb1'), ('aaa', 'bb2'); diff --git a/mysql-test/r/insert_select.result b/mysql-test/r/insert_select.result index 8cb94072818..d16562d97e2 100644 --- a/mysql-test/r/insert_select.result +++ b/mysql-test/r/insert_select.result @@ -699,6 +699,32 @@ Handler_read_prev 0 Handler_read_rnd 0 Handler_read_rnd_next 1 DROP TABLE t1; +CREATE TABLE t1 ( +f1 int(10) unsigned NOT NULL auto_increment PRIMARY KEY, +f2 varchar(100) NOT NULL default '' +); +CREATE TABLE t2 ( +f1 varchar(10) NOT NULL default '', +f2 char(3) NOT NULL default '', +PRIMARY KEY (`f1`), +KEY `k1` (`f2`, `f1`) +); +INSERT INTO t1 values(NULL, ''); +INSERT INTO `t2` VALUES ('486878','WDT'),('486910','WDT'); +SELECT COUNT(*) FROM t1; +COUNT(*) +1 +SELECT min(t2.f1) FROM t1, t2 where t2.f2 = 'SIR' GROUP BY t1.f1; +min(t2.f1) +INSERT INTO t1 (f2) +SELECT min(t2.f1) FROM t1, t2 where t2.f2 = 'SIR' GROUP BY t1.f1; +SELECT COUNT(*) FROM t1; +COUNT(*) +1 +SELECT * FROM t1; +f1 f2 +1 +DROP TABLE t1, t2; CREATE TABLE t1 (x int, y int); CREATE TABLE t2 (z int, y int); CREATE TABLE t3 (a int, b int); From 124ad9c6403eaf43086ac28426a89ee6df9729fb Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 31 Jul 2007 13:22:01 +0500 Subject: [PATCH 23/26] sql_yacc.yy, sp.result, disabled.def: Post-merge fix. mysql-test/t/disabled.def: Post-merge fix. mysql-test/r/sp.result: Post-merge fix. sql/sql_yacc.yy: Post-merge fix. --- mysql-test/r/sp.result | 8 ++++---- mysql-test/t/disabled.def | 1 - sql/sql_yacc.yy | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 4ac88b995dd..ebdab4a3f89 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -6431,7 +6431,7 @@ select 1; select 3; select 4; -end utf8 utf8_general_ci latin1_swedish_ci +end latin1 latin1_swedish_ci latin1_swedish_ci call proc_25411_a(); 1 1 @@ -6451,7 +6451,7 @@ proc_25411_b CREATE DEFINER=`root`@`localhost` PROCEDURE `proc_25411_b`( ) begin select p1, p2; -end utf8 utf8_general_ci latin1_swedish_ci +end latin1 latin1_swedish_ci latin1_swedish_ci select name, param_list, body from mysql.proc where name like "%25411%"; name param_list body proc_25411_a begin @@ -6489,7 +6489,7 @@ select 1 ,2 ,3; select 1,2 ,3 ; select 1 ,2 ,3 ; select 1 ,2 ,3 ; -end utf8 utf8_general_ci latin1_swedish_ci +end latin1 latin1_swedish_ci latin1_swedish_ci call proc_25411_c(); 1 2 3 1 2 3 @@ -6510,7 +6510,7 @@ select 1 /* testing */; show create procedure proc_26302; Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation proc_26302 CREATE DEFINER=`root`@`localhost` PROCEDURE `proc_26302`() -select 1 /* testing */ utf8 utf8_general_ci latin1_swedish_ci +select 1 /* testing */ latin1 latin1_swedish_ci latin1_swedish_ci select ROUTINE_NAME, ROUTINE_DEFINITION from information_schema.ROUTINES where ROUTINE_NAME = "proc_26302"; ROUTINE_NAME ROUTINE_DEFINITION diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index fff651e54c9..368a659d939 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -25,4 +25,3 @@ ctype_big5 : BUG#26711 2007-06-21 Lars Test has never worked on Do mysql_upgrade : Bug#28560 test links to /usr/local/mysql/lib libraries, causes non-determinism and failures on ABI breakage federated_transactions : Bug#29523 Transactions do not work -ddl_i18n_koi8r : Bug #30120 SP with local variables with non-ASCII names crashes server diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 5d665d5a6a2..855c8dede5f 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -9506,7 +9506,7 @@ simple_ident: splocal= new Item_splocal($1, spv->offset, spv->type, lip->get_tok_start_prev() - lex->sphead->m_tmp_query, - lip->tok_end - lip->tok_start_prev); + lip->get_tok_end() - lip->get_tok_start_prev()); #ifndef DBUG_OFF if (splocal) splocal->m_sp= lex->sphead; From 21d639e573d483a354c8ddbf17471ee468cce926 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 31 Jul 2007 14:42:56 +0300 Subject: [PATCH 24/26] addendum for the fix for bug 27417: extend the assert so it will run the testsuite --- sql/sql_update.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sql/sql_update.cc b/sql/sql_update.cc index e20647dc808..c78e246f518 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -1333,7 +1333,8 @@ multi_update::~multi_update() if (copy_field) delete [] copy_field; thd->count_cuted_fields= CHECK_FIELD_IGNORE; // Restore this setting - DBUG_ASSERT(trans_safe || thd->transaction.all.modified_non_trans_table); + DBUG_ASSERT(trans_safe || !updated || + thd->transaction.all.modified_non_trans_table); } From 8e1ec7ab5e819aa3d42ba2f2b381c44253dc9021 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 31 Jul 2007 14:58:04 +0300 Subject: [PATCH 25/26] merge of the fix for bug 17417 5.0-opt->5.1-opt --- .../mix_innodb_myisam_binlog.test | 118 ----------------- .../r/binlog_stm_mix_innodb_myisam.result | 24 ++-- .../t/binlog_stm_mix_innodb_myisam.test | 120 ++++++++++++++++++ sql/sql_class.cc | 2 +- sql/sql_insert.cc | 2 +- sql/sql_parse.cc | 2 +- 6 files changed, 135 insertions(+), 133 deletions(-) diff --git a/mysql-test/extra/binlog_tests/mix_innodb_myisam_binlog.test b/mysql-test/extra/binlog_tests/mix_innodb_myisam_binlog.test index 831f13893a1..7141bd1abb9 100644 --- a/mysql-test/extra/binlog_tests/mix_innodb_myisam_binlog.test +++ b/mysql-test/extra/binlog_tests/mix_innodb_myisam_binlog.test @@ -316,121 +316,3 @@ disconnect con3; connection con4; select get_lock("a",10); # wait for rollback to finish -# -# Bug #27417 thd->no_trans_update.stmt lost value inside of SF-exec-stack -# bug #28960 non-trans temp table changes with insert .. select -# not binlogged after rollback -# -# testing appearence of insert into temp_table in binlog. -# There are two branches of execution that require different setup. - -## send_eof() branch - -# prepare - -create temporary table tt (a int unique); -create table ti (a int) engine=innodb; -reset master; -show master status; - -# action - -begin; -insert into ti values (1); -insert into ti values (2) ; -insert into tt select * from ti; -rollback; - -# check - -select count(*) from tt /* 2 */; -show master status; ---replace_column 2 # 5 # -show binlog events from 98; -select count(*) from ti /* zero */; -insert into ti select * from tt; -select * from ti /* that is what slave would miss - a bug */; - - -## send_error() branch -delete from ti; -delete from tt where a=1; -reset master; -show master status; - -# action - -begin; -insert into ti values (1); -insert into ti values (2) /* to make the dup error in the following */; ---error ER_DUP_ENTRY -insert into tt select * from ti /* one affected and error */; -rollback; - -# check - -show master status; ---replace_column 2 # 5 # -show binlog events from 98; -select count(*) from ti /* zero */; -insert into ti select * from tt; -select * from tt /* that is what otherwise slave missed - the bug */; - -drop table ti; - - -# -# Bug #27417 thd->no_trans_update.stmt lost value inside of SF-exec-stack -# -# Testing asserts: if there is a side effect of modifying non-transactional -# table thd->no_trans_update.stmt must be TRUE; -# the assert is active with debug build -# - ---disable_warnings -drop function if exists bug27417; -drop table if exists t1,t2; ---enable_warnings -# side effect table -CREATE TABLE t1 (a int NOT NULL auto_increment primary key) ENGINE=MyISAM; -# target tables -CREATE TABLE t2 (a int NOT NULL auto_increment, PRIMARY KEY (a)); - -delimiter |; -create function bug27417(n int) -RETURNS int(11) -begin - insert into t1 values (null); - return n; -end| -delimiter ;| - -reset master; - -# execute - -insert into t2 values (bug27417(1)); -insert into t2 select bug27417(2); -reset master; - ---error ER_DUP_ENTRY -insert into t2 values (bug27417(2)); -show master status; /* only (!) with fixes for #23333 will show there is the query */; -select count(*) from t1 /* must be 3 */; - -reset master; -select count(*) from t2; -delete from t2 where a=bug27417(3); -select count(*) from t2 /* nothing got deleted */; -show master status; /* the query must be in regardless of #23333 */; -select count(*) from t1 /* must be 5 */; - ---enable_info -delete t2 from t2 where t2.a=bug27417(100) /* must not affect t2 */; ---disable_info -select count(*) from t1 /* must be 7 */; - -drop function bug27417; -drop table t1,t2; - ---echo end of tests diff --git a/mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result b/mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result index 56dee7838cd..87641d6fae4 100644 --- a/mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result +++ b/mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result @@ -380,12 +380,12 @@ select @a like "%#%error_code=0%ROLLBACK/*!*/;%ROLLBACK /* added by mysqlbinlog */;%" @a not like "%#%error_code=%error_code=%" 1 1 drop table t1, t2; -create temporary table tt (a int unique); +create table tt (a int unique); create table ti (a int) engine=innodb; reset master; show master status; File Position Binlog_Do_DB Binlog_Ignore_DB -master-bin.000001 98 +master-bin.000001 106 begin; insert into ti values (1); insert into ti values (2) ; @@ -398,8 +398,8 @@ count(*) 2 show master status; File Position Binlog_Do_DB Binlog_Ignore_DB -master-bin.000001 507 -show binlog events from 98; +master-bin.000001 515 +show binlog events from 106; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 # Query 1 # use `test`; BEGIN master-bin.000001 # Query 1 # use `test`; insert into ti values (1) @@ -419,19 +419,19 @@ delete from tt where a=1; reset master; show master status; File Position Binlog_Do_DB Binlog_Ignore_DB -master-bin.000001 98 +master-bin.000001 106 begin; insert into ti values (1); insert into ti values (2) /* to make the dup error in the following */; insert into tt select * from ti /* one affected and error */; -ERROR 23000: Duplicate entry '2' for key 1 +ERROR 23000: Duplicate entry '2' for key 'a' rollback; Warnings: Warning 1196 Some non-transactional changed tables couldn't be rolled back show master status; File Position Binlog_Do_DB Binlog_Ignore_DB -master-bin.000001 581 -show binlog events from 98; +master-bin.000001 589 +show binlog events from 106; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 # Query 1 # use `test`; BEGIN master-bin.000001 # Query 1 # use `test`; insert into ti values (1) @@ -446,7 +446,7 @@ select * from tt /* that is what otherwise slave missed - the bug */; a 1 2 -drop table ti; +drop table ti,tt; drop function if exists bug27417; drop table if exists t1,t2; CREATE TABLE t1 (a int NOT NULL auto_increment primary key) ENGINE=MyISAM; @@ -462,10 +462,10 @@ insert into t2 values (bug27417(1)); insert into t2 select bug27417(2); reset master; insert into t2 values (bug27417(2)); -ERROR 23000: Duplicate entry '2' for key 1 +ERROR 23000: Duplicate entry '2' for key 'PRIMARY' show master status; File Position Binlog_Do_DB Binlog_Ignore_DB -master-bin.000001 98 +master-bin.000001 218 /* only (!) with fixes for #23333 will show there is the query */; select count(*) from t1 /* must be 3 */; count(*) @@ -480,7 +480,7 @@ count(*) 2 show master status; File Position Binlog_Do_DB Binlog_Ignore_DB -master-bin.000001 195 +master-bin.000001 223 /* the query must be in regardless of #23333 */; select count(*) from t1 /* must be 5 */; count(*) diff --git a/mysql-test/suite/binlog/t/binlog_stm_mix_innodb_myisam.test b/mysql-test/suite/binlog/t/binlog_stm_mix_innodb_myisam.test index 72651c13be7..fd2b948a35e 100644 --- a/mysql-test/suite/binlog/t/binlog_stm_mix_innodb_myisam.test +++ b/mysql-test/suite/binlog/t/binlog_stm_mix_innodb_myisam.test @@ -21,4 +21,124 @@ is not null; eval select @a like "%#%error_code=0%ROLLBACK/*!*/;%ROLLBACK /* added by mysqlbinlog */;%", @a not like "%#%error_code=%error_code=%"; + drop table t1, t2; + +# +# Bug #27417 thd->no_trans_update.stmt lost value inside of SF-exec-stack +# bug #28960 non-trans temp table changes with insert .. select +# not binlogged after rollback +# +# testing appearence of insert into temp_table in binlog. +# There are two branches of execution that require different setup. + +## send_eof() branch + +# prepare + +create table tt (a int unique); +create table ti (a int) engine=innodb; +reset master; +show master status; + +# action + +begin; +insert into ti values (1); +insert into ti values (2) ; +insert into tt select * from ti; +rollback; + +# check + +select count(*) from tt /* 2 */; +show master status; +--replace_column 2 # 5 # +show binlog events from 106; +select count(*) from ti /* zero */; +insert into ti select * from tt; +select * from ti /* that is what slave would miss - a bug */; + + +## send_error() branch +delete from ti; +delete from tt where a=1; +reset master; +show master status; + +# action + +begin; +insert into ti values (1); +insert into ti values (2) /* to make the dup error in the following */; +--error ER_DUP_ENTRY +insert into tt select * from ti /* one affected and error */; +rollback; + +# check + +show master status; +--replace_column 2 # 5 # +show binlog events from 106; +select count(*) from ti /* zero */; +insert into ti select * from tt; +select * from tt /* that is what otherwise slave missed - the bug */; + +drop table ti,tt; + + +# +# Bug #27417 thd->no_trans_update.stmt lost value inside of SF-exec-stack +# +# Testing asserts: if there is a side effect of modifying non-transactional +# table thd->no_trans_update.stmt must be TRUE; +# the assert is active with debug build +# + +--disable_warnings +drop function if exists bug27417; +drop table if exists t1,t2; +--enable_warnings +# side effect table +CREATE TABLE t1 (a int NOT NULL auto_increment primary key) ENGINE=MyISAM; +# target tables +CREATE TABLE t2 (a int NOT NULL auto_increment, PRIMARY KEY (a)); + +delimiter |; +create function bug27417(n int) +RETURNS int(11) +begin + insert into t1 values (null); + return n; +end| +delimiter ;| + +reset master; + +# execute + +insert into t2 values (bug27417(1)); +insert into t2 select bug27417(2); +reset master; + +--error ER_DUP_ENTRY +insert into t2 values (bug27417(2)); +show master status; /* only (!) with fixes for #23333 will show there is the query */; +select count(*) from t1 /* must be 3 */; + +reset master; +select count(*) from t2; +delete from t2 where a=bug27417(3); +select count(*) from t2 /* nothing got deleted */; +show master status; /* the query must be in regardless of #23333 */; +select count(*) from t1 /* must be 5 */; + +--enable_info +delete t2 from t2 where t2.a=bug27417(100) /* must not affect t2 */; +--disable_info +select count(*) from t1 /* must be 7 */; + +drop function bug27417; +drop table t1,t2; + +--echo end of tests diff --git a/sql/sql_class.cc b/sql/sql_class.cc index b64e74d5d36..b884b21b47c 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -2573,7 +2573,7 @@ extern "C" int thd_slave_thread(const MYSQL_THD thd) extern "C" int thd_non_transactional_update(const MYSQL_THD thd) { - return(thd->no_trans_update.all); + return(thd->transaction.all.modified_non_trans_table); } extern "C" int thd_binlog_format(const MYSQL_THD thd) diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index d77661ad367..6d7e69e9ffc 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -3188,7 +3188,7 @@ void select_insert::abort() { table->file->has_transactions(), FALSE); if (!thd->current_stmt_binlog_row_based && !table->s->tmp_table && !can_rollback_data()) - thd->no_trans_update.all= TRUE; + thd->transaction.all.modified_non_trans_table= TRUE; query_cache_invalidate3(thd, table, 1); } } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index f9b857f56fd..da3a634ffd4 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5176,7 +5176,7 @@ void mysql_reset_thd_for_next_command(THD *thd) if (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) { thd->options&= ~OPTION_KEEP_LOG; - thd->no_trans_update.all= FALSE; + thd->transaction.all.modified_non_trans_table= FALSE; } DBUG_ASSERT(thd->security_ctx== &thd->main_security_ctx); thd->tmp_table_used= 0; From 31e33aba7b48150abfb361d3fe754ba739e7457d Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 31 Jul 2007 18:04:05 +0300 Subject: [PATCH 26/26] Addendum to bug 27417: poor test results fixes. mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result: Addendum to bug 27417: removed tests for another bug mysql-test/suite/binlog/t/binlog_stm_mix_innodb_myisam.test: Addendum to bug 27417: removed tests for another bug mysql-test/suite/rpl/r/rpl_row_create_table.result: Addendum to bug 27417: changes to non-transactional tables should be logged even on rollback. --- .../suite/binlog/r/binlog_stm_mix_innodb_myisam.result | 8 -------- .../suite/binlog/t/binlog_stm_mix_innodb_myisam.test | 6 ++++-- mysql-test/suite/rpl/r/rpl_row_create_table.result | 8 ++++++++ 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result b/mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result index 87641d6fae4..5ef36861c30 100644 --- a/mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result +++ b/mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result @@ -463,10 +463,6 @@ insert into t2 select bug27417(2); reset master; insert into t2 values (bug27417(2)); ERROR 23000: Duplicate entry '2' for key 'PRIMARY' -show master status; -File Position Binlog_Do_DB Binlog_Ignore_DB -master-bin.000001 218 -/* only (!) with fixes for #23333 will show there is the query */; select count(*) from t1 /* must be 3 */; count(*) 3 @@ -478,10 +474,6 @@ delete from t2 where a=bug27417(3); select count(*) from t2 /* nothing got deleted */; count(*) 2 -show master status; -File Position Binlog_Do_DB Binlog_Ignore_DB -master-bin.000001 223 -/* the query must be in regardless of #23333 */; select count(*) from t1 /* must be 5 */; count(*) 5 diff --git a/mysql-test/suite/binlog/t/binlog_stm_mix_innodb_myisam.test b/mysql-test/suite/binlog/t/binlog_stm_mix_innodb_myisam.test index fd2b948a35e..1815f3deb34 100644 --- a/mysql-test/suite/binlog/t/binlog_stm_mix_innodb_myisam.test +++ b/mysql-test/suite/binlog/t/binlog_stm_mix_innodb_myisam.test @@ -123,14 +123,16 @@ reset master; --error ER_DUP_ENTRY insert into t2 values (bug27417(2)); -show master status; /* only (!) with fixes for #23333 will show there is the query */; +#TODO: Andrei: enable this test after 23333 is pushed +#show master status; /* only (!) with fixes for #23333 will show there is the query */; select count(*) from t1 /* must be 3 */; reset master; select count(*) from t2; delete from t2 where a=bug27417(3); select count(*) from t2 /* nothing got deleted */; -show master status; /* the query must be in regardless of #23333 */; +#TODO: Andrei: enable this test after 23333 is pushed +#show master status; /* the query must be in regardless of #23333 */; select count(*) from t1 /* must be 5 */; --enable_info diff --git a/mysql-test/suite/rpl/r/rpl_row_create_table.result b/mysql-test/suite/rpl/r/rpl_row_create_table.result index f22881bd4a9..d6e4845b13f 100644 --- a/mysql-test/suite/rpl/r/rpl_row_create_table.result +++ b/mysql-test/suite/rpl/r/rpl_row_create_table.result @@ -392,12 +392,20 @@ FROM t1 WHERE a MOD 2 = 1; INSERT INTO t2 SELECT a+2 FROM tt2; ROLLBACK; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back SELECT * FROM t2 ORDER BY a; a SHOW BINLOG EVENTS FROM 631; Log_name Pos Event_type Server_id End_log_pos Info # 631 Query # 711 use `test`; TRUNCATE TABLE t2 # 711 Xid # 738 COMMIT /* XID */ +# 738 Query # 806 use `test`; BEGIN +# 806 Table_map # 845 table_id: # (test.t2) +# 845 Write_rows # 889 table_id: # flags: STMT_END_F +# 889 Table_map # 928 table_id: # (test.t2) +# 928 Write_rows # 967 table_id: # flags: STMT_END_F +# 967 Query # 1038 use `test`; ROLLBACK SELECT * FROM t2 ORDER BY a; a DROP TABLE t1,t2;