Commit 8b5cf30e authored by zYne's avatar zYne

Updated Pgsql datadict driver, moved transaction isolation functionality to Doctrine_Transaction

parent 256fbd53
...@@ -21,14 +21,14 @@ ...@@ -21,14 +21,14 @@
/** /**
* Doctrine_Connection * Doctrine_Connection
* *
* @package Doctrine * @package Doctrine
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @category Object Relational Mapping * @category Object Relational Mapping
* @link www.phpdoctrine.com * @link www.phpdoctrine.com
* @since 1.0 * @since 1.0
* @version $Revision$ * @version $Revision$
* @author Konsta Vesterinen <kvesteri@cc.hut.fi> * @author Konsta Vesterinen <kvesteri@cc.hut.fi>
*/ */
abstract class Doctrine_Connection extends Doctrine_Configurable implements Countable, IteratorAggregate { abstract class Doctrine_Connection extends Doctrine_Configurable implements Countable, IteratorAggregate {
/** /**
* @var $dbh the database handler * @var $dbh the database handler
...@@ -295,41 +295,82 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun ...@@ -295,41 +295,82 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
throw new Doctrine_Connection_Exception('Altering charset not supported by this driver.'); throw new Doctrine_Connection_Exception('Altering charset not supported by this driver.');
} }
/** /**
* setTransactionIsolation * fetchAll
*
* Set the transacton isolation level.
* (implemented by the connection drivers)
* *
* example: * @param string $statement sql query to be executed
* @param array $params prepared statement params
* @return array
*/
public function fetchAll($statement, array $params = array()) {
return $this->query($statement, $params)->fetchAll(PDO::FETCH_ASSOC);
}
/**
* fetchOne
* *
* <code> * @param string $statement sql query to be executed
* $conn->setTransactionIsolation('READ UNCOMMITTED'); * @param array $params prepared statement params
* </code> * @return mixed
*/
public function fetchOne($statement, array $params = array()) {
return current($this->query($statement, $params)->fetch(PDO::FETCH_NUM));
}
/**
* fetchRow
* *
* @param string standard isolation level * @param string $statement sql query to be executed
* READ UNCOMMITTED (allows dirty reads) * @param array $params prepared statement params
* READ COMMITTED (prevents dirty reads) * @return array
* REPEATABLE READ (prevents nonrepeatable reads) */
* SERIALIZABLE (prevents phantom reads) public function fetchRow($statement, array $params = array()) {
return $this->query($statement, $params)->fetch(PDO::FETCH_ASSOC);
}
/**
* fetchArray
* *
* @throws Doctrine_Connection_Exception if the feature is not supported by the driver * @param string $statement sql query to be executed
* @throws PDOException if something fails at the PDO level * @param array $params prepared statement params
* @return void * @return array
*/ */
public function setTransactionIsolation($isolation) { public function fetchArray($statement, array $params = array()) {
throw new Doctrine_Connection_Exception('Transaction isolation levels not supported by this driver.'); return $this->query($statement, $params)->fetch(PDO::FETCH_NUM);
} }
/**
* fetchColumn
*
* @param string $statement sql query to be executed
* @param array $params prepared statement params
* @return array
*/
public function fetchColumn($statement, array $params = array()) {
$result = $this->query($statement, $params)->fetchAll(PDO::FETCH_COLUMN);
if($this->options['portability'] & Doctrine::PORTABILITY_FIX_CASE)
$result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
return $result;
}
/** /**
* getTransactionIsolation * fetchAssoc
* *
* @throws Doctrine_Connection_Exception if the feature is not supported by the driver * @param string $statement sql query to be executed
* @throws PDOException if something fails at the PDO level * @param array $params prepared statement params
* @return string returns the current session transaction isolation level * @return array
*/
public function fetchAssoc($statement, array $params = array()) {
return $this->query($statement, $params)->fetchAll(PDO::FETCH_ASSOC);
}
/**
* fetchBoth
*
* @param string $statement sql query to be executed
* @param array $params prepared statement params
* @return array
*/ */
public function getTransactionIsolation() { public function fetchBoth($statement, array $params = array()) {
throw new Doctrine_Connection_Exception('Fetching transaction isolation level not supported by this driver.'); return $this->query($statement, $params)->fetchAll(PDO::FETCH_BOTH);
} }
/** /**
* query * query
* queries the database using Doctrine Query Language * queries the database using Doctrine Query Language
......
...@@ -19,15 +19,17 @@ ...@@ -19,15 +19,17 @@
* <http://www.phpdoctrine.com>. * <http://www.phpdoctrine.com>.
*/ */
/** /**
* @package Doctrine * @package Doctrine
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @author Konsta Vesterinen <kvesteri@cc.hut.fi> * @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library) * @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
* @version $Revision$ * @author Frank M. Kromann <frank@kromann.info> (PEAR MDB2 Mssql driver)
* @category Object Relational Mapping * @author David Coallier <davidc@php.net> (PEAR MDB2 Mssql driver)
* @link www.phpdoctrine.com * @version $Revision$
* @since 1.0 * @category Object Relational Mapping
*/ * @link www.phpdoctrine.com
* @since 1.0
*/
class Doctrine_DataDict_Mssql extends Doctrine_DataDict { 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
...@@ -189,7 +191,22 @@ class Doctrine_DataDict_Mssql extends Doctrine_DataDict { ...@@ -189,7 +191,22 @@ class Doctrine_DataDict_Mssql extends Doctrine_DataDict {
* @return array * @return array
*/ */
public function listSequences($database = null) { public function listSequences($database = null) {
$query = "SELECT name FROM sysobjects WHERE xtype = 'U'";
$table_names = $db->queryCol($query);
if (PEAR::isError($table_names)) {
return $table_names;
}
$result = array();
foreach ($table_names as $table_name) {
if ($sqn = $this->_fixSequenceName($table_name, true)) {
$result[] = $sqn;
}
}
if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
$result = array_map(($db->options['field_case'] == CASE_LOWER ?
'strtolower' : 'strtoupper'), $result);
}
return $result;
} }
/** /**
* lists table constraints * lists table constraints
...@@ -207,7 +224,7 @@ class Doctrine_DataDict_Mssql extends Doctrine_DataDict { ...@@ -207,7 +224,7 @@ class Doctrine_DataDict_Mssql extends Doctrine_DataDict {
* @return array * @return array
*/ */
public function listTableColumns($table) { public function listTableColumns($table) {
$sql = "exec sp_columns @table_name = " . $this->quoteIdentifier($table); $sql = 'EXEC sp_columns @table_name = ' . $this->quoteIdentifier($table);
$result = $this->dbh->query($sql)->fetchAll(PDO::FETCH_ASSOC); $result = $this->dbh->query($sql)->fetchAll(PDO::FETCH_ASSOC);
$columns = array(); $columns = array();
...@@ -262,7 +279,24 @@ class Doctrine_DataDict_Mssql extends Doctrine_DataDict { ...@@ -262,7 +279,24 @@ class Doctrine_DataDict_Mssql extends Doctrine_DataDict {
* @return array * @return array
*/ */
public function listTableTriggers($table) { public function listTableTriggers($table) {
$table = $db->quote($table, 'text');
$query = "SELECT name FROM sysobjects WHERE xtype = 'TR'";
if (!is_null($table)) {
$query .= "AND object_name(parent_obj) = $table";
}
$result = $db->queryCol($query);
if (PEAR::isError($results)) {
return $result;
}
if ($db->options['portability'] & Doctrine::PORTABILITY_FIX_CASE &&
$db->options['field_case'] == CASE_LOWER)
{
$result = array_map(($db->options['field_case'] == CASE_LOWER ?
'strtolower' : 'strtoupper'), $result);
}
return $result;
} }
/** /**
* lists table views * lists table views
...@@ -271,7 +305,34 @@ class Doctrine_DataDict_Mssql extends Doctrine_DataDict { ...@@ -271,7 +305,34 @@ class Doctrine_DataDict_Mssql extends Doctrine_DataDict {
* @return array * @return array
*/ */
public function listTableViews($table) { public function listTableViews($table) {
$keyName = 'INDEX_NAME';
$pkName = 'PK_NAME';
if ($db->options['portability'] & Doctrine::PORTABILITY_FIX_CASE) {
if ($db->options['field_case'] == CASE_LOWER) {
$keyName = strtolower($keyName);
$pkName = strtolower($pkName);
} else {
$keyName = strtoupper($keyName);
$pkName = strtoupper($pkName);
}
}
$table = $db->quote($table, 'text');
$query = 'EXEC sp_statistics @table_name = ' . $table;
$indexes = $db->queryCol($query, 'text', $keyName);
$query = 'EXEC sp_pkeys @table_name = ' . $table;
$pkAll = $db->queryCol($query, 'text', $pkName);
$result = array();
foreach ($indexes as $index) {
if (!in_array($index, $pkAll) && $index != null) {
$result[$this->_fixIndexName($index)] = true;
}
}
if ($db->options['portability'] & Doctrine::PORTABILITY_FIX_CASE) {
$result = array_change_key_case($result, $db->options['field_case']);
}
return array_keys($result);
} }
/** /**
* lists database users * lists database users
...@@ -288,6 +349,16 @@ class Doctrine_DataDict_Mssql extends Doctrine_DataDict { ...@@ -288,6 +349,16 @@ class Doctrine_DataDict_Mssql extends Doctrine_DataDict {
* @return array * @return array
*/ */
public function listViews($database = null) { public function listViews($database = null) {
$query = "SELECT name FROM sysobjects WHERE xtype = 'V'";
$result = $db->queryCol($query);
if ($db->options['portability'] & Doctrine::PORTABILITY_FIX_CASE &&
$db->options['field_case'] == CASE_LOWER)
{
$result = array_map(($db->options['field_case'] == CASE_LOWER ?
'strtolower' : 'strtoupper'), $result);
}
return $result;
} }
} }
...@@ -532,12 +532,15 @@ class Doctrine_DataDict_Pgsql extends Doctrine_DataDict { ...@@ -532,12 +532,15 @@ class Doctrine_DataDict_Pgsql extends Doctrine_DataDict {
return array($type, $length, $unsigned, $fixed); return array($type, $length, $unsigned, $fixed);
} }
/** /**
* listDatabases
* lists all databases * lists all databases
* *
* @return array * @return array
*/ */
public function listDatabases() { public function listDatabases() {
$query = 'SELECT datname FROM pg_database';
return $this->conn->fetchColumn($query);
} }
/** /**
* lists all availible database functions * lists all availible database functions
...@@ -545,7 +548,20 @@ class Doctrine_DataDict_Pgsql extends Doctrine_DataDict { ...@@ -545,7 +548,20 @@ class Doctrine_DataDict_Pgsql extends Doctrine_DataDict {
* @return array * @return array
*/ */
public function listFunctions() { public function listFunctions() {
$query = "
SELECT
proname
FROM
pg_proc pr,
pg_type tp
WHERE
tp.oid = pr.prorettype
AND pr.proisagg = FALSE
AND tp.typname <> 'trigger'
AND pr.pronamespace IN
(SELECT oid FROM pg_namespace WHERE nspname NOT LIKE 'pg_%' AND nspname != 'information_schema')";
return $this->conn->fetchColumn($query);
} }
/** /**
* lists all database triggers * lists all database triggers
...@@ -563,7 +579,10 @@ class Doctrine_DataDict_Pgsql extends Doctrine_DataDict { ...@@ -563,7 +579,10 @@ class Doctrine_DataDict_Pgsql extends Doctrine_DataDict {
* @return array * @return array
*/ */
public function listSequences($database = null) { public function listSequences($database = null) {
$query = "SELECT relname FROM pg_class WHERE relkind = 'S' AND relnamespace IN";
$query.= "(SELECT oid FROM pg_namespace WHERE nspname NOT LIKE 'pg_%' AND nspname != 'information_schema')";
return $this->conn->fetchColumn($query);
} }
/** /**
* lists table constraints * lists table constraints
...@@ -572,7 +591,12 @@ class Doctrine_DataDict_Pgsql extends Doctrine_DataDict { ...@@ -572,7 +591,12 @@ class Doctrine_DataDict_Pgsql extends Doctrine_DataDict {
* @return array * @return array
*/ */
public function listTableConstraints($table) { public function listTableConstraints($table) {
$table = $db->quote($table, 'text');
$subquery = "SELECT indexrelid FROM pg_index, pg_class";
$subquery.= " WHERE pg_class.relname=$table AND pg_class.oid=pg_index.indrelid AND (indisunique = 't' OR indisprimary = 't')";
$query = "SELECT relname FROM pg_class WHERE oid IN ($subquery)";
return $this->conn->fetchColumn($query);
} }
/** /**
* lists table constraints * lists table constraints
...@@ -619,13 +643,18 @@ class Doctrine_DataDict_Pgsql extends Doctrine_DataDict { ...@@ -619,13 +643,18 @@ class Doctrine_DataDict_Pgsql extends Doctrine_DataDict {
return $columns; return $columns;
} }
/** /**
* lists table constraints * list all indexes in a table
* *
* @param string $table database table name * @param string $table database table name
* @return array * @return array
*/ */
public function listTableIndexes($table) { public function listTableIndexes($table) {
$table = $db->quote($table, 'text');
$subquery = "SELECT indexrelid FROM pg_index, pg_class";
$subquery.= " WHERE pg_class.relname=$table AND pg_class.oid=pg_index.indrelid AND indisunique != 't' AND indisprimary != 't'";
$query = "SELECT relname FROM pg_class WHERE oid IN ($subquery)";
return $this->conn->fetchColumn($query);
} }
/** /**
* lists tables * lists tables
...@@ -659,21 +688,25 @@ class Doctrine_DataDict_Pgsql extends Doctrine_DataDict { ...@@ -659,21 +688,25 @@ class Doctrine_DataDict_Pgsql extends Doctrine_DataDict {
} }
/** /**
* lists table views * list the views in the database that reference a given table
* *
* @param string $table database table name * @param string $table database table name
* @return array * @return array
*/ */
public function listTableViews($table) { public function listTableViews($table) {
$query = 'SELECT viewname FROM pg_views';
return $this->conn->fetchColumn($query);
} }
/** /**
* lists database users * lists database users
* *
* @return array * @return array
*/ */
public function listUsers() { public function listUsers() {
$query = 'SELECT usename FROM pg_user';
return $this->conn->fetchColumn($query);
} }
/** /**
* lists database views * lists database views
...@@ -681,7 +714,9 @@ class Doctrine_DataDict_Pgsql extends Doctrine_DataDict { ...@@ -681,7 +714,9 @@ class Doctrine_DataDict_Pgsql extends Doctrine_DataDict {
* @param string|null $database * @param string|null $database
* @return array * @return array
*/ */
public function listViews($database = null) { public function listViews($database = null) {
$query = 'SELECT viewname FROM pg_views';
return $this->conn->fetchColumn($query);
} }
} }
...@@ -30,21 +30,17 @@ ...@@ -30,21 +30,17 @@
*/ */
class Doctrine_Transaction { class Doctrine_Transaction {
/** /**
* Doctrine_Transaction is in open state when it is opened and there are no active transactions * Doctrine_Transaction is in sleep state when it has no active transactions
*/ */
const STATE_OPEN = 0; const STATE_SLEEP = 0;
/**
* Doctrine_Transaction is in closed state when it is closed
*/
const STATE_CLOSED = 1;
/** /**
* Doctrine_Transaction is in active state when it has one active transaction * Doctrine_Transaction is in active state when it has one active transaction
*/ */
const STATE_ACTIVE = 2; const STATE_ACTIVE = 1;
/** /**
* Doctrine_Transaction is in busy state when it has multiple active transactions * Doctrine_Transaction is in busy state when it has multiple active transactions
*/ */
const STATE_BUSY = 3; const STATE_BUSY = 2;
/** /**
* @var Doctrine_Connection $conn the connection object * @var Doctrine_Connection $conn the connection object
*/ */
...@@ -93,6 +89,8 @@ class Doctrine_Transaction { ...@@ -93,6 +89,8 @@ class Doctrine_Transaction {
* beginTransaction * beginTransaction
* Start a transaction or set a savepoint. * Start a transaction or set a savepoint.
* *
* Listeners: onPreTransactionBegin, onTransactionBegin
*
* @param string $savepoint name of a savepoint to set * @param string $savepoint name of a savepoint to set
* @throws Doctrine_Transaction_Exception if trying to create a savepoint and there * @throws Doctrine_Transaction_Exception if trying to create a savepoint and there
* are no active transactions * are no active transactions
...@@ -122,8 +120,9 @@ class Doctrine_Transaction { ...@@ -122,8 +120,9 @@ class Doctrine_Transaction {
* commit * commit
* Commit the database changes done during a transaction that is in * Commit the database changes done during a transaction that is in
* progress or release a savepoint. This function may only be called when * progress or release a savepoint. This function may only be called when
* auto-committing is disabled, otherwise it will fail. Therefore, a new * auto-committing is disabled, otherwise it will fail.
* transaction is implicitly started after committing the pending changes. *
* Listeners: onPreTransactionCommit, onTransactionCommit
* *
* @param string $savepoint name of a savepoint to release * @param string $savepoint name of a savepoint to release
* @throws Doctrine_Transaction_Exception if the transaction fails at PDO level * @throws Doctrine_Transaction_Exception if the transaction fails at PDO level
...@@ -145,7 +144,7 @@ class Doctrine_Transaction { ...@@ -145,7 +144,7 @@ class Doctrine_Transaction {
try { try {
$this->bulkDelete(); $this->bulkDelete();
} catch(Exception $e) { } catch(Exception $e) {
$this->rollback(); $this->rollback();
...@@ -227,4 +226,45 @@ class Doctrine_Transaction { ...@@ -227,4 +226,45 @@ class Doctrine_Transaction {
public function rollbackSavePoint($savepoint) { public function rollbackSavePoint($savepoint) {
throw new Doctrine_Transaction_Exception('Savepoints not supported by this driver.'); throw new Doctrine_Transaction_Exception('Savepoints not supported by this driver.');
} }
/**
* setIsolation
*
* Set the transacton isolation level.
* (implemented by the connection drivers)
*
* example:
*
* <code>
* $tx->setIsolation('READ UNCOMMITTED');
* </code>
*
* @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_Exception if the feature is not supported by the driver
* @throws PDOException if something fails at the PDO level
* @return void
*/
public function setIsolation($isolation) {
throw new Doctrine_Connection_Exception('Transaction isolation levels not supported by this driver.');
}
/**
* getTransactionIsolation
*
* fetches the current session transaction isolation level
*
* note: some drivers may support setting the transaction isolation level
* but not fetching it
*
* @throws Doctrine_Connection_Exception if the feature is not supported by the driver
* @throws PDOException if something fails at the PDO level
* @return string returns the current session transaction isolation level
*/
public function getIsolation() {
throw new Doctrine_Connection_Exception('Fetching transaction isolation level not supported by this driver.');
}
} }
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