From dcd38d37ec71e3253cf5c90947bb870f64be0104 Mon Sep 17 00:00:00 2001 From: Alexander Ebert Date: Thu, 15 Dec 2011 16:03:37 +0100 Subject: [PATCH] Using transaction now 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. --- .../lib/data/DatabaseObjectEditor.class.php | 5 ++- .../files/lib/system/WCFSetup.class.php | 8 +++-- .../statement/PreparedStatement.class.php | 32 ++++++++++++++++--- 3 files changed, 37 insertions(+), 8 deletions(-) diff --git a/wcfsetup/install/files/lib/data/DatabaseObjectEditor.class.php b/wcfsetup/install/files/lib/data/DatabaseObjectEditor.class.php index 453d3741e8..7aa1d1b59f 100644 --- a/wcfsetup/install/files/lib/data/DatabaseObjectEditor.class.php +++ b/wcfsetup/install/files/lib/data/DatabaseObjectEditor.class.php @@ -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); } diff --git a/wcfsetup/install/files/lib/system/WCFSetup.class.php b/wcfsetup/install/files/lib/system/WCFSetup.class.php index 0188a839f2..3646644399 100644 --- a/wcfsetup/install/files/lib/system/WCFSetup.class.php +++ b/wcfsetup/install/files/lib/system/WCFSetup.class.php @@ -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'); diff --git a/wcfsetup/install/files/lib/system/database/statement/PreparedStatement.class.php b/wcfsetup/install/files/lib/system/database/statement/PreparedStatement.class.php index d979a9865f..5421e29385 100644 --- a/wcfsetup/install/files/lib/system/database/statement/PreparedStatement.class.php +++ b/wcfsetup/install/files/lib/system/database/statement/PreparedStatement.class.php @@ -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); -- 2.20.1