Skip to content

UPDATE OR REPLACE does not fire FK CASCADE on implicitly-deleted row #5537

@LeMikaelF

Description

@LeMikaelF

Description

When UPDATE OR REPLACE causes an existing row to be implicitly deleted (because the update would violate a UNIQUE constraint), Turso does not fire FK CASCADE actions on the deleted row's children. This leaves orphaned child rows with dangling foreign key references.

Reproducer

PRAGMA foreign_keys = ON;

CREATE TABLE parent(id INTEGER PRIMARY KEY, name TEXT UNIQUE);
CREATE TABLE child(id INTEGER PRIMARY KEY, parent_id INT REFERENCES parent(id) ON DELETE CASCADE);

INSERT INTO parent VALUES (10, 'x'), (20, 'y');
INSERT INTO child VALUES (10, 10), (20, 20);

-- REPLACE deletes parent(20) first, then updates parent(10)
UPDATE OR REPLACE parent SET name = 'y' WHERE id = 10;

SELECT * FROM child ORDER BY id;
-- Turso:  10|10 and 20|20  (child 20 survives with dangling FK)
-- SQLite: 10|10             (child 20 correctly cascade-deleted)

Per SQLite documentation: "An ON DELETE CASCADE action means that each row in the child table that was associated with the deleted parent row is also deleted."

The UPDATE OR REPLACE code path handles the REPLACE by deleting the conflicting row directly but does not invoke the FK cascade machinery for that implicit deletion.


This issue brought to you by Mikaël and Claude Code.

Metadata

Metadata

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions