From: He Zhenxing Date: July 11 2010 8:14am Subject: bzr commit into mysql-5.1-bugteam branch (zhenxing.he:3418) Bug#42415 List-Archive: http://lists.mysql.com/commits/113293 X-Bug: 42415 Message-Id: <201007110814.o6B8EDQD023618@hezx-dev.localdomain> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============1090337504913554123==" --===============1090337504913554123== 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 08:14:00 +0000 @@ -412,4 +412,50 @@ 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; +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 08:14:00 +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,38 @@ 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; + +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 08:14:00 +0000 @@ -92,6 +92,18 @@ 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 && + !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 +487,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 08:14:00 +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 08:14:00 +0000 @@ -2492,6 +2492,29 @@ 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 && + (((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 08:14:00 +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 08:14:00 +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,18 @@ 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 && + !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; --===============1090337504913554123== 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: fc003373b24c5772ceea231f19e129dc03ea08f4 # timestamp: 2010-07-11 16:14:13 +0800 # base_revision_id: ramil@stripped # # Begin bundle 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 --===============1090337504913554123==--