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;
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;
......@@ -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;
......@@ -4525,6 +4525,7 @@ mysql_execute_command(THD *thd)
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);
}
......
......@@ -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;
......
......@@ -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 @@ multi_update::initialize_tables(JOIN *join)
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,
......
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