Skip to content

Commit fbc5050

Browse files
committed
Added ORDER BY to delete operation.
1 parent 678e24c commit fbc5050

File tree

1 file changed

+25
-1
lines changed

1 file changed

+25
-1
lines changed

src/NodeTrait.php

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -627,7 +627,31 @@ protected function deleteDescendants()
627627
? 'forceDelete'
628628
: 'delete';
629629

630-
$this->descendants()->{$method}();
630+
// We must delete the nodes in correct order to avoid failing
631+
// foreign key constraints when we delete an entire subtree.
632+
// For MySQL we must avoid that a parent is deleted before its
633+
// children although the complete subtree will be deleted eventually.
634+
// Hence, deletion must start with the deepest node, i.e. with the
635+
// highest _lft value first.
636+
// Note: `DELETE ... ORDER BY` is non-standard SQL but required by
637+
// MySQL (see https://dev.mysql.com/doc/refman/8.0/en/delete.html),
638+
// because MySQL only supports "row consistency".
639+
// This means the DB must be consistent before and after every single
640+
// operation on a row.
641+
// This is contrasted by statement and transaction consistency which
642+
// means that the DB must be consistent before and after every
643+
// completed statement/transaction.
644+
// (See https://dev.mysql.com/doc/refman/8.0/en/ansi-diff-foreign-keys.html)
645+
// ANSI Standard SQL requires support for statement/transaction
646+
// consistency, but only PostgreSQL supports it.
647+
// (Good PosgreSQL :-) )
648+
// PostgreSQL does not support `DELETE ... ORDER BY` but also has no
649+
// need for it.
650+
// The grammar compiler removes the superfluous "ORDER BY" for
651+
// PostgreSQL.
652+
$this->descendants()
653+
->orderBy($this->getLftName(), 'desc')
654+
->{$method}();
631655

632656
if ($this->hardDeleting()) {
633657
$height = $rgt - $lft + 1;

0 commit comments

Comments
 (0)