From dc4b5734056ea938b79ef3a6d396749a04f2484e Mon Sep 17 00:00:00 2001 From: Matthias Schmidt Date: Tue, 13 Apr 2021 16:21:54 +0200 Subject: [PATCH] Properly handle foreign keys referencing tables created later on If a foreign key of the first table references a table to be created later on, this foreign key can only be created once the referenced table was created. --- .../DatabaseTableChangeProcessor.class.php | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/wcfsetup/install/files/lib/system/database/table/DatabaseTableChangeProcessor.class.php b/wcfsetup/install/files/lib/system/database/table/DatabaseTableChangeProcessor.class.php index 202065ff00..318d517c89 100644 --- a/wcfsetup/install/files/lib/system/database/table/DatabaseTableChangeProcessor.class.php +++ b/wcfsetup/install/files/lib/system/database/table/DatabaseTableChangeProcessor.class.php @@ -448,6 +448,12 @@ class DatabaseTableChangeProcessor { } } else if ($matchingExistingForeignKey === null) { + // If the referenced database table does not already exists, delay the + // foreign key creation until after the referenced table has been created. + if (!in_array($foreignKey->getReferencedTable(), $this->existingTableNames)) { + continue; + } + if (!isset($this->foreignKeysToAdd[$tableName])) { $this->foreignKeysToAdd[$tableName] = []; } @@ -648,10 +654,18 @@ class DatabaseTableChangeProcessor { $this->dbEditor->createTable($table->getName(), $columnData, $indexData); foreach ($table->getForeignKeys() as $foreignKey) { - $this->dbEditor->addForeignKey($table->getName(), $foreignKey->getName(), $foreignKey->getData()); - - // foreign keys need to be explicitly logged for proper uninstallation - $this->createForeignKeyLog($table->getName(), $foreignKey); + // Only try to create the foreign key if the referenced database table already exists. + // If it will be created later on, delay the foreign key creation until after the + // referenced table has been created. + if ( + in_array($foreignKey->getReferencedTable(), $this->existingTableNames) + || $foreignKey->getReferencedTable() === $table->getName() + ) { + $this->dbEditor->addForeignKey($table->getName(), $foreignKey->getName(), $foreignKey->getData()); + + // foreign keys need to be explicitly logged for proper uninstallation + $this->createForeignKeyLog($table->getName(), $foreignKey); + } } } -- 2.20.1