Commit 78ce54a7 authored by lsmith's avatar lsmith

- added colnum parameter to fetchOne and fetchColumn

- use fetchColumn() in fetchOne()
- removed PORTABILITY_FIX_CASE handling in fetchColumn() since this can be handled by PDO internally
parent 2933cd2d
<?php <?php
/* /*
* $Id$ * $Id$
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* *
* This software consists of voluntary contributions made by many individuals * This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see * and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.com>. * <http://www.phpdoctrine.com>.
*/ */
/** /**
* 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>
* @author Lukas Smith <smith@pooteeweet.org> (MDB2 library) * @author Lukas Smith <smith@pooteeweet.org> (MDB2 library)
*/ */
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
*/ */
protected $dbh; protected $dbh;
/** /**
* @var array $tables an array containing all the initialized Doctrine_Table objects * @var array $tables an array containing all the initialized Doctrine_Table objects
* keys representing Doctrine_Table component names and values as Doctrine_Table objects * keys representing Doctrine_Table component names and values as Doctrine_Table objects
*/ */
protected $tables = array(); protected $tables = array();
/** /**
* @var string $driverName the name of this connection driver * @var string $driverName the name of this connection driver
*/ */
protected $driverName; protected $driverName;
/** /**
* @var array $supported an array containing all features this driver supports, * @var array $supported an array containing all features this driver supports,
* keys representing feature names and values as * keys representing feature names and values as
* one of the following (true, false, 'emulated') * one of the following (true, false, 'emulated')
*/ */
protected $supported = array(); protected $supported = array();
/** /**
* @var array $modules an array containing all modules * @var array $modules an array containing all modules
* transaction Doctrine_Transaction driver, handles savepoint and transaction isolation abstraction * transaction Doctrine_Transaction driver, handles savepoint and transaction isolation abstraction
* *
* expression Doctrine_Expression driver, handles expression abstraction * expression Doctrine_Expression driver, handles expression abstraction
* *
* dataDict Doctrine_DataDict driver, handles datatype abstraction * dataDict Doctrine_DataDict driver, handles datatype abstraction
* *
* export Doctrine_Export driver, handles db structure modification abstraction (contains * export Doctrine_Export driver, handles db structure modification abstraction (contains
* methods such as alterTable, createConstraint etc.) * methods such as alterTable, createConstraint etc.)
* *
* @see Doctrine_Connection::__get() * @see Doctrine_Connection::__get()
* @see Doctrine_DataDict * @see Doctrine_DataDict
* @see Doctrine_Expression * @see Doctrine_Expression
* @see Doctrine_Export * @see Doctrine_Export
* @see Doctrine_Transaction * @see Doctrine_Transaction
*/ */
private $modules = array('transaction' => false, private $modules = array('transaction' => false,
'expression' => false, 'expression' => false,
'dataDict' => false, 'dataDict' => false,
'export' => false, 'export' => false,
'unitOfWork' => false, 'unitOfWork' => false,
); );
/** /**
* @var array $properties an array of connection properties * @var array $properties an array of connection properties
*/ */
protected $properties = array('sql_comments' => array(array('start' => '--', 'end' => "\n", 'escape' => false), protected $properties = array('sql_comments' => array(array('start' => '--', 'end' => "\n", 'escape' => false),
array('start' => '/*', 'end' => '*/', 'escape' => false) array('start' => '/*', 'end' => '*/', 'escape' => false)
), ),
'identifier_quoting' => array('start' => '"', 'identifier_quoting' => array('start' => '"',
'end' => '"', 'end' => '"',
'escape' => '"' 'escape' => '"'
), ),
'string_quoting' => array('start' => "'", 'string_quoting' => array('start' => "'",
'end' => "'", 'end' => "'",
'escape' => false, 'escape' => false,
'escape_pattern' => false 'escape_pattern' => false
), ),
'wildcards' => array('%', '_') 'wildcards' => array('%', '_')
); );
/** /**
* @var array $availibleDrivers an array containing all availible drivers * @var array $availibleDrivers an array containing all availible drivers
*/ */
private static $availibleDrivers = array( private static $availibleDrivers = array(
'Mysql', 'Mysql',
'Pgsql', 'Pgsql',
'Oracle', 'Oracle',
'Informix', 'Informix',
'Mssql', 'Mssql',
'Sqlite', 'Sqlite',
'Firebird' 'Firebird'
); );
/** /**
* the constructor * the constructor
* *
* @param Doctrine_Manager $manager the manager object * @param Doctrine_Manager $manager the manager object
* @param PDO|Doctrine_Adapter_Interface $adapter database driver * @param PDO|Doctrine_Adapter_Interface $adapter database driver
*/ */
public function __construct(Doctrine_Manager $manager, $adapter) public function __construct(Doctrine_Manager $manager, $adapter)
{ {
if ( ! ($adapter instanceof PDO) && ! in_array('Doctrine_Adapter_Interface', class_implements($adapter))) { if ( ! ($adapter instanceof PDO) && ! in_array('Doctrine_Adapter_Interface', class_implements($adapter))) {
throw new Doctrine_Connection_Exception("First argument should be an instance of PDO or implement Doctrine_Adapter_Interface"); throw new Doctrine_Connection_Exception("First argument should be an instance of PDO or implement Doctrine_Adapter_Interface");
} }
$this->dbh = $adapter; $this->dbh = $adapter;
//$this->modules['transaction'] = new Doctrine_Connection_Transaction($this); //$this->modules['transaction'] = new Doctrine_Connection_Transaction($this);
$this->modules['unitOfWork'] = new Doctrine_Connection_UnitOfWork($this); $this->modules['unitOfWork'] = new Doctrine_Connection_UnitOfWork($this);
$this->setParent($manager); $this->setParent($manager);
$this->dbh->setAttribute(PDO::ATTR_CASE, PDO::CASE_NATURAL); $this->dbh->setAttribute(PDO::ATTR_CASE, PDO::CASE_NATURAL);
$this->dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $this->dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->getAttribute(Doctrine::ATTR_LISTENER)->onOpen($this); $this->getAttribute(Doctrine::ATTR_LISTENER)->onOpen($this);
} }
/** /**
* getName * getName
* returns the name of this driver * returns the name of this driver
* *
* @return string the name of this driver * @return string the name of this driver
*/ */
public function getName() public function getName()
{ {
return $this->driverName; return $this->driverName;
} }
/** /**
* __get * __get
* lazy loads given module and returns it * lazy loads given module and returns it
* *
* @see Doctrine_DataDict * @see Doctrine_DataDict
* @see Doctrine_Expression * @see Doctrine_Expression
* @see Doctrine_Export * @see Doctrine_Export
* @see Doctrine_Transaction * @see Doctrine_Transaction
* @see Doctrine_Connection::$modules all availible modules * @see Doctrine_Connection::$modules all availible modules
* @param string $name the name of the module to get * @param string $name the name of the module to get
* @throws Doctrine_Connection_Exception if trying to get an unknown module * @throws Doctrine_Connection_Exception if trying to get an unknown module
* @return Doctrine_Connection_Module connection module * @return Doctrine_Connection_Module connection module
*/ */
public function __get($name) public function __get($name)
{ {
if (isset($this->properties[$name])) if (isset($this->properties[$name]))
return $this->properties[$name]; return $this->properties[$name];
if ( ! isset($this->modules[$name])) { if ( ! isset($this->modules[$name])) {
throw new Doctrine_Connection_Exception('Unknown module / property ' . $name); throw new Doctrine_Connection_Exception('Unknown module / property ' . $name);
} }
if ($this->modules[$name] === false) { if ($this->modules[$name] === false) {
switch ($name) { switch ($name) {
case 'unitOfWork': case 'unitOfWork':
$this->modules[$name] = new Doctrine_Connection_UnitOfWork($this); $this->modules[$name] = new Doctrine_Connection_UnitOfWork($this);
break; break;
default: default:
$class = 'Doctrine_' . ucwords($name) . '_' . $this->getName(); $class = 'Doctrine_' . ucwords($name) . '_' . $this->getName();
$this->modules[$name] = new $class($this); $this->modules[$name] = new $class($this);
} }
} }
return $this->modules[$name]; return $this->modules[$name];
} }
/** /**
* Quotes pattern (% and _) characters in a string) * Quotes pattern (% and _) characters in a string)
* *
* EXPERIMENTAL * EXPERIMENTAL
* *
* WARNING: this function is experimental and may change signature at * WARNING: this function is experimental and may change signature at
* any time until labelled as non-experimental * any time until labelled as non-experimental
* *
* @param string the input string to quote * @param string the input string to quote
* *
* @return string quoted string * @return string quoted string
*/ */
public function escapePattern($text) public function escapePattern($text)
{ {
if ($this->string_quoting['escape_pattern']) { if ($this->string_quoting['escape_pattern']) {
$text = str_replace($this->string_quoting['escape_pattern'], $this->string_quoting['escape_pattern'] . $this->string_quoting['escape_pattern'], $text); $text = str_replace($this->string_quoting['escape_pattern'], $this->string_quoting['escape_pattern'] . $this->string_quoting['escape_pattern'], $text);
foreach ($this->wildcards as $wildcard) { foreach ($this->wildcards as $wildcard) {
$text = str_replace($wildcard, $this->string_quoting['escape_pattern'] . $wildcard, $text); $text = str_replace($wildcard, $this->string_quoting['escape_pattern'] . $wildcard, $text);
} }
} }
return $text; return $text;
} }
/** /**
* Quote a string so it can be safely used as a table or column name * Quote a string so it can be safely used as a table or column name
* *
* Delimiting style depends on which database driver is being used. * Delimiting style depends on which database driver is being used.
* *
* NOTE: just because you CAN use delimited identifiers doesn't mean * NOTE: just because you CAN use delimited identifiers doesn't mean
* you SHOULD use them. In general, they end up causing way more * you SHOULD use them. In general, they end up causing way more
* problems than they solve. * problems than they solve.
* *
* Portability is broken by using the following characters inside * Portability is broken by using the following characters inside
* delimited identifiers: * delimited identifiers:
* + backtick (<kbd>`</kbd>) -- due to MySQL * + backtick (<kbd>`</kbd>) -- due to MySQL
* + double quote (<kbd>"</kbd>) -- due to Oracle * + double quote (<kbd>"</kbd>) -- due to Oracle
* + brackets (<kbd>[</kbd> or <kbd>]</kbd>) -- due to Access * + brackets (<kbd>[</kbd> or <kbd>]</kbd>) -- due to Access
* *
* Delimited identifiers are known to generally work correctly under * Delimited identifiers are known to generally work correctly under
* the following drivers: * the following drivers:
* + mssql * + mssql
* + mysql * + mysql
* + mysqli * + mysqli
* + oci8 * + oci8
* + pgsql * + pgsql
* + sqlite * + sqlite
* *
* InterBase doesn't seem to be able to use delimited identifiers * InterBase doesn't seem to be able to use delimited identifiers
* via PHP 4. They work fine under PHP 5. * via PHP 4. They work fine under PHP 5.
* *
* @param string $str identifier name to be quoted * @param string $str identifier name to be quoted
* @param bool $checkOption check the 'quote_identifier' option * @param bool $checkOption check the 'quote_identifier' option
* *
* @return string quoted identifier string * @return string quoted identifier string
*/ */
public function quoteIdentifier($str, $checkOption = true) public function quoteIdentifier($str, $checkOption = true)
{ {
if ($checkOption && ! $this->getAttribute(Doctrine::ATTR_QUOTE_IDENTIFIER)) { if ($checkOption && ! $this->getAttribute(Doctrine::ATTR_QUOTE_IDENTIFIER)) {
return $str; return $str;
} }
$str = str_replace($this->properties['identifier_quoting']['end'], $str = str_replace($this->properties['identifier_quoting']['end'],
$this->properties['identifier_quoting']['escape'] . $this->properties['identifier_quoting']['escape'] .
$this->properties['identifier_quoting']['end'], $str); $this->properties['identifier_quoting']['end'], $str);
return $this->properties['identifier_quoting']['start'] return $this->properties['identifier_quoting']['start']
. $str . $this->properties['identifier_quoting']['end']; . $str . $this->properties['identifier_quoting']['end'];
} }
/** /**
* returns the manager that created this connection * returns the manager that created this connection
* *
* @return Doctrine_Manager * @return Doctrine_Manager
*/ */
public function getManager() public function getManager()
{ {
return $this->getParent(); return $this->getParent();
} }
/** /**
* returns the database handler of which this connection uses * returns the database handler of which this connection uses
* *
* @return PDO the database handler * @return PDO the database handler
*/ */
public function getDbh() public function getDbh()
{ {
return $this->dbh; return $this->dbh;
} }
/** /**
* converts given driver name * converts given driver name
* *
* @param * @param
*/ */
public function driverName($name) public function driverName($name)
{ {
} }
/** /**
* supports * supports
* *
* @param string $feature the name of the feature * @param string $feature the name of the feature
* @return boolean whether or not this drivers supports given feature * @return boolean whether or not this drivers supports given feature
*/ */
public function supports($feature) public function supports($feature)
{ {
return (isset($this->supported[$feature]) return (isset($this->supported[$feature])
&& ($this->supported[$feature] === 'emulated' && ($this->supported[$feature] === 'emulated'
|| $this->supported[$feature] || $this->supported[$feature]
) )
); );
} }
/** /**
* quote * quote
* quotes given input parameter * quotes given input parameter
* *
* @param mixed $input parameter to be quoted * @param mixed $input parameter to be quoted
* @param string $type * @param string $type
* @return mixed * @return mixed
*/ */
public function quote($input, $type = null) public function quote($input, $type = null)
{ {
if ($type == null) { if ($type == null) {
$type = gettype($input); $type = gettype($input);
} }
switch ($type) { switch ($type) {
case 'integer': case 'integer':
case 'enum': case 'enum':
case 'boolean': case 'boolean':
return $input; return $input;
case 'array': case 'array':
case 'object': case 'object':
$input = serialize($input); $input = serialize($input);
case 'string': case 'string':
case 'char': case 'char':
case 'varchar': case 'varchar':
case 'text': case 'text':
case 'gzip': case 'gzip':
case 'blob': case 'blob':
case 'clob': case 'clob':
return $this->dbh->quote($input); return $this->dbh->quote($input);
} }
} }
/** /**
* Removes any formatting in an sequence name using the 'seqname_format' option * Removes any formatting in an sequence name using the 'seqname_format' option
* *
* @param string $sqn string that containts name of a potential sequence * @param string $sqn string that containts name of a potential sequence
* @return string name of the sequence with possible formatting removed * @return string name of the sequence with possible formatting removed
*/ */
public function fixSequenceName($sqn) public function fixSequenceName($sqn)
{ {
$seqPattern = '/^'.preg_replace('/%s/', '([a-z0-9_]+)', $this->getAttribute(Doctrine::ATTR_SEQNAME_FORMAT)).'$/i'; $seqPattern = '/^'.preg_replace('/%s/', '([a-z0-9_]+)', $this->getAttribute(Doctrine::ATTR_SEQNAME_FORMAT)).'$/i';
$seqName = preg_replace($seqPattern, '\\1', $sqn); $seqName = preg_replace($seqPattern, '\\1', $sqn);
if ($seqName && ! strcasecmp($sqn, $this->getSequenceName($seqName))) { if ($seqName && ! strcasecmp($sqn, $this->getSequenceName($seqName))) {
return $seqName; return $seqName;
} }
return $sqn; return $sqn;
} }
/** /**
* Removes any formatting in an index name using the 'idxname_format' option * Removes any formatting in an index name using the 'idxname_format' option
* *
* @param string $idx string that containts name of anl index * @param string $idx string that containts name of anl index
* @return string name of the index with possible formatting removed * @return string name of the index with possible formatting removed
*/ */
public function fixIndexName($idx) public function fixIndexName($idx)
{ {
$indexPattern = '/^'.preg_replace('/%s/', '([a-z0-9_]+)', $this->getAttribute(Doctrine::ATTR_IDXNAME_FORMAT)).'$/i'; $indexPattern = '/^'.preg_replace('/%s/', '([a-z0-9_]+)', $this->getAttribute(Doctrine::ATTR_IDXNAME_FORMAT)).'$/i';
$indexName = preg_replace($indexPattern, '\\1', $idx); $indexName = preg_replace($indexPattern, '\\1', $idx);
if ($indexName && ! strcasecmp($idx, $this->getIndexName($indexName))) { if ($indexName && ! strcasecmp($idx, $this->getIndexName($indexName))) {
return $indexName; return $indexName;
} }
return $idx; return $idx;
} }
/** /**
* adds sequence name formatting to a sequence name * adds sequence name formatting to a sequence name
* *
* @param string name of the sequence * @param string name of the sequence
* @return string formatted sequence name * @return string formatted sequence name
*/ */
public function getSequenceName($sqn) public function getSequenceName($sqn)
{ {
return sprintf($this->getAttribute(Doctrine::ATTR_SEQNAME_FORMAT), return sprintf($this->getAttribute(Doctrine::ATTR_SEQNAME_FORMAT),
preg_replace('/[^a-z0-9_\$.]/i', '_', $sqn)); preg_replace('/[^a-z0-9_\$.]/i', '_', $sqn));
} }
/** /**
* adds index name formatting to a index name * adds index name formatting to a index name
* *
* @param string name of the index * @param string name of the index
* @return string formatted index name * @return string formatted index name
*/ */
public function getIndexName($idx) public function getIndexName($idx)
{ {
return sprintf($this->getAttribute(Doctrine::ATTR_IDXNAME_FORMAT), return sprintf($this->getAttribute(Doctrine::ATTR_IDXNAME_FORMAT),
preg_replace('/[^a-z0-9_\$]/i', '_', $idx)); preg_replace('/[^a-z0-9_\$]/i', '_', $idx));
} }
/** /**
* Execute a SQL REPLACE query. A REPLACE query is identical to a INSERT * Execute a SQL REPLACE query. A REPLACE query is identical to a INSERT
* query, except that if there is already a row in the table with the same * query, except that if there is already a row in the table with the same
* key field values, the REPLACE query just updates its values instead of * key field values, the REPLACE query just updates its values instead of
* inserting a new row. * inserting a new row.
* *
* The REPLACE type of query does not make part of the SQL standards. Since * The REPLACE type of query does not make part of the SQL standards. Since
* practically only MySQL and SQLIte implement it natively, this type of * practically only MySQL and SQLIte implement it natively, this type of
* query isemulated through this method for other DBMS using standard types * query isemulated through this method for other DBMS using standard types
* of queries inside a transaction to assure the atomicity of the operation. * of queries inside a transaction to assure the atomicity of the operation.
* *
* @param string name of the table on which the REPLACE query will * @param string name of the table on which the REPLACE query will
* be executed. * be executed.
* *
* @param array an associative array that describes the fields and the * @param array an associative array that describes the fields and the
* values that will be inserted or updated in the specified table. The * values that will be inserted or updated in the specified table. The
* indexes of the array are the names of all the fields of the table. * indexes of the array are the names of all the fields of the table.
* *
* The values of the array are values to be assigned to the specified field. * The values of the array are values to be assigned to the specified field.
* *
* @param array $keys an array containing all key fields (primary key fields * @param array $keys an array containing all key fields (primary key fields
* or unique index fields) for this table * or unique index fields) for this table
* *
* the uniqueness of a row will be determined according to * the uniqueness of a row will be determined according to
* the provided key fields * the provided key fields
* *
* this method will fail if no key fields are specified * this method will fail if no key fields are specified
* *
* @throws Doctrine_Connection_Exception if this driver doesn't support replace * @throws Doctrine_Connection_Exception if this driver doesn't support replace
* @throws Doctrine_Connection_Exception if some of the key values was null * @throws Doctrine_Connection_Exception if some of the key values was null
* @throws Doctrine_Connection_Exception if there were no key fields * @throws Doctrine_Connection_Exception if there were no key fields
* @throws PDOException if something fails at PDO level * @throws PDOException if something fails at PDO level
* @return integer number of rows affected * @return integer number of rows affected
*/ */
public function replace($table, array $fields, array $keys) public function replace($table, array $fields, array $keys)
{ {
//if ( ! $this->supports('replace')) //if ( ! $this->supports('replace'))
// throw new Doctrine_Connection_Exception('replace query is not supported'); // throw new Doctrine_Connection_Exception('replace query is not supported');
if (empty($keys)) { if (empty($keys)) {
throw new Doctrine_Connection_Exception('Not specified which fields are keys'); throw new Doctrine_Connection_Exception('Not specified which fields are keys');
} }
$condition = $values = array(); $condition = $values = array();
foreach ($fields as $name => $value) { foreach ($fields as $name => $value) {
$values[$name] = $value; $values[$name] = $value;
if (in_array($name, $keys)) { if (in_array($name, $keys)) {
if ($value === null) if ($value === null)
throw new Doctrine_Connection_Exception('key value '.$name.' may not be null'); throw new Doctrine_Connection_Exception('key value '.$name.' may not be null');
$condition[] = $name . ' = ?'; $condition[] = $name . ' = ?';
$conditionValues[] = $value; $conditionValues[] = $value;
} }
} }
$query = 'DELETE FROM '. $table . ' WHERE ' . implode(' AND ', $condition); $query = 'DELETE FROM '. $table . ' WHERE ' . implode(' AND ', $condition);
$affectedRows = $this->exec($query); $affectedRows = $this->exec($query);
$this->insert($table, $values); $this->insert($table, $values);
$affectedRows++; $affectedRows++;
return $affectedRows; return $affectedRows;
} }
/** /**
* Inserts a table row with specified data. * Inserts a table row with specified data.
* *
* @param string $table The table to insert data into. * @param string $table The table to insert data into.
* @param array $values An associateve array containing column-value pairs. * @param array $values An associateve array containing column-value pairs.
* @return boolean * @return boolean
*/ */
public function insert($table, array $values = array()) { public function insert($table, array $values = array()) {
if (empty($values)) { if (empty($values)) {
return false; return false;
} }
// column names are specified as array keys // column names are specified as array keys
$cols = array_keys($values); $cols = array_keys($values);
// build the statement // build the statement
$query = "INSERT INTO $table " $query = "INSERT INTO $table "
. '(' . implode(', ', $cols) . ') ' . '(' . implode(', ', $cols) . ') '
. 'VALUES (' . substr(str_repeat('?, ', count($values)), 0, -2) . ')'; . 'VALUES (' . substr(str_repeat('?, ', count($values)), 0, -2) . ')';
// prepare and execute the statement // prepare and execute the statement
$stmt = $this->dbh->prepare($query); $stmt = $this->dbh->prepare($query);
$stmt->execute(array_values($values)); $stmt->execute(array_values($values));
return true; return true;
} }
/** /**
* returns the next value in the given sequence * returns the next value in the given sequence
* *
* @param string $sequence * @param string $sequence
* @throws PDOException if something went wrong at database level * @throws PDOException if something went wrong at database level
* @return integer * @return integer
*/ */
public function nextId($sequence) public function nextId($sequence)
{ {
throw new Doctrine_Connection_Exception('NextId() for sequences not supported by this driver.'); throw new Doctrine_Connection_Exception('NextId() for sequences not supported by this driver.');
} }
/** /**
* Set the charset on the current connection * Set the charset on the current connection
* *
* @param string charset * @param string charset
* *
* @return void * @return void
*/ */
public function setCharset($charset) public function setCharset($charset)
{ {
} }
/** /**
* fetchAll * fetchAll
* *
* @param string $statement sql query to be executed * @param string $statement sql query to be executed
* @param array $params prepared statement params * @param array $params prepared statement params
* @return array * @return array
*/ */
public function fetchAll($statement, array $params = array()) { public function fetchAll($statement, array $params = array()) {
return $this->query($statement, $params)->fetchAll(PDO::FETCH_ASSOC); return $this->query($statement, $params)->fetchAll(PDO::FETCH_ASSOC);
} }
/** /**
* fetchOne * fetchOne
* *
* @param string $statement sql query to be executed * @param string $statement sql query to be executed
* @param array $params prepared statement params * @param array $params prepared statement params
* @return mixed * @param int $colnum 0-indexed column number to retrieve
*/ * @return mixed
public function fetchOne($statement, array $params = array()) { */
return current($this->execute($statement, $params)->fetch(PDO::FETCH_NUM)); public function fetchOne($statement, array $params = array(), $colnum = 0) {
} return $this->execute($statement, $params)->fetchColumn($colnum);
/** }
* fetchRow /**
* * fetchRow
* @param string $statement sql query to be executed *
* @param array $params prepared statement params * @param string $statement sql query to be executed
* @return array * @param array $params prepared statement params
*/ * @return array
public function fetchRow($statement, array $params = array()) { */
return $this->query($statement, $params)->fetch(PDO::FETCH_ASSOC); public function fetchRow($statement, array $params = array()) {
} return $this->query($statement, $params)->fetch(PDO::FETCH_ASSOC);
/** }
* fetchArray /**
* * fetchArray
* @param string $statement sql query to be executed *
* @param array $params prepared statement params * @param string $statement sql query to be executed
* @return array * @param array $params prepared statement params
*/ * @return array
public function fetchArray($statement, array $params = array()) { */
return $this->query($statement, $params)->fetch(PDO::FETCH_NUM); public function fetchArray($statement, array $params = array()) {
} return $this->query($statement, $params)->fetch(PDO::FETCH_NUM);
/** }
* fetchColumn /**
* * fetchColumn
* @param string $statement sql query to be executed *
* @param array $params prepared statement params * @param string $statement sql query to be executed
* @return array * @param array $params prepared statement params
*/ * @param int $colnum 0-indexed column number to retrieve
public function fetchColumn($statement, array $params = array()) { * @return array
$result = $this->query($statement, $params)->fetchAll(PDO::FETCH_COLUMN); */
public function fetchColumn($statement, array $params = array(), $colnum = 0) {
if ($this->options['portability'] & Doctrine::PORTABILITY_FIX_CASE) { return $this->query($statement, $params)->fetchAll(PDO::FETCH_COLUMN, $colnum);
$result = array_map(($this->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); }
} /**
return $result; * fetchAssoc
} *
/** * @param string $statement sql query to be executed
* fetchAssoc * @param array $params prepared statement params
* * @return array
* @param string $statement sql query to be executed */
* @param array $params prepared statement params public function fetchAssoc($statement, array $params = array()) {
* @return array return $this->query($statement, $params)->fetchAll(PDO::FETCH_ASSOC);
*/ }
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
* fetchBoth * @param array $params prepared statement params
* * @return array
* @param string $statement sql query to be executed */
* @param array $params prepared statement params public function fetchBoth($statement, array $params = array()) {
* @return array return $this->query($statement, $params)->fetchAll(PDO::FETCH_BOTH);
*/ }
public function fetchBoth($statement, array $params = array()) { /**
return $this->query($statement, $params)->fetchAll(PDO::FETCH_BOTH); * query
} * queries the database using Doctrine Query Language
/** * returns a collection of Doctrine_Record objects
* query *
* queries the database using Doctrine Query Language * <code>
* returns a collection of Doctrine_Record objects * $users = $conn->query('SELECT u.* FROM User u');
* *
* <code> * $users = $conn->query('SELECT u.* FROM User u WHERE u.name LIKE ?', array('someone'));
* $users = $conn->query('SELECT u.* FROM User u'); * </code>
* *
* $users = $conn->query('SELECT u.* FROM User u WHERE u.name LIKE ?', array('someone')); * @param string $query DQL query
* </code> * @param array $params query parameters
* * @see Doctrine_Query
* @param string $query DQL query * @return Doctrine_Collection Collection of Doctrine_Record objects
* @param array $params query parameters */
* @see Doctrine_Query public function query($query, array $params = array()) {
* @return Doctrine_Collection Collection of Doctrine_Record objects $parser = new Doctrine_Query($this);
*/
public function query($query, array $params = array()) { return $parser->query($query, $params);
$parser = new Doctrine_Query($this); }
/**
return $parser->query($query, $params); * query
} * queries the database using Doctrine Query Language and returns
/** * the first record found
* query *
* queries the database using Doctrine Query Language and returns * <code>
* the first record found * $user = $conn->queryOne('SELECT u.* FROM User u WHERE u.id = ?', array(1));
* *
* <code> * $user = $conn->queryOne('SELECT u.* FROM User u WHERE u.name LIKE ? AND u.password = ?',
* $user = $conn->queryOne('SELECT u.* FROM User u WHERE u.id = ?', array(1)); * array('someone', 'password')
* * );
* $user = $conn->queryOne('SELECT u.* FROM User u WHERE u.name LIKE ? AND u.password = ?', * </code>
* array('someone', 'password') *
* ); * @param string $query DQL query
* </code> * @param array $params query parameters
* * @see Doctrine_Query
* @param string $query DQL query * @return Doctrine_Record|false Doctrine_Record object on success,
* @param array $params query parameters * boolean false on failure
* @see Doctrine_Query */
* @return Doctrine_Record|false Doctrine_Record object on success, public function queryOne($query, array $params = array()) {
* boolean false on failure $parser = new Doctrine_Query($this);
*/
public function queryOne($query, array $params = array()) { $coll = $parser->query($query, $params);
$parser = new Doctrine_Query($this); if ( ! $coll->contains(0)) {
return false;
$coll = $parser->query($query, $params); }
if ( ! $coll->contains(0)) { return $coll[0];
return false; }
} /**
return $coll[0]; * queries the database with limit and offset
} * added to the query and returns a PDOStatement object
/** *
* queries the database with limit and offset * @param string $query
* added to the query and returns a PDOStatement object * @param integer $limit
* * @param integer $offset
* @param string $query * @return PDOStatement
* @param integer $limit */
* @param integer $offset public function select($query,$limit = 0,$offset = 0)
* @return PDOStatement {
*/ if ($limit > 0 || $offset > 0) {
public function select($query,$limit = 0,$offset = 0) $query = $this->modifyLimitQuery($query, $limit, $offset);
{ }
if ($limit > 0 || $offset > 0) { return $this->dbh->query($query);
$query = $this->modifyLimitQuery($query, $limit, $offset); }
} /**
return $this->dbh->query($query); * execute
} * @param string $query sql query
/** * @param array $params query parameters
* execute *
* @param string $query sql query * @return PDOStatement|Doctrine_Adapter_Statement
* @param array $params query parameters */
* public function execute($query, array $params = array()) {
* @return PDOStatement|Doctrine_Adapter_Statement try {
*/ if ( ! empty($params)) {
public function execute($query, array $params = array()) { $stmt = $this->dbh->prepare($query);
try { $stmt->execute($params);
if ( ! empty($params)) { return $stmt;
$stmt = $this->dbh->prepare($query); } else {
$stmt->execute($params); return $this->dbh->query($query);
return $stmt; }
} else { } catch(Doctrine_Adapter_Exception $e) {
return $this->dbh->query($query); } catch(PDOException $e) { }
}
} catch(Doctrine_Adapter_Exception $e) { $this->rethrowException($e);
} catch(PDOException $e) { } }
/**
$this->rethrowException($e); * exec
} * @param string $query sql query
/** * @param array $params query parameters
* exec *
* @param string $query sql query * @return PDOStatement|Doctrine_Adapter_Statement
* @param array $params query parameters */
* public function exec($query, array $params = array()) {
* @return PDOStatement|Doctrine_Adapter_Statement try {
*/ if ( ! empty($params)) {
public function exec($query, array $params = array()) { $stmt = $this->dbh->prepare($query);
try { $stmt->execute($params);
if ( ! empty($params)) { return $stmt;
$stmt = $this->dbh->prepare($query); } else {
$stmt->execute($params); return $this->dbh->exec($query);
return $stmt; }
} else { } catch(Doctrine_Adapter_Exception $e) {
return $this->dbh->exec($query); } catch(PDOException $e) { }
}
} catch(Doctrine_Adapter_Exception $e) { $this->rethrowException($e);
} catch(PDOException $e) { } }
/**
$this->rethrowException($e); * rethrowException
} *
/** * @throws Doctrine_Connection_Exception
* rethrowException */
* private function rethrowException(Exception $e)
* @throws Doctrine_Connection_Exception {
*/ $name = 'Doctrine_Connection_' . $this->driverName . '_Exception';
private function rethrowException(Exception $e)
{ $exc = new $name($e->getMessage(), (int) $e->getCode());
$name = 'Doctrine_Connection_' . $this->driverName . '_Exception'; if ( ! is_array($e->errorInfo)) {
$e->errorInfo = array(null, null, null, null);
$exc = new $name($e->getMessage(), (int) $e->getCode()); }
if ( ! is_array($e->errorInfo)) { $exc->processErrorInfo($e->errorInfo);
$e->errorInfo = array(null, null, null, null);
} throw $exc;
$exc->processErrorInfo($e->errorInfo); }
/**
throw $exc; * hasTable
} * whether or not this connection has table $name initialized
/** *
* hasTable * @param mixed $name
* whether or not this connection has table $name initialized * @return boolean
* */
* @param mixed $name public function hasTable($name)
* @return boolean {
*/ return isset($this->tables[$name]);
public function hasTable($name) }
{ /**
return isset($this->tables[$name]); * returns a table object for given component name
} *
/** * @param string $name component name
* returns a table object for given component name * @return object Doctrine_Table
* */
* @param string $name component name public function getTable($name)
* @return object Doctrine_Table {
*/ if (isset($this->tables[$name])) {
public function getTable($name) return $this->tables[$name];
{ }
if (isset($this->tables[$name])) { $class = $name."Table";
return $this->tables[$name];
} if (class_exists($class) && in_array("Doctrine_Table", class_parents($class))) {
$class = $name."Table"; return new $class($name, $this);
} else {
if (class_exists($class) && in_array("Doctrine_Table", class_parents($class))) { return new Doctrine_Table($name, $this);
return new $class($name, $this); }
} else { }
return new Doctrine_Table($name, $this); /**
} * returns an array of all initialized tables
} *
/** * @return array
* returns an array of all initialized tables */
* public function getTables()
* @return array {
*/ return $this->tables;
public function getTables() }
{ /**
return $this->tables; * returns an iterator that iterators through all
} * initialized table objects
/** *
* returns an iterator that iterators through all * <code>
* initialized table objects * foreach ($conn as $index => $table) {
* * print $table; // get a string representation of each table object
* <code> * }
* foreach ($conn as $index => $table) { * </code>
* print $table; // get a string representation of each table object *
* } * @return ArrayIterator SPL ArrayIterator object
* </code> */
* public function getIterator()
* @return ArrayIterator SPL ArrayIterator object {
*/ return new ArrayIterator($this->tables);
public function getIterator() }
{ /**
return new ArrayIterator($this->tables); * returns the count of initialized table objects
} *
/** * @return integer
* returns the count of initialized table objects */
* public function count()
* @return integer {
*/ return count($this->tables);
public function count() }
{ /**
return count($this->tables); * addTable
} * adds a Doctrine_Table object into connection registry
/** *
* addTable * @param $objTable a Doctrine_Table object to be added into registry
* adds a Doctrine_Table object into connection registry * @return boolean
* */
* @param $objTable a Doctrine_Table object to be added into registry public function addTable(Doctrine_Table $objTable)
* @return boolean {
*/ $name = $objTable->getComponentName();
public function addTable(Doctrine_Table $objTable)
{ if (isset($this->tables[$name])) {
$name = $objTable->getComponentName(); return false;
}
if (isset($this->tables[$name])) { $this->tables[$name] = $objTable;
return false; return true;
} }
$this->tables[$name] = $objTable; /**
return true; * create
} * creates a record
/** *
* create * create creates a record
* creates a record * @param string $name component name
* * @return Doctrine_Record Doctrine_Record object
* create creates a record */
* @param string $name component name public function create($name)
* @return Doctrine_Record Doctrine_Record object {
*/ return $this->getTable($name)->create();
public function create($name) }
{ /**
return $this->getTable($name)->create(); * flush
} * saves all the records from all tables
/** * this operation is isolated using a transaction
* flush *
* saves all the records from all tables * @throws PDOException if something went wrong at database level
* this operation is isolated using a transaction * @return void
* */
* @throws PDOException if something went wrong at database level public function flush()
* @return void {
*/ $this->beginTransaction();
public function flush() $this->unitOfWork->saveAll();
{ $this->commit();
$this->beginTransaction(); }
$this->unitOfWork->saveAll(); /**
$this->commit(); * clear
} * clears all repositories
/** *
* clear * @return void
* clears all repositories */
* public function clear()
* @return void {
*/ foreach ($this->tables as $k => $table) {
public function clear() $table->getRepository()->evictAll();
{ $table->clear();
foreach ($this->tables as $k => $table) { }
$table->getRepository()->evictAll(); }
$table->clear(); /**
} * evictTables
} * evicts all tables
/** *
* evictTables * @return void
* evicts all tables */
* public function evictTables()
* @return void {
*/ $this->tables = array();
public function evictTables() }
{ /**
$this->tables = array(); * close
} * closes the connection
/** *
* close * @return void
* closes the connection */
* public function close()
* @return void {
*/ $this->getAttribute(Doctrine::ATTR_LISTENER)->onPreClose($this);
public function close()
{ $this->clear();
$this->getAttribute(Doctrine::ATTR_LISTENER)->onPreClose($this);
$this->getAttribute(Doctrine::ATTR_LISTENER)->onClose($this);
$this->clear(); }
/**
$this->getAttribute(Doctrine::ATTR_LISTENER)->onClose($this); * get the current transaction nesting level
} *
/** * @return integer
* get the current transaction nesting level */
* public function getTransactionLevel()
* @return integer {
*/ return $this->transaction->getTransactionLevel();
public function getTransactionLevel() }
{ /**
return $this->transaction->getTransactionLevel(); * beginTransaction
} * starts a new transaction
/** *
* beginTransaction * this method can be listened by onPreBeginTransaction and onBeginTransaction
* starts a new transaction * listener methods
* *
* this method can be listened by onPreBeginTransaction and onBeginTransaction * @return void
* listener methods */
* public function beginTransaction()
* @return void {
*/ $this->transaction->beginTransaction();
public function beginTransaction() }
{ /**
$this->transaction->beginTransaction(); * commits the current transaction
} * if lockmode is optimistic this method starts a transaction
/** * and commits it instantly
* commits the current transaction *
* if lockmode is optimistic this method starts a transaction * @return void
* and commits it instantly */
* public function commit()
* @return void {
*/ $this->transaction->commit();
public function commit() }
{ /**
$this->transaction->commit(); * rollback
} * rolls back all transactions
/** *
* rollback * this method also listens to onPreTransactionRollback and onTransactionRollback
* rolls back all transactions * eventlisteners
* *
* this method also listens to onPreTransactionRollback and onTransactionRollback * @return void
* eventlisteners */
* public function rollback()
* @return void {
*/ $this->transaction->rollback();
public function rollback() }
{ /**
$this->transaction->rollback(); * saves the given record
} *
/** * @param Doctrine_Record $record
* saves the given record * @return void
* */
* @param Doctrine_Record $record public function save(Doctrine_Record $record)
* @return void {
*/ $record->getTable()->getAttribute(Doctrine::ATTR_LISTENER)->onPreSave($record);
public function save(Doctrine_Record $record)
{ switch ($record->getState()) {
$record->getTable()->getAttribute(Doctrine::ATTR_LISTENER)->onPreSave($record); case Doctrine_Record::STATE_TDIRTY:
$this->unitOfWork->insert($record);
switch ($record->getState()) { break;
case Doctrine_Record::STATE_TDIRTY: case Doctrine_Record::STATE_DIRTY:
$this->unitOfWork->insert($record); case Doctrine_Record::STATE_PROXY:
break; $this->unitOfWork->update($record);
case Doctrine_Record::STATE_DIRTY: break;
case Doctrine_Record::STATE_PROXY: case Doctrine_Record::STATE_CLEAN:
$this->unitOfWork->update($record); case Doctrine_Record::STATE_TCLEAN:
break; // do nothing
case Doctrine_Record::STATE_CLEAN: break;
case Doctrine_Record::STATE_TCLEAN: };
// do nothing
break; $record->getTable()->getAttribute(Doctrine::ATTR_LISTENER)->onSave($record);
}; }
/**
$record->getTable()->getAttribute(Doctrine::ATTR_LISTENER)->onSave($record); * deletes this data access object and all the related composites
} * this operation is isolated by a transaction
/** *
* deletes this data access object and all the related composites * this event can be listened by the onPreDelete and onDelete listeners
* this operation is isolated by a transaction *
* * @return boolean true on success, false on failure
* this event can be listened by the onPreDelete and onDelete listeners */
* public function delete(Doctrine_Record $record)
* @return boolean true on success, false on failure {
*/ if ( ! $record->exists()) {
public function delete(Doctrine_Record $record) return false;
{ }
if ( ! $record->exists()) { $this->beginTransaction();
return false;
} $record->getTable()->getListener()->onPreDelete($record);
$this->beginTransaction();
$this->unitOfWork->deleteComposites($record);
$record->getTable()->getListener()->onPreDelete($record);
$this->transaction->addDelete($record);
$this->unitOfWork->deleteComposites($record);
$record->getTable()->getListener()->onDelete($record);
$this->transaction->addDelete($record);
$this->commit();
$record->getTable()->getListener()->onDelete($record);
return true;
$this->commit(); }
/**
return true; * returns a string representation of this object
} * @return string
/** */
* returns a string representation of this object public function __toString()
* @return string {
*/ return Doctrine_Lib::getConnectionAsString($this);
public function __toString() }
{ }
return Doctrine_Lib::getConnectionAsString($this);
}
}
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