Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
982 changes: 982 additions & 0 deletions mysql-test/main/cte_update_delete.result

Large diffs are not rendered by default.

402 changes: 402 additions & 0 deletions mysql-test/main/cte_update_delete.test

Large diffs are not rendered by default.

12 changes: 12 additions & 0 deletions sql/sql_cte.cc
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,18 @@ bool LEX::resolve_references_to_cte(TABLE_LIST *tables,
{
With_element *with_elem= 0;

/*
Add back the tables collected during definition of the CTEs, but cleared
during mysql_init_delete
*/
if (save_list.elements)
{
for (TABLE_LIST *saved= save_list.first; saved; saved= saved->next_global)
add_to_query_tables(saved);
save_list.empty();
last_table()->next_global= nullptr;
}

for (TABLE_LIST *tbl= tables; tbl != *tables_last; tbl= tbl->next_global)
{
if (tbl->derived)
Expand Down
8 changes: 7 additions & 1 deletion sql/sql_lex.h
Original file line number Diff line number Diff line change
Expand Up @@ -3348,7 +3348,13 @@ struct LEX: public Query_tables_list
uint select_stack_outer_barrier;

SQL_I_List<ORDER> proc_list;
SQL_I_List<TABLE_LIST> auxiliary_table_list, save_list;
SQL_I_List<TABLE_LIST> auxiliary_table_list;
/*
save_list is used by
- Parsing CREATE TABLE t0 (...) UNION = (t1, t2, t3)
- CTEs for DELETE, see mysql_init_delete().
*/
SQL_I_List<TABLE_LIST> save_list;
Column_definition *last_field;
Table_function_json_table *json_table;
Item_sum *in_sum_func;
Expand Down
7 changes: 7 additions & 0 deletions sql/sql_parse.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6070,6 +6070,7 @@ mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt)
thd->variables.default_master_connection.str)
thd->lex->mi.connection_name= null_clex_str;

lex->save_list.empty();
if (lex->sql_command != SQLCOM_SET_OPTION)
DEBUG_SYNC(thd, "end_of_statement");
DBUG_RETURN(res || thd->is_error());
Expand Down Expand Up @@ -7619,6 +7620,12 @@ void create_select_for_variable(THD *thd, LEX_CSTRING *var_name)

void mysql_init_delete(LEX *lex)
{
if (lex->with_cte_resolution)
{
// Save and clear lex->query_tables.
lex->save_list.insert(lex->query_tables, &lex->query_tables);
lex->query_tables_last= &lex->query_tables;
}
lex->init_select();
lex->first_select_lex()->limit_params.clear();
lex->unit.lim.clear();
Expand Down
3 changes: 2 additions & 1 deletion sql/sql_select.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23812,7 +23812,8 @@ free_tmp_table(THD *thd, TABLE *entry)

if (entry->pos_in_table_list && entry->pos_in_table_list->table)
{
DBUG_ASSERT(entry->pos_in_table_list->table == entry);
DBUG_ASSERT(entry->pos_in_table_list->table == entry ||
entry->pos_in_table_list->merged_for_insert);
entry->pos_in_table_list->table= NULL;
}

Expand Down
11 changes: 6 additions & 5 deletions sql/sql_update.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1886,7 +1886,7 @@ int multi_update::prepare(List<Item> &not_used_values,
{
TABLE_LIST *table_ref;
SQL_I_List<TABLE_LIST> update_list;
Item_field *item;
Item *item;
List_iterator_fast<Item> field_it(*fields);
List_iterator_fast<Item> value_it(*values);
uint i, max_fields;
Expand Down Expand Up @@ -1975,15 +1975,16 @@ int multi_update::prepare(List<Item> &not_used_values,

/* Split fields into fields_for_table[] and values_by_table[] */

while ((item= (Item_field *) field_it++))
while ((item= field_it++))
{
Item_field *item_field= (Item_field *)item->real_item();
Item *value= value_it++;
uint offset= item->field->table->pos_in_table_list->shared;
uint offset= item_field->field->table->pos_in_table_list->shared;

if (value->associate_with_target_field(thd, item))
if (value->associate_with_target_field(thd, item_field))
DBUG_RETURN(1);

fields_for_table[offset]->push_back(item, thd->mem_root);
fields_for_table[offset]->push_back(item_field, thd->mem_root);
values_for_table[offset]->push_back(value, thd->mem_root);
}
if (unlikely(thd->is_fatal_error))
Expand Down
25 changes: 19 additions & 6 deletions sql/sql_yacc.yy
Original file line number Diff line number Diff line change
Expand Up @@ -1974,7 +1974,7 @@ rule:
'-' '+' '*' '/' '%' '(' ')'
',' '!' '{' '}' '&' '|'

%type <with_clause> with_clause
%type <with_clause> with_clause opt_with_clause

%type <with_element_head> with_element_head

Expand Down Expand Up @@ -14092,15 +14092,19 @@ update_table_list:
/* Update rows in a table */

update:
opt_with_clause
UPDATE_SYM opt_optimizer_hint
{
LEX *lex= Lex;
if (Lex->main_select_push())
MYSQL_YYABORT;
lex->init_select();
Lex->first_select_lex()->set_optimizer_hints($2);
Lex->first_select_lex()->set_optimizer_hints($3);
lex->sql_command= SQLCOM_UPDATE;
lex->duplicates= DUP_ERROR;
Lex->first_select_lex()->master_unit()->set_with_clause($1);
if ($1)
$1->attach_to(Lex->first_select_lex());
}
opt_low_priority opt_ignore update_table_list
SET update_list
Expand Down Expand Up @@ -14128,12 +14132,12 @@ update:
be too pessimistic. We will decrease lock level if possible
later while processing the statement.
*/
slex->set_lock_for_tables($4, slex->table_list.elements == 1, false);
slex->set_lock_for_tables($5, slex->table_list.elements == 1, false);
}
opt_where_clause opt_order_clause delete_limit_clause
{
if ($11)
Select->order_list= *($11);
if ($12)
Select->order_list= *($12);
} stmt_end {}
;

Expand Down Expand Up @@ -14181,6 +14185,7 @@ opt_low_priority:
/* Delete rows from a table */

delete:
opt_with_clause
DELETE_SYM opt_optimizer_hint
{
LEX *lex= Lex;
Expand All @@ -14191,7 +14196,10 @@ delete:
mysql_init_delete(lex);
lex->ignore= 0;
lex->first_select_lex()->order_list.empty();
lex->first_select_lex()->set_optimizer_hints($2);
lex->first_select_lex()->set_optimizer_hints($3);
lex->first_select_lex()->master_unit()->set_with_clause($1);
if ($1)
$1->attach_to(lex->first_select_lex());
}
delete_part2
{
Expand Down Expand Up @@ -15895,6 +15903,11 @@ temporal_literal:
}
;

opt_with_clause:
/* empty */ { $$= NULL; }
| with_clause { $$= $1; }
;

with_clause:
WITH opt_recursive
{
Expand Down
3 changes: 2 additions & 1 deletion sql/table.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6190,7 +6190,8 @@ bool TABLE_LIST::create_field_translation(THD *thd)
It's needed because some items in the select list, like IN subselects,
might be substituted for optimized ones.
*/
if (is_view() && get_unit()->prepared && !field_translation_updated)
if (is_merged_derived() &&
get_unit()->prepared && !field_translation_updated)
{
field_translation_updated= TRUE;
if (static_cast<uint>(field_translation_end - field_translation) <
Expand Down
Loading