From 36937565309c54237b81732cbcb7151772eac052 Mon Sep 17 00:00:00 2001 From: Matthias Schmidt Date: Sun, 6 Dec 2020 14:09:21 +0100 Subject: [PATCH] Fix column logs if renaming database column that was added later --- .../DatabaseTableChangeProcessor.class.php | 66 +++++++++++++++++-- 1 file changed, 59 insertions(+), 7 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 329cc79eec..54436c8eca 100644 --- a/wcfsetup/install/files/lib/system/database/table/DatabaseTableChangeProcessor.class.php +++ b/wcfsetup/install/files/lib/system/database/table/DatabaseTableChangeProcessor.class.php @@ -249,6 +249,14 @@ class DatabaseTableChangeProcessor { $this->prepareColumnLog($tableName, $column); } + $renamedColumnsWithLog = []; + foreach ($columnsToAlter as $column) { + if ($column->getNewName() && $this->getColumnLog($tableName, $column) !== null) { + $this->prepareColumnLog($tableName, $column, true); + $renamedColumnsWithLog[] = $column; + } + } + $this->applyColumnChanges( $tableName, $columnsToAdd, @@ -260,6 +268,11 @@ class DatabaseTableChangeProcessor { $this->finalizeColumnLog($tableName, $column); } + foreach ($renamedColumnsWithLog as $column) { + $this->finalizeColumnLog($tableName, $column, true); + $this->deleteColumnLog($tableName, $column); + } + foreach ($columnsToDrop as $column) { $this->deleteColumnLog($tableName, $column); } @@ -324,7 +337,7 @@ class DatabaseTableChangeProcessor { $columnData = []; foreach ($droppedColumns as $droppedColumn) { $columnData[$droppedColumn->getName()] = [ - 'action' => 'drop' + 'action' => 'drop', ]; foreach ($this->getExistingTable($tableName)->getForeignKeys() as $foreignKey) { @@ -336,14 +349,14 @@ class DatabaseTableChangeProcessor { foreach ($addedColumns as $addedColumn) { $columnData[$addedColumn->getName()] = [ 'action' => 'add', - 'data' => $addedColumn->getData() + 'data' => $addedColumn->getData(), ]; } foreach ($alteredColumns as $alteredColumn) { $columnData[$alteredColumn->getName()] = [ 'action' => 'alter', 'data' => $alteredColumn->getData(), - 'newColumnName' => $alteredColumn->getNewName() ?? $alteredColumn->getName() + 'newColumnName' => $alteredColumn->getNewName() ?? $alteredColumn->getName(), ]; } @@ -816,9 +829,13 @@ class DatabaseTableChangeProcessor { * * @param string $tableName * @param IDatabaseTableColumn $column + * @param bool $useNewName */ - protected function finalizeColumnLog($tableName, IDatabaseTableColumn $column) { - $this->finalizeLog(['sqlTable' => $tableName, 'sqlColumn' => $column->getName()]); + protected function finalizeColumnLog($tableName, IDatabaseTableColumn $column, bool $useNewName = false) { + $this->finalizeLog([ + 'sqlTable' => $tableName, + 'sqlColumn' => $useNewName ? $column->getNewName() : $column->getName(), + ]); } /** @@ -873,6 +890,37 @@ class DatabaseTableChangeProcessor { $this->finalizeLog(['sqlTable' => $table->getName()]); } + /** + * Returns the log entry for the given column or `null` if there is no explicit entry for + * this column. + * + * @param string $tableName + * @param IDatabaseTableColumn $column + * @return array|null + * @since 5.4 + */ + protected function getColumnLog(string $tableName, IDatabaseTableColumn $column): ?array { + $sql = "SELECT * + FROM wcf" . WCF_N . "_package_installation_sql_log + WHERE packageID = ? + AND sqlTable = ? + AND sqlColumn = ?"; + $statement = WCF::getDB()->prepareStatement($sql); + + $statement->execute([ + $this->package->packageID, + $tableName, + $column->getName(), + ]); + + $row = $statement->fetchSingleRow(); + if ($row === false) { + return null; + } + + return $row; + } + /** * Returns the id of the package to with the given column belongs to. If there is no specific * log entry for the given column, the table log is checked and the relevant package id of @@ -952,9 +1000,13 @@ class DatabaseTableChangeProcessor { * * @param string $tableName * @param IDatabaseTableColumn $column + * @param bool $useNewName */ - protected function prepareColumnLog($tableName, IDatabaseTableColumn $column) { - $this->prepareLog(['sqlTable' => $tableName, 'sqlColumn' => $column->getName()]); + protected function prepareColumnLog($tableName, IDatabaseTableColumn $column, bool $useNewName = false) { + $this->prepareLog([ + 'sqlTable' => $tableName, + 'sqlColumn' => $useNewName ? $column->getNewName() : $column->getName(), + ]); } /** -- 2.20.1