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:
None 
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 15:33] Konstantin Osipov
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
[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)

Portions of this website are copyright © 2001, 2002 The PHP Group

Page generated in 0.053 sec. using MySQL 8.4.7-u6-cloud

Timestamp references displayed by the system are UTC.
Content reproduced on this site is the property of the respective copyright holders.
It is not reviewed in advance by Oracle and does not necessarily represent the opinion of Oracle or any other party.