1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00

MDEV-30469 Support ORDER BY and LIMIT for multi-table DELETE, index hints for single-table DELETE

We now allow multitable queries with order by and limit, such as:
  delete t1.*, t2.* from t1, t2 order by t1.id desc limit 3;
To predict what rows will be deleted, run the equivalent select:
  select t1.*, t2.* from t1, t2 order by t1.id desc limit 3;
Additionally, index hints are now supported with single table delete statements:
  delete from t2 use index(xid) order by (id) limit 2;

This approach changes the multi_delete SELECT result interceptor to use a temporary
table to collect row ids pertaining to the rows that will be deleted, rather than
directly deleting rows from the target table(s).  Row ids are collected during
send_data, then read during send_eof to delete target rows.  In the event that the
temporary table created in memory is not big enough for all matching rows, it is
converted to an aria table.

Other changes:
  - Deleting from a sequence now affects zero rows instead of emitting an error

Limitations:
  - The federated connector does not create implicit row ids, so we to use a key
  when conditionally deleting.  See the change in federated_maybe_16324629.test
This commit is contained in:
Dave Gosselin
2024-12-03 09:43:45 -05:00
parent 02dc8615f2
commit 5001300bd4
22 changed files with 915 additions and 192 deletions

View File

@ -7562,16 +7562,17 @@ class SORT_INFO;
class multi_delete :public select_result_interceptor
{
TABLE_LIST *delete_tables, *table_being_deleted;
TMP_TABLE_PARAM *tmp_table_param;
TABLE **tmp_tables, *main_table;
Unique **tempfiles;
ha_rows deleted, found;
uint num_of_tables;
uint table_count;
int error;
bool do_delete;
/* True if at least one table we delete from is transactional */
bool transactional_tables;
/* True if at least one table we delete from is not transactional */
bool normal_tables;
bool delete_while_scanning;
/*
error handling (rollback and binlogging) can happen in send_eof()
so that afterward abort_result_set() needs to find out that.
@ -7580,15 +7581,17 @@ class multi_delete :public select_result_interceptor
public:
// Methods used by ColumnStore
uint get_num_of_tables() const { return num_of_tables; }
uint get_num_of_tables() const { return table_count; }
TABLE_LIST* get_tables() const { return delete_tables; }
public:
multi_delete(THD *thd_arg, TABLE_LIST *dt, uint num_of_tables);
~multi_delete();
int prepare(List<Item> &list, SELECT_LEX_UNIT *u) override;
int prepare2(JOIN *join) override;
int send_data(List<Item> &items) override;
bool initialize_tables (JOIN *join) override;
int do_deletes();
int rowid_table_deletes(TABLE *table, bool ignore);
int do_table_deletes(TABLE *table, SORT_INFO *sort_info, bool ignore);
bool send_eof() override;
inline ha_rows num_deleted() const { return deleted; }