mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
MDEV-14551 Can't find record in table on multi-table update with ORDER BY
preserve positions if the multi-update join is using tmp table: * store positions in the tmp table if needed JOIN::add_fields_for_current_rowid() * take positions from the tmp table, not from file->position(): multi_update::prepare2()
This commit is contained in:
@ -2198,10 +2198,66 @@ loop_end:
|
||||
DBUG_RETURN(1);
|
||||
tmp_tables[cnt]->file->extra(HA_EXTRA_WRITE_CACHE);
|
||||
}
|
||||
join->tmp_table_keep_current_rowid= TRUE;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
static TABLE *item_rowid_table(Item *item)
|
||||
{
|
||||
if (item->type() != Item::FUNC_ITEM)
|
||||
return NULL;
|
||||
Item_func *func= (Item_func *)item;
|
||||
if (func->functype() != Item_func::TEMPTABLE_ROWID)
|
||||
return NULL;
|
||||
Item_temptable_rowid *itr= (Item_temptable_rowid *)func;
|
||||
return itr->table;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
multi_update stores a rowid and new field values for every updated row in a
|
||||
temporary table (one temporary table per updated table). These rowids are
|
||||
obtained via Item_temptable_rowid's by calling handler::position(). But if
|
||||
the join is resolved via a temp table, rowids cannot be obtained from
|
||||
handler::position() in the multi_update::send_data(). So, they're stored in
|
||||
the join's temp table (JOIN::add_fields_for_current_rowid()) and here we
|
||||
replace Item_temptable_rowid's (that would've done handler::position()) with
|
||||
Item_field's (that will simply take the corresponding field value from the
|
||||
temp table).
|
||||
*/
|
||||
int multi_update::prepare2(JOIN *join)
|
||||
{
|
||||
if (!join->need_tmp || !join->tmp_table_keep_current_rowid)
|
||||
return 0;
|
||||
|
||||
// there cannot be many tmp tables in multi-update
|
||||
JOIN_TAB *tmptab= join->join_tab + join->exec_join_tab_cnt();
|
||||
|
||||
for (Item **it= tmptab->tmp_table_param->items_to_copy; *it ; it++)
|
||||
{
|
||||
TABLE *tbl= item_rowid_table(*it);
|
||||
if (!tbl)
|
||||
continue;
|
||||
for (uint i= 0; i < table_count; i++)
|
||||
{
|
||||
for (Item **it2= tmp_table_param[i].items_to_copy; *it2; it2++)
|
||||
{
|
||||
if (item_rowid_table(*it2) != tbl)
|
||||
continue;
|
||||
Item *fld= new (thd->mem_root)
|
||||
Item_field(thd, (*it)->get_tmp_table_field());
|
||||
if (!fld)
|
||||
return 1;
|
||||
fld->set_result_field((*it2)->get_tmp_table_field());
|
||||
*it2= fld;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
multi_update::~multi_update()
|
||||
{
|
||||
TABLE_LIST *table;
|
||||
|
Reference in New Issue
Block a user