Skip to content

[Compatibility]: ON DELETE referential actions inflate affected-row counts #28308

Description

@Ariznawlll

Is there an existing issue for the same bug?

  • I have checked the existing issues.

Branch Name

main

Commit ID

bcd5ed8

Other Environment Information

- MatrixOne was built from the commit above and started locally with etc/launch/launch.toml.
- MySQL comparison version: 8.0.45 (InnoDB).
- The client OK-packet affected-row value and SELECT ROW_COUNT() return the same value on each server.

Actual Behavior

MatrixOne includes child rows changed implicitly by ON DELETE CASCADE and
ON DELETE SET NULL in the affected-row count of the parent DELETE.
MySQL counts only the parent rows directly matched by the DELETE statement.

For one matched parent with two child rows:

Referential action MatrixOne MySQL 8.0.45
ON DELETE CASCADE 3 1
ON DELETE SET NULL 3 1

The difference scales with the implicit child work:

Shape MatrixOne MySQL 8.0.45
two parents and three children, CASCADE 5 2
two parents and three children, SET NULL 5 2
one parent, one child, one grandchild 3 1
prepared parent delete with two children 3 1

The stored data is correct in both systems: CASCADE removes the related
children and SET NULL clears their foreign keys. A parent row with no related
children reports 1 on both systems. ON UPDATE CASCADE and ON UPDATE SET NULL
also report 1 on both systems for the equivalent one-parent/two-child setup.

This difference is visible both to connectors through the OK packet and to SQL
through ROW_COUNT(), so applications that use affected rows for auditing,
optimistic workflows, or batch progress receive a larger count from MatrixOne.

Expected Behavior

For MySQL compatibility, a parent DELETE should report the number of parent
rows directly affected by that statement. Rows changed only by a foreign-key
referential action should not increase the OK-packet affected-row value or
ROW_COUNT().

Steps to Reproduce

CREATE DATABASE fk_delete_affected_rows;
USE fk_delete_affected_rows;

CREATE TABLE p_cascade(id INT PRIMARY KEY);
CREATE TABLE c_cascade(
  id INT PRIMARY KEY,
  pid INT,
  FOREIGN KEY(pid) REFERENCES p_cascade(id) ON DELETE CASCADE
);
INSERT INTO p_cascade VALUES (1),(2);
INSERT INTO c_cascade VALUES (10,1),(11,1),(20,2);

DELETE FROM p_cascade WHERE id=1;
SELECT ROW_COUNT();
-- MatrixOne: 3
-- MySQL 8.0.45: 1

CREATE TABLE p_null(id INT PRIMARY KEY);
CREATE TABLE c_null(
  id INT PRIMARY KEY,
  pid INT,
  FOREIGN KEY(pid) REFERENCES p_null(id) ON DELETE SET NULL
);
INSERT INTO p_null VALUES (1),(2);
INSERT INTO c_null VALUES (10,1),(11,1),(20,2);

DELETE FROM p_null WHERE id=1;
SELECT ROW_COUNT();
-- MatrixOne: 3
-- MySQL 8.0.45: 1

SELECT * FROM c_cascade ORDER BY id;
SELECT * FROM c_null ORDER BY id;

The same count is returned when the parent delete is executed through a
prepared statement and when it is one target of a multi-table DELETE.

Additional information

MySQL documents ROW_COUNT() as the affected-row value returned by the client
API and describes CASCADE/SET NULL as automatic child-table actions:

The MatrixOne result is not a generic index-maintenance count: ordinary primary,
unique, secondary, and FULLTEXT index deletes report the same count as MySQL.
The difference is isolated to child changes caused by parent-side ON DELETE
referential actions.

Activity

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

Metadata

Metadata

Assignees

Labels

kind/bugSomething isn't workingneeds-triageNeeds evaluation before prioritization. Not yet decided whether to proceed

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions