summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergei Golubchik <serg@mariadb.org>2017-09-26 10:28:00 +0200
committerSergei Golubchik <serg@mariadb.org>2017-10-03 20:23:33 +0200
commit26ff92f7ac2dc373769b8053e936e4593a2ee302 (patch)
treed64ef7d8b9f9de77795a89609d30dd0e9217fc0e
parentb6a5be9eaa715c190d05d370998f6ef4f72acaab (diff)
downloadmariadb-git-26ff92f7ac2dc373769b8053e936e4593a2ee302.tar.gz
MDEV-13911 Support ORDER BY and LIMIT in multi-table update
-rw-r--r--mysql-test/r/multi_update.result27
-rw-r--r--mysql-test/t/multi_update.test14
-rw-r--r--sql/sql_parse.cc11
-rw-r--r--sql/sql_select.cc3
-rw-r--r--sql/sql_update.cc11
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,