Commit 6b328358 authored by Lukas Kahwe Smith's avatar Lukas Kahwe Smith

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 4a5624b2
......@@ -101,6 +101,12 @@ class Connection implements DriverConnection
*/
private $_transactionIsolationLevel;
/**
* If nested transations should use savepoints
*
* @var integer
*/
private $_nestTransactionsWithSavepoints;
/**
* The parameters used during creation of the Connection instance.
*
......@@ -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
* "savepointFormat" parameter is not set
*
* @return mixed a string with the savepoint name or false
*/
protected function _getNestedTransactionSavePointName($transactionNestingLevel) {
//TODO this should be configured not hardcoded, but how to do user configuration
$this->_params['savepointFormat'] = 'DOCTRINE2_SAVEPOINT_%s';
if ($this->_platform->supportsSavepoints() && !empty($this->_params['savepointFormat'])) {
return sprintf($this->_params['savepointFormat'], $this->_transactionNestingLevel);
protected function _getNestedTransactionSavePointName() {
if ($this->_platform->supportsSavepoints() && !empty($this->_nestTransactionsWithSavepoints)) {
return 'DOCTRINE2_SAVEPOINT_'.$this->_transactionNestingLevel;
}
return false;
......@@ -848,7 +875,10 @@ class Connection implements DriverConnection
*/
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));
}
......@@ -861,7 +891,10 @@ class Connection implements DriverConnection
*/
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));
}
......@@ -874,7 +907,10 @@ class Connection implements DriverConnection
*/
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));
}
......
......@@ -41,4 +41,9 @@ class ConnectionException extends DBALException
{
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
$this->assertEquals(1, $this->_conn->getTransactionNestingLevel());
//no rethrow
}
if ($this->_conn->getDatabasePlatform()->supportsSavepoints()) {
$this->assertFalse($this->_conn->isRollbackOnly());
} else {
$this->assertTrue($this->_conn->isRollbackOnly());
$this->_conn->commit(); // should throw exception
$this->fail('Transaction commit after failed nested transaction should fail.');
}
} catch (ConnectionException $e) {
$this->assertEquals(1, $this->_conn->getTransactionNestingLevel());
$this->_conn->rollback();
......@@ -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()
{
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