Skip to content

MDEV-39226: Push whole multi-table update/delete down into engines - #5529

Open
bsrikanth-mariadb wants to merge 1 commit into
mainfrom
13.2-MDEV-39226-direct-multi_table-update-delete
Open

MDEV-39226: Push whole multi-table update/delete down into engines#5529
bsrikanth-mariadb wants to merge 1 commit into
mainfrom
13.2-MDEV-39226-direct-multi_table-update-delete

Conversation

@bsrikanth-mariadb

@bsrikanth-mariadb bsrikanth-mariadb commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Give storage engines a way to take over an entire multi-table
UPDATE/DELETE, the way they can already take over a SELECT. Without it the
join, the row matching and every modification run in the SQL layer even
when an engine could do the whole statement itself in one step; a
single-table UPDATE/DELETE already avoids this via
direct_update_rows()/direct_delete_rows(), but a multi-table statement has
no primary handler object to drive that path.

This adds a generic, engine-agnostic pushdown interface: the SQL layer
offers the statement to the engine, and if the engine accepts it, it
performs the whole thing and reports only the row counts.

  • Split select_handler into a pushdown_handler base with select_handler
    (result set) and a new multi_upddel_handler (runs a whole UPDATE/DELETE,
    reports row counts, reported as PUSHED UPDATE/PUSHED DELETE); add
    handlerton::create_multi_upddel, looked up in Sql_cmd_dml::execute_inner().
  • multi_update/multi_delete gain direct_update_delete_done(), which records
    the engine's counts so send_eof() binlogs and replies without the
    SQL-layer loop; it forces statement-format binlogging so the change still
    replicates under binlog_format=ROW, and errors out instead of silently
    dropping counts for an unsupported result object.
  • FederatedX implements the interface as the reference engine used to test
    correctness: it prints the statement back and runs it remotely, passes
    the engine's error code/SQLSTATE through, reads the matched count from the
    remote info string, executes IGNORE locally, and only pushes down when all
    tables share one remote server (same as SELECT/derived/unit pushdown).

Test: federated.federatedx_pushdown_upd_del.

@bsrikanth-mariadb
bsrikanth-mariadb marked this pull request as draft August 11, 2026 10:54
@bsrikanth-mariadb
bsrikanth-mariadb force-pushed the 13.2-MDEV-39226-direct-multi_table-update-delete branch 5 times, most recently from f2ce815 to 44765e4 Compare August 14, 2026 08:16
Comment thread sql/sql_explain.cc Outdated
const char *pushed_select_text= "PUSHED SELECT";
const char *pushed_update_text= "PUSHED DOWN UPDATE";
const char *pushed_delete_text= "PUSHED DOWN DELETE";

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please follow the pattern: if we use PUSHED SELECT, let's add PUSHED UPDATE , not PUSHED DOWN UPDATE.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, true. But, felt "PUSHED DOWN XXXX" was sounding better.

Anyways, will keep them consistent.

@bsrikanth-mariadb
bsrikanth-mariadb force-pushed the 13.2-MDEV-39226-direct-multi_table-update-delete branch 3 times, most recently from b931524 to eb052c3 Compare August 18, 2026 07:04
@bsrikanth-mariadb bsrikanth-mariadb changed the title MDEV-39226: Add multi-table update, delete feature MDEV-39226: Push whole multi-table update/delete down into engines Aug 18, 2026
@bsrikanth-mariadb
bsrikanth-mariadb force-pushed the 13.2-MDEV-39226-direct-multi_table-update-delete branch 4 times, most recently from 7f1147b to 168a3b1 Compare August 19, 2026 02:19
Give storage engines a way to take over an entire multi-table
UPDATE/DELETE, the way they can already take over a SELECT. Without it the
join, the row matching and every modification run in the SQL layer even
when an engine could do the whole statement itself in one step; a
single-table UPDATE/DELETE already avoids this via
direct_update_rows()/direct_delete_rows(), but a multi-table statement has
no primary handler object to drive that path.

This adds a generic, engine-agnostic pushdown interface: the SQL layer
offers the statement to the engine, and if the engine accepts it, it
performs the whole thing and reports only the row counts.

- Split select_handler into a pushdown_handler base with select_handler
  (result set) and a new multi_upddel_handler (runs a whole UPDATE/DELETE,
  reports row counts, reported as PUSHED UPDATE/PUSHED DELETE); add
  handlerton::create_multi_upddel, looked up in Sql_cmd_dml::execute_inner().
- multi_update/multi_delete gain direct_update_delete_done(), which records
  the engine's counts so send_eof() binlogs and replies without the
  SQL-layer loop; it forces statement-format binlogging so the change still
  replicates under binlog_format=ROW, and errors out instead of silently
  dropping counts for an unsupported result object.
- FederatedX implements the interface as the reference engine used to test
  correctness: it prints the statement back and runs it remotely, passes
  the engine's error code/SQLSTATE through, reads the matched count from the
  remote info string, executes IGNORE locally, and only pushes down when all
  tables share one remote server (same as SELECT/derived/unit pushdown).

Test: federated.federatedx_pushdown_upd_del.
@bsrikanth-mariadb
bsrikanth-mariadb force-pushed the 13.2-MDEV-39226-direct-multi_table-update-delete branch from 168a3b1 to f59b0bd Compare August 20, 2026 05:22
@bsrikanth-mariadb
bsrikanth-mariadb marked this pull request as ready for review August 20, 2026 05:41
static multi_upddel_handler *
create_federatedx_multi_upddel_handler(THD *thd, SELECT_LEX *sel_lex)
{
if (!use_pushdown || !is_supported_update_delete(thd->lex->sql_command))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this for? Do we get into this function for non-UPDATE/DELETE ?
I have added

DBUG_ASSERT(is_supported_update_delete(thd->lex->sql_command));

and it survived the tests.

@spetrunia

Copy link
Copy Markdown
Member

Please apply this patch: cleanups.patch

str_eq(a->hostname, b->hostname) &&
str_eq(a->socket, b->socket) &&
str_eq(a->username, b->username) &&
str_eq(a->password, b->password);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even password?
I'm not sure if it's possible to see different data depending on the user... Is password necessary?


ha_federatedx_multi_upddel_handler::~ha_federatedx_multi_upddel_handler()
= default;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this needed?

The range of the error codes of the client library, CR_MIN_ERROR and
CR_MAX_ERROR of errmsg.h. That header cannot be included here because it
defines ER, which the server defines differently.
*/

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If ER is the only problem, can one use

#undef ER
#include ...

?

@spetrunia spetrunia left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above input.

Also, should create_multi_upddel accept SELECT_LEX argument, or LEX would be more meaningful?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

2 participants