diff --git a/core/lib/Drupal/Core/Database/Driver/pgsql/Connection.php b/core/lib/Drupal/Core/Database/Driver/pgsql/Connection.php index 92295a7..bc1a8d9 100644 --- a/core/lib/Drupal/Core/Database/Driver/pgsql/Connection.php +++ b/core/lib/Drupal/Core/Database/Driver/pgsql/Connection.php @@ -101,23 +101,6 @@ public static function open(array &$connection_options = array()) { return $pdo; } - /** - * {@inheritdoc} - */ - public function startTransaction($name = '') { - // Pop off and/or commit any transactions that are on the stack before - // attempting to create and return a new Transaction object. Menu router - // rebuild is the only case in core that creates a new transaction - // explicitly. - if (!empty($this->transactionLayers)) { - foreach ($this->transactionLayers as $savepoint_name) { - $this->popTransaction($savepoint_name); - } - } - - return parent::startTransaction($name); - } - public function query($query, array $args = array(), $options = array()) { $options += $this->defaultOptions(); @@ -298,12 +281,12 @@ public function nextId($existing = 0) { * provides an inherent savepoint before any query in a transaction. * * @param $savepoint_name - * A string representing the savepoint name. By default, "mimic_innodb" is - * used. + * A string representing the savepoint name. By default, + * "mimic_implicit_commit" is used. * * @see Drupal\Core\Database\Connection::pushTransaction(). */ - public function addSavepoint($savepoint_name = 'mimic_innodb') { + public function addSavepoint($savepoint_name = 'mimic_implicit_commit') { if ($this->inTransaction()) { $this->pushTransaction($savepoint_name); } @@ -313,16 +296,29 @@ public function addSavepoint($savepoint_name = 'mimic_innodb') { * Release a savepoint by name. * * @param $savepoint_name - * A string representing the savepoint name. By default, "mimic_innodb" is - * used. + * A string representing the savepoint name. By default, + * "mimic_implicit_commit" is used. * * @see Drupal\Core\Database\Connection::popTransaction(). */ - public function releaseSavepoint($savepoint_name = 'mimic_innodb') { - if ($this->inTransaction()) { + public function releaseSavepoint($savepoint_name = 'mimic_implicit_commit') { + if (isset($this->transactionLayers[$savepoint_name])) { $this->popTransaction($savepoint_name); } } + + /** + * Rollback a savepoint by name if it exists. + * + * @param $savepoint_name + * A string representing the savepoint name. By default, + * "mimic_implicit_commit" is used. + */ + public function rollbackSavepoint($savepoint_name = 'mimic_implicit_commit') { + if (isset($this->transactionLayers[$savepoint_name])) { + $this->rollback($savepoint_name); + } + } } /** diff --git a/core/lib/Drupal/Core/Database/Driver/pgsql/Delete.php b/core/lib/Drupal/Core/Database/Driver/pgsql/Delete.php index 1e3ef51..85c5003 100644 --- a/core/lib/Drupal/Core/Database/Driver/pgsql/Delete.php +++ b/core/lib/Drupal/Core/Database/Driver/pgsql/Delete.php @@ -16,7 +16,13 @@ class Delete extends QueryDelete { */ public function execute() { $this->connection->addSavepoint(); - $result = parent::execute(); + try { + $result = parent::execute(); + } + catch (\Exception $e) { + $this->connection->rollbackSavepoint(); + throw $e; + } $this->connection->releaseSavepoint(); return $result; diff --git a/core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php b/core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php index ad02ac7..219384f 100644 --- a/core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php +++ b/core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php @@ -62,12 +62,17 @@ public function queryTableInformation($table) { // Don't use {} around information_schema.columns table. $this->connection->addSavepoint(); - $result = $this->connection->query("SELECT column_name, data_type, column_default FROM information_schema.columns WHERE table_schema = :schema AND table_name = :table AND (data_type = 'bytea' OR (numeric_precision IS NOT NULL AND column_default LIKE :default))", array( - ':schema' => $schema, - ':table' => $table_name, - ':default' => '%nextval%', - )); - + try { + $result = $this->connection->query("SELECT column_name, data_type, column_default FROM information_schema.columns WHERE table_schema = :schema AND table_name = :table AND (data_type = 'bytea' OR (numeric_precision IS NOT NULL AND column_default LIKE :default))", array( + ':schema' => $schema, + ':table' => $table_name, + ':default' => '%nextval%', + )); + } + catch (\Exception $e) { + $this->connection->rollbackSavepoint(); + throw $e; + } $this->connection->releaseSavepoint(); foreach ($result as $column) { @@ -109,11 +114,17 @@ public function queryFieldInformation($table, $field) { $this->connection->addSavepoint(); - $checks = $this->connection->query("SELECT conname FROM pg_class cl INNER JOIN pg_constraint co ON co.conrelid = cl.oid INNER JOIN pg_attribute attr ON attr.attrelid = cl.oid AND attr.attnum = ANY (co.conkey) INNER JOIN pg_namespace ns ON cl.relnamespace = ns.oid WHERE co.contype = 'c' AND ns.nspname = :schema AND cl.relname = :table AND attr.attname = :column", array( - ':schema' => $schema, - ':table' => $table_name, - ':column' => $field, - )); + try { + $checks = $this->connection->query("SELECT conname FROM pg_class cl INNER JOIN pg_constraint co ON co.conrelid = cl.oid INNER JOIN pg_attribute attr ON attr.attrelid = cl.oid AND attr.attnum = ANY (co.conkey) INNER JOIN pg_namespace ns ON cl.relnamespace = ns.oid WHERE co.contype = 'c' AND ns.nspname = :schema AND cl.relname = :table AND attr.attname = :column", array( + ':schema' => $schema, + ':table' => $table_name, + ':column' => $field, + )); + } + catch (\Exception $e) { + $this->connection->rollbackSavepoint(); + throw $e; + } $this->connection->releaseSavepoint(); diff --git a/core/lib/Drupal/Core/Database/Driver/pgsql/Select.php b/core/lib/Drupal/Core/Database/Driver/pgsql/Select.php index a342e12..2d2203f 100644 --- a/core/lib/Drupal/Core/Database/Driver/pgsql/Select.php +++ b/core/lib/Drupal/Core/Database/Driver/pgsql/Select.php @@ -54,7 +54,7 @@ public function orderRandom() { public function orderBy($field, $direction = 'ASC') { // Call parent function to order on this. $return = parent::orderBy($field, $direction); - + if ($this->hasTag('entity_query')) { return $return; } @@ -114,7 +114,13 @@ public function orderBy($field, $direction = 'ASC') { */ public function execute() { $this->connection->addSavepoint(); - $result = parent::execute(); + try { + $result = parent::execute(); + } + catch (\Exception $e) { + $this->connection->rollbackSavepoint(); + throw $e; + } $this->connection->releaseSavepoint(); return $result; diff --git a/core/lib/Drupal/Core/Database/Driver/pgsql/Truncate.php b/core/lib/Drupal/Core/Database/Driver/pgsql/Truncate.php index c6d39cf..5357e6b 100644 --- a/core/lib/Drupal/Core/Database/Driver/pgsql/Truncate.php +++ b/core/lib/Drupal/Core/Database/Driver/pgsql/Truncate.php @@ -16,7 +16,13 @@ class Truncate extends QueryTruncate { */ public function execute() { $this->connection->addSavepoint(); - $result = parent::execute(); + try { + $result = parent::execute(); + } + catch (\Exception $e) { + $this->connection->rollbackSavepoint(); + throw $e; + } $this->connection->releaseSavepoint(); return $result; diff --git a/core/lib/Drupal/Core/Database/Driver/pgsql/Update.php b/core/lib/Drupal/Core/Database/Driver/pgsql/Update.php index f424dfe..09efb6c 100644 --- a/core/lib/Drupal/Core/Database/Driver/pgsql/Update.php +++ b/core/lib/Drupal/Core/Database/Driver/pgsql/Update.php @@ -66,7 +66,17 @@ public function execute() { $options = $this->queryOptions; $options['already_prepared'] = TRUE; $options['return'] = Database::RETURN_AFFECTED; - return $this->connection->query($stmt, array(), $options); + + $this->connection->addSavepoint(); + try { + $result = $this->connection->query($stmt, array(), $options); + $this->connection->releaseSavepoint(); + return $result; + } + catch (\Exception $e) { + $this->connection->rollbackSavepoint(); + throw $e; + } } }