Commit 02bddbcf authored by zYne's avatar zYne

Support for transaction isolation levels, fixes #186

parent 6aad5f8e
...@@ -136,6 +136,22 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun ...@@ -136,6 +136,22 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
} }
return $this->dataDict; return $this->dataDict;
} }
/**
* Set the transacton isolation level.
* (implemented by the connection drivers)
*
* @param string standard isolation level
* READ UNCOMMITTED (allows dirty reads)
* READ COMMITTED (prevents dirty reads)
* REPEATABLE READ (prevents nonrepeatable reads)
* SERIALIZABLE (prevents phantom reads)
* @throws Doctrine_Connection_Mysql_Exception if using unknown isolation level
* @throws PDOException if something fails at the PDO level
* @return void
*/
public function setTransactionIsolation($isolation) {
throw new Doctrine_Connection_Exception('Transaction isolation levels not supported by this database driver.');
}
/** /**
* getRegexpOperator * getRegexpOperator
* returns the regular expression operator * returns the regular expression operator
......
<?php <?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.com>.
*/
Doctrine::autoload('Doctrine_Connection');
/** /**
* firebird driver * Doctrine_Connection_Firebird
*
* @package Doctrine ORM
* @url www.phpdoctrine.com
* @license LGPL
*/ */
class Doctrine_Connection_Firebird extends Doctrine_Connection { class Doctrine_Connection_Firebird extends Doctrine_Connection {
public function modifyLimitQuery($query,$limit,$offset) { /**
* Adds an driver-specific LIMIT clause to the query
*
* @param string $query
* @param mixed $limit
* @param mixed $offset
*/
public function modifyLimitQuery($query, $limit, $offset) {
return preg_replace('/^([\s(])*SELECT(?!\s*FIRST\s*\d+)/i', return preg_replace('/^([\s(])*SELECT(?!\s*FIRST\s*\d+)/i',
"SELECT FIRST $limit SKIP $offset", $query); "SELECT FIRST $limit SKIP $offset", $query);
} }
......
<?php <?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.com>.
*/
Doctrine::autoload('Doctrine_Connection');
/** /**
* informix database driver * Doctrine_Connection_Mysql
*
* @package Doctrine ORM
* @url www.phpdoctrine.com
* @license LGPL
*/ */
class Doctrine_Connection_Informix extends Doctrine_Connection { } class Doctrine_Connection_Informix extends Doctrine_Connection { }
<?php <?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.com>.
*/
Doctrine::autoload('Doctrine_Connection');
/** /**
* mssql driver * Doctrine_Connection_Mssql
*
* @package Doctrine ORM
* @url www.phpdoctrine.com
* @license LGPL
*/ */
class Doctrine_Connection_Mssql extends Doctrine_Connection { class Doctrine_Connection_Mssql extends Doctrine_Connection {
/** /**
......
<?php <?php
require_once("Common.php"); /*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.com>.
*/
Doctrine::autoload('Doctrine_Connection_Common');
/** /**
* mysql driver * Doctrine_Connection_Mysql
*
* @package Doctrine ORM
* @url www.phpdoctrine.com
* @license LGPL
*/ */
class Doctrine_Connection_Mysql extends Doctrine_Connection_Common { class Doctrine_Connection_Mysql extends Doctrine_Connection_Common {
...@@ -23,6 +46,33 @@ class Doctrine_Connection_Mysql extends Doctrine_Connection_Common { ...@@ -23,6 +46,33 @@ class Doctrine_Connection_Mysql extends Doctrine_Connection_Common {
public function getRegexpOperator() { public function getRegexpOperator() {
return 'RLIKE'; return 'RLIKE';
} }
/**
* Set the transacton isolation level.
*
* @param string standard isolation level
* READ UNCOMMITTED (allows dirty reads)
* READ COMMITTED (prevents dirty reads)
* REPEATABLE READ (prevents nonrepeatable reads)
* SERIALIZABLE (prevents phantom reads)
* @throws Doctrine_Connection_Mysql_Exception if using unknown isolation level
* @throws PDOException if something fails at the PDO level
* @return void
*/
public function setTransactionIsolation($isolation) {
switch ($isolation) {
case 'READ UNCOMMITTED':
case 'READ COMMITTED':
case 'REPEATABLE READ':
case 'SERIALIZABLE':
break;
default:
throw new Doctrine_Connection_Mysql_Exception('Isolation level ' . $isolation . ' is not supported.');
}
$query = "SET SESSION TRANSACTION ISOLATION LEVEL $isolation";
return $this->dbh->query($query);
}
/** /**
* Returns string to concatenate two or more string parameters * Returns string to concatenate two or more string parameters
* *
......
<?php <?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.com>.
*/
Doctrine::autoload('Doctrine_Connection');
/** /**
* oracle driver * Doctrine_Connection_Oracle
*
* @package Doctrine ORM
* @url www.phpdoctrine.com
* @license LGPL
*/ */
class Doctrine_Connection_Oracle extends Doctrine_Connection { class Doctrine_Connection_Oracle extends Doctrine_Connection {
/** /**
...@@ -18,6 +42,32 @@ class Doctrine_Connection_Oracle extends Doctrine_Connection { ...@@ -18,6 +42,32 @@ class Doctrine_Connection_Oracle extends Doctrine_Connection {
$query = "SELECT $fields FROM (SELECT rownum as linenum, $fields FROM ($query) WHERE rownum <= ($offset + $limit)) WHERE linenum >= ".++$offset; $query = "SELECT $fields FROM (SELECT rownum as linenum, $fields FROM ($query) WHERE rownum <= ($offset + $limit)) WHERE linenum >= ".++$offset;
return $query; return $query;
} }
/**
* Set the transacton isolation level.
*
* @param string standard isolation level
* READ UNCOMMITTED (allows dirty reads)
* READ COMMITTED (prevents dirty reads)
* REPEATABLE READ (prevents nonrepeatable reads)
* SERIALIZABLE (prevents phantom reads)
* @return mixed MDB2_OK on success, a MDB2 error on failure
*/
function setTransactionIsolation($isolation) {
switch ($isolation) {
case 'READ UNCOMMITTED':
$isolation = 'READ COMMITTED';
case 'READ COMMITTED':
case 'REPEATABLE READ':
$isolation = 'SERIALIZABLE';
case 'SERIALIZABLE':
break;
default:
throw new Doctrine_Connection_Oracle_Exception('Isolation level ' . $isolation . 'is not supported.');
}
$query = 'ALTER SESSION ISOLATION LEVEL ' . $isolation;
return $this->dbh->query($query);
}
/** /**
* returns the next value in the given sequence * returns the next value in the given sequence
* @param string $sequence * @param string $sequence
......
<?php <?php
require_once("Common.php"); /*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.com>.
*/
Doctrine::autoload("Doctrine_Connection_Common");
/** /**
* pgsql driver * Doctrine_Connection_Pgsql
*
* @package Doctrine ORM
* @url www.phpdoctrine.com
* @license LGPL
*/ */
class Doctrine_Connection_Pgsql extends Doctrine_Connection_Common { class Doctrine_Connection_Pgsql extends Doctrine_Connection_Common {
/** /**
...@@ -14,6 +37,29 @@ class Doctrine_Connection_Pgsql extends Doctrine_Connection_Common { ...@@ -14,6 +37,29 @@ class Doctrine_Connection_Pgsql extends Doctrine_Connection_Common {
$data = $stmt->fetch(PDO::FETCH_NUM); $data = $stmt->fetch(PDO::FETCH_NUM);
return $data[0]; return $data[0];
} }
/**
* Set the transacton isolation level.
*
* @param string standard isolation level
* READ UNCOMMITTED (allows dirty reads)
* READ COMMITTED (prevents dirty reads)
* REPEATABLE READ (prevents nonrepeatable reads)
* SERIALIZABLE (prevents phantom reads)
* @return void
*/
function setTransactionIsolation($isolation) {
switch ($isolation) {
case 'READ UNCOMMITTED':
case 'READ COMMITTED':
case 'REPEATABLE READ':
case 'SERIALIZABLE':
break;
throw new Doctrine_Connection_Pgsql_Exception('Isolation level '.$isolation.' is not supported.');
}
$query = 'SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL ' . $isolation;
return $this->dbh->query($query);
}
/** /**
* getRegexpOperator * getRegexpOperator
* *
......
...@@ -45,6 +45,33 @@ class Doctrine_Connection_Sqlite extends Doctrine_Connection_Common { ...@@ -45,6 +45,33 @@ class Doctrine_Connection_Sqlite extends Doctrine_Connection_Common {
return 'datetime(\'now\')'; return 'datetime(\'now\')';
} }
} }
/**
* Set the transacton isolation level.
*
* @param string standard isolation level
* READ UNCOMMITTED (allows dirty reads)
* READ COMMITTED (prevents dirty reads)
* REPEATABLE READ (prevents nonrepeatable reads)
* SERIALIZABLE (prevents phantom reads)
* @return void
*/
function setTransactionIsolation($isolation) {
switch ($isolation) {
case 'READ UNCOMMITTED':
$isolation = 0;
break;
case 'READ COMMITTED':
case 'REPEATABLE READ':
case 'SERIALIZABLE':
$isolation = 1;
break;
default:
throw new Doctrine_Connection_Sqlite_Exception('Isolation level ' . $isolation . 'is not supported.');
}
$query = "PRAGMA read_uncommitted=$isolation";
return $this->_doQuery($query, true);
}
/** /**
* return string to call a function to get a substring inside an SQL statement * return string to call a function to get a substring inside an SQL statement
* *
......
...@@ -154,7 +154,7 @@ class Doctrine_Connection_Transaction implements Countable, IteratorAggregate { ...@@ -154,7 +154,7 @@ class Doctrine_Connection_Transaction implements Countable, IteratorAggregate {
} catch(Exception $e) { } catch(Exception $e) {
$this->rollback(); $this->rollback();
throw new Doctrine_Exception($e->__toString()); throw new Doctrine_Connection_Transaction_Exception($e->__toString());
} }
if(count($this->invalid) > 0) { if(count($this->invalid) > 0) {
......
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