From: He Zhenxing Date: July 11 2010 1:30pm Subject: bzr commit into mysql-5.1-bugteam branch (zhenxing.he:3418) Bug#42415 List-Archive: http://lists.mysql.com/commits/113297 X-Bug: 42415 Message-Id: <201007111330.o6BDUxbU024594@hezx-dev.localdomain> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============0181206957387340075==" --===============0181206957387340075== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline #At file:///media/sdb2/hezx/work/mysql/bzr/b42415/5.1-bugteam/ based on revid:ramil@stripped 3418 He Zhenxing 2010-07-11 Bug #42415 UPDATE/DELETE with LIMIT clause unsafe for SBL even with ORDER BY PK clause Before the patch, when using STATEMENT mode, unsafe warnings were issued for all DML statements (INSERT...SELECT, UPDATE, DELETE) with LIMIT clause due to the possobility of non-deterministic result order, even when they also had a ORDER BY primary_key clause. In which case the order would be deterministic. This patch fixed the problem by checking the ORDER BY clause of the statement, and do not issue the warning if the result is ordered by the primary key (thus deterministic). modified: mysql-test/suite/binlog/r/binlog_unsafe.result mysql-test/suite/binlog/t/binlog_unsafe.test sql/sql_delete.cc sql/sql_insert.cc sql/sql_select.cc sql/sql_select.h sql/sql_update.cc === modified file 'mysql-test/suite/binlog/r/binlog_unsafe.result' --- a/mysql-test/suite/binlog/r/binlog_unsafe.result 2010-01-13 09:00:03 +0000 +++ b/mysql-test/suite/binlog/r/binlog_unsafe.result 2010-07-11 13:30:46 +0000 @@ -412,4 +412,53 @@ a 13:46:40 1970-01-12 13:46:40 DROP TABLE t1; +DROP TABLE IF EXISTS t1,t2,t3,t4; +Warnings: +Note 1051 Unknown table 't1' +Note 1051 Unknown table 't2' +Note 1051 Unknown table 't3' +Note 1051 Unknown table 't4' +CREATE TABLE t1 (a INT PRIMARY KEY); +CREATE TABLE t2 (a INT); +CREATE TABLE t3 (a INT); +CREATE TABLE t4 (a INT); +INSERT INTO t1 VALUES (1),(2),(3); +INSERT INTO t2 VALUES (1),(2),(3); +# +# Unsafe statements +# +UPDATE t1 SET a = a+10 LIMIT 1; +Warnings: +Note 1592 Statement may not be safe to log in statement format. +UPDATE t2 SET a = a+10 ORDER BY a LIMIT 1; +Warnings: +Note 1592 Statement may not be safe to log in statement format. +INSERT INTO t3 SELECT * FROM t1 LIMIT 1; +Warnings: +Note 1592 Statement may not be safe to log in statement format. +INSERT INTO t4 SELECT * FROM t2 ORDER BY a LIMIT 1; +Warnings: +Note 1592 Statement may not be safe to log in statement format. +INSERT INTO t4 SELECT t1.a FROM t2,t1 ORDER BY t1.a LIMIT 1; +Warnings: +Note 1592 Statement may not be safe to log in statement format. +INSERT INTO t4 SELECT t2.a FROM t1,t2 ORDER BY t2.a LIMIT 1; +Warnings: +Note 1592 Statement may not be safe to log in statement format. +DELETE FROM t1 LIMIT 1; +Warnings: +Note 1592 Statement may not be safe to log in statement format. +DELETE FROM t2 ORDER BY a LIMIT 1; +Warnings: +Note 1592 Statement may not be safe to log in statement format. +# +# Safe statements +# +UPDATE t1 SET a = a+10 ORDER BY a LIMIT 1; +INSERT INTO t3 SELECT * FROM t1 ORDER BY a LIMIT 1; +DELETE FROM t1 ORDER BY a LIMIT 1; +UPDATE t2 SET a = a+10 LIMIT 0; +INSERT INTO t4 SELECT * FROM t2 LIMIT 0; +DELETE FROM t2 LIMIT 0; +DROP TABLE t1, t2, t3, t4; "End of tests" === modified file 'mysql-test/suite/binlog/t/binlog_unsafe.test' --- a/mysql-test/suite/binlog/t/binlog_unsafe.test 2010-01-13 09:00:03 +0000 +++ b/mysql-test/suite/binlog/t/binlog_unsafe.test 2010-07-11 13:30:46 +0000 @@ -49,6 +49,7 @@ # BUG#42640: mysqld crashes when unsafe statements are executed (STRICT_TRANS_TABLES mode) # BUG#47995: Mark user functions as unsafe # BUG#49222: Mare RAND() unsafe +# BUG#42415: UPDATE/DELETE with LIMIT clause unsafe for SBL even with ORDER BY PK clause # # ==== Related test cases ==== # @@ -444,4 +445,41 @@ SELECT * FROM t1; DROP TABLE t1; +# +# Test case for BUG#42415 +# UPDATE/DELETE with LIMIT clause unsafe for SBL even with ORDER BY PK clause +# +DROP TABLE IF EXISTS t1,t2,t3,t4; +CREATE TABLE t1 (a INT PRIMARY KEY); +CREATE TABLE t2 (a INT); +CREATE TABLE t3 (a INT); +CREATE TABLE t4 (a INT); + +INSERT INTO t1 VALUES (1),(2),(3); +INSERT INTO t2 VALUES (1),(2),(3); + +-- echo # +-- echo # Unsafe statements +-- echo # +UPDATE t1 SET a = a+10 LIMIT 1; +UPDATE t2 SET a = a+10 ORDER BY a LIMIT 1; +INSERT INTO t3 SELECT * FROM t1 LIMIT 1; +INSERT INTO t4 SELECT * FROM t2 ORDER BY a LIMIT 1; +INSERT INTO t4 SELECT t1.a FROM t2,t1 ORDER BY t1.a LIMIT 1; +INSERT INTO t4 SELECT t2.a FROM t1,t2 ORDER BY t2.a LIMIT 1; +DELETE FROM t1 LIMIT 1; +DELETE FROM t2 ORDER BY a LIMIT 1; + +-- echo # +-- echo # Safe statements +-- echo # +UPDATE t1 SET a = a+10 ORDER BY a LIMIT 1; +INSERT INTO t3 SELECT * FROM t1 ORDER BY a LIMIT 1; +DELETE FROM t1 ORDER BY a LIMIT 1; +UPDATE t2 SET a = a+10 LIMIT 0; +INSERT INTO t4 SELECT * FROM t2 LIMIT 0; +DELETE FROM t2 LIMIT 0; + +DROP TABLE t1, t2, t3, t4; + --echo "End of tests" === modified file 'sql/sql_delete.cc' --- a/sql/sql_delete.cc 2010-05-14 11:36:27 +0000 +++ b/sql/sql_delete.cc 2010-07-11 13:30:46 +0000 @@ -92,6 +92,19 @@ bool mysql_delete(THD *thd, TABLE_LIST * } } + /* + Statement-based replication of DELETE ... LIMIT is not safe as + order of rows is not defined unless ORDER BY primary_key, so in + mixed mode we go to row-based. + */ + if (thd->lex->current_select->select_limit && + select_lex->select_limit->val_int() && + !is_order_deterministic(table_list->table, (ORDER*)order->first)) + { + thd->lex->set_stmt_unsafe(); + thd->set_current_stmt_binlog_row_based_if_mixed(); + } + const_cond= (!conds || conds->const_item()); safe_update=test(thd->options & OPTION_SAFE_UPDATES); if (safe_update && const_cond) @@ -475,19 +488,6 @@ int mysql_prepare_delete(THD *thd, TABLE DBUG_ENTER("mysql_prepare_delete"); List all_fields; - /* - Statement-based replication of DELETE ... LIMIT is not safe as order of - rows is not defined, so in mixed mode we go to row-based. - - Note that we may consider a statement as safe if ORDER BY primary_key - is present. However it may confuse users to see very similiar statements - replicated differently. - */ - if (thd->lex->current_select->select_limit) - { - thd->lex->set_stmt_unsafe(); - thd->set_current_stmt_binlog_row_based_if_mixed(); - } thd->lex->allow_sum_func= 0; if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context, &thd->lex->select_lex.top_join_list, === modified file 'sql/sql_insert.cc' --- a/sql/sql_insert.cc 2010-03-29 02:32:30 +0000 +++ b/sql/sql_insert.cc 2010-07-11 13:30:46 +0000 @@ -2881,19 +2881,6 @@ bool mysql_insert_select_prepare(THD *th DBUG_ENTER("mysql_insert_select_prepare"); /* - Statement-based replication of INSERT ... SELECT ... LIMIT is not safe - as order of rows is not defined, so in mixed mode we go to row-based. - - Note that we may consider a statement as safe if ORDER BY primary_key - is present or we SELECT a constant. However it may confuse users to - see very similiar statements replicated differently. - */ - if (lex->current_select->select_limit) - { - lex->set_stmt_unsafe(); - thd->set_current_stmt_binlog_row_based_if_mixed(); - } - /* SELECT_LEX do not belong to INSERT statement, so we can't add WHERE clause if table is VIEW */ === modified file 'sql/sql_select.cc' --- a/sql/sql_select.cc 2010-05-27 15:13:53 +0000 +++ b/sql/sql_select.cc 2010-07-11 13:30:46 +0000 @@ -2492,6 +2492,30 @@ mysql_select(THD *thd, Item ***rref_poin } } + if (thd->lex->sql_command == SQLCOM_INSERT_SELECT || + thd->lex->sql_command == SQLCOM_REPLACE_SELECT) + { + /* + Statement-based replication of INSERT ... SELECT ... LIMIT is + not safe as order of rows is not defined unless ORDER BY + primary_key, so in mixed mode we go to row-based. + + NOTE: When more than one tables are joined in the SELECT part, + it will very hard to figure out whether the result order will be + deterministic or not, so they are always considered unsafe to + simplify the logic. + */ + if (!thd->lex->is_stmt_unsafe() && select_lex->select_limit && + select_lex->select_limit->val_int() && + (((TABLE_LIST*)select_lex->table_list.first)->next_local || + !is_order_deterministic(((TABLE_LIST *)select_lex->table_list.first)->table, + (ORDER *)(select_lex->order_list.first)))) + { + thd->lex->set_stmt_unsafe(); + thd->set_current_stmt_binlog_row_based_if_mixed(); + } + } + if ((err= join->optimize())) { goto err; // 1 === modified file 'sql/sql_select.h' --- a/sql/sql_select.h 2010-02-26 13:16:46 +0000 +++ b/sql/sql_select.h 2010-07-11 13:30:46 +0000 @@ -794,3 +794,4 @@ inline bool optimizer_flag(THD *thd, uin return (thd->variables.optimizer_switch & flag); } +bool is_order_deterministic(TABLE *table, ORDER *order); === modified file 'sql/sql_update.cc' --- a/sql/sql_update.cc 2010-05-27 20:07:40 +0000 +++ b/sql/sql_update.cc 2010-07-11 13:30:46 +0000 @@ -850,6 +850,35 @@ err: } /* + Test if the result order is deterministic. + + @retval FALSE not deterministic + @retval TRUE deterministic + */ +bool is_order_deterministic(TABLE *table, ORDER *order) +{ + MY_BITMAP order_set; + MY_BITMAP key_set; + uint key= table->s->primary_key; + + if (order == NULL) + return FALSE; + if (key == MAX_KEY) + return FALSE; + + bitmap_init(&order_set, NULL, table->s->fields, FALSE); + for (; order; order=order->next) + { + Field *field=((Item_field*) (*order->item)->real_item())->field; + bitmap_set_bit(&order_set, field->field_index); + } + + bitmap_init(&key_set, NULL, table->s->fields, FALSE); + table->mark_columns_used_by_index_no_reset(key, &key_set); + return bitmap_is_subset(&key_set, &order_set); +} + +/* Prepare items in UPDATE statement SYNOPSIS @@ -875,19 +904,6 @@ bool mysql_prepare_update(THD *thd, TABL SELECT_LEX *select_lex= &thd->lex->select_lex; DBUG_ENTER("mysql_prepare_update"); - /* - Statement-based replication of UPDATE ... LIMIT is not safe as order of - rows is not defined, so in mixed mode we go to row-based. - - Note that we may consider a statement as safe if ORDER BY primary_key - is present. However it may confuse users to see very similiar statements - replicated differently. - */ - if (thd->lex->current_select->select_limit) - { - thd->lex->set_stmt_unsafe(); - thd->set_current_stmt_binlog_row_based_if_mixed(); - } #ifndef NO_EMBEDDED_ACCESS_CHECKS table_list->grant.want_privilege= table->grant.want_privilege= (SELECT_ACL & ~table->grant.privilege); @@ -908,6 +924,19 @@ bool mysql_prepare_update(THD *thd, TABL setup_ftfuncs(select_lex)) DBUG_RETURN(TRUE); + /* + Statement-based replication of UPDATE ... LIMIT is not safe as + order of rows is not defined unless ORDER BY primary_key, so in + mixed mode we go to row-based. + */ + if (thd->lex->current_select->select_limit && + select_lex->select_limit->val_int() && + !is_order_deterministic(table_list->table, order)) + { + thd->lex->set_stmt_unsafe(); + thd->set_current_stmt_binlog_row_based_if_mixed(); + } + /* Check that we are not using table that we are updating in a sub select */ { TABLE_LIST *duplicate; --===============0181206957387340075== MIME-Version: 1.0 Content-Type: text/bzr-bundle; charset="us-ascii"; name="bzr/zhenxing.he@stripped" Content-Transfer-Encoding: 7bit Content-Disposition: inline # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: zhenxing.he@stripped # target_branch: file:///media/sdb2/hezx/work/mysql/bzr/b42415/5.1-\ # bugteam/ # testament_sha1: 4ee36e4c15317ccbbc42190f0fa2df630287bdd0 # timestamp: 2010-07-11 21:30:58 +0800 # base_revision_id: ramil@stripped # # Begin bundle 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 --===============0181206957387340075==--