mirror of https://github.com/MariaDB/server
Browse Source
(Variant 2) Multi-table UPDATE ... ORDER BY ... LIMIT could update the wrong rows when ORDER BY was resolved by Using temporary + Using filesort. == Background: ref_pointer_array == join->order[->next*]->item point into join->ref_pointer_array, which has pointers to the used Item objects. This indirection is employed so that we can switch the ORDER BY expressions from using the original Items to using the values of their "image" fields in the temporary table. The variant of ref_pointer_array that has pointers to temp table fields is created when JOIN::make_aggr_tables_info() calls change_refs_to_tmp_fields(). == The problem == The created array didn't match element-by-element the original ref_pointer_array. When arrays were switched, ORDER BY elements started to point to the wrong temp.table fields, causing the wrong sorting. == The cause == The cause is JOIN::add_fields_for_current_rowid(). This function is called for UPDATE statements to make the rowids of rows in the original tables to be saved in the temporary tables. It adds extra columns to the select list in table_fields argument. However, select lists are organized in a way that extra elements must be added *to the front* of the list, and then change_refs_to_tmp_fields() will add extra fields *to the end* of ref_pointer_array. So, add_fields_for_current_rowid() adds new fields to the back of table_fields list. This caused change_refs_to_tmp_fields() to produce ref_pointer_array slice with extra elements in the front, causing any references through ref_pointer_array to come to the wrong values. == The fix == Make JOIN::add_fields_for_current_rowid() add fields to the front of the select list.bb-11.8-mdev-30469
committed by
Dave Gosselin
3 changed files with 125 additions and 1 deletions
Loading…
Reference in new issue