Using transaction now
authorAlexander Ebert <ebert@woltlab.com>
Thu, 15 Dec 2011 15:03:37 +0000 (16:03 +0100)
committerAlexander Ebert <ebert@woltlab.com>
Thu, 15 Dec 2011 15:03:37 +0000 (16:03 +0100)
Changes to PreparedStatement: execute() will now automatically wrap itself in a transaction before committing changes, including an automatic rollback on failure.

If you want to send multiple queries at once, you should wrap the whole loop in a transaction and use executeUnbuffered() instead.

You SHOULD NOT use executeUnbuffered() without a transaction.

wcfsetup/install/files/lib/data/DatabaseObjectEditor.class.php
wcfsetup/install/files/lib/system/WCFSetup.class.php
wcfsetup/install/files/lib/system/database/statement/PreparedStatement.class.php

index 453d3741e80ada5a39e096ee4e4e89ec365348d3..7aa1d1b59f3cb17144b269eceae35b40fc7e9868 100644 (file)
@@ -105,9 +105,12 @@ abstract class DatabaseObjectEditor extends DatabaseObjectDecorator implements I
                $sql = "DELETE FROM     ".static::getDatabaseTableName()."
                        WHERE           ".static::getDatabaseTableIndexName()." = ?";
                $statement = WCF::getDB()->prepareStatement($sql);
+               
+               WCF::getDB()->beginTransaction();
                foreach ($objectIDs as $objectID) {
-                       $statement->execute(array($objectID));
+                       $statement->executeUnbuffered(array($objectID));
                }
+               WCF::getDB()->commitTransaction();
                
                return count($objectIDs);
        }
index 0188a839f289de597635c1c31cffbceb03125706..364664439921d8960b3174cbbbbd6a575806805a 100644 (file)
@@ -705,9 +705,11 @@ class WCFSetup extends WCF {
                                VALUES          (?)";
                        $statement = self::getDB()->prepareStatement($sql);
                        
+                       self::getDB()->beginTransaction();
                        foreach ($acpTemplateInserts as $acpTemplate) {
-                               $statement->execute(array($acpTemplate));
+                               $statement->executeUnbuffered(array($acpTemplate));
                        }
+                       self::getDB()->commitTransaction();
                }
                
                // save file log
@@ -717,9 +719,11 @@ class WCFSetup extends WCF {
                                VALUES          (?)";
                        $statement = self::getDB()->prepareStatement($sql);
                        
+                       self::getDB()->beginTransaction();
                        foreach ($fileInserts as $file) {
-                               $statement->execute(array($file));
+                               $statement->executeUnbuffered(array($file));
                        }
+                       self::getDB()->commitTransaction();
                }
                
                $this->gotoNextStep('installLanguage');
index d979a9865f003b08f273beb020a978df137265a8..5421e293857c1fba614ad99e1693b66c09487551 100644 (file)
@@ -71,23 +71,45 @@ class PreparedStatement {
        }
        
        /**
-        * Executes a prepared statement.
+        * Executes a prepared statement within a transaction.
         *
         * @param       array           $parameters
-        * @return      boolean         true on success
         */
        public function execute(array $parameters = array()) {
                $this->database->incrementQueryCount();
+               $this->database->beginTransaction();
                
                try {
                        if (WCF::benchmarkIsEnabled()) Benchmark::getInstance()->start($this->query, Benchmark::TYPE_SQL_QUERY);
                        
-                       if (!count($parameters)) $result = $this->pdoStatement->execute();
-                       else $result = $this->pdoStatement->execute($parameters);
+                       if (!count($parameters)) $this->pdoStatement->execute();
+                       else $this->pdoStatement->execute($parameters);
                        
                        if (WCF::benchmarkIsEnabled()) Benchmark::getInstance()->stop();
                        
-                       return $result;
+                       $this->database->commitTransaction();
+               }
+               catch (\PDOException $e) {
+                       $this->database->rollBackTransaction();
+                       throw new DatabaseException('Could not execute prepared statement: '.$e->getMessage(), $this->database, $this);
+               }
+       }
+       
+       /**
+        * Executes a prepared statement.
+        *
+        * @param       array           $parameters
+        */
+       public function executeUnbuffered(array $parameters = array()) {
+               $this->database->incrementQueryCount();
+               
+               try {
+                       if (WCF::benchmarkIsEnabled()) Benchmark::getInstance()->start($this->query, Benchmark::TYPE_SQL_QUERY);
+                       
+                       if (!count($parameters)) $this->pdoStatement->execute();
+                       else $this->pdoStatement->execute($parameters);
+                       
+                       if (WCF::benchmarkIsEnabled()) Benchmark::getInstance()->stop();
                }
                catch (\PDOException $e) {
                        throw new DatabaseException('Could not execute prepared statement: '.$e->getMessage(), $this->database, $this);