1
0
mirror of synced 2025-01-19 06:51:40 +03:00

Support for transaction isolation levels, fixes #186

This commit is contained in:
zYne 2006-10-22 20:50:27 +00:00
parent 6aad5f8e73
commit 02bddbcf52
10 changed files with 315 additions and 48 deletions

View File

@ -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

View File

@ -1,9 +1,40 @@
<?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);
} }

View File

@ -1,6 +1,29 @@
<?php <?php
/** /*
* informix database driver * $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>.
*/ */
class Doctrine_Connection_Informix extends Doctrine_Connection { } Doctrine::autoload('Doctrine_Connection');
/**
* Doctrine_Connection_Mysql
*
* @package Doctrine ORM
* @url www.phpdoctrine.com
* @license LGPL
*/
class Doctrine_Connection_Informix extends Doctrine_Connection { }

View File

@ -1,6 +1,30 @@
<?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 {
/** /**

View File

@ -1,7 +1,30 @@
<?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 {
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
* *

View File

@ -1,6 +1,30 @@
<?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 {
$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

View File

@ -1,7 +1,30 @@
<?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 {
$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
* *

View File

@ -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
* *

View File

@ -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) {

View File

@ -32,7 +32,7 @@ class Doctrine_DataDict_Mssql extends Doctrine_DataDict {
/** /**
* Obtain DBMS specific SQL code portion needed to declare an text type * Obtain DBMS specific SQL code portion needed to declare an text type
* field to be used in statements like CREATE TABLE. * field to be used in statements like CREATE TABLE.
* *
* @param array $field associative array with the name of the properties * @param array $field associative array with the name of the properties
* of the field being declared as array indexes. Currently, the types * of the field being declared as array indexes. Currently, the types
* of supported field properties are as follows: * of supported field properties are as follows:
@ -109,48 +109,48 @@ class Doctrine_DataDict_Mssql extends Doctrine_DataDict {
// todo: unsigned handling seems to be missing // todo: unsigned handling seems to be missing
$unsigned = $fixed = null; $unsigned = $fixed = null;
switch ($db_type) { switch ($db_type) {
case 'bit': case 'bit':
$type[0] = 'boolean'; $type[0] = 'boolean';
break; break;
case 'int': case 'int':
$type[0] = 'integer'; $type[0] = 'integer';
break; break;
case 'datetime': case 'datetime':
$type[0] = 'timestamp'; $type[0] = 'timestamp';
break; break;
case 'float': case 'float':
case 'real': case 'real':
case 'numeric': case 'numeric':
$type[0] = 'float'; $type[0] = 'float';
break; break;
case 'decimal': case 'decimal':
case 'money': case 'money':
$type[0] = 'decimal'; $type[0] = 'decimal';
break; break;
case 'text': case 'text':
case 'varchar': case 'varchar':
$fixed = false; $fixed = false;
case 'char': case 'char':
$type[0] = 'text'; $type[0] = 'text';
if ($length == '1') { if ($length == '1') {
$type[] = 'boolean'; $type[] = 'boolean';
if (preg_match('/^[is|has]/', $field['name'])) { if (preg_match('/^[is|has]/', $field['name'])) {
$type = array_reverse($type); $type = array_reverse($type);
}
} elseif (strstr($db_type, 'text')) {
$type[] = 'clob';
}
if ($fixed !== false) {
$fixed = true;
} }
} elseif (strstr($db_type, 'text')) {
$type[] = 'clob';
}
if ($fixed !== false) {
$fixed = true;
}
break; break;
case 'image': case 'image':
case 'varbinary': case 'varbinary':
$type[] = 'blob'; $type[] = 'blob';
$length = null; $length = null;
break; break;
default: default:
throw new Doctrine_DataDict_Mssql_Exception('mapNativeDatatype: unknown database attribute type: '.$db_type); throw new Doctrine_DataDict_Mssql_Exception('mapNativeDatatype: unknown database attribute type: '.$db_type);
} }
return array($type, $length, $unsigned, $fixed); return array($type, $length, $unsigned, $fixed);