Fixed multiple package installation issues
authorMarcel Werk <burntime@woltlab.com>
Tue, 19 Jul 2011 18:49:29 +0000 (20:49 +0200)
committerMarcel Werk <burntime@woltlab.com>
Tue, 19 Jul 2011 18:49:29 +0000 (20:49 +0200)
wcfsetup/install/files/lib/system/database/editor/DatabaseEditor.class.php
wcfsetup/install/files/lib/system/database/editor/MySQLDatabaseEditor.class.php
wcfsetup/install/files/lib/system/database/editor/PostgreSQLDatabaseEditor.class.php
wcfsetup/install/files/lib/system/database/util/SQLParser.class.php
wcfsetup/install/files/lib/system/package/PackageInstallationDispatcher.class.php
wcfsetup/install/files/lib/system/package/PackageUninstallationNodeBuilder.class.php
wcfsetup/install/files/lib/system/package/plugin/SQLPackageInstallationPlugin.class.php

index df739ffc2f3bd00668c25cb01373a6aefac743f9..7cd88bc5a0c585e41b63f262860187ce1ce4891a 100644 (file)
@@ -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);
 }
index 70f6b659ab430815f0d5d4118e3bb8c1c09c627d..a70f50fd3a09dccd6ca3c05bff5845861cf3bd2e 100644 (file)
@@ -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.
         * 
index 7b1faf44d343756a782407949e9d39141fb4b5f4..c511c96b99da76c4ad1c4c8e64578be47c7e6512 100644 (file)
@@ -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.
         * 
index 853c07500a1d412f654381683a8c4581db8c4fb7..45ba7b2fa8b2cf99401da0e91acf7bc36a778e29 100644 (file)
@@ -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 : '');
+       }
 }
index e7c66fa6eaab4c94a9a840cf8c54506ef691aab9..3bb8054852c82a457e36bcc627dcf1964e3d077d 100644 (file)
@@ -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
index db32b579284cb2879108c8fff3cbc4b9a29b6131..cf1a571fa1c614f367fefc1bbfc8aa4d25d48457 100644 (file)
@@ -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()) {
index 9d29b86826d07e1d1b4dc1e2dab97a59f5411be2..a7649bf76ffbea9357ac025f2d79d53b26aa9272 100644 (file)
@@ -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