From b6ae7d04959c1b92034b282cc514d1de2c91c256 Mon Sep 17 00:00:00 2001 From: Marcel Werk Date: Tue, 19 Jul 2011 20:49:29 +0200 Subject: [PATCH] Fixed multiple package installation issues --- .../database/editor/DatabaseEditor.class.php | 8 +++++++ .../editor/MySQLDatabaseEditor.class.php | 9 ++++++++ .../editor/PostgreSQLDatabaseEditor.class.php | 7 ++++++ .../system/database/util/SQLParser.class.php | 21 ++++++++++++++--- .../PackageInstallationDispatcher.class.php | 23 +++++-------------- ...PackageUninstallationNodeBuilder.class.php | 10 +------- .../SQLPackageInstallationPlugin.class.php | 16 +++++++++---- 7 files changed, 60 insertions(+), 34 deletions(-) diff --git a/wcfsetup/install/files/lib/system/database/editor/DatabaseEditor.class.php b/wcfsetup/install/files/lib/system/database/editor/DatabaseEditor.class.php index df739ffc2f..7cd88bc5a0 100644 --- a/wcfsetup/install/files/lib/system/database/editor/DatabaseEditor.class.php +++ b/wcfsetup/install/files/lib/system/database/editor/DatabaseEditor.class.php @@ -120,4 +120,12 @@ abstract class DatabaseEditor { * @param string $indexName */ public abstract function dropIndex($tableName, $indexName); + + /** + * Drops an existing foreign key. + * + * @param string $tableName + * @param string $indexName + */ + public abstract function dropForeignKey($tableName, $indexName); } diff --git a/wcfsetup/install/files/lib/system/database/editor/MySQLDatabaseEditor.class.php b/wcfsetup/install/files/lib/system/database/editor/MySQLDatabaseEditor.class.php index 70f6b659ab..a70f50fd3a 100644 --- a/wcfsetup/install/files/lib/system/database/editor/MySQLDatabaseEditor.class.php +++ b/wcfsetup/install/files/lib/system/database/editor/MySQLDatabaseEditor.class.php @@ -165,6 +165,15 @@ class MySQLDatabaseEditor extends DatabaseEditor { $statement->execute(); } + /** + * @see DatabaseEditor::dropForeignKey() + */ + public function dropForeignKey($tableName, $indexName) { + $sql = "ALTER TABLE ".$tableName." DROP FOREIGN KEY ".$indexName; + $statement = $this->dbObj->prepareStatement($sql); + $statement->execute(); + } + /** * Builds a column definition for execution in a create table or alter table statement. * diff --git a/wcfsetup/install/files/lib/system/database/editor/PostgreSQLDatabaseEditor.class.php b/wcfsetup/install/files/lib/system/database/editor/PostgreSQLDatabaseEditor.class.php index 7b1faf44d3..c511c96b99 100644 --- a/wcfsetup/install/files/lib/system/database/editor/PostgreSQLDatabaseEditor.class.php +++ b/wcfsetup/install/files/lib/system/database/editor/PostgreSQLDatabaseEditor.class.php @@ -274,6 +274,13 @@ class PostgreSQLDatabaseEditor extends DatabaseEditor { $statement->execute(); } + /** + * @see DatabaseEditor::dropForeignKey() + */ + public function dropForeignKey($tableName, $indexName) { + // TODO: implement this function + } + /** * Builds a column definition for execution in a create table or alter table statement. * diff --git a/wcfsetup/install/files/lib/system/database/util/SQLParser.class.php b/wcfsetup/install/files/lib/system/database/util/SQLParser.class.php index 853c07500a..45ba7b2fa8 100644 --- a/wcfsetup/install/files/lib/system/database/util/SQLParser.class.php +++ b/wcfsetup/install/files/lib/system/database/util/SQLParser.class.php @@ -119,11 +119,11 @@ class SQLParser { case 'ALTER TABLE': // add index if (preg_match('~^ALTER\s+TABLE\s+(\w+)\s+ADD\s+(?:(UNIQUE|FULLTEXT)\s+)?(?:INDEX|KEY)\s+(?:(\w+)\s*)?\((\s*\w+\s*(?:,\s*\w+\s*)*)\)~is', $query, $match)) { - $this->executeAddIndexStatement($match[1], $match[3], array('type' => strtoupper($match[2]), 'columns' => $match[4])); + $this->executeAddIndexStatement($match[1], ($match[3] ? $match[3] : self::getGenericIndexName($match[1], $match[4])), array('type' => strtoupper($match[2]), 'columns' => $match[4])); } // add foreign key else if (preg_match('~^ALTER\s+TABLE\s+(\w+)\s+ADD\s+FOREIGN KEY\s+(?:(\w+)\s*)?\((\s*\w+\s*(?:,\s*\w+\s*)*)\)\s+REFERENCES\s+(\w+)\s+\((\s*\w+\s*(?:,\s*\w+\s*)*)\)(?:\s+ON\s+(UPDATE|DELETE)\s+(CASCADE|SET NULL|NO ACTION))?~is', $query, $match)) { - $this->executeAddForeignKeyStatement($match[1], $match[2], array('columns' => $match[3], 'referencedTable' => $match[4], 'referencedColumns' => $match[5], 'operation' => $match[6], 'action' => $match[7])); + $this->executeAddForeignKeyStatement($match[1], ($match[2] ? $match[2] : self::getGenericIndexName($match[1], $match[3], 'fk')), array('columns' => $match[3], 'referencedTable' => $match[4], 'referencedColumns' => $match[5], 'operation' => $match[6], 'action' => $match[7])); } // add/change column else if (preg_match("~^ALTER\s+TABLE\s+(\w+)\s+(?:(ADD)\s+(?:COLUMN\s+)?|(CHANGE)\s+(?:COLUMN\s+)?(\w+)\s+)(\w+)\s+(\w+)(?:\s*\((\s*(?:\d+(?:\s*,\s*\d+)?|'[^']*'(?:\s*,\s*'[^']*')*))\))?(?:\s+UNSIGNED)?(?:\s+(NOT NULL|NULL))?(?:\s+DEFAULT\s+(\d+.\d+|\d+|NULL|'[^'\\\\]*(?:\\\\.[^'\\\\]*)*'))?(?:\s+(AUTO_INCREMENT))?(?:\s+(UNIQUE|PRIMARY)(?: KEY)?)?~is", $query, $match)) { @@ -170,7 +170,7 @@ class SQLParser { case 'CREATE INDEX': if (preg_match('~^CREATE\s+(?:(UNIQUE|FULLTEXT)\s+)?INDEX\s+(\w+)\s+ON\s+(\w+)\s+\((\s*\w+\s*(?:,\s*\w+\s*)*)\)~is', $query, $match)) { - $this->executeAddIndexStatement($match[3], $match[2], array('type' => strtoupper($match[1]), 'columns' => $match[4])); + $this->executeAddIndexStatement($match[3], ($match[2] ? $match[2] : self::getGenericIndexName($match[3], $match[4])), array('type' => strtoupper($match[1]), 'columns' => $match[4])); } else { throw new SystemException("Unsupported SQL statement '".$query."'"); @@ -298,4 +298,19 @@ class SQLParser { $statement = WCF::getDB()->prepareStatement($query); $statement->execute(); } + + /** + * Creates a generic index name. + * + * @param string $tableName + * @param string $columns + * @param string $suffix + * @return string index name + */ + protected static function getGenericIndexName($tableName, $columns, $suffix = '') { + // get first column + $columns = ArrayUtil::trim(explode(',', $columns)); + + return $tableName . '_' . reset($columns) . ($suffix ? '_' . $suffix : ''); + } } diff --git a/wcfsetup/install/files/lib/system/package/PackageInstallationDispatcher.class.php b/wcfsetup/install/files/lib/system/package/PackageInstallationDispatcher.class.php index e7c66fa6ea..3bb8054852 100644 --- a/wcfsetup/install/files/lib/system/package/PackageInstallationDispatcher.class.php +++ b/wcfsetup/install/files/lib/system/package/PackageInstallationDispatcher.class.php @@ -294,29 +294,18 @@ class PackageInstallationDispatcher { // fetch all pips associated with current PACKAGE_ID and include pips // previously installed by current installation queue - $sql = "SELECT pip.className, package.packageDir - FROM wcf".WCF_N."_package_installation_plugin pip - LEFT JOIN wcf".WCF_N."_package_dependency package_dependency - ON (package_dependency.packageID = pip.packageID) - LEFT JOIN wcf".WCF_N."_package package - ON (package.packageID = pip.packageID) - WHERE pip.pluginName = ? - AND ( - package_dependency.dependency = ? - OR pip.packageID = ? - OR pip.packageID IS NULL - )"; + $sql = "SELECT className + FROM wcf".WCF_N."_package_installation_plugin + WHERE pluginName = ?"; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute(array( - $nodeData['pip'], - PACKAGE_ID, - $this->queue->packageID + $nodeData['pip'] )); $row = $statement->fetchArray(); - // PIP is unknown, ignore + // PIP is unknown if (!$row) { - return $installationStep; + throw new SystemException("unable to find package installation plugin '".$nodeData['pip']."'"); } // valdidate class definition diff --git a/wcfsetup/install/files/lib/system/package/PackageUninstallationNodeBuilder.class.php b/wcfsetup/install/files/lib/system/package/PackageUninstallationNodeBuilder.class.php index db32b57928..cf1a571fa1 100644 --- a/wcfsetup/install/files/lib/system/package/PackageUninstallationNodeBuilder.class.php +++ b/wcfsetup/install/files/lib/system/package/PackageUninstallationNodeBuilder.class.php @@ -38,15 +38,7 @@ class PackageUninstallationNodeBuilder extends PackageInstallationNodeBuilder { $sql = "SELECT pluginName, className, CASE pluginName WHEN 'packageinstallationplugins' THEN 1 WHEN 'files' THEN 2 ELSE 0 END 'pluginOrder' FROM wcf".WCF_N."_package_installation_plugin - WHERE packageID IN ( - 1 /* TESTING ONLY */ - /* - SELECT dependency - FROM wcf".WCF_N."_package_dependency - WHERE packageID = ".$this->installation->queue->packageID." - */ - ) - ORDER BY pluginOrder ASC, priority DESC"; + ORDER BY pluginOrder, priority"; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute(); while ($row = $statement->fetchArray()) { diff --git a/wcfsetup/install/files/lib/system/package/plugin/SQLPackageInstallationPlugin.class.php b/wcfsetup/install/files/lib/system/package/plugin/SQLPackageInstallationPlugin.class.php index 9d29b86826..a7649bf76f 100644 --- a/wcfsetup/install/files/lib/system/package/plugin/SQLPackageInstallationPlugin.class.php +++ b/wcfsetup/install/files/lib/system/package/plugin/SQLPackageInstallationPlugin.class.php @@ -82,9 +82,10 @@ class SQLPackageInstallationPlugin extends AbstractPackageInstallationPlugin { */ public function uninstall() { // get logged sql tables/columns - $sql = "SELECT * - FROM wcf".WCF_N."_package_installation_sql_log - WHERE packageID = ?"; + $sql = "SELECT * + FROM wcf".WCF_N."_package_installation_sql_log + WHERE packageID = ? + ORDER BY sqlIndex DESC, sqlColumn DESC"; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute(array($this->installation->getPackageID())); $entries = array(); @@ -98,7 +99,7 @@ class SQLPackageInstallationPlugin extends AbstractPackageInstallationPlugin { // delete or alter tables foreach ($entries as $entry) { // don't alter table if it should be dropped - if (!empty($entry['sqlColumn']) || !empty($entry['sqlIndex'])) { + if (!empty($entry['sqlColumn'])/* || !empty($entry['sqlIndex'])*/) { $isDropped = false; foreach ($entries as $entry2) { if ($entry['sqlTable'] == $entry2['sqlTable'] && empty($entry2['sqlColumn']) && empty($entry2['sqlIndex'])) { @@ -117,7 +118,12 @@ class SQLPackageInstallationPlugin extends AbstractPackageInstallationPlugin { } // drop index else if (in_array($entry['sqlTable'], $existingTableNames) && !empty($entry['sqlIndex'])) { - WCF::getDB()->getEditor()->dropIndex($entry['sqlTable'], $entry['sqlIndex']); + if (substr($entry['sqlIndex'], -3) == '_fk') { + WCF::getDB()->getEditor()->dropForeignKey($entry['sqlTable'], $entry['sqlIndex']); + } + else { + WCF::getDB()->getEditor()->dropIndex($entry['sqlTable'], $entry['sqlIndex']); + } } } // delete from log table -- 2.20.1