diff --git a/code/SQLite3Database.php b/code/SQLite3Database.php index ad50e49..006bc54 100644 --- a/code/SQLite3Database.php +++ b/code/SQLite3Database.php @@ -485,25 +485,77 @@ class SQLite3Database extends Database public function transactionRollback($savepoint = false) { + // Named transaction if ($savepoint) { $this->query("ROLLBACK TO $savepoint;"); - } else { - --$this->transactionNesting; - if ($this->transactionNesting > 0) { - $this->transactionRollback('NESTEDTRANSACTION' . $this->transactionNesting); - } else { - $this->query('ROLLBACK;'); - } + return true; } + + // Fail if transaction isn't available + if (!$this->transactionNesting) { + return false; + } + + --$this->transactionNesting; + if ($this->transactionNesting > 0) { + $this->transactionRollback('NESTEDTRANSACTION' . $this->transactionNesting); + } else { + $this->query('ROLLBACK;'); + } + return true; + } + + public function transactionDepth() + { + return $this->transactionNesting; } public function transactionEnd($chain = false) { + // Fail if transaction isn't available + if (!$this->transactionNesting) { + return false; + } --$this->transactionNesting; if ($this->transactionNesting <= 0) { $this->transactionNesting = 0; $this->query('COMMIT;'); } + return true; + } + + /** + * In error condition, set transactionNesting to zero + */ + protected function resetTransactionNesting() + { + $this->transactionNesting = 0; + } + + public function query($sql, $errorLevel = E_USER_ERROR) + { + $this->inspectQuery($sql); + return parent::query($sql, $errorLevel); + } + + public function preparedQuery($sql, $parameters, $errorLevel = E_USER_ERROR) + { + $this->inspectQuery($sql); + return parent::preparedQuery($sql, $parameters, $errorLevel); + } + + /** + * Inspect a SQL query prior to execution + * + * @param string $sql + */ + protected function inspectQuery($sql) + { + // Any DDL discards transactions. + $isDDL = $this->getConnector()->isQueryDDL($sql); + if ($isDDL) { + $this->resetTransactionNesting(); + } } public function clearTable($table)