diff options
author | Sergei Golubchik <serg@mariadb.org> | 2017-09-26 10:28:00 +0200 |
---|---|---|
committer | Sergei Golubchik <serg@mariadb.org> | 2017-10-03 20:23:33 +0200 |
commit | 26ff92f7ac2dc373769b8053e936e4593a2ee302 (patch) | |
tree | d64ef7d8b9f9de77795a89609d30dd0e9217fc0e | |
parent | b6a5be9eaa715c190d05d370998f6ef4f72acaab (diff) | |
download | mariadb-git-26ff92f7ac2dc373769b8053e936e4593a2ee302.tar.gz |
MDEV-13911 Support ORDER BY and LIMIT in multi-table update
-rw-r--r-- | mysql-test/r/multi_update.result | 27 | ||||
-rw-r--r-- | mysql-test/t/multi_update.test | 14 | ||||
-rw-r--r-- | sql/sql_parse.cc | 11 | ||||
-rw-r--r-- | sql/sql_select.cc | 3 | ||||
-rw-r--r-- | sql/sql_update.cc | 11 |
5 files changed, 51 insertions, 15 deletions
diff --git a/mysql-test/r/multi_update.result b/mysql-test/r/multi_update.result index 2a0a6677c6f..339dc35e9c4 100644 --- a/mysql-test/r/multi_update.result +++ b/mysql-test/r/multi_update.result @@ -942,3 +942,30 @@ deallocate prepare stmt1; drop view v3,v2,v1; drop table t1,t2,t3; end of 5.5 tests +create table t1 (c1 int, c3 int); +insert t1(c3) values (1), (2), (3), (4), (5), (6), (7), (8); +create table t2 select * from t1; +update t1, t2 set t1.c1=t2.c3 where t1.c3=t2.c3 order by t1.c3 limit 3; +select * from t1; +c1 c3 +1 1 +2 2 +3 3 +NULL 4 +NULL 5 +NULL 6 +NULL 7 +NULL 8 +update t1 set c1=NULL; +update t1, t2 set t1.c1=t2.c3 where t1.c3=t2.c3 order by t1.c3 desc limit 2; +select * from t1; +c1 c3 +NULL 1 +NULL 2 +NULL 3 +NULL 4 +NULL 5 +NULL 6 +7 7 +8 8 +drop table t1, t2; diff --git a/mysql-test/t/multi_update.test b/mysql-test/t/multi_update.test index 0a7e6b221eb..bd5d7a9768c 100644 --- a/mysql-test/t/multi_update.test +++ b/mysql-test/t/multi_update.test @@ -901,3 +901,17 @@ deallocate prepare stmt1; drop view v3,v2,v1; drop table t1,t2,t3; --echo end of 5.5 tests + +# +# MDEV-13911 Support ORDER BY and LIMIT in multi-table update +# + +create table t1 (c1 int, c3 int); +insert t1(c3) values (1), (2), (3), (4), (5), (6), (7), (8); +create table t2 select * from t1; +update t1, t2 set t1.c1=t2.c3 where t1.c3=t2.c3 order by t1.c3 limit 3; +select * from t1; +update t1 set c1=NULL; +update t1, t2 set t1.c1=t2.c3 where t1.c3=t2.c3 order by t1.c3 desc limit 2; +select * from t1; +drop table t1, t2; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 145a12afb52..5a153414adb 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -4525,6 +4525,7 @@ end_with_restore_list: else res= 0; + unit->set_limit(select_lex); res= mysql_multi_update_prepare(thd); #ifdef HAVE_REPLICATION @@ -9059,7 +9060,6 @@ Item * all_any_subquery_creator(THD *thd, Item *left_expr, bool multi_update_precheck(THD *thd, TABLE_LIST *tables) { - const char *msg= 0; TABLE_LIST *table; LEX *lex= thd->lex; SELECT_LEX *select_lex= &lex->select_lex; @@ -9115,15 +9115,6 @@ bool multi_update_precheck(THD *thd, TABLE_LIST *tables) } } - if (select_lex->order_list.elements) - msg= "ORDER BY"; - else if (select_lex->select_limit) - msg= "LIMIT"; - if (msg) - { - my_error(ER_WRONG_USAGE, MYF(0), "UPDATE", msg); - DBUG_RETURN(TRUE); - } DBUG_RETURN(FALSE); } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index a4caa4077fa..e4ab9c0b405 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1988,7 +1988,8 @@ int JOIN::optimize_stage2() FORCE INDEX FOR ORDER BY can be used to prevent join buffering when sorting on the first table. */ - if (!stable || !stable->force_index_order) + if (!stable || (!stable->force_index_order && + !map2table[stable->tablenr]->keep_current_rowid)) { if (group_list) simple_group= 0; diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 25fc1993536..a0c1f3598b5 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -1595,10 +1595,9 @@ bool mysql_multi_update(THD *thd, List<Item> total_list; res= mysql_select(thd, - table_list, select_lex->with_wild, - total_list, - conds, 0, (ORDER *) NULL, (ORDER *)NULL, (Item *) NULL, - (ORDER *)NULL, + table_list, select_lex->with_wild, total_list, conds, + select_lex->order_list.elements, select_lex->order_list.first, + (ORDER *)NULL, (Item *) NULL, (ORDER *)NULL, options | SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK | OPTION_SETUP_TABLES_DONE, *result, unit, select_lex); @@ -1857,6 +1856,8 @@ static bool safe_update_on_fly(THD *thd, JOIN_TAB *join_tab, TABLE *table= join_tab->table; if (unique_table(thd, table_ref, all_tables, 0)) return 0; + if (join_tab->join->order) // FIXME this is probably too strong + return 0; switch (join_tab->type) { case JT_SYSTEM: case JT_CONST: @@ -1934,6 +1935,7 @@ multi_update::initialize_tables(JOIN *join) } } table->prepare_for_position(); + join->map2table[table->tablenr]->keep_current_rowid= true; /* enable uncacheable flag if we update a view with check option @@ -2001,6 +2003,7 @@ loop_end: that we need a position to be read first. */ tbl->prepare_for_position(); + join->map2table[tbl->tablenr]->keep_current_rowid= true; Field_string *field= new Field_string(tbl->file->ref_length, 0, &field_name, |