| Bug #41477 | InnoDB foreign keys: wrong result if ON DELETE CASCADE, and correlated subquery | ||
|---|---|---|---|
| Submitted: | 15 Dec 2008 15:33 | Modified: | 15 Dec 2008 17:11 |
| Reporter: | Konstantin Osipov (OCA) | Email Updates: | |
| Status: | Verified | Impact on me: | |
| Category: | MySQL Server: DML | Severity: | S3 (Non-critical) |
| Version: | 4.1, 5.0, 5,1, 6.0 bzr | OS: | Any |
| Assigned to: | CPU Architecture: | Any | |
[15 Dec 2008 17:11]
Sveta Smirnova
Thank you for the report. Verified as described.
[13 Feb 2012 8:30]
Fayaz Yusuf Khan
I think my issue is also related to this. mysql> create table A (id int primary key, parent_id int, constraint foreign key (parent_id) references A (id) on delete cascade) engine=InnoDB; Query OK, 0 rows affected (0.16 sec) mysql> insert into A(id, parent_id) values (1,1),(2,1); Query OK, 2 rows affected (0.04 sec) Records: 2 Duplicates: 0 Warnings: 0 mysql> select count(*) from A; +----------+ | count(*) | +----------+ | 2 | +----------+ 1 row in set (0.03 sec) mysql> delete from A; Query OK, 1 row affected (0.05 sec) <-- Says only one row affected. mysql> select count(*) from A; +----------+ | count(*) | +----------+ | 0 | +----------+ 1 row in set (0.00 sec)

Description: If you delete records from the child table through a CASCADE, deletions happen row-by-row and a correlated subquery starts returning wrong results. The set of rows to change, according to the standard, must be evaluated before the change, not during the change.mysql> drop table if exists child, parent; Query OK, 0 rows affected (0.05 sec) mysql> set @@storage_engine=innodb; Query OK, 0 rows affected (0.00 sec) mysql> -- disable the effect of the optimizer mysql> set @@optimizer_switch='no_materialization,no_semijoin'; Query OK, 0 rows affected (0.00 sec) mysql> create table parent (pk int primary key, b int); Query OK, 0 rows affected (0.00 sec) mysql> create table child (fk int, -> foreign key (fk) references parent (pk) -> on delete cascade, b int); Query OK, 0 rows affected (0.01 sec) mysql> insert into parent values (1,2),(2,2); Query OK, 2 rows affected (0.00 sec) Records: 2 Duplicates: 0 Warnings: 0 mysql> insert into child values (1,2),(2,2); Query OK, 2 rows affected (0.00 sec) Records: 2 Duplicates: 0 Warnings: 0 mysql> -- should delete 2 rows, deletes only 1 row mysql> delete from parent where -> (select count(*) from child where b = parent.b) > 1; Query OK, 1 row affected (0.00 sec) mysql> select * from parent; +----+------+ | pk | b | +----+------+ | 2 | 2 | +----+------+ 1 row in set (0.01 sec) How to repeat: drop table if exists child, parent; set @@storage_engine=innodb; -- disable the effect of the optimizer set @@optimizer_switch='no_materialization,no_semijoin'; create table parent (pk int primary key, b int); create table child (fk int, foreign key (fk) references parent (pk) on delete cascade, b int); insert into parent values (1,2),(2,2); insert into child values (1,2),(2,2); -- should delete 2 rows, deletes only 1 row delete from parent where (select count(*) from child where b = parent.b) > 1; select * from parent; Suggested fix: WL#148