Commit 612bb3b4 authored by Lukas Kahwe Smith's avatar Lukas Kahwe Smith Committed by Juozas Kaziukenas

disable savepoints by default, added dedicated getter/setter to...

disable savepoints by default, added dedicated getter/setter to enable/disable, added exceptions when trying to use savepoints when not supported by the platform
parent ec003aad
...@@ -101,6 +101,12 @@ class Connection implements DriverConnection ...@@ -101,6 +101,12 @@ class Connection implements DriverConnection
*/ */
private $_transactionIsolationLevel; private $_transactionIsolationLevel;
/**
* If nested transations should use savepoints
*
* @var integer
*/
private $_nestTransactionsWithSavepoints;
/** /**
* The parameters used during creation of the Connection instance. * The parameters used during creation of the Connection instance.
* *
...@@ -740,18 +746,39 @@ class Connection implements DriverConnection ...@@ -740,18 +746,39 @@ class Connection implements DriverConnection
} }
} }
/**
* Set if nested transactions should use savepoints
*
* @param boolean
*/
public function setNestTransactionsWithSavepoints($nestTransactionsWithSavepoints)
{
if ($nestTransactionsWithSavepoints && !$this->_platform->supportsSavepoints()) {
ConnectionException::savepointsNotSupported();
}
$this->_nestTransactionsWithSavepoints = $nestTransactionsWithSavepoints;
}
/**
* Get if nested transactions should use savepoints
*
* @return boolean
*/
public function getNestTransactionsWithSavepoints()
{
return $this->_nestTransactionsWithSavepoints;
}
/** /**
* Returns the savepoint name to use for nested transactions are false if they are not supported * Returns the savepoint name to use for nested transactions are false if they are not supported
* "savepointFormat" parameter is not set * "savepointFormat" parameter is not set
* *
* @return mixed a string with the savepoint name or false * @return mixed a string with the savepoint name or false
*/ */
protected function _getNestedTransactionSavePointName($transactionNestingLevel) { protected function _getNestedTransactionSavePointName() {
//TODO this should be configured not hardcoded, but how to do user configuration if ($this->_platform->supportsSavepoints() && !empty($this->_nestTransactionsWithSavepoints)) {
$this->_params['savepointFormat'] = 'DOCTRINE2_SAVEPOINT_%s'; return 'DOCTRINE2_SAVEPOINT_'.$this->_transactionNestingLevel;
if ($this->_platform->supportsSavepoints() && !empty($this->_params['savepointFormat'])) {
return sprintf($this->_params['savepointFormat'], $this->_transactionNestingLevel);
} }
return false; return false;
...@@ -848,7 +875,10 @@ class Connection implements DriverConnection ...@@ -848,7 +875,10 @@ class Connection implements DriverConnection
*/ */
public function createSavePoint($savepoint) public function createSavePoint($savepoint)
{ {
//TODO check if save points are supported? if so where? if (!$this->_platform->supportsSavepoints()) {
ConnectionException::savepointsNotSupported();
}
return $this->_conn->exec($this->_platform->createSavePoint($savepoint)); return $this->_conn->exec($this->_platform->createSavePoint($savepoint));
} }
...@@ -861,7 +891,10 @@ class Connection implements DriverConnection ...@@ -861,7 +891,10 @@ class Connection implements DriverConnection
*/ */
public function releaseSavePoint($savepoint) public function releaseSavePoint($savepoint)
{ {
//TODO check if save points are supported? if so where? if (!$this->_platform->supportsSavepoints()) {
ConnectionException::savepointsNotSupported();
}
return $this->_conn->exec($this->_platform->releaseSavePoint($savepoint)); return $this->_conn->exec($this->_platform->releaseSavePoint($savepoint));
} }
...@@ -874,7 +907,10 @@ class Connection implements DriverConnection ...@@ -874,7 +907,10 @@ class Connection implements DriverConnection
*/ */
public function rollbackSavePoint($savepoint) public function rollbackSavePoint($savepoint)
{ {
//TODO check if save points are supported? if so where? if (!$this->_platform->supportsSavepoints()) {
ConnectionException::savepointsNotSupported();
}
return $this->_conn->exec($this->_platform->rollbackSavePoint($savepoint)); return $this->_conn->exec($this->_platform->rollbackSavePoint($savepoint));
} }
......
...@@ -41,4 +41,9 @@ class ConnectionException extends DBALException ...@@ -41,4 +41,9 @@ class ConnectionException extends DBALException
{ {
return new self("There is no active transaction."); return new self("There is no active transaction.");
} }
public static function savepointsNotSupported()
{
return new self("Savepoints are not supported transaction.");
}
} }
\ No newline at end of file
...@@ -43,14 +43,10 @@ class ConnectionTest extends \Doctrine\Tests\DbalFunctionalTestCase ...@@ -43,14 +43,10 @@ class ConnectionTest extends \Doctrine\Tests\DbalFunctionalTestCase
$this->assertEquals(1, $this->_conn->getTransactionNestingLevel()); $this->assertEquals(1, $this->_conn->getTransactionNestingLevel());
//no rethrow //no rethrow
} }
if ($this->_conn->getDatabasePlatform()->supportsSavepoints()) {
$this->assertFalse($this->_conn->isRollbackOnly());
} else {
$this->assertTrue($this->_conn->isRollbackOnly()); $this->assertTrue($this->_conn->isRollbackOnly());
$this->_conn->commit(); // should throw exception $this->_conn->commit(); // should throw exception
$this->fail('Transaction commit after failed nested transaction should fail.'); $this->fail('Transaction commit after failed nested transaction should fail.');
}
} catch (ConnectionException $e) { } catch (ConnectionException $e) {
$this->assertEquals(1, $this->_conn->getTransactionNestingLevel()); $this->assertEquals(1, $this->_conn->getTransactionNestingLevel());
$this->_conn->rollback(); $this->_conn->rollback();
...@@ -58,6 +54,33 @@ class ConnectionTest extends \Doctrine\Tests\DbalFunctionalTestCase ...@@ -58,6 +54,33 @@ class ConnectionTest extends \Doctrine\Tests\DbalFunctionalTestCase
} }
} }
public function testTransactionNestingBehaviorWithSavepoints()
{
if ($this->_conn->getDatabasePlatform()->supportsSavepoints()) {
$this->_conn->setNestTransactionsWithSavepoints(true);
try {
$this->_conn->beginTransaction();
$this->assertEquals(1, $this->_conn->getTransactionNestingLevel());
try {
$this->_conn->beginTransaction();
$this->assertEquals(2, $this->_conn->getTransactionNestingLevel());
throw new \Exception;
$this->_conn->commit(); // never reached
} catch (\Exception $e) {
$this->_conn->rollback();
$this->assertEquals(1, $this->_conn->getTransactionNestingLevel());
//no rethrow
}
$this->assertFalse($this->_conn->isRollbackOnly());
$this->_conn->commit(); // should not throw exception
} catch (ConnectionException $e) {
$this->fail('Transaction commit after failed nested transaction should not fail when using savepoints.');
$this->_conn->rollback();
}
}
}
public function testTransactionBehaviorWithRollback() public function testTransactionBehaviorWithRollback()
{ {
try { try {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment