Is there an existing issue for the same bug?
Branch Name
main
Commit ID
ad143902644719e65fa703df6397a011dc7d7dfa (PR #27996 head reviewed on 2026-09-02)
Other Environment Information
- Local embedded single-CN / single-TN / single-Log test cluster
- Parent table with an integer primary key and a referencing child foreign key using
ON UPDATE CASCADE
Actual Behavior
A branch-side primary-key change is emitted as an independent delete of the old key plus an insert of the new key. DATA BRANCH MERGE and DATA BRANCH PICK replay that as DELETE/INSERT, so the parent-row delete fails with the foreign-key constraint error. An ordinary UPDATE on the same parent key succeeds and cascades to the child.
Expected Behavior
When a source update changes a referenced primary key, Data Branch apply should preserve it as one native destination UPDATE, allowing declared ON UPDATE CASCADE actions to run.
Steps to Reproduce
create database branch_pk_cascade;
use branch_pk_cascade;
create table parent_t (id int primary key, payload varchar(32));
create table child_t (id int primary key, parent_id int,
constraint fk_child_parent foreign key (parent_id) references parent_t(id) on update cascade);
insert into parent_t values (2, 'two');
insert into child_t values (1, 2);
data branch create table merge_src from parent_t;
update merge_src set id = 3 where id = 2;
data branch merge merge_src into parent_t when conflict accept;
-- Control: update parent_t set id = 3 where id = 2; cascades child_t.parent_id.
The equivalent PICK setup (source and destination branches, keys(2)) fails for the same reason.
Root Cause and Scope
multi_update deletes the old row while writing the replacement without a durable operation identity. databranchutils.CollectChanges therefore exposes the old row ID/key as a tombstone and the replacement row ID/key as data. buildHashmapForTable and findDeleteAndUpdateBat correlate the two only by primary-key value; once the key changes, there is no safe association.
Matching rows by commit timestamp or iteration order would conflate independent delete/insert operations with updates and could trigger unintended cascades, so it is not a safe fix. This needs an explicit old-to-new update provenance link through the change stream, followed by native UPDATE apply and MERGE/PICK regressions for cascade, non-cascade rejection, and atomicity.
Related
Is there an existing issue for the same bug?
ON UPDATEactions.Branch Name
main
Commit ID
ad143902644719e65fa703df6397a011dc7d7dfa(PR #27996 head reviewed on 2026-09-02)Other Environment Information
ON UPDATE CASCADEActual Behavior
A branch-side primary-key change is emitted as an independent delete of the old key plus an insert of the new key.
DATA BRANCH MERGEandDATA BRANCH PICKreplay that as DELETE/INSERT, so the parent-row delete fails with the foreign-key constraint error. An ordinaryUPDATEon the same parent key succeeds and cascades to the child.Expected Behavior
When a source update changes a referenced primary key, Data Branch apply should preserve it as one native destination
UPDATE, allowing declaredON UPDATE CASCADEactions to run.Steps to Reproduce
The equivalent PICK setup (source and destination branches,
keys(2)) fails for the same reason.Root Cause and Scope
multi_updatedeletes the old row while writing the replacement without a durable operation identity.databranchutils.CollectChangestherefore exposes the old row ID/key as a tombstone and the replacement row ID/key as data.buildHashmapForTableandfindDeleteAndUpdateBatcorrelate the two only by primary-key value; once the key changes, there is no safe association.Matching rows by commit timestamp or iteration order would conflate independent delete/insert operations with updates and could trigger unintended cascades, so it is not a safe fix. This needs an explicit old-to-new update provenance link through the change stream, followed by native UPDATE apply and MERGE/PICK regressions for cascade, non-cascade rejection, and atomicity.
Related