Commit 909e98c6 authored by romanb's avatar romanb

[2.0][DDC-202][DDC-132][DDC-185] Fixed.

parent a26464da
......@@ -292,7 +292,8 @@ class Connection
/**
* Establishes the connection with the database.
*
* @return boolean
* @return boolean TRUE if the connection was successfully established, FALSE if
* the connection is already open.
*/
public function connect()
{
......@@ -311,11 +312,13 @@ class Connection
}
/**
* Convenience method for PDO::query("...") followed by $stmt->fetch(PDO::FETCH_ASSOC).
* Prepares and executes an SQL query and returns the first row of the result
* as an associative array.
*
* @param string $statement The SQL query.
* @param array $params The query parameters.
* @return array
* @todo Rename: fetchAssoc
*/
public function fetchRow($statement, array $params = array())
{
......@@ -323,7 +326,8 @@ class Connection
}
/**
* Convenience method for PDO::query("...") followed by $stmt->fetch(PDO::FETCH_NUM).
* Prepares and executes an SQL query and returns the first row of the result
* as a numerically indexed array.
*
* @param string $statement sql query to be executed
* @param array $params prepared statement params
......@@ -335,12 +339,13 @@ class Connection
}
/**
* Convenience method for PDO::query("...") followed by $stmt->fetchColumn(...).
* Prepares and executes an SQL query and returns the value of a single column
* of the first row of the result.
*
* @param string $statement sql query to be executed
* @param array $params prepared statement params
* @param int $colnum 0-indexed column number to retrieve
* @return array
* @return mixed
*/
public function fetchColumn($statement, array $params = array(), $colnum = 0)
{
......@@ -357,22 +362,10 @@ class Connection
return $this->_isConnected;
}
/**
* Convenience method for PDO::query("...") followed by $stmt->fetchAll(PDO::FETCH_BOTH).
*
* @param string $statement sql query to be executed
* @param array $params prepared statement params
* @return array
*/
public function fetchBoth($statement, array $params = array())
{
return $this->execute($statement, $params)->fetchAll(Connection::FETCH_BOTH);
}
/**
* Deletes table row(s) matching the specified identifier.
*
* @param string $table The table to delete data from
* @param string $table The table to delete data from.
* @param array $identifier An associateve array containing identifier fieldname-value pairs.
* @return integer The number of affected rows
*/
......@@ -532,7 +525,7 @@ class Connection
}
/**
* Convenience method for PDO::query("...") followed by $stmt->fetchAll(PDO::FETCH_ASSOC).
* Prepares and executes an SQL query and returns the result as an associative array.
*
* @param string $sql The SQL query.
* @param array $params The query parameters.
......@@ -546,8 +539,8 @@ class Connection
/**
* Prepares an SQL statement.
*
* @param string $statement
* @return Statement
* @param string $statement The SQL statement to prepare.
* @return Statement The prepared statement.
*/
public function prepare($statement)
{
......@@ -557,29 +550,11 @@ class Connection
}
/**
* Queries the database with limit and offset added to the query and returns
* a Statement object.
* Prepares and executes an SQL query.
*
* @param string $query
* @param integer $limit
* @param integer $offset
* @return Statement
*/
public function select($query, $limit = 0, $offset = 0)
{
if ($limit > 0 || $offset > 0) {
$query = $this->_platform->modifyLimitQuery($query, $limit, $offset);
}
return $this->execute($query);
}
/**
* Executes an SQL SELECT query with the given parameters.
*
* @param string $query sql query
* @param array $params query parameters
* @return PDOStatement
* @param string $query The SQL query to prepare and execute.
* @param array $params The parameters, if any.
* @return Statement The prepared and executed statement.
*/
public function execute($query, array $params = array())
{
......@@ -599,6 +574,35 @@ class Connection
return $stmt;
}
/**
* Prepares and executes an SQL query and returns the result, optionally applying a
* transformation on the rows of the result.
*
* @param string $query The SQL query to execute.
* @param array $params The parameters, if any.
* @param Closure $mapper The transformation function that is applied on each row.
* The function receives a single paramater, an array, that
* represents a row of the result set.
* @return mixed The (possibly transformed) result of the query.
*/
public function query($query, array $params = array(), \Closure $mapper = null)
{
$result = array();
$stmt = $this->execute($query, $params);
while ($row = $stmt->fetch()) {
if ($mapper === null) {
$result[] = $row;
} else {
$result[] = $mapper($row);
}
}
$stmt->closeCursor();
return $result;
}
/**
* Executes an SQL INSERT/UPDATE/DELETE query with the given parameters.
*
......@@ -726,7 +730,7 @@ class Connection
* this method can be listened with onPreTransactionRollback and onTransactionRollback
* eventlistener methods
*
* @throws ConnectionException If the rollback operation fails at database level.
* @throws ConnectionException If the rollback operation failed.
*/
public function rollback()
{
......
......@@ -143,7 +143,7 @@ class OCI8Statement implements \Doctrine\DBAL\Driver\Statement
/**
* {@inheritdoc}
*/
public function fetch($fetchStyle = Connection::FETCH_BOTH, $cursorOrientation = \PDO::FETCH_ORI_NEXT, $cursorOffset = 0)
public function fetch($fetchStyle = Connection::FETCH_BOTH)
{
if ( ! isset(self::$fetchStyleMap[$fetchStyle])) {
throw new \InvalidArgumentException("Invalid fetch style: " . $fetchStyle);
......@@ -176,38 +176,6 @@ class OCI8Statement implements \Doctrine\DBAL\Driver\Statement
return $row[$columnIndex];
}
/**
* {@inheritdoc}
*/
public function fetchObject($className = 'stdClass', $args = array())
{
throw new \Exception(__METHOD__ . " not supported.");
}
/**
* {@inheritdoc}
*/
public function getAttribute($attribute)
{
throw new \Exception(__METHOD__ . " not supported.");
}
/**
* {@inheritdoc}
*/
public function getColumnMeta($column)
{
throw new \Exception(__METHOD__ . " not supported.");
}
/**
* {@inheritdoc}
*/
public function nextRowset()
{
throw new \Exception(__METHOD__ . " not supported.");
}
/**
* {@inheritdoc}
*/
......@@ -215,21 +183,4 @@ class OCI8Statement implements \Doctrine\DBAL\Driver\Statement
{
return oci_num_rows($this->_sth);
}
/**
* {@inheritdoc}
*/
public function setAttribute($attribute, $value)
{
throw new \Exception(__METHOD__ . " not supported.");
}
/**
* {@inheritdoc}
*/
public function setFetchMode($mode, $arg1)
{
throw new \Exception(__METHOD__ . " not supported.");
}
}
\ No newline at end of file
......@@ -36,6 +36,5 @@ class PDOConnection extends PDO implements Connection
parent::__construct($dsn, $user, $password, $options);
$this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('Doctrine\DBAL\Driver\PDOStatement', array()));
$this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
//$this->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER);
}
}
\ No newline at end of file
......@@ -21,11 +21,13 @@
namespace Doctrine\DBAL\Driver;
use Doctrine\DBAL\Connection as DBALConnection;
/**
* Statement interface.
* Drivers must implement this interface.
*
* This resembles the PDOStatement interface.
* This resembles (a subset of) the PDOStatement interface.
*
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Roman Borschel <roman@code-factory.org>
......@@ -92,7 +94,6 @@ interface Statement
function bindParam($column, &$variable, $type = null, $length = null, $driverOptions = array());
/**
* closeCursor
* Closes the cursor, enabling the statement to be executed again.
*
* @return boolean Returns TRUE on success or FALSE on failure.
......@@ -170,12 +171,9 @@ interface Statement
*
* @return mixed
*/
function fetch($fetchStyle = Query::HYDRATE_BOTH,
$cursorOrientation = Query::HYDRATE_ORI_NEXT,
$cursorOffset = null);
function fetch($fetchStyle = DBALConnection::FETCH_BOTH);
/**
* fetchAll
* Returns an array containing all of the result set rows
*
* @param integer $fetchStyle Controls how the next row will be returned to the caller.
......@@ -187,7 +185,7 @@ interface Statement
*
* @return array
*/
function fetchAll($fetchStyle = Query::HYDRATE_BOTH);
function fetchAll($fetchStyle = DBALConnection::FETCH_BOTH);
/**
* fetchColumn
......@@ -202,62 +200,6 @@ interface Statement
*/
function fetchColumn($columnIndex = 0);
/**
* fetchObject
* 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
* PDOStatement->fetch() with Query::HYDRATE_CLASS or Query::HYDRATE_OBJ style.
*
* @param string $className Name of the created class, defaults to stdClass.
* @param array $args Elements of this array are passed to the constructor.
*
* @return mixed an instance of the required class with property names that correspond
* to the column names or FALSE in case of an error.
*/
function fetchObject($className = 'stdClass', $args = array());
/**
* getAttribute
* Retrieve a statement attribute
*
* @param integer $attribute
* @see Doctrine::ATTR_* constants
* @return mixed the attribute value
*/
function getAttribute($attribute);
/**
* getColumnMeta
* Returns metadata for a column in a result set
*
* @param integer $column The 0-indexed column in the result set.
*
* @return array Associative meta data array with the following structure:
*
* native_type The PHP native type used to represent the column value.
* driver:decl_ type The SQL type used to represent the column value in the database. If the column in the result set is the result of a function, this value is not returned by PDOStatement->getColumnMeta().
* flags Any flags set for this column.
* name The name of this column as returned by the database.
* len The length of this column. Normally -1 for types other than floating point decimals.
* precision The numeric precision of this column. Normally 0 for types other than floating point decimals.
* pdo_type The type of this column as represented by the PDO::PARAM_* constants.
*/
function getColumnMeta($column);
/**
* nextRowset
* Advances to the next rowset in a multi-rowset statement handle
*
* Some database servers support stored procedures that return more than one rowset
* (also known as a result set). The nextRowset() method enables you to access the second
* and subsequent rowsets associated with a PDOStatement object. Each rowset can have a
* different set of columns from the preceding rowset.
*
* @return boolean Returns TRUE on success or FALSE on failure.
*/
function nextRowset();
/**
* rowCount
* rowCount() returns the number of rows affected by the last DELETE, INSERT, or UPDATE statement
......@@ -271,23 +213,4 @@ interface Statement
* @return integer Returns the number of rows.
*/
function rowCount();
/**
* setAttribute
* Set a statement attribute
*
* @param integer $attribute
* @param mixed $value the value of given attribute
* @return boolean Returns TRUE on success or FALSE on failure.
*/
function setAttribute($attribute, $value);
/**
* setFetchMode
* Set the default fetch mode for this statement
*
* @param integer $mode The fetch mode must be one of the Query::HYDRATE_* constants.
* @return boolean Returns 1 on success or FALSE on failure.
*/
function setFetchMode($mode, $arg1);
}
\ No newline at end of file
......@@ -62,7 +62,7 @@ class ObjectHydrator extends AbstractHydrator
foreach ($this->_rsm->aliasMap as $dqlAlias => $className) {
$this->_identifierMap[$dqlAlias] = array();
$this->_resultPointers[$dqlAlias] = array();
//$this->_resultPointers[$dqlAlias] = array();
$this->_idTemplate[$dqlAlias] = '';
$class = $this->_em->getClassMetadata($className);
......
......@@ -334,7 +334,7 @@ final class ClassMetadata extends ClassMetadataInfo
'inheritanceType',
'inheritedAssociationFields',
'insertSql',
'inverseMappings',
'inverseMappings', //TODO: Remove!
'isIdentifierComposite',
'isMappedSuperclass',
'isVersioned',
......@@ -343,7 +343,6 @@ final class ClassMetadata extends ClassMetadataInfo
'namespace',
'parentClasses',
'primaryTable',
'resultColumnNames',
'rootEntityName',
'sequenceGeneratorDefinition',
'subClasses',
......
......@@ -21,7 +21,7 @@
namespace Doctrine\ORM\Mapping;
use Doctrine\Common\DoctrineException,
use Doctrine\ORM\ORMException,
Doctrine\DBAL\Platforms\AbstractPlatform,
Doctrine\ORM\Events;
......@@ -189,7 +189,6 @@ class ClassMetadataFactory
$class->setVersioned($parent->isVersioned);
$class->setVersionField($parent->versionField);
$class->setDiscriminatorMap($parent->discriminatorMap);
$class->setResultColumnNames($parent->resultColumnNames);
}
// Invoke driver
......@@ -230,13 +229,6 @@ class ClassMetadataFactory
$this->_generateStaticSql($class);
}
if ($parent) {
foreach ($visited as $parentClassName) {
$parentClass = $this->_loadedMetadata[$parentClassName];
$parentClass->setResultColumnNames(array_merge($parentClass->resultColumnNames, $class->resultColumnNames));
}
}
$this->_loadedMetadata[$className] = $class;
$parent = $class;
......@@ -321,11 +313,6 @@ class ClassMetadataFactory
if (isset($class->fieldMappings[$name]['inherited']) && ! isset($class->fieldMappings[$name]['id'])
|| isset($class->inheritedAssociationFields[$name])
|| ($versioned && $versionField == $name)) {
if (isset($class->columnNames[$name])) {
// Add column mapping for SQL result sets
$columnName = $class->columnNames[$name];
$class->resultColumnNames[$this->_targetPlatform->getSqlResultCasing($columnName)] = $columnName;
}
continue;
}
......@@ -334,19 +321,10 @@ class ClassMetadataFactory
if ($assoc->isOneToOne() && $assoc->isOwningSide) {
foreach ($assoc->targetToSourceKeyColumns as $sourceCol) {
$columns[] = $assoc->getQuotedJoinColumnName($sourceCol, $this->_targetPlatform);
// Add column mapping for SQL result sets
$class->resultColumnNames[$this->_targetPlatform->getSqlResultCasing($sourceCol)] = $sourceCol;
}
}
} else if ($class->name != $class->rootEntityName || ! $class->isIdGeneratorIdentity() || $class->identifier[0] != $name) {
$columns[] = $class->getQuotedColumnName($name, $this->_targetPlatform);
// Add column mapping for SQL result sets
$columnName = $class->columnNames[$name];
$class->resultColumnNames[$this->_targetPlatform->getSqlResultCasing($columnName)] = $columnName;
} else {
// Add column mapping for SQL result sets
$columnName = $class->columnNames[$name];
$class->resultColumnNames[$this->_targetPlatform->getSqlResultCasing($columnName)] = $columnName;
}
}
} else {
......@@ -360,19 +338,10 @@ class ClassMetadataFactory
if ($assoc->isOwningSide && $assoc->isOneToOne()) {
foreach ($assoc->targetToSourceKeyColumns as $sourceCol) {
$columns[] = $assoc->getQuotedJoinColumnName($sourceCol, $this->_targetPlatform);
// Add column mapping for SQL result sets
$class->resultColumnNames[$this->_targetPlatform->getSqlResultCasing($sourceCol)] = $sourceCol;
}
}
} else if ($class->generatorType != ClassMetadata::GENERATOR_TYPE_IDENTITY || $class->identifier[0] != $name) {
$columns[] = $class->getQuotedColumnName($name, $this->_targetPlatform);
// Add column mapping for SQL result sets
$columnName = $class->columnNames[$name];
$class->resultColumnNames[$this->_targetPlatform->getSqlResultCasing($columnName)] = $columnName;
} else {
// Add column mapping for SQL result sets
$columnName = $class->columnNames[$name];
$class->resultColumnNames[$this->_targetPlatform->getSqlResultCasing($columnName)] = $columnName;
}
}
}
......@@ -383,9 +352,6 @@ class ClassMetadataFactory
&& $class->name == $class->rootEntityName) {
$columns[] = $class->getQuotedDiscriminatorColumnName($this->_targetPlatform);
}
// Add column mapping for SQL result sets
$columnName = $class->discriminatorColumn['name'];
$class->resultColumnNames[$this->_targetPlatform->getSqlResultCasing($columnName)] = $columnName;
}
if (empty($columns)) {
......@@ -448,10 +414,10 @@ class ClassMetadataFactory
$class->setIdGenerator(new \Doctrine\ORM\Id\Assigned());
break;
case ClassMetadata::GENERATOR_TYPE_TABLE:
throw new DoctrineException("DoctrineTableGenerator not yet implemented.");
throw new ORMException("TableGenerator not yet implemented.");
break;
default:
throw new DoctrineException("Unexhaustive match.");
throw new ORMException("Unknown generator type: " . $class->generatorType);
}
}
}
......@@ -258,18 +258,6 @@ class ClassMetadataInfo
*/
public $columnNames = array();
/**
* A map of column names as they appear in an SQL result set to column names as they
* are defined in the mapping. This includes the columns of all mapped fields as well
* as any join columns and discriminator columns.
*
* @var array
* @todo Remove. Or at least remove from serialization/unserialization and instead
* populate them during runtime.
* See http://www.doctrine-project.org/jira/browse/DDC-132.
*/
public $resultColumnNames = array();
/**
* Whether to automatically OUTER JOIN subtypes when a basetype is queried.
*
......@@ -340,6 +328,7 @@ class ClassMetadataInfo
* List of inverse association mappings, indexed by mappedBy field name.
*
* @var array
* @todo Remove! See http://www.doctrine-project.org/jira/browse/DDC-193
*/
public $inverseMappings = array();
......
......@@ -21,7 +21,7 @@
namespace Doctrine\ORM\Persisters;
use Doctrine\Common\DoctrineException;
use Doctrine\ORM\ORMException;
/**
* The joined subclass persister maps a single entity instance to several tables in the
......@@ -52,8 +52,7 @@ class JoinedSubclassPersister extends StandardEntityPersister
if ($isInsert) {
$discColumn = $this->_class->discriminatorColumn;
$rootClass = $this->_em->getClassMetadata($this->_class->rootEntityName);
$result[$rootClass->primaryTable['name']][$discColumn['name']] =
$this->_class->discriminatorValue;
$result[$rootClass->primaryTable['name']][$discColumn['name']] = $this->_class->discriminatorValue;
}
}
......@@ -280,6 +279,7 @@ class JoinedSubclassPersister extends StandardEntityPersister
$aliasIndex = 1;
$idColumns = $this->_class->getIdentifierColumnNames();
$baseTableAlias = 't0';
$setResultColumnNames = empty($this->_resultColumnNames);
foreach (array_merge($this->_class->subClasses, $this->_class->parentClasses) as $className) {
$tableAliases[$className] = 't' . $aliasIndex++;
......@@ -292,6 +292,11 @@ class JoinedSubclassPersister extends StandardEntityPersister
$tableAliases[$mapping['inherited']] : $baseTableAlias;
if ($columnList != '') $columnList .= ', ';
$columnList .= $tableAlias . '.' . $this->_class->getQuotedColumnName($fieldName, $this->_platform);
if ($setResultColumnNames) {
$resultColumnName = $this->_platform->getSqlResultCasing($mapping['columnName']);
$this->_resultColumnNames[$resultColumnName] = $mapping['columnName'];
}
}
// Add foreign key columns
......@@ -299,6 +304,11 @@ class JoinedSubclassPersister extends StandardEntityPersister
if ($assoc2->isOwningSide && $assoc2->isOneToOne()) {
foreach ($assoc2->targetToSourceKeyColumns as $srcColumn) {
$columnList .= ', ' . $assoc2->getQuotedJoinColumnName($srcColumn, $this->_platform);
if ($setResultColumnNames) {
$resultColumnName = $this->_platform->getSqlResultCasing($srcColumn);
$this->_resultColumnNames[$resultColumnName] = $srcColumn;
}
}
}
}
......@@ -312,6 +322,11 @@ class JoinedSubclassPersister extends StandardEntityPersister
$this->_class->getQuotedDiscriminatorColumnName($this->_platform);
}
if ($setResultColumnNames) {
$resultColumnName = $this->_platform->getSqlResultCasing($this->_class->discriminatorColumn['name']);
$this->_resultColumnNames[$resultColumnName] = $this->_class->discriminatorColumn['name'];
}
// INNER JOIN parent tables
$joinSql = '';
foreach ($this->_class->parentClasses as $parentClassName) {
......@@ -336,6 +351,11 @@ class JoinedSubclassPersister extends StandardEntityPersister
continue;
}
$columnList .= ', ' . $tableAlias . '.' . $subClass->getQuotedColumnName($fieldName, $this->_platform);
if ($setResultColumnNames) {
$resultColumnName = $this->_platform->getSqlResultCasing($mapping['columnName']);
$this->_resultColumnNames[$resultColumnName] = $mapping['columnName'];
}
}
// Add join columns (foreign keys)
......@@ -343,6 +363,11 @@ class JoinedSubclassPersister extends StandardEntityPersister
if ($assoc2->isOwningSide && $assoc2->isOneToOne() && ! isset($subClass->inheritedAssociationFields[$assoc2->sourceFieldName])) {
foreach ($assoc2->targetToSourceKeyColumns as $srcColumn) {
$columnList .= ', ' . $tableAlias . '.' . $assoc2->getQuotedJoinColumnName($srcColumn, $this->_platform);
if ($setResultColumnNames) {
$resultColumnName = $this->_platform->getSqlResultCasing($srcColumn);
$this->_resultColumnNames[$resultColumnName] = $srcColumn;
}
}
}
}
......@@ -365,7 +390,7 @@ class JoinedSubclassPersister extends StandardEntityPersister
} else if ($assoc !== null) {
$conditionSql .= $assoc->getQuotedJoinColumnName($field, $this->_platform);
} else {
throw DoctrineException::unrecognizedField($field);
throw ORMException::unrecognizedField($field);
}
$conditionSql .= ' = ?';
}
......
......@@ -50,9 +50,16 @@ class SingleTablePersister extends StandardEntityPersister
/** @override */
protected function _getSelectColumnList()
{
$setResultColumnNames = empty($this->_resultColumnNames);
$columnList = parent::_getSelectColumnList();
// Append discriminator column
$columnList .= ', ' . $this->_class->getQuotedDiscriminatorColumnName($this->_platform);
if ($setResultColumnNames) {
$resultColumnName = $this->_platform->getSqlResultCasing($this->_class->discriminatorColumn['name']);
$this->_resultColumnNames[$resultColumnName] = $this->_class->discriminatorColumn['name'];
}
///$tableAlias = $this->_class->getQuotedTableName($this->_platform);
foreach ($this->_class->subClasses as $subClassName) {
$subClass = $this->_em->getClassMetadata($subClassName);
......@@ -60,6 +67,10 @@ class SingleTablePersister extends StandardEntityPersister
foreach ($subClass->fieldMappings as $fieldName => $mapping) {
if ( ! isset($mapping['inherited'])) {
$columnList .= ', ' . $subClass->getQuotedColumnName($fieldName, $this->_platform);
if ($setResultColumnNames) {
$resultColumnName = $this->_platform->getSqlResultCasing($mapping['columnName']);
$this->_resultColumnNames[$resultColumnName] = $mapping['columnName'];
}
}
}
......@@ -68,6 +79,10 @@ class SingleTablePersister extends StandardEntityPersister
if ($assoc->isOwningSide && $assoc->isOneToOne() && ! isset($subClass->inheritedAssociationFields[$assoc->sourceFieldName])) {
foreach ($assoc->targetToSourceKeyColumns as $srcColumn) {
$columnList .= ', ' /*. $tableAlias . '.'*/ . $assoc->getQuotedJoinColumnName($srcColumn, $this->_platform);
if ($setResultColumnNames) {
$resultColumnName = $this->_platform->getSqlResultCasing($srcColumn);
$this->_resultColumnNames[$resultColumnName] = $srcColumn;
}
}
}
}
......
......@@ -87,6 +87,8 @@ class StandardEntityPersister
*/
protected $_queuedInserts = array();
protected $_resultColumnNames = array();
/**
* Initializes a new instance of a class derived from AbstractEntityPersister
* that uses the given EntityManager and persists instances of the class described
......@@ -189,8 +191,8 @@ class StandardEntityPersister
$identifier = $this->_class->getIdentifierColumnNames();
$versionFieldColumnName = $this->_class->getColumnName($versionField);
//FIXME: Order with composite keys might not be correct
$sql = "SELECT " . $versionFieldColumnName . " FROM " . $class->getQuotedTableName($this->_platform) .
" WHERE " . implode(' = ? AND ', $identifier) . " = ?";
$sql = "SELECT " . $versionFieldColumnName . " FROM " . $class->getQuotedTableName($this->_platform)
. " WHERE " . implode(' = ? AND ', $identifier) . " = ?";
$value = $this->_conn->fetchColumn($sql, array_values((array)$id));
$this->_class->setFieldValue($entity, $versionField, $value);
}
......@@ -453,7 +455,7 @@ class StandardEntityPersister
// Refresh simple state
foreach ($result as $column => $value) {
$column = $this->_class->resultColumnNames[$column];
$column = isset($this->_resultColumnNames[$column]) ? $this->_resultColumnNames[$column] : $column;
if (isset($this->_class->fieldNames[$column])) {
$fieldName = $this->_class->fieldNames[$column];
$type = Type::getType($this->_class->fieldMappings[$fieldName]['type']);
......@@ -636,7 +638,7 @@ class StandardEntityPersister
{
$data = array();
foreach ($sqlResult as $column => $value) {
$column = $this->_class->resultColumnNames[$column];
$column = isset($this->_resultColumnNames[$column]) ? $this->_resultColumnNames[$column] : $column;
if (isset($this->_class->fieldNames[$column])) {
$field = $this->_class->fieldNames[$column];
$data[$field] = Type::getType($this->_class->fieldMappings[$field]['type'])
......@@ -690,11 +692,18 @@ class StandardEntityPersister
protected function _getSelectColumnList()
{
$columnList = '';
$tableName = $this->_class->getQuotedTableName($this->_platform);
$setResultColumnNames = empty($this->_resultColumnNames);
// Add regular columns to select list
foreach ($this->_class->fieldNames as $field) {
if ($columnList != '') $columnList .= ', ';
$columnList .= $this->_class->getQuotedColumnName($field, $this->_platform);
$columnList .= $tableName . '.' . $this->_class->getQuotedColumnName($field, $this->_platform);
if ($setResultColumnNames) {
$resultColumnName = $this->_platform->getSqlResultCasing($this->_class->columnNames[$field]);
$this->_resultColumnNames[$resultColumnName] = $this->_class->columnNames[$field];
}
}
// Add join columns (foreign keys) to select list
......@@ -702,6 +711,11 @@ class StandardEntityPersister
if ($assoc->isOwningSide && $assoc->isOneToOne()) {
foreach ($assoc->targetToSourceKeyColumns as $srcColumn) {
$columnList .= ', ' . $assoc->getQuotedJoinColumnName($srcColumn, $this->_platform);
if ($setResultColumnNames) {
$resultColumnName = $this->_platform->getSqlResultCasing($srcColumn);
$this->_resultColumnNames[$resultColumnName] = $srcColumn;
}
}
}
}
......@@ -717,22 +731,6 @@ class StandardEntityPersister
*/
protected function _getSelectManyToManyEntityCollectionSql($manyToMany, array &$criteria)
{
$columnList = '';
$tableName = $this->_class->getQuotedTableName($this->_platform);
foreach ($this->_class->fieldNames as $field) {
if ($columnList != '') $columnList .= ', ';
$columnList .= $tableName . '.' . $this->_class->getQuotedColumnName($field, $this->_platform);
}
foreach ($this->_class->associationMappings as $assoc) {
if ($assoc->isOwningSide && $assoc->isOneToOne()) {
foreach ($assoc->targetToSourceKeyColumns as $srcColumn) {
$columnList .= ', ' . $assoc->getQuotedJoinColumnName($srcColumn, $this->_platform);
}
}
}
if ($manyToMany->isOwningSide) {
$owningAssoc = $manyToMany;
$joinClauses = $manyToMany->relationToTargetKeyColumns;
......@@ -762,7 +760,7 @@ class StandardEntityPersister
$conditionSql .= $columnName . ' = ?';
}
return 'SELECT ' . $columnList
return 'SELECT ' . $this->_getSelectColumnList()
. ' FROM ' . $this->_class->getQuotedTableName($this->_platform)
. $joinSql
. ' WHERE ' . $conditionSql;
......@@ -774,7 +772,7 @@ class StandardEntityPersister
$data = array();
$entityName = $this->_class->name;
foreach ($sqlResult as $column => $value) {
$column = $this->_class->resultColumnNames[$column];
$column = isset($this->_resultColumnNames[$column]) ? $this->_resultColumnNames[$column] : $column;
if (($class = $this->_findDeclaringClass($column)) !== false) {
$field = $class->fieldNames[$column];
$data[$field] = Type::getType($class->fieldMappings[$field]['type'])
......
......@@ -45,7 +45,7 @@ class LifecycleCallbackTest extends \Doctrine\Tests\OrmFunctionalTestCase
{
$user = new LifecycleCallbackTestUser;
$user->setName('Bob');
$user->setValue('');
$user->setValue('value');
$this->_em->persist($user);
$this->_em->flush();
......
......@@ -11,6 +11,9 @@ class DDC168Test extends \Doctrine\Tests\OrmFunctionalTestCase
parent::setUp();
}
/**
* @group DDC-168
*/
public function testJoinedSubclassPersisterRequiresSpecificOrderOfMetadataReflFieldsArray()
{
$metadata = $this->_em->getClassMetadata('Doctrine\Tests\Models\Company\CompanyEmployee');
......
......@@ -84,7 +84,7 @@ class DDC199ChildClass extends DDC199ParentClass
public $childData;
}
/** @Entity @Table(name="ddcxxx_relatedclass") */
/** @Entity @Table(name="ddc199_relatedclass") */
class DDC199RelatedClass
{
/** @Id @Column(type="integer") @GeneratedValue(strategy="AUTO") */
......
......@@ -8,6 +8,8 @@ use Doctrine\ORM\Proxy\ProxyFactory;
use Doctrine\ORM\Mapping\AssociationMapping;
use Doctrine\ORM\Query;
use Doctrine\Tests\Models\CMS\CmsUser;
require_once __DIR__ . '/../../TestInit.php';
class ObjectHydratorTest extends HydrationTestCase
......@@ -686,6 +688,62 @@ class ObjectHydratorTest extends HydrationTestCase
}
public function testChainedJoinWithEmptyCollections()
{
$rsm = new ResultSetMapping;
$rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsUser', 'u');
$rsm->addJoinedEntityResult(
'Doctrine\Tests\Models\CMS\CmsArticle',
'a',
'u',
'articles'
);
$rsm->addJoinedEntityResult(
'Doctrine\Tests\Models\CMS\CmsComment',
'c',
'a',
'comments'
);
$rsm->addFieldResult('u', 'u__id', 'id');
$rsm->addFieldResult('u', 'u__status', 'status');
$rsm->addFieldResult('a', 'a__id', 'id');
$rsm->addFieldResult('a', 'a__topic', 'topic');
$rsm->addFieldResult('c', 'c__id', 'id');
$rsm->addFieldResult('c', 'c__topic', 'topic');
// Faked result set
$resultSet = array(
//row1
array(
'u__id' => '1',
'u__status' => 'developer',
'a__id' => null,
'a__topic' => null,
'c__id' => null,
'c__topic' => null
),
array(
'u__id' => '2',
'u__status' => 'developer',
'a__id' => null,
'a__topic' => null,
'c__id' => null,
'c__topic' => null
),
);
$stmt = new HydratorMockStatement($resultSet);
$hydrator = new \Doctrine\ORM\Internal\Hydration\ObjectHydrator($this->_em);
$result = $hydrator->hydrateAll($stmt, $rsm, array(Query::HINT_FORCE_PARTIAL_LOAD => true));
$this->assertEquals(2, count($result));
$this->assertTrue($result[0] instanceof CmsUser);
$this->assertTrue($result[1] instanceof CmsUser);
$this->assertEquals(0, $result[0]->articles->count());
$this->assertEquals(0, $result[1]->articles->count());
}
public function testResultIteration()
{
$rsm = new ResultSetMapping;
......
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