|
15 | 15 | use craft\db\Connection; |
16 | 16 | use craft\db\Query; |
17 | 17 | use craft\db\Table; |
| 18 | +use craft\db\TableSchema; |
18 | 19 | use craft\elements\Asset; |
19 | 20 | use craft\elements\Category; |
20 | 21 | use craft\elements\Entry; |
@@ -151,6 +152,7 @@ public function run(bool $force = false): void |
151 | 152 | $this->_deleteOrphanedSearchIndexes(); |
152 | 153 | $this->_deleteOrphanedRelations(); |
153 | 154 | $this->_deleteOrphanedStructureElements(); |
| 155 | + $this->_deleteOrphanedFkRows(); |
154 | 156 |
|
155 | 157 | $this->_hardDeleteStructures(); |
156 | 158 |
|
@@ -525,6 +527,57 @@ private function _deleteOrphanedStructureElements(): void |
525 | 527 | $this->_stdout("done\n", Console::FG_GREEN); |
526 | 528 | } |
527 | 529 |
|
| 530 | + private function _deleteOrphanedFkRows(): void |
| 531 | + { |
| 532 | + $this->_stdout(' > deleting orphaned foreign key rows ... '); |
| 533 | + |
| 534 | + // Disable FK checks |
| 535 | + $qb = $this->db->getSchema()->getQueryBuilder(); |
| 536 | + $this->db->createCommand($qb->checkIntegrity(false))->execute(); |
| 537 | + |
| 538 | + $isMysql = $this->db->getIsMysql(); |
| 539 | + foreach ($this->db->getSchema()->getTableSchemas() as $table) { |
| 540 | + /** @var TableSchema $table */ |
| 541 | + $extendedFkInfo = $table->getExtendedForeignKeys(); |
| 542 | + $counter = 0; |
| 543 | + foreach ($table->foreignKeys as $fk) { |
| 544 | + if ($extendedFkInfo[$counter]['deleteType'] === 'CASCADE') { |
| 545 | + $fk = array_merge($fk); |
| 546 | + $refTable = array_shift($fk); |
| 547 | + |
| 548 | + foreach ($fk as $fkColumn => $pkColumn) { |
| 549 | + if ($isMysql) { |
| 550 | + $sql = <<<SQL |
| 551 | +DELETE t.* FROM $table->name t |
| 552 | +LEFT JOIN $refTable t2 ON t2.$pkColumn = t.$fkColumn |
| 553 | +WHERE t.$fkColumn IS NOT NULL |
| 554 | +AND t2.$pkColumn IS NULL |
| 555 | +SQL; |
| 556 | + } else { |
| 557 | + $sql = <<<SQL |
| 558 | +DELETE FROM $table->name t |
| 559 | +WHERE t2.$pkColumn IS NULL |
| 560 | +AND NOT EXISTS ( |
| 561 | + SELECT * FROM $refTable |
| 562 | + WHERE "$pkColumn" = t."$fkColumn" |
| 563 | +) |
| 564 | +SQL; |
| 565 | + } |
| 566 | + |
| 567 | + $this->db->createCommand($sql)->execute(); |
| 568 | + } |
| 569 | + } |
| 570 | + |
| 571 | + $counter++; |
| 572 | + } |
| 573 | + } |
| 574 | + |
| 575 | + // Re-enable FK checks |
| 576 | + $this->db->createCommand($qb->checkIntegrity())->execute(); |
| 577 | + |
| 578 | + $this->_stdout("done\n", Console::FG_GREEN); |
| 579 | + } |
| 580 | + |
528 | 581 | /** |
529 | 582 | * Deletes field layouts that are no longer used. |
530 | 583 | * |
|
0 commit comments