Commit 26ff92f7 authored by Sergei Golubchik's avatar Sergei Golubchik

MDEV-13911 Support ORDER BY and LIMIT in multi-table update

parent b6a5be9e
...@@ -942,3 +942,30 @@ deallocate prepare stmt1; ...@@ -942,3 +942,30 @@ deallocate prepare stmt1;
drop view v3,v2,v1; drop view v3,v2,v1;
drop table t1,t2,t3; drop table t1,t2,t3;
end of 5.5 tests 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;
...@@ -901,3 +901,17 @@ deallocate prepare stmt1; ...@@ -901,3 +901,17 @@ deallocate prepare stmt1;
drop view v3,v2,v1; drop view v3,v2,v1;
drop table t1,t2,t3; drop table t1,t2,t3;
--echo end of 5.5 tests --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;
...@@ -4525,6 +4525,7 @@ mysql_execute_command(THD *thd) ...@@ -4525,6 +4525,7 @@ mysql_execute_command(THD *thd)
else else
res= 0; res= 0;
unit->set_limit(select_lex);
res= mysql_multi_update_prepare(thd); res= mysql_multi_update_prepare(thd);
#ifdef HAVE_REPLICATION #ifdef HAVE_REPLICATION
...@@ -9059,7 +9060,6 @@ Item * all_any_subquery_creator(THD *thd, Item *left_expr, ...@@ -9059,7 +9060,6 @@ Item * all_any_subquery_creator(THD *thd, Item *left_expr,
bool multi_update_precheck(THD *thd, TABLE_LIST *tables) bool multi_update_precheck(THD *thd, TABLE_LIST *tables)
{ {
const char *msg= 0;
TABLE_LIST *table; TABLE_LIST *table;
LEX *lex= thd->lex; LEX *lex= thd->lex;
SELECT_LEX *select_lex= &lex->select_lex; SELECT_LEX *select_lex= &lex->select_lex;
...@@ -9115,15 +9115,6 @@ bool multi_update_precheck(THD *thd, TABLE_LIST *tables) ...@@ -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); DBUG_RETURN(FALSE);
} }
......
...@@ -1988,7 +1988,8 @@ int JOIN::optimize_stage2() ...@@ -1988,7 +1988,8 @@ int JOIN::optimize_stage2()
FORCE INDEX FOR ORDER BY can be used to prevent join buffering when FORCE INDEX FOR ORDER BY can be used to prevent join buffering when
sorting on the first table. 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) if (group_list)
simple_group= 0; simple_group= 0;
......
...@@ -1595,10 +1595,9 @@ bool mysql_multi_update(THD *thd, ...@@ -1595,10 +1595,9 @@ bool mysql_multi_update(THD *thd,
List<Item> total_list; List<Item> total_list;
res= mysql_select(thd, res= mysql_select(thd,
table_list, select_lex->with_wild, table_list, select_lex->with_wild, total_list, conds,
total_list, select_lex->order_list.elements, select_lex->order_list.first,
conds, 0, (ORDER *) NULL, (ORDER *)NULL, (Item *) NULL, (ORDER *)NULL, (Item *) NULL, (ORDER *)NULL,
(ORDER *)NULL,
options | SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK | options | SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK |
OPTION_SETUP_TABLES_DONE, OPTION_SETUP_TABLES_DONE,
*result, unit, select_lex); *result, unit, select_lex);
...@@ -1857,6 +1856,8 @@ static bool safe_update_on_fly(THD *thd, JOIN_TAB *join_tab, ...@@ -1857,6 +1856,8 @@ static bool safe_update_on_fly(THD *thd, JOIN_TAB *join_tab,
TABLE *table= join_tab->table; TABLE *table= join_tab->table;
if (unique_table(thd, table_ref, all_tables, 0)) if (unique_table(thd, table_ref, all_tables, 0))
return 0; return 0;
if (join_tab->join->order) // FIXME this is probably too strong
return 0;
switch (join_tab->type) { switch (join_tab->type) {
case JT_SYSTEM: case JT_SYSTEM:
case JT_CONST: case JT_CONST:
...@@ -1934,6 +1935,7 @@ multi_update::initialize_tables(JOIN *join) ...@@ -1934,6 +1935,7 @@ multi_update::initialize_tables(JOIN *join)
} }
} }
table->prepare_for_position(); table->prepare_for_position();
join->map2table[table->tablenr]->keep_current_rowid= true;
/* /*
enable uncacheable flag if we update a view with check option enable uncacheable flag if we update a view with check option
...@@ -2001,6 +2003,7 @@ multi_update::initialize_tables(JOIN *join) ...@@ -2001,6 +2003,7 @@ multi_update::initialize_tables(JOIN *join)
that we need a position to be read first. that we need a position to be read first.
*/ */
tbl->prepare_for_position(); tbl->prepare_for_position();
join->map2table[tbl->tablenr]->keep_current_rowid= true;
Field_string *field= new Field_string(tbl->file->ref_length, 0, Field_string *field= new Field_string(tbl->file->ref_length, 0,
&field_name, &field_name,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment