1
0
mirror of synced 2025-01-06 00:57:10 +03:00

Intermediate checkin.

This commit is contained in:
romanb 2008-08-02 17:41:37 +00:00
parent e704cd0fd2
commit 3cd4fc5542
22 changed files with 793 additions and 883 deletions

View File

@ -0,0 +1,455 @@
<?php
#namespace Doctrine::ORM;
/**
* The ActiveEntity class adds an ActiveRecord-like interface to Entity classes
* that allows the Entities to directly interact with the persistence layer.
* This is mostly just a convenient wrapper for people who want it that forwards
* most method calls to the EntityManager.
*
* @since 2.0
*/
class Doctrine_ActiveEntity extends Doctrine_Entity
{
/**
* Saves the current state of the entity into the database.
*
* @param Doctrine_Connection $conn optional connection parameter
* @return void
* @todo ActiveEntity method.
*/
public function save()
{
// TODO: Forward to EntityManager. There: registerNew() OR registerDirty() on UnitOfWork.
$this->_em->save($this);
}
/**
* 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
* key field values, the REPLACE query just updates its values instead of
* inserting a new row.
*
* 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
* query isemulated through this method for other DBMS using standard types
* of queries inside a transaction to assure the atomicity of the operation.
*
* @param Doctrine_Connection $conn optional connection parameter
* @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 something fails at database level
* @return integer number of rows affected
* @todo ActiveEntity method.
*/
public function replace()
{
return $this->_em->replace(
$this->_class,
$this->getPrepared(),
$this->_id);
}
/**
* Creates an array representation of the object's data.
*
* @param boolean $deep - Return also the relations
* @return array
* @todo ActiveEntity method.
* @todo Move implementation to EntityManager.
*/
public function toArray($deep = true, $prefixKey = false)
{
$a = array();
foreach ($this as $column => $value) {
if ($value === Doctrine_Null::$INSTANCE || is_object($value)) {
$value = null;
}
$a[$column] = $value;
}
if ($this->_class->getIdentifierType() == Doctrine::IDENTIFIER_AUTOINC) {
$idFieldNames = $this->_class->getIdentifier();
$idFieldName = $idFieldNames[0];
$ids = $this->identifier();
$id = count($ids) > 0 ? array_pop($ids) : null;
$a[$idFieldName] = $id;
}
if ($deep) {
foreach ($this->_references as $key => $relation) {
if ( ! $relation instanceof Doctrine_Null) {
$a[$key] = $relation->toArray($deep, $prefixKey);
}
}
}
// [FIX] Prevent mapped Doctrine_Entitys from being displayed fully
foreach ($this->_values as $key => $value) {
if ($value instanceof Doctrine_Entity) {
$a[$key] = $value->toArray($deep, $prefixKey);
} else {
$a[$key] = $value;
}
}
return $a;
}
/**
* Merges this Entity with an array of values
* or with another existing instance of.
*
* @param mixed $data Data to merge. Either another instance of this model or an array
* @param bool $deep Bool value for whether or not to merge the data deep
* @return void
* @todo ActiveEntity method.
* @todo Move implementation to EntityManager.
*/
public function merge($data, $deep = true)
{
if ($data instanceof $this) {
$array = $data->toArray($deep);
} else if (is_array($data)) {
$array = $data;
} else {
$array = array();
}
return $this->fromArray($array, $deep);
}
/**
* fromArray
*
* @param string $array
* @param bool $deep Bool value for whether or not to merge the data deep
* @return void
* @todo ActiveEntity method.
* @todo Move implementation to EntityManager.
*/
public function fromArray($array, $deep = true)
{
if (is_array($array)) {
foreach ($array as $key => $value) {
if ($deep && $this->getTable()->hasRelation($key)) {
$this->$key->fromArray($value, $deep);
} else if ($this->getTable()->hasField($key)) {
$this->set($key, $value);
}
}
}
}
/**
* Synchronizes a Doctrine_Entity and its relations with data from an array
*
* It expects an array representation of a Doctrine_Entity similar to the return
* value of the toArray() method. If the array contains relations it will create
* those that don't exist, update the ones that do, and delete the ones missing
* on the array but available on the Doctrine_Entity
*
* @param array $array representation of a Doctrine_Entity
* @todo ActiveEntity method.
* @todo Move implementation to EntityManager.
*/
public function synchronizeFromArray(array $array)
{
foreach ($array as $key => $value) {
if ($this->getTable()->hasRelation($key)) {
$this->get($key)->synchronizeFromArray($value);
} else if ($this->getTable()->hasColumn($key)) {
$this->set($key, $value);
}
}
// eliminate relationships missing in the $array
foreach ($this->_references as $name => $obj) {
if ( ! isset($array[$name])) {
unset($this->$name);
}
}
}
/**
* exportTo
*
* @param string $type
* @param string $deep
* @return void
* @todo ActiveEntity method.
*/
public function exportTo($type, $deep = true)
{
if ($type == 'array') {
return $this->toArray($deep);
} else {
return Doctrine_Parser::dump($this->toArray($deep, true), $type);
}
}
/**
* importFrom
*
* @param string $type
* @param string $data
* @return void
* @author Jonathan H. Wage
* @todo ActiveEntity method.
*/
public function importFrom($type, $data)
{
if ($type == 'array') {
return $this->fromArray($data);
} else {
return $this->fromArray(Doctrine_Parser::load($data, $type));
}
}
/**
* Deletes the persistent state of the entity.
*
* @return boolean TRUE on success, FALSE on failure.
* @todo ActiveRecord method.
*/
public function delete()
{
// TODO: Forward to EntityManager. There: registerRemoved() on UnitOfWork
return $this->_em->remove($this);
}
/**
* Creates a copy of the entity.
*
* @return Doctrine_Entity
* @todo ActiveEntity method. Implementation to EntityManager.
*/
public function copy($deep = true)
{
$data = $this->_data;
if ($this->_class->getIdentifierType() === Doctrine::IDENTIFIER_AUTOINC) {
$idFieldNames = (array)$this->_class->getIdentifier();
$id = $idFieldNames[0];
unset($data[$id]);
}
$ret = $this->_em->createEntity($this->_entityName, $data);
$modified = array();
foreach ($data as $key => $val) {
if ( ! ($val instanceof Doctrine_Null)) {
$ret->_modified[] = $key;
}
}
if ($deep) {
foreach ($this->_references as $key => $value) {
if ($value instanceof Doctrine_Collection) {
foreach ($value as $record) {
$ret->{$key}[] = $record->copy($deep);
}
} else {
$ret->set($key, $value->copy($deep));
}
}
}
return $ret;
}
/**
* Removes links from this record to given records
* if no ids are given, it removes all links
*
* @param string $alias related component alias
* @param array $ids the identifiers of the related records
* @return Doctrine_Entity this object
* @todo ActiveEntity method.
*/
public function unlink($alias, $ids = array())
{
$ids = (array) $ids;
$q = new Doctrine_Query();
$rel = $this->getTable()->getRelation($alias);
if ($rel instanceof Doctrine_Relation_Association) {
$q->delete()
->from($rel->getAssociationTable()->getComponentName())
->where($rel->getLocal() . ' = ?', array_values($this->identifier()));
if (count($ids) > 0) {
$q->whereIn($rel->getForeign(), $ids);
}
$q->execute();
} else if ($rel instanceof Doctrine_Relation_ForeignKey) {
$q->update($rel->getTable()->getComponentName())
->set($rel->getForeign(), '?', array(null))
->addWhere($rel->getForeign() . ' = ?', array_values($this->identifier()));
if (count($ids) > 0) {
$relTableIdFieldNames = (array)$rel->getTable()->getIdentifier();
$q->whereIn($relTableIdFieldNames[0], $ids);
}
$q->execute();
}
if (isset($this->_references[$alias])) {
foreach ($this->_references[$alias] as $k => $record) {
if (in_array(current($record->identifier()), $ids)) {
$this->_references[$alias]->remove($k);
}
}
$this->_references[$alias]->takeSnapshot();
}
return $this;
}
/**
* Creates links from this record to given records.
*
* @param string $alias related component alias
* @param array $ids the identifiers of the related records
* @return Doctrine_Entity this object
* @todo ActiveEntity method.
*/
public function link($alias, array $ids)
{
if ( ! count($ids)) {
return $this;
}
$identifier = array_values($this->identifier());
$identifier = array_shift($identifier);
$rel = $this->getTable()->getRelation($alias);
if ($rel instanceof Doctrine_Relation_Association) {
$modelClassName = $rel->getAssociationTable()->getComponentName();
$localFieldName = $rel->getLocalFieldName();
$localFieldDef = $rel->getAssociationTable()->getColumnDefinition($localFieldName);
if ($localFieldDef['type'] == 'integer') {
$identifier = (integer) $identifier;
}
$foreignFieldName = $rel->getForeignFieldName();
$foreignFieldDef = $rel->getAssociationTable()->getColumnDefinition($foreignFieldName);
if ($foreignFieldDef['type'] == 'integer') {
for ($i = 0; $i < count($ids); $i++) {
$ids[$i] = (integer) $ids[$i];
}
}
foreach ($ids as $id) {
$record = new $modelClassName;
$record[$localFieldName] = $identifier;
$record[$foreignFieldName] = $id;
$record->save();
}
} else if ($rel instanceof Doctrine_Relation_ForeignKey) {
$q = new Doctrine_Query();
$q->update($rel->getTable()->getComponentName())
->set($rel->getForeign(), '?', array_values($this->identifier()));
if (count($ids) > 0) {
$relTableIdFieldNames = (array)$rel->getTable()->getIdentifier();
$q->whereIn($relTableIdFieldNames[0], $ids);
}
$q->execute();
} else if ($rel instanceof Doctrine_Relation_LocalKey) {
$q = new Doctrine_Query();
$q->update($this->getTable()->getComponentName())
->set($rel->getLocalFieldName(), '?', $ids);
if (count($ids) > 0) {
$relTableIdFieldNames = (array)$rel->getTable()->getIdentifier();
$q->whereIn($relTableIdFieldNames[0], array_values($this->identifier()));
}
$q->execute();
}
return $this;
}
/**
* Refresh internal data from the database
*
* @param bool $deep If true, fetch also current relations. Caution: this deletes
* any aggregated values you may have queried beforee
*
* @throws Doctrine_Record_Exception When the refresh operation fails (when the database row
* this record represents does not exist anymore)
* @return boolean
* @todo Implementation to EntityManager.
* @todo Move to ActiveEntity (extends Entity). Implementation to EntityManager.
*/
public function refresh($deep = false)
{
$id = $this->identifier();
if ( ! is_array($id)) {
$id = array($id);
}
if (empty($id)) {
return false;
}
$id = array_values($id);
if ($deep) {
$query = $this->_em->createQuery()->from($this->_entityName);
foreach (array_keys($this->_references) as $name) {
$query->leftJoin(get_class($this) . '.' . $name);
}
$query->where(implode(' = ? AND ', $this->_class->getIdentifierColumnNames()) . ' = ?');
$this->clearRelated();
$record = $query->fetchOne($id);
} else {
// Use FETCH_ARRAY to avoid clearing object relations
$record = $this->getRepository()->find($this->identifier(), Doctrine::HYDRATE_ARRAY);
if ($record) {
$this->hydrate($record);
}
}
if ($record === false) {
throw new Doctrine_Record_Exception('Failed to refresh. Record does not exist.');
}
$this->_modified = array();
$this->_extractIdentifier();
$this->_state = Doctrine_Entity::STATE_CLEAN;
return $this;
}
/**
* Hydrates this object from given array
*
* @param array $data
* @return boolean
*/
final public function hydrate(array $data)
{
$this->_data = array_merge($this->_data, $data);
$this->_extractIdentifier();
}
}
?>

View File

@ -63,13 +63,13 @@ class Doctrine_Configuration
/** /**
* Initializes the attributes. * Initializes the attributes.
* Changes null default values to references to the Null object to allow
* fast isset() checks instead of array_key_exists().
* *
* @return void * @return void
*/ */
private function _initAttributes() private function _initAttributes()
{ {
// Change null default values to references to the Null object to allow
// fast isset() checks instead of array_key_exists().
foreach ($this->_attributes as $key => $value) { foreach ($this->_attributes as $key => $value) {
if ($value === null) { if ($value === null) {
$this->_attributes[$key] = $this->_nullObject; $this->_attributes[$key] = $this->_nullObject;

View File

@ -26,7 +26,7 @@
#use Doctrine::DBAL::Exceptions::ConnectionException; #use Doctrine::DBAL::Exceptions::ConnectionException;
/** /**
* A thin connection wrapper on top of PDO. * A thin wrapper on top of the PDO class.
* *
* 1. Event listeners * 1. Event listeners
* An easy to use, pluggable eventlistener architecture. Aspects such as * An easy to use, pluggable eventlistener architecture. Aspects such as
@ -117,9 +117,9 @@ abstract class Doctrine_Connection
protected $_quoteIdentifiers; protected $_quoteIdentifiers;
/** /**
* @var array $serverInfo * @var array
*/ */
protected $serverInfo = array(); protected $_serverInfo = array();
/** /**
* The parameters used during creation of the Connection. * The parameters used during creation of the Connection.
@ -154,11 +154,18 @@ abstract class Doctrine_Connection
protected $_platform; protected $_platform;
/** /**
* Enter description here... * The transaction object.
* *
* @var Doctrine::DBAL::Transactions::Transaction * @var Doctrine::DBAL::Transactions::Transaction
*/ */
protected $_transaction; protected $_transaction;
/**
* The sequence manager.
*
* @var Doctrine::DBAL::Sequencing::SequenceManager
*/
protected $_sequenceManager;
/** /**
* Constructor. * Constructor.
@ -339,20 +346,13 @@ abstract class Doctrine_Connection
* *
* @return string * @return string
* @todo make abstract, implement in subclasses. * @todo make abstract, implement in subclasses.
* @todo throw different exception?
*/ */
protected function _constructPdoDsn() protected function _constructPdoDsn()
{ {
throw Doctrine_Exception::notImplemented('_constructPdoDsn', get_class($this)); throw Doctrine_Exception::notImplemented('_constructPdoDsn', get_class($this));
} }
/**
* @todo Remove. Breaks encapsulation.
*/
public function incrementQueryCount()
{
$this->_queryCount++;
}
/** /**
* 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
@ -360,8 +360,8 @@ abstract class Doctrine_Connection
* 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 is emulated 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
@ -490,7 +490,7 @@ abstract class Doctrine_Connection
// column names are specified as array keys // column names are specified as array keys
$cols = array(); $cols = array();
// the query VALUES will contain either expresions (eg 'NOW()') or ? // the query VALUES will contain either expressions (eg 'NOW()') or ?
$a = array(); $a = array();
foreach ($data as $columnName => $value) { foreach ($data as $columnName => $value) {
$cols[] = $this->quoteIdentifier($columnName); $cols[] = $this->quoteIdentifier($columnName);
@ -502,13 +502,10 @@ abstract class Doctrine_Connection
} }
} }
// build the statement
$query = 'INSERT INTO ' . $this->quoteIdentifier($tableName) $query = 'INSERT INTO ' . $this->quoteIdentifier($tableName)
. ' (' . implode(', ', $cols) . ') ' . ' (' . implode(', ', $cols) . ') '
. 'VALUES ('; . 'VALUES (';
$query .= implode(', ', $a) . ')'; $query .= implode(', ', $a) . ')';
// prepare and execute the statement
return $this->exec($query, array_values($data)); return $this->exec($query, array_values($data));
} }
@ -567,14 +564,15 @@ abstract class Doctrine_Connection
// quick fix for the identifiers that contain a dot // quick fix for the identifiers that contain a dot
if (strpos($str, '.')) { if (strpos($str, '.')) {
$e = explode('.', $str); $e = explode('.', $str);
return $this->quoteIdentifier($e[0]) . '.' return $this->quoteIdentifier($e[0])
. '.'
. $this->quoteIdentifier($e[1]); . $this->quoteIdentifier($e[1]);
} }
$q = $this->properties['identifier_quoting'];
$str = str_replace($q['end'], $q['escape'] . $q['end'], $str);
return $q['start'] . $str . $q['end']; $c = $this->_platform->getIdentifierQuoteCharacter();
$str = str_replace($c, $c . $c, $str);
return $c . $str . $c;
} }
/** /**
@ -603,55 +601,16 @@ abstract class Doctrine_Connection
} }
/** /**
* 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 Type of the parameter.
* @return mixed * @return string The quoted parameter.
*/ */
public function quote($input, $type = null) public function quote($input, $type = null)
{ {
return $this->_pdo->quote($input, $type); return $this->_pdo->quote($input, $type);
} }
/**
* quote
* quotes given input parameter
*
* @param mixed $input parameter to be quoted
* @param string $type
* @return mixed
*/
/*public function quote($input, $type = null)
{
if ($type == null) {
$type = gettype($input);
}
switch ($type) {
case 'integer':
case 'enum':
case 'boolean':
case 'double':
case 'float':
case 'bool':
case 'decimal':
case 'int':
return $input;
case 'array':
case 'object':
$input = serialize($input);
case 'date':
case 'time':
case 'timestamp':
case 'string':
case 'char':
case 'varchar':
case 'text':
case 'gzip':
case 'blob':
case 'clob':
return $this->conn->quote($input);
}
}*/
/** /**
* Set the date/time format for the current connection * Set the date/time format for the current connection
@ -882,21 +841,14 @@ abstract class Doctrine_Connection
* @throws Doctrine_Connection_Exception * @throws Doctrine_Connection_Exception
*/ */
public function rethrowException(Exception $e, $invoker) public function rethrowException(Exception $e, $invoker)
{ {
//$event = new Doctrine_Event($this, Doctrine_Event::CONN_ERROR);
//$this->getListener()->preError($event);
$name = 'Doctrine_Connection_' . $this->_driverName . '_Exception'; $name = 'Doctrine_Connection_' . $this->_driverName . '_Exception';
$exc = new $name($e->getMessage(), (int) $e->getCode()); $exc = new $name($e->getMessage(), (int) $e->getCode());
if ( ! is_array($e->errorInfo)) { if ( ! is_array($e->errorInfo)) {
$e->errorInfo = array(null, null, null, null); $e->errorInfo = array(null, null, null, null);
} }
$exc->processErrorInfo($e->errorInfo); $exc->processErrorInfo($e->errorInfo);
throw $exc; throw $exc;
//$this->getListener()->postError($event);
} }
/** /**
@ -1007,7 +959,7 @@ abstract class Doctrine_Connection
*/ */
public function commit($savepoint = null) public function commit($savepoint = null)
{ {
return $this->transaction->commit($savepoint); return $this->_transaction->commit($savepoint);
} }
/** /**
@ -1025,7 +977,7 @@ abstract class Doctrine_Connection
*/ */
public function rollback($savepoint = null) public function rollback($savepoint = null)
{ {
$this->transaction->rollback($savepoint); $this->_transaction->rollback($savepoint);
} }
/** /**
@ -1202,31 +1154,18 @@ abstract class Doctrine_Connection
return Doctrine_Lib::getConnectionAsString($this); return Doctrine_Lib::getConnectionAsString($this);
} }
/*
* ----------- Mixed methods (need to figure out where they go) ---------------
*/
/** /**
* retrieves a database connection attribute * Gets the SequenceManager that can be used to retrieve sequence values
* through this connection.
* *
* @param integer $attribute * @return Doctrine::DBAL::Sequencing::SequenceManager
* @return mixed
* @todo Implementation or remove if not needed. Configuration is the main
* container for all the attributes now.
*/ */
public function getAttribute($attribute)
{
if ($attribute == Doctrine::ATTR_QUOTE_IDENTIFIER) {
return false;
}
}
public function getSequenceManager() public function getSequenceManager()
{ {
if ( ! $this->modules['sequence']) { if ( ! $this->_sequenceManager) {
$class = "Doctrine_Sequence_" . $this->_driverName; $class = "Doctrine_Sequence_" . $this->_driverName;
$this->modules['sequence'] = new $class; $this->_sequenceManager = new $class;
} }
return $this->modules['sequence']; return $this->_sequenceManager;
} }
} }

View File

@ -58,7 +58,10 @@ class Doctrine_Connection_Mock extends Doctrine_Connection_Common
} }
public function quote($input, $type = null) public function quote($input, $type = null)
{ {
if ($type === 'string') {
return "'" . $input . "'";
}
return $input; return $input;
} }
} }

View File

@ -18,12 +18,10 @@
* and is licensed under the LGPL. For more information, see * and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.org>. * <http://www.phpdoctrine.org>.
*/ */
Doctrine::autoload('Doctrine_Adapter_Statement_Interface');
/** /**
* Doctrine_Connection_Statement * A thin wrapper around PDOStatement.
* *
* @package Doctrine
* @subpackage Connection
* @author Konsta Vesterinen <kvesteri@cc.hut.fi> * @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.phpdoctrine.org * @link www.phpdoctrine.org
@ -31,7 +29,7 @@ Doctrine::autoload('Doctrine_Adapter_Statement_Interface');
* @version $Revision: 1532 $ * @version $Revision: 1532 $
* @todo Do we seriously need this wrapper? * @todo Do we seriously need this wrapper?
*/ */
class Doctrine_Connection_Statement implements Doctrine_Adapter_Statement_Interface class Doctrine_Connection_Statement
{ {
/** /**
* @var Doctrine_Connection $conn Doctrine_Connection object, every connection * @var Doctrine_Connection $conn Doctrine_Connection object, every connection
@ -40,7 +38,7 @@ class Doctrine_Connection_Statement implements Doctrine_Adapter_Statement_Interf
protected $_conn; protected $_conn;
/** /**
* @var mixed $_stmt PDOStatement object, boolean false or Doctrine_Adapter_Statement object * @var PDOStatement $_stmt PDOStatement object, boolean false or Doctrine_Adapter_Statement object
*/ */
protected $_stmt; protected $_stmt;
@ -81,7 +79,6 @@ class Doctrine_Connection_Statement implements Doctrine_Adapter_Statement_Interf
} }
/** /**
* bindColumn
* Bind a column to a PHP variable * Bind a column to a PHP variable
* *
* @param mixed $column Number of the column (1-indexed) or name of the column in the result set. * @param mixed $column Number of the column (1-indexed) or name of the column in the result set.
@ -125,7 +122,6 @@ class Doctrine_Connection_Statement implements Doctrine_Adapter_Statement_Interf
} }
/** /**
* bindParam
* Binds a PHP variable to a corresponding named or question mark placeholder in the * Binds a PHP variable to a corresponding named or question mark placeholder in the
* SQL statement that was use to prepare the statement. Unlike Doctrine_Adapter_Statement_Interface->bindValue(), * SQL statement that was use to prepare the statement. Unlike Doctrine_Adapter_Statement_Interface->bindValue(),
* the variable is bound as a reference and will only be evaluated at the time * the variable is bound as a reference and will only be evaluated at the time
@ -161,7 +157,6 @@ class Doctrine_Connection_Statement implements Doctrine_Adapter_Statement_Interf
} }
/** /**
* closeCursor
* Closes the cursor, enabling the statement to be executed again. * Closes the cursor, enabling the statement to be executed again.
* *
* @return boolean Returns TRUE on success or FALSE on failure. * @return boolean Returns TRUE on success or FALSE on failure.
@ -172,7 +167,6 @@ class Doctrine_Connection_Statement implements Doctrine_Adapter_Statement_Interf
} }
/** /**
* columnCount
* Returns the number of columns in the result set * Returns the number of columns in the result set
* *
* @return integer Returns the number of columns in the result set represented * @return integer Returns the number of columns in the result set represented
@ -185,7 +179,6 @@ class Doctrine_Connection_Statement implements Doctrine_Adapter_Statement_Interf
} }
/** /**
* errorCode
* Fetch the SQLSTATE associated with the last operation on the statement handle * Fetch the SQLSTATE associated with the last operation on the statement handle
* *
* @see Doctrine_Adapter_Interface::errorCode() * @see Doctrine_Adapter_Interface::errorCode()
@ -197,7 +190,6 @@ class Doctrine_Connection_Statement implements Doctrine_Adapter_Statement_Interf
} }
/** /**
* errorInfo
* Fetch extended error information associated with the last operation on the statement handle * Fetch extended error information associated with the last operation on the statement handle
* *
* @see Doctrine_Adapter_Interface::errorInfo() * @see Doctrine_Adapter_Interface::errorInfo()
@ -209,7 +201,6 @@ class Doctrine_Connection_Statement implements Doctrine_Adapter_Statement_Interf
} }
/** /**
* execute
* Executes a prepared statement * Executes a prepared statement
* *
* If the prepared statement included parameter markers, you must either: * If the prepared statement included parameter markers, you must either:
@ -226,24 +217,22 @@ class Doctrine_Connection_Statement implements Doctrine_Adapter_Statement_Interf
public function execute($params = null) public function execute($params = null)
{ {
try { try {
$event = new Doctrine_Event($this, Doctrine_Event::STMT_EXECUTE, $this->getQuery(), $params); //$event = new Doctrine_Event($this, Doctrine_Event::STMT_EXECUTE, $this->getQuery(), $params);
$this->_conn->getListener()->preStmtExecute($event); //$this->_conn->getListener()->preStmtExecute($event);
$result = true; $result = true;
if ( ! $event->skipOperation) { //if ( ! $event->skipOperation) {
$result = $this->_stmt->execute($params); $result = $this->_stmt->execute($params);
$this->_conn->incrementQueryCount(); //$this->_conn->incrementQueryCount();
} //}
$this->_conn->getListener()->postStmtExecute($event); //$this->_conn->getListener()->postStmtExecute($event);
return $result; return $result;
} catch (PDOException $e) { } catch (PDOException $e) {
} catch (Doctrine_Adapter_Exception $e) { $this->_conn->rethrowException($e, $this);
} }
$this->_conn->rethrowException($e, $this);
return false; return false;
} }
@ -278,25 +267,23 @@ class Doctrine_Connection_Statement implements Doctrine_Adapter_Statement_Interf
$cursorOrientation = Doctrine::FETCH_ORI_NEXT, $cursorOrientation = Doctrine::FETCH_ORI_NEXT,
$cursorOffset = null) $cursorOffset = null)
{ {
$event = new Doctrine_Event($this, Doctrine_Event::STMT_FETCH, $this->getQuery()); //$event = new Doctrine_Event($this, Doctrine_Event::STMT_FETCH, $this->getQuery());
//$event->fetchMode = $fetchMode;
//$event->cursorOrientation = $cursorOrientation;
//$event->cursorOffset = $cursorOffset;
$event->fetchMode = $fetchMode; //$data = $this->_conn->getListener()->preFetch($event);
$event->cursorOrientation = $cursorOrientation;
$event->cursorOffset = $cursorOffset;
$data = $this->_conn->getListener()->preFetch($event); //if ( ! $event->skipOperation) {
if ( ! $event->skipOperation) {
$data = $this->_stmt->fetch($fetchMode, $cursorOrientation, $cursorOffset); $data = $this->_stmt->fetch($fetchMode, $cursorOrientation, $cursorOffset);
} //}
$this->_conn->getListener()->postFetch($event); //$this->_conn->getListener()->postFetch($event);
return $data; return $data;
} }
/** /**
* fetchAll
* Returns an array containing all of the result set rows * Returns an array containing all of the result set rows
* *
* @param integer $fetchMode Controls how the next row will be returned to the caller. * @param integer $fetchMode Controls how the next row will be returned to the caller.
@ -308,32 +295,28 @@ class Doctrine_Connection_Statement implements Doctrine_Adapter_Statement_Interf
* *
* @return array * @return array
*/ */
public function fetchAll($fetchMode = Doctrine::FETCH_BOTH, public function fetchAll($fetchMode = Doctrine::FETCH_BOTH, $columnIndex = null)
$columnIndex = null)
{ {
$event = new Doctrine_Event($this, Doctrine_Event::STMT_FETCHALL, $this->getQuery()); //$event = new Doctrine_Event($this, Doctrine_Event::STMT_FETCHALL, $this->getQuery());
$event->fetchMode = $fetchMode; //$event->fetchMode = $fetchMode;
$event->columnIndex = $columnIndex; //$event->columnIndex = $columnIndex;
//$this->_conn->getListener()->preFetchAll($event);
$this->_conn->getListener()->preFetchAll($event); //if ( ! $event->skipOperation) {
if ( ! $event->skipOperation) {
if ($columnIndex !== null) { if ($columnIndex !== null) {
$data = $this->_stmt->fetchAll($fetchMode, $columnIndex); $data = $this->_stmt->fetchAll($fetchMode, $columnIndex);
} else { } else {
$data = $this->_stmt->fetchAll($fetchMode); $data = $this->_stmt->fetchAll($fetchMode);
} }
//$event->data = $data;
//}
$event->data = $data; //$this->_conn->getListener()->postFetchAll($event);
}
$this->_conn->getListener()->postFetchAll($event);
return $data; return $data;
} }
/** /**
* fetchColumn
* Returns a single column from the next row of a * Returns a single column from the next row of a
* result set or FALSE if there are no more rows. * result set or FALSE if there are no more rows.
* *
@ -349,7 +332,6 @@ class Doctrine_Connection_Statement implements Doctrine_Adapter_Statement_Interf
} }
/** /**
* fetchObject
* Fetches the next row and returns it as an object. * Fetches the next row and returns it as an object.
* *
* Fetches the next row and returns it as an object. This function is an alternative to * Fetches the next row and returns it as an object. This function is an alternative to
@ -367,7 +349,6 @@ class Doctrine_Connection_Statement implements Doctrine_Adapter_Statement_Interf
} }
/** /**
* getAttribute
* Retrieve a statement attribute * Retrieve a statement attribute
* *
* @param integer $attribute * @param integer $attribute
@ -380,7 +361,6 @@ class Doctrine_Connection_Statement implements Doctrine_Adapter_Statement_Interf
} }
/** /**
* getColumnMeta
* Returns metadata for a column in a result set * Returns metadata for a column in a result set
* *
* @param integer $column The 0-indexed column in the result set. * @param integer $column The 0-indexed column in the result set.
@ -401,7 +381,6 @@ class Doctrine_Connection_Statement implements Doctrine_Adapter_Statement_Interf
} }
/** /**
* nextRowset
* Advances to the next rowset in a multi-rowset statement handle * Advances to the next rowset in a multi-rowset statement handle
* *
* Some database servers support stored procedures that return more than one rowset * Some database servers support stored procedures that return more than one rowset
@ -417,7 +396,6 @@ class Doctrine_Connection_Statement implements Doctrine_Adapter_Statement_Interf
} }
/** /**
* rowCount
* rowCount() returns the number of rows affected by the last DELETE, INSERT, or UPDATE statement * rowCount() returns the number of rows affected by the last DELETE, INSERT, or UPDATE statement
* executed by the corresponding object. * executed by the corresponding object.
* *
@ -434,7 +412,6 @@ class Doctrine_Connection_Statement implements Doctrine_Adapter_Statement_Interf
} }
/** /**
* setAttribute
* Set a statement attribute * Set a statement attribute
* *
* @param integer $attribute * @param integer $attribute
@ -447,7 +424,6 @@ class Doctrine_Connection_Statement implements Doctrine_Adapter_Statement_Interf
} }
/** /**
* setFetchMode
* Set the default fetch mode for this statement * Set the default fetch mode for this statement
* *
* @param integer $mode The fetch mode must be one of the Doctrine::FETCH_* constants. * @param integer $mode The fetch mode must be one of the Doctrine::FETCH_* constants.

View File

@ -10,66 +10,64 @@
* @author Roman Borschel <roman@code-factory.org> * @author Roman Borschel <roman@code-factory.org>
*/ */
abstract class Doctrine_DatabasePlatform abstract class Doctrine_DatabasePlatform
{ {
/** /**
* An array containing all features this platform supports, keys representing feature * Constructor.
* names and values as one of the following (true, false, 'emulated').
*
* @var array
*/ */
protected $_supported = array();
/**
* Platform specific properties. Subclasses can override these in the
* constructor.
*
* @var array $properties
*/
protected $_properties = array(
'sql_comments' => array(
array(
'start' => '--',
'end' => "\n",
'escape' => false
),
array(
'start' => '/*',
'end' => '*/',
'escape' => false
)
),
'identifier_quoting' => array(
'start' => '"',
'end' => '"',
'escape' => '"'
),
'string_quoting' => array(
'start' => "'",
'end' => "'",
'escape' => false,
'escape_pattern' => false
),
'wildcards' => array('%', '_'),
'varchar_max_length' => 255,
);
public function __construct() {} public function __construct() {}
/** /**
* Checks whether a certain feature is supported. * Gets the character used for identifier quoting.
* *
* @param string $feature the name of the feature * @return string
* @return boolean whether or not this drivers supports given feature
*/ */
public function supports($feature) public function getIdentifierQuoteCharacter()
{ {
return (isset($this->_supported[$feature]) && return '"';
($this->_supported[$feature] === 'emulated' || $this->_supported[$feature]));
} }
/** /**
* regexp * Gets the string portion that starts an SQL comment.
* returns the regular expression operator *
* @return string
*/
public function getSqlCommentStartString()
{
return "--";
}
/**
* Gets the string portion that starts an SQL comment.
*
* @return string
*/
public function getSqlCommentEndString()
{
return "\n";
}
/**
* Gets the maximum length of a varchar field.
*
* @return integer
*/
public function getVarcharMaxLength()
{
return 255;
}
/**
* Gets all SQL wildcard characters of the platform.
*
* @return array
*/
public function getWildcards()
{
return array('%', '_');
}
/**
* Returns the regular expression operator.
* *
* @return string * @return string
*/ */
@ -889,9 +887,10 @@ abstract class Doctrine_DatabasePlatform
* *
* @param string $query The SQL string to write to / append to. * @param string $query The SQL string to write to / append to.
* @return string * @return string
* @todo Remove the ORM dependency
*/ */
public function writeLimitClauseInSubquery(Doctrine_ClassMetadata $rootClass, $query, public function writeLimitClauseInSubquery(Doctrine_ClassMetadata $rootClass,
$limit = false, $offset = false) $query, $limit = false, $offset = false)
{ {
return $this->modifyLimitQuery($query, $limit, $offset); return $this->modifyLimitQuery($query, $limit, $offset);
} }
@ -910,6 +909,46 @@ abstract class Doctrine_DatabasePlatform
} }
return $this->_properties[$name]; return $this->_properties[$name];
} }
public function supportsSequences()
{
return false;
}
public function supportsIdentityColumns()
{
return false;
}
public function supportsIndexes()
{
return true;
}
public function supportsTransactions()
{
return true;
}
public function supportsSavepoints()
{
return true;
}
public function supportsPrimaryConstraints()
{
return true;
}
public function supportsForeignKeyConstraints()
{
return true;
}
public function supportsGettingAffectedRows()
{
return true;
}
} }

View File

@ -16,26 +16,6 @@ class Doctrine_DatabasePlatform_FirebirdPlatform extends Doctrine_DatabasePlatfo
public function __construct() public function __construct()
{ {
parent::__construct(); parent::__construct();
$this->_supported = array(
'sequences' => true,
'indexes' => true,
'affected_rows' => true,
'summary_functions' => true,
'order_by_text' => true,
'transactions' => true,
'savepoints' => true,
'current_id' => true,
'limit_queries' => 'emulated',
'LOBs' => true,
'replace' => 'emulated',
'sub_selects' => true,
'auto_increment' => true,
'primary_key' => true,
'result_introspection' => true,
'prepared_statements' => true,
'identifier_quoting' => false,
'pattern_escaping' => true
);
} }
/** /**

View File

@ -8,24 +8,6 @@ class Doctrine_DatabasePlatform_MsSqlPlatform extends Doctrine_DatabasePlatform
public function __construct() public function __construct()
{ {
parent::__construct(); parent::__construct();
// initialize all driver options
$this->_supported = array(
'sequences' => 'emulated',
'indexes' => true,
'affected_rows' => true,
'transactions' => true,
'summary_functions' => true,
'order_by_text' => true,
'current_id' => 'emulated',
'limit_queries' => 'emulated',
'LOBs' => true,
'replace' => 'emulated',
'sub_selects' => true,
'auto_increment' => true,
'primary_key' => true,
'result_introspection' => true,
'prepared_statements' => 'emulated',
);
} }
/** /**

View File

@ -15,7 +15,7 @@ class Doctrine_DatabasePlatform_MySqlPlatform extends Doctrine_DatabasePlatform
* @var array * @var array
* @todo Needed? What about lazy initialization? * @todo Needed? What about lazy initialization?
*/ */
protected static $_reservedKeywords = array( /*protected static $_reservedKeywords = array(
'ADD', 'ALL', 'ALTER', 'ADD', 'ALL', 'ALTER',
'ANALYZE', 'AND', 'AS', 'ANALYZE', 'AND', 'AS',
'ASC', 'ASENSITIVE', 'BEFORE', 'ASC', 'ASENSITIVE', 'BEFORE',
@ -90,56 +90,30 @@ class Doctrine_DatabasePlatform_MySqlPlatform extends Doctrine_DatabasePlatform
'WHEN', 'WHERE', 'WHILE', 'WHEN', 'WHERE', 'WHILE',
'WITH', 'WRITE', 'X509', 'WITH', 'WRITE', 'X509',
'XOR', 'YEAR_MONTH', 'ZEROFILL' 'XOR', 'YEAR_MONTH', 'ZEROFILL'
); );*/
/** /**
* Constructor. * Constructor.
* Creates a new MySqlPlatform. * Creates a new MySqlPlatform instance.
*/ */
public function __construct() public function __construct()
{ {
parent::__construct(); parent::__construct();
$this->_supported = array(
'sequences' => 'emulated',
'indexes' => true,
'affected_rows' => true,
'transactions' => true,
'savepoints' => false,
'summary_functions' => true,
'order_by_text' => true,
'current_id' => 'emulated',
'limit_queries' => true,
'LOBs' => true,
'replace' => true,
'sub_selects' => true,
'auto_increment' => true,
'primary_key' => true,
'result_introspection' => true,
'prepared_statements' => 'emulated',
'identifier_quoting' => true,
'pattern_escaping' => true
);
$this->_properties['string_quoting'] = array(
'start' => "'",
'end' => "'",
'escape' => '\\',
'escape_pattern' => '\\');
$this->_properties['identifier_quoting'] = array(
'start' => '`',
'end' => '`',
'escape' => '`');
$this->_properties['sql_comments'] = array(
array('start' => '-- ', 'end' => "\n", 'escape' => false),
array('start' => '#', 'end' => "\n", 'escape' => false),
array('start' => '/*', 'end' => '*/', 'escape' => false),
);
$this->properties['varchar_max_length'] = 255;
} }
/** /**
* returns the regular expression operator * Gets the character used for identifier quoting.
*
* @return string
* @override
*/
public function getIdentifierQuoteCharacter()
{
return '`';
}
/**
* Returns the regular expression operator.
* *
* @return string * @return string
* @override * @override
@ -204,6 +178,7 @@ class Doctrine_DatabasePlatform_MySqlPlatform extends Doctrine_DatabasePlatform
} }
$match.= "'"; $match.= "'";
$match.= $this->patternEscapeString(); $match.= $this->patternEscapeString();
return $match; return $match;
} }
@ -555,6 +530,29 @@ class Doctrine_DatabasePlatform_MySqlPlatform extends Doctrine_DatabasePlatform
{ {
return true; return true;
} }
/**
* Whether the platform supports identity columns.
* MySql supports this through AUTO_INCREMENT columns.
*
* @return boolean
* @override
*/
public function supportsIdentityColumns()
{
return true;
}
/**
* Whether the platform supports savepoints. MySql does not.
*
* @return boolean
* @override
*/
public function supportsSavepoints()
{
return false;
}
} }
?> ?>

View File

@ -8,26 +8,6 @@ class Doctrine_DatabasePlatform_OraclePlatform extends Doctrine_DatabasePlatform
public function __construct() public function __construct()
{ {
parent::__construct(); parent::__construct();
$this->_supported = array(
'sequences' => true,
'indexes' => true,
'summary_functions' => true,
'order_by_text' => true,
'current_id' => true,
'affected_rows' => true,
'transactions' => true,
'savepoints' => true,
'limit_queries' => true,
'LOBs' => true,
'replace' => 'emulated',
'sub_selects' => true,
'auto_increment' => false, // implementation is broken
'primary_key' => true,
'result_introspection' => true,
'prepared_statements' => true,
'identifier_quoting' => true,
'pattern_escaping' => true,
);
} }
/** /**
@ -44,6 +24,9 @@ class Doctrine_DatabasePlatform_OraclePlatform extends Doctrine_DatabasePlatform
return $this->_createLimitSubquery($query, $limit, $offset); return $this->_createLimitSubquery($query, $limit, $offset);
} }
/**
* @todo Doc
*/
private function _createLimitSubquery($query, $limit, $offset, $column = null) private function _createLimitSubquery($query, $limit, $offset, $column = null)
{ {
$limit = (int) $limit; $limit = (int) $limit;

View File

@ -9,7 +9,7 @@ class Doctrine_DatabasePlatform_PostgreSqlPlatform extends Doctrine_DatabasePlat
* @param array * @param array
* @todo Nedded? What about lazy initialization? * @todo Nedded? What about lazy initialization?
*/ */
protected static $_reservedKeywords = array( /*protected static $_reservedKeywords = array(
'abort', 'absolute', 'access', 'action', 'add', 'after', 'aggregate', 'abort', 'absolute', 'access', 'action', 'add', 'after', 'aggregate',
'all', 'alter', 'analyse', 'analyze', 'and', 'any', 'as', 'asc', 'all', 'alter', 'analyse', 'analyze', 'and', 'any', 'as', 'asc',
'assertion', 'assignment', 'at', 'authorization', 'backward', 'before', 'assertion', 'assignment', 'at', 'authorization', 'backward', 'before',
@ -54,7 +54,7 @@ class Doctrine_DatabasePlatform_PostgreSqlPlatform extends Doctrine_DatabasePlat
'unknown', 'unlisten', 'until', 'update', 'usage', 'user', 'using', 'unknown', 'unlisten', 'until', 'update', 'usage', 'user', 'using',
'vacuum', 'valid', 'validator', 'values', 'varchar', 'varying', 'vacuum', 'valid', 'validator', 'values', 'varchar', 'varying',
'verbose', 'version', 'view', 'volatile', 'when', 'where', 'with', 'verbose', 'version', 'view', 'volatile', 'when', 'where', 'with',
'without', 'work', 'write', 'year','zone'); 'without', 'work', 'write', 'year','zone');*/
/** /**
@ -63,28 +63,7 @@ class Doctrine_DatabasePlatform_PostgreSqlPlatform extends Doctrine_DatabasePlat
*/ */
public function __construct() public function __construct()
{ {
parent::__construct(); parent::__construct();
$this->_supported = array(
'sequences' => true,
'indexes' => true,
'affected_rows' => true,
'summary_functions' => true,
'order_by_text' => true,
'transactions' => true,
'savepoints' => true,
'current_id' => true,
'limit_queries' => true,
'LOBs' => true,
'replace' => 'emulated',
'sub_selects' => true,
'auto_increment' => 'emulated',
'primary_key' => true,
'result_introspection' => true,
'prepared_statements' => true,
'identifier_quoting' => true,
'pattern_escaping' => true,
);
$this->_properties['string_quoting'] = array('start' => "'", $this->_properties['string_quoting'] = array('start' => "'",
'end' => "'", 'end' => "'",
'escape' => "'", 'escape' => "'",
@ -94,7 +73,6 @@ class Doctrine_DatabasePlatform_PostgreSqlPlatform extends Doctrine_DatabasePlat
'escape' => '"'); 'escape' => '"');
} }
/** /**
* 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.
@ -509,7 +487,39 @@ class Doctrine_DatabasePlatform_PostgreSqlPlatform extends Doctrine_DatabasePlat
public function parseBoolean($value) public function parseBoolean($value)
{ {
return $value; return $value;
} }
/**
* Whether the platform supports sequences.
* Postgres has native support for sequences.
*
* @return boolean
*/
public function supportsSequences()
{
return true;
}
/**
* Whether the platform supports identity columns.
* Postgres supports these through the SERIAL keyword.
*
* @return boolean
*/
public function supportsIdentityColumns()
{
return true;
}
/**
* Whether the platform prefers sequences for ID generation.
*
* @return boolean
*/
public function prefersSequences()
{
return true;
}
} }
?> ?>

View File

@ -16,26 +16,6 @@ class Doctrine_DatabasePlatform_SqlitePlatform extends Doctrine_DatabasePlatform
public function __construct() public function __construct()
{ {
parent::__construct(); parent::__construct();
$this->_supported = array(
'sequences' => 'emulated',
'indexes' => true,
'affected_rows' => true,
'summary_functions' => true,
'order_by_text' => true,
'current_id' => 'emulated',
'limit_queries' => true,
'LOBs' => true,
'replace' => true,
'transactions' => true,
'savepoints' => false,
'sub_selects' => true,
'auto_increment' => true,
'primary_key' => true,
'result_introspection' => false, // not implemented
'prepared_statements' => 'emulated',
'identifier_quoting' => true,
'pattern_escaping' => false,
);
} }
/** /**

View File

@ -39,7 +39,6 @@
* @link www.phpdoctrine.org * @link www.phpdoctrine.org
* @since 2.0 * @since 2.0
* @version $Revision: 4342 $ * @version $Revision: 4342 $
* @todo Split up into "Entity" and "ActiveEntity" (extends Entity).
*/ */
abstract class Doctrine_Entity extends Doctrine_Access implements Serializable abstract class Doctrine_Entity extends Doctrine_Access implements Serializable
{ {
@ -208,18 +207,6 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable
return $this->_oid; return $this->_oid;
} }
/**
* Hydrates this object from given array
*
* @param array $data
* @return boolean
*/
final public function hydrate(array $data)
{
$this->_data = array_merge($this->_data, $data);
$this->_extractIdentifier();
}
/** /**
* Copies the identifier names and values from _data into _id. * Copies the identifier names and values from _data into _id.
*/ */
@ -375,58 +362,6 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable
} }
} }
/**
* Refresh internal data from the database
*
* @param bool $deep If true, fetch also current relations. Caution: this deletes
* any aggregated values you may have queried beforee
*
* @throws Doctrine_Record_Exception When the refresh operation fails (when the database row
* this record represents does not exist anymore)
* @return boolean
* @todo Implementation to EntityManager.
* @todo Move to ActiveEntity (extends Entity). Implementation to EntityManager.
*/
public function refresh($deep = false)
{
$id = $this->identifier();
if ( ! is_array($id)) {
$id = array($id);
}
if (empty($id)) {
return false;
}
$id = array_values($id);
if ($deep) {
$query = $this->_em->createQuery()->from($this->_entityName);
foreach (array_keys($this->_references) as $name) {
$query->leftJoin(get_class($this) . '.' . $name);
}
$query->where(implode(' = ? AND ', $this->_class->getIdentifierColumnNames()) . ' = ?');
$this->clearRelated();
$record = $query->fetchOne($id);
} else {
// Use FETCH_ARRAY to avoid clearing object relations
$record = $this->getRepository()->find($this->identifier(), Doctrine::HYDRATE_ARRAY);
if ($record) {
$this->hydrate($record);
}
}
if ($record === false) {
throw new Doctrine_Record_Exception('Failed to refresh. Record does not exist.');
}
$this->_modified = array();
$this->_extractIdentifier();
$this->_state = Doctrine_Entity::STATE_CLEAN;
return $this;
}
/** /**
* Gets the current field values. * Gets the current field values.
* *
@ -438,48 +373,38 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable
} }
/** /**
* INTERNAL: (Usage from within extending classes is intended)
*
* Gets the value of a field (regular field or reference). * Gets the value of a field (regular field or reference).
* If the field is not yet loaded this method does NOT load it. * If the field is not yet loaded this method does NOT load it.
*
* NOTE: Use of this method from outside the scope of an extending class
* is strongly discouraged.
* *
* @param $name name of the property * @param $name name of the property
* @throws Doctrine_Entity_Exception if trying to get an unknown field * @throws Doctrine_Entity_Exception if trying to get an unknown field
* @return mixed * @return mixed
*/ */
final public function _get($fieldName) final protected function _get($fieldName)
{ {
if (isset($this->_data[$fieldName])) { if (isset($this->_data[$fieldName])) {
return $this->_rawGetField($fieldName); return $this->_internalGetField($fieldName);
} else if (isset($this->_references[$fieldName])) { } else if (isset($this->_references[$fieldName])) {
return $this->_rawGetReference($fieldName); return $this->_internalGetReference($fieldName);
} else { } else {
throw Doctrine_Entity_Exception::unknownField($fieldName); throw Doctrine_Entity_Exception::unknownField($fieldName);
} }
} }
/** /**
* INTERNAL: (Usage from within extending classes is intended)
*
* Sets the value of a field (regular field or reference). * Sets the value of a field (regular field or reference).
* If the field is not yet loaded this method does NOT load it. * If the field is not yet loaded this method does NOT load it.
*
* NOTE: Use of this method from outside the scope of an extending class
* is strongly discouraged.
* *
* @param $name name of the field * @param $name name of the field
* @throws Doctrine_Entity_Exception if trying to get an unknown field * @throws Doctrine_Entity_Exception if trying to get an unknown field
* @return mixed * @return mixed
*/ */
final public function _set($fieldName, $value) final protected function _set($fieldName, $value)
{ {
if (isset($this->_data[$fieldName])) { if ($this->_class->hasField($fieldName)) {
return $this->_rawSetField($fieldName, $value); return $this->_internalSetField($fieldName, $value);
} else if (isset($this->_references[$fieldName])) { } else if ($this->_class->hasRelation($fieldName)) {
return $this->_rawSetReference($fieldName, $value); return $this->_internalSetReference($fieldName, $value);
} else { } else {
throw Doctrine_Entity_Exception::unknownField($fieldName); throw Doctrine_Entity_Exception::unknownField($fieldName);
} }
@ -489,15 +414,15 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable
* INTERNAL: * INTERNAL:
* Gets the value of a field. * Gets the value of a field.
* *
* NOTE: Use of this method from outside the scope of an extending class * NOTE: Use of this method in userland code is strongly discouraged.
* is strongly discouraged. This method does NOT check whether the field * This method does NOT check whether the field exists.
* exists. _get() in extending classes should be preferred. * _get() in extending classes should be preferred.
* *
* @param string $fieldName * @param string $fieldName
* @return mixed * @return mixed
* @todo Rename to _unsafeGetField() * @todo Rename to _unsafeGetField()
*/ */
final public function _rawGetField($fieldName) final public function _internalGetField($fieldName)
{ {
if ($this->_data[$fieldName] === Doctrine_Null::$INSTANCE) { if ($this->_data[$fieldName] === Doctrine_Null::$INSTANCE) {
return null; return null;
@ -509,15 +434,14 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable
* INTERNAL: * INTERNAL:
* Sets the value of a field. * Sets the value of a field.
* *
* NOTE: Use of this method from outside the scope of an extending class * NOTE: Use of this method in userland code is strongly discouraged.
* is strongly discouraged. This method does NOT check whether the field * This method does NOT check whether the field exists.
* exists. _set() in extending classes should be preferred. * _set() in extending classes should be preferred.
* *
* @param string $fieldName * @param string $fieldName
* @param mixed $value * @param mixed $value
* @todo Rename to _unsafeSetField()
*/ */
final public function _rawSetField($fieldName, $value) final public function _internalSetField($fieldName, $value)
{ {
$this->_data[$fieldName] = $value; $this->_data[$fieldName] = $value;
} }
@ -525,14 +449,12 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable
/** /**
* Gets a reference to another Entity. * Gets a reference to another Entity.
* *
* NOTE: Use of this method from outside the scope of an extending class * NOTE: Use of this method in userland code is strongly discouraged.
* is strongly discouraged. This method does NOT check whether the reference * This method does NOT check whether the reference exists.
* exists.
* *
* @param string $fieldName * @param string $fieldName
* @todo Rename to _unsafeGetReference().
*/ */
final public function _rawGetReference($fieldName) final public function _internalGetReference($fieldName)
{ {
if ($this->_references[$fieldName] === Doctrine_Null::$INSTANCE) { if ($this->_references[$fieldName] === Doctrine_Null::$INSTANCE) {
return null; return null;
@ -544,14 +466,14 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable
* INTERNAL: * INTERNAL:
* Sets a reference to another Entity. * Sets a reference to another Entity.
* *
* NOTE: Use of this method is strongly discouraged for user-code. * NOTE: Use of this method in userland code is strongly discouraged.
* *
* @param string $fieldName * @param string $fieldName
* @param mixed $value * @param mixed $value
* @todo Refactor. What about composite keys? * @todo Refactor. What about composite keys?
* @todo Rename to _unsafeSetReference() * @todo Rename to _unsafeSetReference()
*/ */
final public function _rawSetReference($name, $value) final public function _internalSetReference($name, $value)
{ {
if ($value === Doctrine_Null::$INSTANCE) { if ($value === Doctrine_Null::$INSTANCE) {
$this->_references[$name] = $value; $this->_references[$name] = $value;
@ -602,11 +524,9 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable
} }
/** /**
* Generic getter. * Generic getter for all persistent fields.
* *
* @param mixed $name name of the property or related component * @param string $fieldName Name of the field.
* @param boolean $load whether or not to invoke the loading procedure
* @throws Doctrine_Record_Exception if trying to get a value of unknown property / related component
* @return mixed * @return mixed
*/ */
final public function get($fieldName) final public function get($fieldName)
@ -710,10 +630,10 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable
} }
/** /**
* Generic setter. * Generic setter for persistent fields.
* *
* @param mixed $name name of the property or reference * @param string $name The name of the field to set.
* @param mixed $value value of the property or reference * @param mixed $value The value of the field.
*/ */
final public function set($fieldName, $value) final public function set($fieldName, $value)
{ {
@ -742,7 +662,7 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable
} }
} }
} else if ($this->_class->hasRelation($fieldName)) { } else if ($this->_class->hasRelation($fieldName)) {
$this->_rawSetReference($fieldName, $value); $this->_internalSetReference($fieldName, $value);
} else { } else {
throw Doctrine_Entity_Exception::invalidField($fieldName); throw Doctrine_Entity_Exception::invalidField($fieldName);
} }
@ -795,45 +715,6 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable
} }
} }
} }
/**
* Saves the current state of the entity into the database.
*
* @param Doctrine_Connection $conn optional connection parameter
* @return void
* @todo ActiveEntity method.
*/
public function save()
{
// TODO: Forward to EntityManager. There: registerNew() OR registerDirty() on UnitOfWork.
$this->_em->save($this);
}
/**
* 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
* key field values, the REPLACE query just updates its values instead of
* inserting a new row.
*
* 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
* query isemulated through this method for other DBMS using standard types
* of queries inside a transaction to assure the atomicity of the operation.
*
* @param Doctrine_Connection $conn optional connection parameter
* @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 something fails at database level
* @return integer number of rows affected
* @todo ActiveEntity method.
*/
public function replace()
{
return $this->_em->replace(
$this->_class,
$this->getPrepared(),
$this->_id);
}
/** /**
* INTERNAL: * INTERNAL:
@ -908,160 +789,6 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable
return $dataSet; return $dataSet;
} }
/**
* Creates an array representation of the object's data.
*
* @param boolean $deep - Return also the relations
* @return array
* @todo ActiveEntity method.
*/
public function toArray($deep = true, $prefixKey = false)
{
$a = array();
foreach ($this as $column => $value) {
if ($value === Doctrine_Null::$INSTANCE || is_object($value)) {
$value = null;
}
$a[$column] = $value;
}
if ($this->_class->getIdentifierType() == Doctrine::IDENTIFIER_AUTOINC) {
$idFieldNames = $this->_class->getIdentifier();
$idFieldName = $idFieldNames[0];
$ids = $this->identifier();
$id = count($ids) > 0 ? array_pop($ids) : null;
$a[$idFieldName] = $id;
}
if ($deep) {
foreach ($this->_references as $key => $relation) {
if ( ! $relation instanceof Doctrine_Null) {
$a[$key] = $relation->toArray($deep, $prefixKey);
}
}
}
// [FIX] Prevent mapped Doctrine_Entitys from being displayed fully
foreach ($this->_values as $key => $value) {
if ($value instanceof Doctrine_Entity) {
$a[$key] = $value->toArray($deep, $prefixKey);
} else {
$a[$key] = $value;
}
}
return $a;
}
/**
* Merges this Entity with an array of values
* or with another existing instance of.
*
* @param mixed $data Data to merge. Either another instance of this model or an array
* @param bool $deep Bool value for whether or not to merge the data deep
* @return void
* @todo ActiveEntity method.
*/
public function merge($data, $deep = true)
{
if ($data instanceof $this) {
$array = $data->toArray($deep);
} else if (is_array($data)) {
$array = $data;
} else {
$array = array();
}
return $this->fromArray($array, $deep);
}
/**
* fromArray
*
* @param string $array
* @param bool $deep Bool value for whether or not to merge the data deep
* @return void
* @todo ActiveEntity method.
*/
public function fromArray($array, $deep = true)
{
if (is_array($array)) {
foreach ($array as $key => $value) {
if ($deep && $this->getTable()->hasRelation($key)) {
$this->$key->fromArray($value, $deep);
} else if ($this->getTable()->hasField($key)) {
$this->set($key, $value);
}
}
}
}
/**
* Synchronizes a Doctrine_Entity and its relations with data from an array
*
* It expects an array representation of a Doctrine_Entity similar to the return
* value of the toArray() method. If the array contains relations it will create
* those that don't exist, update the ones that do, and delete the ones missing
* on the array but available on the Doctrine_Entity
*
* @param array $array representation of a Doctrine_Entity
* @todo ActiveEntity method.
*/
public function synchronizeFromArray(array $array)
{
foreach ($array as $key => $value) {
if ($this->getTable()->hasRelation($key)) {
$this->get($key)->synchronizeFromArray($value);
} else if ($this->getTable()->hasColumn($key)) {
$this->set($key, $value);
}
}
// eliminate relationships missing in the $array
foreach ($this->_references as $name => $obj) {
if ( ! isset($array[$name])) {
unset($this->$name);
}
}
}
/**
* exportTo
*
* @param string $type
* @param string $deep
* @return void
* @todo ActiveEntity method.
*/
public function exportTo($type, $deep = true)
{
if ($type == 'array') {
return $this->toArray($deep);
} else {
return Doctrine_Parser::dump($this->toArray($deep, true), $type);
}
}
/**
* importFrom
*
* @param string $type
* @param string $data
* @return void
* @author Jonathan H. Wage
* @todo ActiveEntity method.
*/
public function importFrom($type, $data)
{
if ($type == 'array') {
return $this->fromArray($data);
} else {
return $this->fromArray(Doctrine_Parser::load($data, $type));
}
}
/** /**
* Checks whether the entity already has a persistent state. * Checks whether the entity already has a persistent state.
@ -1084,58 +811,6 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable
return count($this->_modified) > 0; return count($this->_modified) > 0;
} }
/**
* Deletes the persistent state of the entity.
*
* @return boolean TRUE on success, FALSE on failure.
* @todo ActiveRecord method.
*/
public function delete()
{
// TODO: Forward to EntityManager. There: registerRemoved() on UnitOfWork
return $this->_em->remove($this);
}
/**
* Creates a copy of the entity.
*
* @return Doctrine_Entity
* @todo ActiveEntity method. Implementation to EntityManager.
*/
public function copy($deep = true)
{
$data = $this->_data;
if ($this->_class->getIdentifierType() === Doctrine::IDENTIFIER_AUTOINC) {
$idFieldNames = (array)$this->_class->getIdentifier();
$id = $idFieldNames[0];
unset($data[$id]);
}
$ret = $this->_em->createEntity($this->_entityName, $data);
$modified = array();
foreach ($data as $key => $val) {
if ( ! ($val instanceof Doctrine_Null)) {
$ret->_modified[] = $key;
}
}
if ($deep) {
foreach ($this->_references as $key => $value) {
if ($value instanceof Doctrine_Collection) {
foreach ($value as $record) {
$ret->{$key}[] = $record->copy($deep);
}
} else {
$ret->set($key, $value->copy($deep));
}
}
}
return $ret;
}
/** /**
* INTERNAL: * INTERNAL:
* Assigns an identifier to the entity. This is only intended for use by * Assigns an identifier to the entity. This is only intended for use by
@ -1219,132 +894,6 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable
$this->_references[$alias] = $coll; $this->_references[$alias] = $coll;
} }
/**
* Removes links from this record to given records
* if no ids are given, it removes all links
*
* @param string $alias related component alias
* @param array $ids the identifiers of the related records
* @return Doctrine_Entity this object
* @todo ActiveEntity method.
*/
public function unlink($alias, $ids = array())
{
$ids = (array) $ids;
$q = new Doctrine_Query();
$rel = $this->getTable()->getRelation($alias);
if ($rel instanceof Doctrine_Relation_Association) {
$q->delete()
->from($rel->getAssociationTable()->getComponentName())
->where($rel->getLocal() . ' = ?', array_values($this->identifier()));
if (count($ids) > 0) {
$q->whereIn($rel->getForeign(), $ids);
}
$q->execute();
} else if ($rel instanceof Doctrine_Relation_ForeignKey) {
$q->update($rel->getTable()->getComponentName())
->set($rel->getForeign(), '?', array(null))
->addWhere($rel->getForeign() . ' = ?', array_values($this->identifier()));
if (count($ids) > 0) {
$relTableIdFieldNames = (array)$rel->getTable()->getIdentifier();
$q->whereIn($relTableIdFieldNames[0], $ids);
}
$q->execute();
}
if (isset($this->_references[$alias])) {
foreach ($this->_references[$alias] as $k => $record) {
if (in_array(current($record->identifier()), $ids)) {
$this->_references[$alias]->remove($k);
}
}
$this->_references[$alias]->takeSnapshot();
}
return $this;
}
/**
* Creates links from this record to given records.
*
* @param string $alias related component alias
* @param array $ids the identifiers of the related records
* @return Doctrine_Entity this object
* @todo ActiveEntity method.
*/
public function link($alias, array $ids)
{
if ( ! count($ids)) {
return $this;
}
$identifier = array_values($this->identifier());
$identifier = array_shift($identifier);
$rel = $this->getTable()->getRelation($alias);
if ($rel instanceof Doctrine_Relation_Association) {
$modelClassName = $rel->getAssociationTable()->getComponentName();
$localFieldName = $rel->getLocalFieldName();
$localFieldDef = $rel->getAssociationTable()->getColumnDefinition($localFieldName);
if ($localFieldDef['type'] == 'integer') {
$identifier = (integer) $identifier;
}
$foreignFieldName = $rel->getForeignFieldName();
$foreignFieldDef = $rel->getAssociationTable()->getColumnDefinition($foreignFieldName);
if ($foreignFieldDef['type'] == 'integer') {
for ($i = 0; $i < count($ids); $i++) {
$ids[$i] = (integer) $ids[$i];
}
}
foreach ($ids as $id) {
$record = new $modelClassName;
$record[$localFieldName] = $identifier;
$record[$foreignFieldName] = $id;
$record->save();
}
} else if ($rel instanceof Doctrine_Relation_ForeignKey) {
$q = new Doctrine_Query();
$q->update($rel->getTable()->getComponentName())
->set($rel->getForeign(), '?', array_values($this->identifier()));
if (count($ids) > 0) {
$relTableIdFieldNames = (array)$rel->getTable()->getIdentifier();
$q->whereIn($relTableIdFieldNames[0], $ids);
}
$q->execute();
} else if ($rel instanceof Doctrine_Relation_LocalKey) {
$q = new Doctrine_Query();
$q->update($this->getTable()->getComponentName())
->set($rel->getLocalFieldName(), '?', $ids);
if (count($ids) > 0) {
$relTableIdFieldNames = (array)$rel->getTable()->getIdentifier();
$q->whereIn($relTableIdFieldNames[0], array_values($this->identifier()));
}
$q->execute();
}
return $this;
}
/** /**
* Gets the ClassMetadata object that describes the entity class. * Gets the ClassMetadata object that describes the entity class.
* *
@ -1390,7 +939,7 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable
*/ */
public function __toString() public function __toString()
{ {
return (string) $this->_oid; return (string)$this->_oid;
} }
/** /**

View File

@ -74,7 +74,7 @@ class Doctrine_Hydrator_RecordDriver
$relatedClass = $relation->getTable(); $relatedClass = $relation->getTable();
$coll = $this->getElementCollection($relatedClass->getClassName()); $coll = $this->getElementCollection($relatedClass->getClassName());
$coll->setReference($entity, $relation); $coll->setReference($entity, $relation);
$entity->_rawSetReference($name, $coll); $entity->_internalSetReference($name, $coll);
$this->_initializedRelations[$entity->getOid()][$name] = true; $this->_initializedRelations[$entity->getOid()][$name] = true;
} }
} }
@ -97,23 +97,23 @@ class Doctrine_Hydrator_RecordDriver
public function addRelatedIndexedElement(Doctrine_Entity $entity1, $property, public function addRelatedIndexedElement(Doctrine_Entity $entity1, $property,
Doctrine_Entity $entity2, $indexField) Doctrine_Entity $entity2, $indexField)
{ {
$entity1->_rawGetReference($property)->add($entity2, $entity2->_rawGetField($indexField)); $entity1->_internalGetReference($property)->add($entity2, $entity2->_internalGetField($indexField));
} }
public function addRelatedElement(Doctrine_Entity $entity1, $property, public function addRelatedElement(Doctrine_Entity $entity1, $property,
Doctrine_Entity $entity2) Doctrine_Entity $entity2)
{ {
$entity1->_rawGetReference($property)->add($entity2); $entity1->_internalGetReference($property)->add($entity2);
} }
public function setRelatedElement(Doctrine_Entity $entity1, $property, $entity2) public function setRelatedElement(Doctrine_Entity $entity1, $property, $entity2)
{ {
$entity1->_rawSetReference($property, $entity2); $entity1->_internalSetReference($property, $entity2);
} }
public function isIndexKeyInUse(Doctrine_Entity $entity, $assocField, $indexField) public function isIndexKeyInUse(Doctrine_Entity $entity, $assocField, $indexField)
{ {
return $entity->_rawGetReference($assocField)->contains($indexField); return $entity->_internalGetReference($assocField)->contains($indexField);
} }
public function isFieldSet(Doctrine_Entity $entity, $field) public function isFieldSet(Doctrine_Entity $entity, $field)
@ -123,17 +123,17 @@ class Doctrine_Hydrator_RecordDriver
public function getFieldValue(Doctrine_Entity $entity, $field) public function getFieldValue(Doctrine_Entity $entity, $field)
{ {
return $entity->_rawGetField($field); return $entity->_internalGetField($field);
} }
public function getReferenceValue(Doctrine_Entity $entity, $field) public function getReferenceValue(Doctrine_Entity $entity, $field)
{ {
return $entity->_rawGetReference($field); return $entity->_internalGetReference($field);
} }
public function addElementToIndexedCollection($coll, $entity, $keyField) public function addElementToIndexedCollection($coll, $entity, $keyField)
{ {
$coll->add($entity, $entity->_rawGetField($keyField)); $coll->add($entity, $entity->_internalGetField($keyField));
} }
public function addElementToCollection($coll, $entity) public function addElementToCollection($coll, $entity)

View File

@ -165,7 +165,6 @@ class Doctrine_Query_Parser
if ( ! $isMatch) { if ( ! $isMatch) {
// No definition for value checking. // No definition for value checking.
$this->syntaxError($this->_keywordTable->getLiteral($token)); $this->syntaxError($this->_keywordTable->getLiteral($token));
} }
$this->next(); $this->next();

View File

@ -45,26 +45,26 @@ class Doctrine_Query_Production_Atom extends Doctrine_Query_Production
case Doctrine_Query_Token::T_STRING: case Doctrine_Query_Token::T_STRING:
$this->_parser->match(Doctrine_Query_Token::T_STRING); $this->_parser->match(Doctrine_Query_Token::T_STRING);
$this->_type = 'string'; $this->_type = 'string';
break; break;
case Doctrine_Query_Token::T_INTEGER: case Doctrine_Query_Token::T_INTEGER:
$this->_parser->match(Doctrine_Query_Token::T_INTEGER); $this->_parser->match(Doctrine_Query_Token::T_INTEGER);
$this->_type = 'integer'; $this->_type = 'integer';
break; break;
case Doctrine_Query_Token::T_FLOAT: case Doctrine_Query_Token::T_FLOAT:
$this->_parser->match(Doctrine_Query_Token::T_FLOAT); $this->_parser->match(Doctrine_Query_Token::T_FLOAT);
$this->_type = 'float'; $this->_type = 'float';
break; break;
case Doctrine_Query_Token::T_INPUT_PARAMETER: case Doctrine_Query_Token::T_INPUT_PARAMETER:
$this->_parser->match(Doctrine_Query_Token::T_INPUT_PARAMETER); $this->_parser->match(Doctrine_Query_Token::T_INPUT_PARAMETER);
$this->_type = 'param'; $this->_type = 'param';
break; break;
default: default:
$this->_parser->syntaxError('string, number or parameter (? or :)'); $this->_parser->syntaxError('string, number or parameter (? or :)');
break; break;
} }
$this->_value = $this->_parser->token['value']; $this->_value = $this->_parser->token['value'];
@ -78,19 +78,20 @@ class Doctrine_Query_Production_Atom extends Doctrine_Query_Production
switch ($this->_type) { switch ($this->_type) {
case 'param': case 'param':
return $this->_value; return $this->_value;
break; case 'string':
//FIXME: Remove the quotes from _value! Should the scanner do that or where?
case 'integer': // 'mystring' => mystring. Otherwise 'mystring' is the content (with quotes)!
case 'float': // Eg: select ... from ... where f.foo = 'bar'
// => $conn->quote('bar',...), CURRENTLY: $conn->quote("'bar'",...)
// This fix looks a bit ugly or ... ? Should this happen earlier? Syntax?
// Scanner?
if (strpos($this->_value, "'") === 0) {
$this->_value = substr($this->_value, 1, strlen($this->_value) - 2);
}
return $conn->quote($this->_value, $this->_type); return $conn->quote($this->_value, $this->_type);
break;
default: default:
$stringQuoting = $conn->getDatabasePlatform()->getProperty('string_quoting'); return $conn->quote($this->_value, $this->_type);
return $stringQuoting['start']
. $conn->quote($this->_value, $this->_type)
. $stringQuoting['end'];
break;
} }
} }

View File

@ -33,14 +33,18 @@
class Doctrine_Query_Scanner class Doctrine_Query_Scanner
{ {
/** /**
* Array of scanned tokens * Array of scanned tokens.
* *
* @var array * @var array
*/ */
protected $_tokens = array(); protected $_tokens = array();
/**
* @todo Doc
*/
protected $_position = 0; protected $_position = 0;
/**
* @todo Doc
*/
protected $_peek = 0; protected $_peek = 0;
/** /**
@ -109,7 +113,9 @@ class Doctrine_Query_Scanner
} }
} }
/**
* @todo Doc
*/
protected function _getType(&$value) protected function _getType(&$value)
{ {
// $value is referenced because it can be changed if it is numeric. // $value is referenced because it can be changed if it is numeric.
@ -117,30 +123,32 @@ class Doctrine_Query_Scanner
$type = Doctrine_Query_Token::T_NONE; $type = Doctrine_Query_Token::T_NONE;
$newVal = $this->_getNumeric($value); $newVal = $this->_getNumeric($value);
if($newVal !== false){ if ($newVal !== false){
$value = $newVal; $value = $newVal;
if (strpos($value, '.') !== false || stripos($value, 'e') !== false) { if (strpos($value, '.') !== false || stripos($value, 'e') !== false) {
$type = Doctrine_Query_Token::T_FLOAT; $type = Doctrine_Query_Token::T_FLOAT;
} else{ } else {
$type = Doctrine_Query_Token::T_INTEGER; $type = Doctrine_Query_Token::T_INTEGER;
} }
} }
if ($value[0] === "'" && $value[strlen($value) - 1] === "'") { if ($value[0] === "'" && $value[strlen($value) - 1] === "'") {
$type = Doctrine_Query_Token::T_STRING; $type = Doctrine_Query_Token::T_STRING;
} elseif (ctype_alpha($value[0]) || $value[0] === '_') { } else if (ctype_alpha($value[0]) || $value[0] === '_') {
$type = $this->_checkLiteral($value); $type = $this->_checkLiteral($value);
} elseif ($value[0] === '?' || $value[0] === ':') { } else if ($value[0] === '?' || $value[0] === ':') {
$type = Doctrine_Query_Token::T_INPUT_PARAMETER; $type = Doctrine_Query_Token::T_INPUT_PARAMETER;
} }
return $type; return $type;
} }
/**
* @todo Doc
*/
protected function _getNumeric($value) protected function _getNumeric($value)
{ {
if (!is_scalar($value)) { if ( ! is_scalar($value)) {
return false; return false;
} }
// Checking for valid numeric numbers: 1.234, -1.234e-2 // Checking for valid numeric numbers: 1.234, -1.234e-2
@ -164,7 +172,9 @@ class Doctrine_Query_Scanner
} }
/**
* @todo Doc
*/
public function isA($value, $token) public function isA($value, $token)
{ {
$type = $this->_getType($value); $type = $this->_getType($value);
@ -172,7 +182,9 @@ class Doctrine_Query_Scanner
return $type === $token; return $type === $token;
} }
/**
* @todo Doc
*/
public function peek() public function peek()
{ {
if (isset($this->_tokens[$this->_position + $this->_peek])) { if (isset($this->_tokens[$this->_position + $this->_peek])) {
@ -182,13 +194,14 @@ class Doctrine_Query_Scanner
} }
} }
/**
* @todo Doc
*/
public function resetPeek() public function resetPeek()
{ {
$this->_peek = 0; $this->_peek = 0;
} }
/** /**
* Returns the next token in the input string. * Returns the next token in the input string.
* *
@ -211,7 +224,9 @@ class Doctrine_Query_Scanner
} }
} }
/**
* @todo Doc
*/
public function resetPosition($position = 0) public function resetPosition($position = 0)
{ {
$this->_position = $position; $this->_position = $position;

View File

@ -29,7 +29,8 @@
* @version $Revision: 1397 $ * @version $Revision: 1397 $
* @link www.phpdoctrine.org * @link www.phpdoctrine.org
* @since 1.0 * @since 1.0
* @todo Composite key support? * @todo Composite key support?
* @todo Remove. Association mapping needs a reimplementation.
*/ */
class Doctrine_Relation_Parser class Doctrine_Relation_Parser
{ {

View File

@ -44,9 +44,9 @@ class Doctrine_Sequence_Mysql extends Doctrine_Sequence
*/ */
public function nextId($seqName, $onDemand = true) public function nextId($seqName, $onDemand = true)
{ {
$sequenceName = $this->conn->quoteIdentifier($this->conn->formatter->getSequenceName($seqName), true); $sequenceName = $this->conn->quoteIdentifier($this->conn->formatter->getSequenceName($seqName), true);
$seqcolName = $this->conn->quoteIdentifier($this->conn->getAttribute(Doctrine::ATTR_SEQCOL_NAME), true); $seqcolName = $this->conn->quoteIdentifier($this->conn->getAttribute(Doctrine::ATTR_SEQCOL_NAME), true);
$query = 'INSERT INTO ' . $sequenceName . ' (' . $seqcolName . ') VALUES (NULL)'; $query = 'INSERT INTO ' . $sequenceName . ' (' . $seqcolName . ') VALUES (NULL)';
try { try {
$this->conn->exec($query); $this->conn->exec($query);
@ -68,7 +68,7 @@ class Doctrine_Sequence_Mysql extends Doctrine_Sequence
$query = 'DELETE FROM ' . $sequenceName . ' WHERE ' . $seqcolName . ' < ' . $value; $query = 'DELETE FROM ' . $sequenceName . ' WHERE ' . $seqcolName . ' < ' . $value;
try { try {
$this->conn->exec($query); $this->conn->exec($query);
} catch(Doctrine_Exception $e) { } catch (Doctrine_Exception $e) {
throw new Doctrine_Sequence_Exception('could not delete previous sequence table values from ' . $seqName); throw new Doctrine_Sequence_Exception('could not delete previous sequence table values from ' . $seqName);
} }
} }

View File

@ -40,7 +40,7 @@ class Doctrine_Sequence_Oracle extends Doctrine_Sequence
* *
* @return integer next id in the given sequence * @return integer next id in the given sequence
*/ */
public function nextID($seqName, $onDemand = true) public function nextId($seqName, $onDemand = true)
{ {
$sequenceName = $this->conn->quoteIdentifier($this->conn->formatter->getSequenceName($seqName), true); $sequenceName = $this->conn->quoteIdentifier($this->conn->formatter->getSequenceName($seqName), true);
$query = 'SELECT ' . $sequenceName . '.nextval FROM DUAL'; $query = 'SELECT ' . $sequenceName . '.nextval FROM DUAL';
@ -69,10 +69,10 @@ class Doctrine_Sequence_Oracle extends Doctrine_Sequence
* @param string name of the table into which a new row was inserted * @param string name of the table into which a new row was inserted
* @param string name of the field into which a new row was inserted * @param string name of the field into which a new row was inserted
*/ */
public function lastInsertID($table = null, $field = null) public function lastInsertId($table = null, $field = null)
{ {
$seqName = $table . (empty($field) ? '' : '_'.$field); $seqName = $table . (empty($field) ? '' : '_'.$field);
$sequenceName = $this->conn->quoteIdentifier($this->conn->formatter->getSequenceName($seqName), true); $sequenceName = $this->conn->quoteIdentifier($this->conn->formatter->getSequenceName($seqName), true);
return $this->conn->fetchOne('SELECT ' . $sequenceName . '.currval'); return $this->conn->fetchOne('SELECT ' . $sequenceName . '.currval');
} }
@ -84,7 +84,7 @@ class Doctrine_Sequence_Oracle extends Doctrine_Sequence
* *
* @return integer current id in the given sequence * @return integer current id in the given sequence
*/ */
public function currID($seqName) public function currId($seqName)
{ {
$sequenceName = $this->conn->quoteIdentifier($this->conn->formatter->getSequenceName($seqName), true); $sequenceName = $this->conn->quoteIdentifier($this->conn->formatter->getSequenceName($seqName), true);
$query = 'SELECT (last_number-1) FROM user_sequences'; $query = 'SELECT (last_number-1) FROM user_sequences';

View File

@ -13,8 +13,6 @@ class Orm_Entity_AccessorTest extends Doctrine_OrmTestCase
$entity2->username = 'romanb'; $entity2->username = 'romanb';
$this->assertEquals('romanb?!', $entity1->username); $this->assertEquals('romanb?!', $entity1->username);
} }
} }
@ -41,12 +39,12 @@ class CustomAccessorMutatorTestEntity extends Doctrine_Entity
public function getUsernameCustom() public function getUsernameCustom()
{ {
return $this->_rawGetField('username') . "!"; return $this->_get('username') . "!";
} }
public function setUsernameCustom($username) public function setUsernameCustom($username)
{ {
$this->_rawSetField('username', $username . "?"); $this->_set('username', $username . "?");
} }
} }
@ -69,11 +67,11 @@ class MagicAccessorMutatorTestEntity extends Doctrine_Entity
public function getUsername() public function getUsername()
{ {
return $this->_rawGetField('username') . "!"; return $this->_get('username') . "!";
} }
public function setUsername($username) public function setUsername($username)
{ {
$this->_rawSetField('username', $username . "?"); $this->_set('username', $username . "?");
} }
} }

View File

@ -134,7 +134,9 @@ class Orm_Query_SelectSqlGenerationTest extends Doctrine_OrmTestCase
{ {
$this->assertSqlGeneration( $this->assertSqlGeneration(
"SELECT u.name FROM CmsUser u WHERE TRIM(u.name) = 'someone'", "SELECT u.name FROM CmsUser u WHERE TRIM(u.name) = 'someone'",
"SELECT cu.name AS cu__name FROM cms_user cu WHERE TRIM(cu.name) = ''someone''" // SQLite double slashes for strings // String quoting in the SQL usually depends on the database platform.
// This test works with a mock connection which uses ' for string quoting.
"SELECT cu.name AS cu__name FROM cms_user cu WHERE TRIM(cu.name) = 'someone'"
); );
} }