MDEV-12302: Execute triggers for foreign key updates/deletes#3496
MDEV-12302: Execute triggers for foreign key updates/deletes#3496Simoffsky wants to merge 6 commits intoMariaDB:mainfrom
Conversation
fd0fe05 to
5ed8787
Compare
954b0e6 to
bfda058
Compare
|
Hello @Simoffsky! As the project is close to its final stage, it's time to reorganize your code, also covering @vuvova's request from #3354. Please move the triggers processing (and other sql-layer "hooks") code to the sql layer. Let's consider two approaches to this. 1. Make two sql-side functions related to hooks: before and afterI will refer to hooks as to ephemere trigger like actions, that are to be done before or after a row change. We can already observe that before hooks differ from after hooks: before hooks also include updating virtual fields, whereas after hooks don't. In the close future, the list will expand (like with row logging, CHEK constraints, etc). So it makes sense for making two functions. This approach would look as placing two functions in This also could make sense to be done in four functions instead of two. Then, in This approach also requires a manual conversion back from sql format (in case if triggers change the data) 2. Call an sql-layer function instead of innodb's
|
|
Please also join all tests in a single file. Test execution time is a problem for us, as every test run has a significant latency. Note that we maintain 80 characters width for the c/c++ sode, with putting an opening |
b700b79 to
33545f7
Compare
f2b8b9f to
1ca8660
Compare
42c3ab6 to
5709403
Compare
5709403 to
e41df1e
Compare
e41df1e to
88beee6
Compare
9c53dcf to
11a22ef
Compare
f1fe0e8 to
79551cf
Compare
FooBarrior
left a comment
There was a problem hiding this comment.
@Simoffsky I'm going to have a time to focus on my leftovers, and this patch is of my high interest.
Let's go through it, perhaps, and see what could we miss?
| row_sel_store_mysql_rec(maria_table->record[1], prebuilt, rec, NULL, | ||
| true, clust_index, offsets); | ||
|
|
||
| //if (node->upd_row == NULL) { |
There was a problem hiding this comment.
do you remember what was the problem with this line? Perhaps, just a comment not removed
storage/innobase/row/row0mysql.cc
Outdated
| thr->prebuilt->m_mysql_table = NULL; | ||
| row_upd_step(thr); | ||
| thr->prebuilt->m_mysql_table = mysql_table; | ||
| //row_upd_step(thr); |
There was a problem hiding this comment.
another quirk. what should we do with it?
b61e283 to
ba4d913
Compare
Bypass the errors from sql layer, through innodb back to sql layer. New handler error: HA_ERR_CASCADE_SQL New innodb error: DB_SQL_ERROR This error is not visible to user and serves only for correct error transport. The real error code is expected to be stored in thd->m_stmt_da, that is, already reported This is a fixup commit. Original author: Simoffsky <maks-kirsanov26@mail.ru>
* Move inc and dec for fk_cascade_depth close to each other, in a symmetrical manner, wrapping the recursive call. * Remove conputation-heavy node traversal with row_ins_cascade_n_ancestors for each cascade call, resulting in O(depth^2) total passes. It should be enough to do that only as an assertion. Historically, there could be more than one thr, joined in chains (but then we'd better pass over a chain of thr). Now a single thr is used for cascade call, so no need in any graph traversal. * Fix max cascade error handling -- now HA_ERR_FK_DEPTH_EXCEEDED is returned, as implied.
que_thr_t is not bypassed in between trigger calls, that is the count starts from 0 each time in the trigger. This means that an effective depth restriction is a multiplication of FK_MAX_CASCADE_DEL and max_sp_recursion_depth. Moving the control to THD changes this to addition. Now the depth limit is: FK_MAX_CASCADE_DEL + max_sp_recursion_depth
The problem is row_update_vers_insert invoked before the cascade update. Cascade update relies on pre-defined node->pcur, and an insert can invalidate the cursor, if b-tree node split happens. One possible solution is to move the versioned insert after cascade update. This patch goes the described way, but also moves versioned insert to the sql layer. We have to re-set row event bits in trg_event_map, because node->is_delete is determined based on those values. TODO is to fix versioning.foreign 'trx_id,unique' result mismatch.
All the technical provisioning was done yet by MDEV-12302 Execute triggers for foreign key updates/deletes As it executes ha_update_row and ha_delete_row directly. All that is left is remove the restriction and add the tests.
ba4d913 to
4d122cd
Compare
Description
In this approach, an sql-layer api is added for calling on the row delete or update. These callbacks are supposed to be expandable for various needs, and ideally should be capable of everything that would happen during usual update/delete row events: check constraints, binlogging, etc, and in particular, trigger invocation, which is implemented in the base commit.
Innodb fills up the sql-format records and invokes the sql-side. It re-uses an equsting update_node, serving for cascade action, and delivers que_thr_t for re-use. As a result, cascade calls are provisioned with the information on call depth and can handle the depth exceeded errors as before.
For correct error handling of whatever could happen on the sql side, a new error code is introduced both for handler api and innodb: HA_ERR_CASCADE_SQL aka DB_SQL_ERROR. This error is distinguished from generic DB_ERROR: the latter is supposed for the unclassifiable cases and shoudn't normally be exposed through the handler api (so it's a backup plan code).
Foreign key depth control is further refectored for better error handling, more efficient and clear code.
Roadmap:
✅ Simple Delete
✅ Simple Update
✅ Fetch data from secondary indexes
✅ Handle changes coming from BEFORE triggers
✅ Virtual fields
✅ Test ON DELETE/UPDATE SET NULL
✅ Bit fields (probably just test it)
✅ Long blobs
Release Notes
Added support for triggers on events from cascade delete/update foreign key actions. The triggers are invoked the same way as for usual delete/update/insert events.
Basing the PR against the correct MariaDB version
mainbranch.PR quality check