diff --git a/lib/Doctrine/Common/Annotations/Parser.php b/lib/Doctrine/Common/Annotations/Parser.php
index fa57fe9d2..854e8018e 100644
--- a/lib/Doctrine/Common/Annotations/Parser.php
+++ b/lib/Doctrine/Common/Annotations/Parser.php
@@ -269,6 +269,13 @@ class Parser
public function Values()
{
$values = array();
+
+ // Handle the case of a single array as value, i.e. @Foo({....})
+ if ($this->_lexer->isNextToken('{')) {
+ $values['value'] = $this->Value();
+ return $values;
+ }
+
$values[] = $this->Value();
while ($this->_lexer->isNextToken(',')) {
diff --git a/lib/Doctrine/DBAL/Schema/MySqlSchemaManager.php b/lib/Doctrine/DBAL/Schema/MySqlSchemaManager.php
index 4dc29eae4..34b0404f0 100644
--- a/lib/Doctrine/DBAL/Schema/MySqlSchemaManager.php
+++ b/lib/Doctrine/DBAL/Schema/MySqlSchemaManager.php
@@ -34,7 +34,7 @@ class MySqlSchemaManager extends AbstractSchemaManager
{
protected function _getPortableViewDefinition($view)
{
- return $view['table_name'];
+ return $view['TABLE_NAME'];
}
protected function _getPortableTableDefinition($table)
@@ -45,8 +45,8 @@ class MySqlSchemaManager extends AbstractSchemaManager
protected function _getPortableUserDefinition($user)
{
return array(
- 'user' => $user['user'],
- 'password' => $user['password'],
+ 'user' => $user['User'],
+ 'password' => $user['Password'],
);
}
@@ -83,12 +83,12 @@ class MySqlSchemaManager extends AbstractSchemaManager
protected function _getPortableDatabaseDefinition($database)
{
- return $database['database'];
+ return $database['Database'];
}
protected function _getPortableTableColumnDefinition($tableColumn)
{
- $dbType = strtolower($tableColumn['type']);
+ $dbType = strtolower($tableColumn['Type']);
$dbType = strtok($dbType, '(), ');
if ($dbType == 'national') {
$dbType = strtok('(), ');
@@ -117,28 +117,28 @@ class MySqlSchemaManager extends AbstractSchemaManager
if (preg_match('/^(is|has)/', $tableColumn['name'])) {
$type = array_reverse($type);
}
- $unsigned = preg_match('/ unsigned/i', $tableColumn['type']);
+ $unsigned = preg_match('/ unsigned/i', $tableColumn['Type']);
$length = 1;
break;
case 'smallint':
$type = 'integer';
- $unsigned = preg_match('/ unsigned/i', $tableColumn['type']);
+ $unsigned = preg_match('/ unsigned/i', $tableColumn['Type']);
$length = 2;
break;
case 'mediumint':
$type = 'integer';
- $unsigned = preg_match('/ unsigned/i', $tableColumn['type']);
+ $unsigned = preg_match('/ unsigned/i', $tableColumn['Type']);
$length = 3;
break;
case 'int':
case 'integer':
$type = 'integer';
- $unsigned = preg_match('/ unsigned/i', $tableColumn['type']);
+ $unsigned = preg_match('/ unsigned/i', $tableColumn['Type']);
$length = 4;
break;
case 'bigint':
$type = 'integer';
- $unsigned = preg_match('/ unsigned/i', $tableColumn['type']);
+ $unsigned = preg_match('/ unsigned/i', $tableColumn['Type']);
$length = 8;
break;
case 'tinytext':
@@ -249,12 +249,12 @@ class MySqlSchemaManager extends AbstractSchemaManager
$values = isset($def['values']) ? $def['values'] : array();
$column = array(
- 'name' => $tableColumn['field'],
+ 'name' => $tableColumn['Field'],
'values' => $values,
- 'primary' => (bool) (strtolower($tableColumn['key']) == 'pri'),
- 'default' => $tableColumn['default'],
- 'notnull' => (bool) ($tableColumn['null'] != 'YES'),
- 'autoincrement' => (bool) (strpos($tableColumn['extra'], 'auto_increment') !== false),
+ 'primary' => (bool) (strtolower($tableColumn['Key']) == 'pri'),
+ 'default' => $tableColumn['Default'],
+ 'notnull' => (bool) ($tableColumn['Null'] != 'YES'),
+ 'autoincrement' => (bool) (strpos($tableColumn['Extra'], 'auto_increment') !== false),
);
$column = array_merge($column, $def);
diff --git a/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php b/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php
index f73b8cc35..bb5b62063 100644
--- a/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php
+++ b/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php
@@ -40,7 +40,6 @@ class ObjectHydrator extends AbstractHydrator
*/
/* Local ClassMetadata cache to avoid going to the EntityManager all the time. */
private $_ce = array();
- private $_discriminatorMap = array();
/*
* The following parts are reinitialized on every hydration run.
*/
@@ -76,17 +75,6 @@ class ObjectHydrator extends AbstractHydrator
if ( ! isset($this->_ce[$className])) {
$this->_ce[$className] = $class;
- // Gather class descriptors and discriminator values of subclasses, if necessary
- if ($class->isInheritanceTypeSingleTable() || $class->isInheritanceTypeJoined()) {
- $this->_discriminatorMap[$className][$class->discriminatorValue] = $className;
- foreach (array_merge($class->parentClasses, $class->subClasses) as $className) {
- $otherClass = $this->_em->getClassMetadata($className);
- $value = $otherClass->discriminatorValue;
- $this->_ce[$className] = $otherClass;
- $this->_discriminatorMap[$class->name][$value] = $className;
- $this->_discriminatorMap[$className][$value] = $className;
- }
- }
}
// Remember which associations are "fetch joined"
@@ -172,7 +160,7 @@ class ObjectHydrator extends AbstractHydrator
$className = $this->_rsm->aliasMap[$dqlAlias];
if (isset($this->_rsm->discriminatorColumns[$dqlAlias])) {
$discrColumn = $this->_rsm->metaMappings[$this->_rsm->discriminatorColumns[$dqlAlias]];
- $className = $this->_discriminatorMap[$className][$data[$discrColumn]];
+ $className = $this->_ce[$className]->discriminatorMap[$data[$discrColumn]];
unset($data[$discrColumn]);
}
@@ -180,7 +168,7 @@ class ObjectHydrator extends AbstractHydrator
// Properly initialize any unfetched associations, if partial objects are not allowed.
if ( ! $this->_allowPartialObjects) {
- foreach ($this->_ce[$className]->associationMappings as $field => $assoc) {
+ foreach ($this->_getClassMetadata($className)->associationMappings as $field => $assoc) {
// Check if the association is not among the fetch-joined associatons already.
if ( ! isset($this->_fetchedAssociations[$className][$field])) {
if ($assoc->isOneToOne()) {
diff --git a/lib/Doctrine/ORM/Mapping/ClassMetadata.php b/lib/Doctrine/ORM/Mapping/ClassMetadata.php
index 78dafc8c9..059abcd76 100644
--- a/lib/Doctrine/ORM/Mapping/ClassMetadata.php
+++ b/lib/Doctrine/ORM/Mapping/ClassMetadata.php
@@ -254,13 +254,22 @@ final class ClassMetadata
public $fieldNames = array();
/**
- * An array of column names. Keys are field names and values column names.
+ * A map of field names to column names. Keys are field names and values column names.
* Used to look up column names from field names.
* This is the reverse lookup map of $_fieldNames.
*
* @var array
*/
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
+ */
+ public $resultColumnNames = array();
/**
* Whether to automatically OUTER JOIN subtypes when a basetype is queried.
@@ -281,6 +290,17 @@ final class ClassMetadata
* @see _discriminatorColumn
*/
public $discriminatorValue;
+
+ /**
+ * The discriminator map of all mapped classes in the hierarchy.
+ *
+ * This does only apply to the JOINED and SINGLE_TABLE inheritance mapping strategies
+ * where a discriminator column is used.
+ *
+ * @var mixed
+ * @see _discriminatorColumn
+ */
+ public $discriminatorMap = array();
/**
* The definition of the descriminator column used in JOINED and SINGLE_TABLE
@@ -1139,16 +1159,19 @@ final class ClassMetadata
}
/**
- * Sets the subclasses of the mapped class.
- *
- * All entity classes that participate in a hierarchy and have subclasses
- * need to declare them this way.
+ * Sets the mapped subclasses of this class.
*
- * @param array $subclasses The names of all subclasses.
+ * @param array $subclasses The names of all mapped subclasses.
*/
public function setSubclasses(array $subclasses)
{
- $this->subClasses = $subclasses;
+ foreach ($subclasses as $subclass) {
+ if (strpos($subclass, '\\') === false) {
+ $this->subClasses[] = $this->namespace . '\\' . $subclass;
+ } else {
+ $this->subClasses[] = $subclass;
+ }
+ }
}
/**
@@ -1572,14 +1595,24 @@ final class ClassMetadata
}
/**
- * Sets the dsicriminator value used by this class.
+ * Sets the dsicriminator values used by this class.
* Used for JOINED and SINGLE_TABLE inheritance mapping strategies.
*
* @param array $map
*/
- public function setDiscriminatorValue($value)
+ public function setDiscriminatorMap(array $map)
{
- $this->discriminatorValue = $value;
+ foreach ($map as $value => $className) {
+ if (strpos($className, '\\') === false) {
+ $className = $this->namespace . '\\' . $className;
+ }
+ $this->discriminatorMap[$value] = $className;
+ if ($this->name == $className) {
+ $this->discriminatorValue = $value;
+ } else if (is_subclass_of($className, $this->name)) {
+ $this->subClasses[] = $className;
+ }
+ }
}
/**
diff --git a/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php b/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php
index e4b74a6ca..93ec7fab1 100644
--- a/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php
+++ b/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php
@@ -177,6 +177,7 @@ class ClassMetadataFactory
$class->setIdentifier($parent->identifier);
$class->setVersioned($parent->isVersioned);
$class->setVersionField($parent->versionField);
+ $class->setDiscriminatorMap($parent->discriminatorMap);
}
// Invoke driver
@@ -291,6 +292,11 @@ 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;
}
@@ -300,11 +306,20 @@ class ClassMetadataFactory
foreach ($assoc->targetToSourceKeyColumns as $sourceCol) {
$columns[] = $assoc->getQuotedJoinColumnName($sourceCol, $this->_targetPlatform);
$values[] = '?';
+ // 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);
$values[] = '?';
+ // 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 {
@@ -319,19 +334,34 @@ class ClassMetadataFactory
foreach ($assoc->targetToSourceKeyColumns as $sourceCol) {
$columns[] = $assoc->getQuotedJoinColumnName($sourceCol, $this->_targetPlatform);
$values[] = '?';
+ // 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);
$values[] = '?';
+ // 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;
}
}
}
// Add discriminator column to the INSERT SQL if necessary
- if ($class->isInheritanceTypeSingleTable() || $class->isInheritanceTypeJoined() && $class->name == $class->rootEntityName) {
- $columns[] = $class->getQuotedDiscriminatorColumnName($this->_targetPlatform);
- $values[] = '?';
+ if (isset($class->discriminatorColumn['name'])) {
+ if ($class->isInheritanceTypeSingleTable() || $class->isInheritanceTypeJoined()
+ && $class->name == $class->rootEntityName) {
+ $columns[] = $class->getQuotedDiscriminatorColumnName($this->_targetPlatform);
+ $values[] = '?';
+ }
+ // Add column mapping for SQL result sets
+ $columnName = $class->discriminatorColumn['name'];
+ $class->resultColumnNames[$this->_targetPlatform->getSqlResultCasing($columnName)] = $columnName;
}
$class->insertSql = 'INSERT INTO ' .
diff --git a/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php b/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php
index c64a57723..682d1b4f0 100644
--- a/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php
+++ b/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php
@@ -95,10 +95,10 @@ class AnnotationDriver implements Driver
));
}
- // Evaluate DiscriminatorValue annotation
- if (isset($classAnnotations['Doctrine\ORM\Mapping\DiscriminatorValue'])) {
- $discrValueAnnot = $classAnnotations['Doctrine\ORM\Mapping\DiscriminatorValue'];
- $metadata->setDiscriminatorValue($discrValueAnnot->value);
+ // Evaluate DiscriminatorMap annotation
+ if (isset($classAnnotations['Doctrine\ORM\Mapping\DiscriminatorMap'])) {
+ $discrMapAnnot = $classAnnotations['Doctrine\ORM\Mapping\DiscriminatorMap'];
+ $metadata->setDiscriminatorMap($discrMapAnnot->value);
}
// Evaluate DoctrineSubClasses annotation
diff --git a/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php b/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php
index 8c1004f39..499a9cc23 100644
--- a/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php
+++ b/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php
@@ -25,26 +25,25 @@ use \Doctrine\Common\Annotations\Annotation;
/* Annotations */
-final class Entity extends \Doctrine\Common\Annotations\Annotation {
+final class Entity extends Annotation {
public $repositoryClass;
}
final class MappedSuperclass extends Annotation {}
-final class InheritanceType extends \Doctrine\Common\Annotations\Annotation {}
-final class DiscriminatorColumn extends \Doctrine\Common\Annotations\Annotation {
+final class InheritanceType extends Annotation {}
+final class DiscriminatorColumn extends Annotation {
public $name;
public $fieldName; // field name used in non-object hydration (array/scalar)
public $type;
public $length;
}
-final class DiscriminatorValue extends \Doctrine\Common\Annotations\Annotation {}
-final class SubClasses extends \Doctrine\Common\Annotations\Annotation {}
-final class Id extends \Doctrine\Common\Annotations\Annotation {}
-final class GeneratedValue extends \Doctrine\Common\Annotations\Annotation {
+final class DiscriminatorMap extends Annotation {}
+/*final class SubClasses extends Annotation {}*/
+final class Id extends Annotation {}
+final class GeneratedValue extends Annotation {
public $strategy;
- //public $generator;
}
-final class Version extends \Doctrine\Common\Annotations\Annotation {}
-final class JoinColumn extends \Doctrine\Common\Annotations\Annotation {
+final class Version extends Annotation {}
+final class JoinColumn extends Annotation {
public $name;
public $fieldName; // field name used in non-object hydration (array/scalar)
public $referencedColumnName;
@@ -53,8 +52,8 @@ final class JoinColumn extends \Doctrine\Common\Annotations\Annotation {
public $onDelete;
public $onUpdate;
}
-final class JoinColumns extends \Doctrine\Common\Annotations\Annotation {}
-final class Column extends \Doctrine\Common\Annotations\Annotation {
+final class JoinColumns extends Annotation {}
+final class Column extends Annotation {
public $type;
public $length;
public $unique = false;
@@ -62,7 +61,7 @@ final class Column extends \Doctrine\Common\Annotations\Annotation {
public $default;
public $name;
}
-final class OneToOne extends \Doctrine\Common\Annotations\Annotation {
+final class OneToOne extends Annotation {
public $targetEntity;
public $mappedBy;
public $cascade;
@@ -70,54 +69,54 @@ final class OneToOne extends \Doctrine\Common\Annotations\Annotation {
public $optional;
public $orphanRemoval = false;
}
-final class OneToMany extends \Doctrine\Common\Annotations\Annotation {
+final class OneToMany extends Annotation {
public $mappedBy;
public $targetEntity;
public $cascade;
public $fetch;
public $orphanRemoval = false;
}
-final class ManyToOne extends \Doctrine\Common\Annotations\Annotation {
+final class ManyToOne extends Annotation {
public $targetEntity;
public $cascade;
public $fetch;
public $optional;
}
-final class ManyToMany extends \Doctrine\Common\Annotations\Annotation {
+final class ManyToMany extends Annotation {
public $targetEntity;
public $mappedBy;
public $cascade;
public $fetch;
}
-final class ElementCollection extends \Doctrine\Common\Annotations\Annotation {
+final class ElementCollection extends Annotation {
public $tableName;
}
-final class Table extends \Doctrine\Common\Annotations\Annotation {
+final class Table extends Annotation {
public $name;
public $schema;
}
-final class JoinTable extends \Doctrine\Common\Annotations\Annotation {
+final class JoinTable extends Annotation {
public $name;
public $schema;
public $joinColumns;
public $inverseJoinColumns;
}
-final class SequenceGenerator extends \Doctrine\Common\Annotations\Annotation {
+final class SequenceGenerator extends Annotation {
public $sequenceName;
public $allocationSize = 10;
public $initialValue = 1;
}
-final class ChangeTrackingPolicy extends \Doctrine\Common\Annotations\Annotation {}
+final class ChangeTrackingPolicy extends Annotation {}
/* Annotations for lifecycle callbacks */
-final class LifecycleListener extends \Doctrine\Common\Annotations\Annotation {}
-final class PrePersist extends \Doctrine\Common\Annotations\Annotation {}
-final class PostPersist extends \Doctrine\Common\Annotations\Annotation {}
-final class PreUpdate extends \Doctrine\Common\Annotations\Annotation {}
-final class PostUpdate extends \Doctrine\Common\Annotations\Annotation {}
-final class PreRemove extends \Doctrine\Common\Annotations\Annotation {}
-final class PostRemove extends \Doctrine\Common\Annotations\Annotation {}
-final class PostLoad extends \Doctrine\Common\Annotations\Annotation {}
+final class LifecycleListener extends Annotation {}
+final class PrePersist extends Annotation {}
+final class PostPersist extends Annotation {}
+final class PreUpdate extends Annotation {}
+final class PostUpdate extends Annotation {}
+final class PreRemove extends Annotation {}
+final class PostRemove extends Annotation {}
+final class PostLoad extends Annotation {}
/* Generic annotation for Doctrine extensions */
-final class DoctrineX extends \Doctrine\Common\Annotations\Annotation {}
+final class DoctrineX extends Annotation {}
diff --git a/lib/Doctrine/ORM/Persisters/JoinedSubclassPersister.php b/lib/Doctrine/ORM/Persisters/JoinedSubclassPersister.php
index 8636f089a..7da15eae6 100644
--- a/lib/Doctrine/ORM/Persisters/JoinedSubclassPersister.php
+++ b/lib/Doctrine/ORM/Persisters/JoinedSubclassPersister.php
@@ -288,16 +288,25 @@ class JoinedSubclassPersister extends StandardEntityPersister
$tableAlias = isset($mapping['inherited']) ?
$tableAliases[$mapping['inherited']] : $baseTableAlias;
if ($columnList != '') $columnList .= ', ';
- $columnList .= $tableAlias . '.' . $this->_class->columnNames[$fieldName];
+ $columnList .= $tableAlias . '.' . $this->_class->getQuotedColumnName($fieldName, $this->_platform);
+ }
+
+ // Add discriminator column
+ if ($this->_class->rootEntityName == $this->_class->name) {
+ $columnList .= ', ' . $baseTableAlias . '.' .
+ $this->_class->getQuotedDiscriminatorColumnName($this->_platform);
+ } else {
+ $columnList .= ', ' . $tableAliases[$this->_class->rootEntityName] . '.' .
+ $this->_class->getQuotedDiscriminatorColumnName($this->_platform);
}
- $sql = 'SELECT ' . $columnList . ' FROM ' . $this->_class->primaryTable['name']. ' ' . $baseTableAlias;
+ $sql = 'SELECT ' . $columnList . ' FROM ' . $this->_class->getQuotedTableName($this->_platform) . ' ' . $baseTableAlias;
// INNER JOIN parent tables
foreach ($this->_class->parentClasses as $parentClassName) {
$parentClass = $this->_em->getClassMetadata($parentClassName);
$tableAlias = $tableAliases[$parentClassName];
- $sql .= ' INNER JOIN ' . $parentClass->primaryTable['name'] . ' ' . $tableAlias . ' ON ';
+ $sql .= ' INNER JOIN ' . $parentClass->getQuotedTableName($this->_platform) . ' ' . $tableAlias . ' ON ';
$first = true;
foreach ($idColumns as $idColumn) {
if ($first) $first = false; else $sql .= ' AND ';
@@ -309,7 +318,7 @@ class JoinedSubclassPersister extends StandardEntityPersister
foreach ($this->_class->subClasses as $subClassName) {
$subClass = $this->_em->getClassMetadata($subClassName);
$tableAlias = $tableAliases[$subClassName];
- $sql .= ' LEFT JOIN ' . $subClass->primaryTable['name'] . ' ' . $tableAlias . ' ON ';
+ $sql .= ' LEFT JOIN ' . $subClass->getQuotedTableName($this->_platform) . ' ' . $tableAlias . ' ON ';
$first = true;
foreach ($idColumns as $idColumn) {
if ($first) $first = false; else $sql .= ' AND ';
@@ -323,6 +332,6 @@ class JoinedSubclassPersister extends StandardEntityPersister
$conditionSql .= $baseTableAlias . '.' . $this->_class->columnNames[$field] . ' = ?';
}
- return $sql . ' WHERE ' . $conditionSql;
+ return $sql . ($conditionSql != '' ? ' WHERE ' . $conditionSql : '');
}
}
diff --git a/lib/Doctrine/ORM/Persisters/StandardEntityPersister.php b/lib/Doctrine/ORM/Persisters/StandardEntityPersister.php
index 09cbedcb4..debf3cc46 100644
--- a/lib/Doctrine/ORM/Persisters/StandardEntityPersister.php
+++ b/lib/Doctrine/ORM/Persisters/StandardEntityPersister.php
@@ -85,8 +85,6 @@ class StandardEntityPersister
* @var array
*/
protected $_queuedInserts = array();
-
- //protected $_rsm;
/**
* Initializes a new instance of a class derived from AbstractEntityPersister
@@ -483,36 +481,25 @@ class StandardEntityPersister
if ($result === false) {
return null;
}
-
+
$data = $joinColumnValues = array();
-
- /*if ($this->_rsm === null) {
- $this->_rsm = array();
- foreach ($this->_class->columnNames as $column) {
- $this->_rsm[$this->_platform->getSqlResultCasing($column)] = $column;
- }
- foreach ($this->_class->associationMappings as $assoc) {
- if ($assoc->isOwningSide && $assoc->isOneToOne()) {
- foreach ($assoc->targetToSourceKeyColumns as $keyColumn) {
- $this->_rsm[$this->_platform->getSqlResultCasing($keyColumn)] = $keyColumn;
- }
- }
- }
- }*/
+ $entityName = $this->_entityName;
foreach ($result as $column => $value) {
- //$column = $this->_rsm[$column];
+ $column = $this->_class->resultColumnNames[$column];
if (isset($this->_class->fieldNames[$column])) {
$fieldName = $this->_class->fieldNames[$column];
$data[$fieldName] = Type::getType($this->_class->fieldMappings[$fieldName]['type'])
->convertToPHPValue($value, $this->_platform);
+ } else if ($this->_class->discriminatorColumn !== null && $column == $this->_class->discriminatorColumn['name']) {
+ $entityName = $this->_class->discriminatorMap[$value];
} else {
$joinColumnValues[$column] = $value;
}
}
if ($entity === null) {
- $entity = $this->_em->getUnitOfWork()->createEntity($this->_entityName, $data);
+ $entity = $this->_em->getUnitOfWork()->createEntity($entityName, $data);
} else {
foreach ($data as $field => $value) {
$this->_class->reflFields[$field]->setValue($entity, $value);
diff --git a/lib/Doctrine/ORM/Query/Parser.php b/lib/Doctrine/ORM/Query/Parser.php
index cb70099f4..821ee9ded 100644
--- a/lib/Doctrine/ORM/Query/Parser.php
+++ b/lib/Doctrine/ORM/Query/Parser.php
@@ -1689,7 +1689,7 @@ class Parser
/**
* ConditionalPrimary ::= SimpleConditionalExpression | "(" ConditionalExpression ")"
*
- * @return \Doctrine\ORM\Query\AST\ConditionalPrimary
+ * @return Doctrine\ORM\Query\AST\ConditionalPrimary
*/
public function ConditionalPrimary()
{
diff --git a/lib/Doctrine/ORM/Query/SqlWalker.php b/lib/Doctrine/ORM/Query/SqlWalker.php
index c0892481f..0547392c8 100644
--- a/lib/Doctrine/ORM/Query/SqlWalker.php
+++ b/lib/Doctrine/ORM/Query/SqlWalker.php
@@ -248,21 +248,23 @@ class SqlWalker implements TreeWalker
}
}
- // LEFT JOIN subclass tables
- foreach ($class->subClasses as $subClassName) {
- $subClass = $this->_em->getClassMetadata($subClassName);
- $tableAlias = $this->getSqlTableAlias($subClass->primaryTable['name'], $dqlAlias);
- $sql .= ' LEFT JOIN ' . $subClass->getQuotedTableName($this->_platform)
- . ' ' . $tableAlias . ' ON ';
- $first = true;
-
- foreach ($class->identifier as $idField) {
- if ($first) $first = false; else $sql .= ' AND ';
-
- $columnName = $class->getQuotedColumnName($idField, $this->_platform);
- $sql .= $baseTableAlias . '.' . $columnName
- . ' = '
- . $tableAlias . '.' . $columnName;
+ // LEFT JOIN subclass tables, only if partial objects disallowed
+ if ( ! $this->_em->getConfiguration()->getAllowPartialObjects() && ! $this->_query->getHint(Query::HINT_FORCE_PARTIAL_LOAD)) {
+ foreach ($class->subClasses as $subClassName) {
+ $subClass = $this->_em->getClassMetadata($subClassName);
+ $tableAlias = $this->getSqlTableAlias($subClass->primaryTable['name'], $dqlAlias);
+ $sql .= ' LEFT JOIN ' . $subClass->getQuotedTableName($this->_platform)
+ . ' ' . $tableAlias . ' ON ';
+ $first = true;
+
+ foreach ($class->identifier as $idField) {
+ if ($first) $first = false; else $sql .= ' AND ';
+
+ $columnName = $class->getQuotedColumnName($idField, $this->_platform);
+ $sql .= $baseTableAlias . '.' . $columnName
+ . ' = '
+ . $tableAlias . '.' . $columnName;
+ }
}
}
@@ -471,7 +473,7 @@ class SqlWalker implements TreeWalker
$sql .= ", $tblAlias." . $rootClass->getQuotedDiscriminatorColumnName($this->_platform)
. ' AS ' . $columnAlias;
- //$columnAlias = $this->_platform->getSqlResultCasing($columnAlias);
+ $columnAlias = $this->_platform->getSqlResultCasing($columnAlias);
$this->_rsm->setDiscriminatorColumn($dqlAlias, $columnAlias);
$this->_rsm->addMetaResult($dqlAlias, $columnAlias, $discrColumn['fieldName']);
@@ -490,7 +492,7 @@ class SqlWalker implements TreeWalker
$columnAlias = $this->getSqlColumnAlias($srcColumn);
$sql .= ", $sqlTableAlias." . $assoc->getQuotedJoinColumnName($srcColumn, $this->_platform)
. ' AS ' . $columnAlias;
- //$columnAlias = $this->_platform->getSqlResultCasing($columnAlias);
+ $columnAlias = $this->_platform->getSqlResultCasing($columnAlias);
$this->_rsm->addMetaResult($dqlAlias, $columnAlias, $srcColumn);
}
}
@@ -506,7 +508,7 @@ class SqlWalker implements TreeWalker
foreach ($assoc->targetToSourceKeyColumns as $srcColumn) {
$columnAlias = $this->getSqlColumnAlias($srcColumn);
$sql .= ', ' . $sqlTableAlias . '.' . $assoc->getQuotedJoinColumnName($srcColumn, $this->_platform) . ' AS ' . $columnAlias;
- //$columnAlias = $this->_platform->getSqlResultCasing($columnAlias);
+ $columnAlias = $this->_platform->getSqlResultCasing($columnAlias);
$this->_rsm->addMetaResult($dqlAlias, $columnAlias, $srcColumn);
}
}
@@ -748,7 +750,7 @@ class SqlWalker implements TreeWalker
$columnAlias = $this->getSqlColumnAlias($class->columnNames[$fieldName]);
$sql .= $sqlTableAlias . '.' . $columnName . ' AS ' . $columnAlias;
- //$columnAlias = $this->_platform->getSqlResultCasing($columnAlias);
+ $columnAlias = $this->_platform->getSqlResultCasing($columnAlias);
$this->_rsm->addFieldResult($dqlAlias, $columnAlias, $fieldName);
} else {
throw DoctrineException::updateMe(
@@ -765,7 +767,7 @@ class SqlWalker implements TreeWalker
$columnAlias = 'sclr' . $this->_aliasCounter++;
$sql .= $this->walkAggregateExpression($expr) . ' AS ' . $columnAlias;
- //$columnAlias = $this->_platform->getSqlResultCasing($columnAlias);
+ $columnAlias = $this->_platform->getSqlResultCasing($columnAlias);
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
} else if ($expr instanceof AST\Subselect) {
$sql .= $this->walkSubselect($expr);
@@ -779,7 +781,7 @@ class SqlWalker implements TreeWalker
$columnAlias = 'sclr' . $this->_aliasCounter++;
$sql .= $this->walkFunction($expr) . ' AS ' . $columnAlias;
- //$columnAlias = $this->_platform->getSqlResultCasing($columnAlias);
+ $columnAlias = $this->_platform->getSqlResultCasing($columnAlias);
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
} else {
// IdentificationVariable
@@ -807,28 +809,33 @@ class SqlWalker implements TreeWalker
$sql .= $sqlTableAlias . '.' . $class->getQuotedColumnName($fieldName, $this->_platform)
. ' AS ' . $columnAlias;
- //$columnAlias = $this->_platform->getSqlResultCasing($columnAlias);
+ $columnAlias = $this->_platform->getSqlResultCasing($columnAlias);
$this->_rsm->addFieldResult($dqlAlias, $columnAlias, $fieldName);
}
// Add any additional fields of subclasses (not inherited fields)
- foreach ($class->subClasses as $subClassName) {
- $subClass = $this->_em->getClassMetadata($subClassName);
-
- foreach ($subClass->fieldMappings as $fieldName => $mapping) {
- if (isset($mapping['inherited'])) {
- continue;
+ // 1) on Single Table Inheritance: always, since its marginal overhead
+ // 2) on Class Table Inheritance only if partial objects are disallowed,
+ // since it requires outer joining subtables.
+ if ($class->isInheritanceTypeSingleTable() || ! $this->_em->getConfiguration()->getAllowPartialObjects()
+ && ! $this->_query->getHint(Query::HINT_FORCE_PARTIAL_LOAD)) {
+ foreach ($class->subClasses as $subClassName) {
+ $subClass = $this->_em->getClassMetadata($subClassName);
+ foreach ($subClass->fieldMappings as $fieldName => $mapping) {
+ if (isset($mapping['inherited'])) {
+ continue;
+ }
+
+ if ($beginning) $beginning = false; else $sql .= ', ';
+
+ $sqlTableAlias = $this->getSqlTableAlias($subClass->primaryTable['name'], $dqlAlias);
+ $columnAlias = $this->getSqlColumnAlias($mapping['columnName']);
+ $sql .= $sqlTableAlias . '.' . $subClass->getQuotedColumnName($fieldName, $this->_platform)
+ . ' AS ' . $columnAlias;
+
+ $columnAlias = $this->_platform->getSqlResultCasing($columnAlias);
+ $this->_rsm->addFieldResult($dqlAlias, $columnAlias, $fieldName);
}
-
- if ($beginning) $beginning = false; else $sql .= ', ';
-
- $sqlTableAlias = $this->getSqlTableAlias($subClass->primaryTable['name'], $dqlAlias);
- $columnAlias = $this->getSqlColumnAlias($mapping['columnName']);
- $sql .= $sqlTableAlias . '.' . $subClass->getQuotedColumnName($fieldName, $this->_platform)
- . ' AS ' . $columnAlias;
-
- //$columnAlias = $this->_platform->getSqlResultCasing($columnAlias);
- $this->_rsm->addFieldResult($dqlAlias, $columnAlias, $fieldName);
}
}
}
diff --git a/lib/Doctrine/ORM/Tools/SchemaTool.php b/lib/Doctrine/ORM/Tools/SchemaTool.php
index 189100fcd..4dc17ff5c 100644
--- a/lib/Doctrine/ORM/Tools/SchemaTool.php
+++ b/lib/Doctrine/ORM/Tools/SchemaTool.php
@@ -21,8 +21,8 @@
namespace Doctrine\ORM\Tools;
-use Doctrine\DBAL\Types\Type;
-use Doctrine\ORM\EntityManager;
+use Doctrine\DBAL\Types\Type,
+ Doctrine\ORM\EntityManager;
/**
* The SchemaTool is a tool to create and/or drop database schemas based on
@@ -306,4 +306,14 @@ class SchemaTool
{
//TODO
}
+
+ public function updateSchema(array $classes)
+ {
+ //TODO
+ }
+
+ public function getUpdateSchemaSql(array $classes)
+ {
+ //TODO
+ }
}
diff --git a/tests/Doctrine/Tests/Models/Company/CompanyEmployee.php b/tests/Doctrine/Tests/Models/Company/CompanyEmployee.php
index eb8917ae8..46b66cecc 100644
--- a/tests/Doctrine/Tests/Models/Company/CompanyEmployee.php
+++ b/tests/Doctrine/Tests/Models/Company/CompanyEmployee.php
@@ -5,8 +5,6 @@ namespace Doctrine\Tests\Models\Company;
/**
* @Entity
* @Table(name="company_employees")
- * @DiscriminatorValue("employee")
- * @SubClasses({"Doctrine\Tests\Models\Company\CompanyManager"})
*/
class CompanyEmployee extends CompanyPerson
{
diff --git a/tests/Doctrine/Tests/Models/Company/CompanyManager.php b/tests/Doctrine/Tests/Models/Company/CompanyManager.php
index 81964a9b0..cde06ce6c 100644
--- a/tests/Doctrine/Tests/Models/Company/CompanyManager.php
+++ b/tests/Doctrine/Tests/Models/Company/CompanyManager.php
@@ -5,7 +5,6 @@ namespace Doctrine\Tests\Models\Company;
/**
* @Entity
* @Table(name="company_managers")
- * @DiscriminatorValue("manager")
*/
class CompanyManager extends CompanyEmployee
{
diff --git a/tests/Doctrine/Tests/Models/Company/CompanyPerson.php b/tests/Doctrine/Tests/Models/Company/CompanyPerson.php
index 21395dc88..c38dc7428 100644
--- a/tests/Doctrine/Tests/Models/Company/CompanyPerson.php
+++ b/tests/Doctrine/Tests/Models/Company/CompanyPerson.php
@@ -8,11 +8,12 @@ namespace Doctrine\Tests\Models\Company;
* @author robo
* @Entity
* @Table(name="company_persons")
- * @DiscriminatorValue("person")
* @InheritanceType("JOINED")
* @DiscriminatorColumn(name="discr", type="string")
- * @SubClasses({"Doctrine\Tests\Models\Company\CompanyEmployee",
- "Doctrine\Tests\Models\Company\CompanyManager"})
+ * @DiscriminatorMap({
+ * "person" = "CompanyPerson",
+ * "manager" = "CompanyManager",
+ * "employee" = "CompanyEmployee"})
*/
class CompanyPerson
{
@@ -39,6 +40,10 @@ class CompanyPerson
inverseJoinColumns={@JoinColumn(name="friend_id", referencedColumnName="id")})
*/
private $friends;
+
+ public function __construct() {
+ $this->friends = new \Doctrine\Common\Collections\ArrayCollection;
+ }
public function getId() {
return $this->id;
@@ -61,9 +66,6 @@ class CompanyPerson
}
public function addFriend(CompanyPerson $friend) {
- if ( ! $this->friends) {
- $this->friends = new \Doctrine\Common\Collections\ArrayCollection;
- }
if ( ! $this->friends->contains($friend)) {
$this->friends->add($friend);
$friend->addFriend($this);
diff --git a/tests/Doctrine/Tests/ORM/Functional/ClassTableInheritanceTest.php b/tests/Doctrine/Tests/ORM/Functional/ClassTableInheritanceTest.php
index ebcb91dd3..0ea6f9e07 100644
--- a/tests/Doctrine/Tests/ORM/Functional/ClassTableInheritanceTest.php
+++ b/tests/Doctrine/Tests/ORM/Functional/ClassTableInheritanceTest.php
@@ -39,6 +39,7 @@ class ClassTableInheritanceTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->_em->clear();
+ $this->_em->getConfiguration()->setAllowPartialObjects(false);
$query = $this->_em->createQuery("select p from Doctrine\Tests\Models\Company\CompanyPerson p order by p.id asc");
$entities = $query->getResult();
@@ -51,6 +52,7 @@ class ClassTableInheritanceTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->assertEquals('Roman S. Borschel', $entities[0]->getName());
$this->assertEquals('Guilherme Blanco', $entities[1]->getName());
$this->assertEquals(100000, $entities[1]->getSalary());
+ $this->_em->getConfiguration()->setAllowPartialObjects(true);
$this->_em->clear();
@@ -99,6 +101,7 @@ class ClassTableInheritanceTest extends \Doctrine\Tests\OrmFunctionalTestCase
$manager = $this->_em->find('Doctrine\Tests\Models\Company\CompanyManager', $manager->getId());
+ $this->assertTrue($manager instanceof CompanyManager);
$this->assertEquals('Roman B.', $manager->getName());
$this->assertEquals(119000, $manager->getSalary());
$this->assertEquals('CEO', $manager->getTitle());
diff --git a/tests/Doctrine/Tests/ORM/Functional/Locking/OptimisticTest.php b/tests/Doctrine/Tests/ORM/Functional/Locking/OptimisticTest.php
index 1333f7dd0..fc9042904 100644
--- a/tests/Doctrine/Tests/ORM/Functional/Locking/OptimisticTest.php
+++ b/tests/Doctrine/Tests/ORM/Functional/Locking/OptimisticTest.php
@@ -124,10 +124,9 @@ class OptimisticTest extends \Doctrine\Tests\OrmFunctionalTestCase
/**
* @Entity
* @Table(name="optimistic_joined_parent")
- * @DiscriminatorValue("parent")
* @InheritanceType("JOINED")
* @DiscriminatorColumn(name="discr", type="string")
- * @SubClasses({"Doctrine\Tests\ORM\Functional\Locking\OptimisticJoinedChild"})
+ * @DiscriminatorMap({"parent" = "OptimisticJoinedParent", "child" = "OptimisticJoinedChild"})
*/
class OptimisticJoinedParent
{
@@ -151,7 +150,6 @@ class OptimisticJoinedParent
/**
* @Entity
* @Table(name="optimistic_joined_child")
- * @DiscriminatorValue("child")
*/
class OptimisticJoinedChild extends OptimisticJoinedParent
{
diff --git a/tests/Doctrine/Tests/ORM/Functional/SingleTableInheritanceTest.php b/tests/Doctrine/Tests/ORM/Functional/SingleTableInheritanceTest.php
index e67e34fa4..eb5e1fee2 100644
--- a/tests/Doctrine/Tests/ORM/Functional/SingleTableInheritanceTest.php
+++ b/tests/Doctrine/Tests/ORM/Functional/SingleTableInheritanceTest.php
@@ -101,8 +101,7 @@ class SingleTableInheritanceTest extends \Doctrine\Tests\OrmFunctionalTestCase
* @Entity
* @InheritanceType("SINGLE_TABLE")
* @DiscriminatorColumn(name="discr", type="string")
- * @SubClasses({"Doctrine\Tests\ORM\Functional\ChildEntity"})
- * @DiscriminatorValue("parent")
+ * @DiscriminatorMap({"parent"="ParentEntity", "child"="ChildEntity"})
*/
class ParentEntity {
/**
@@ -132,7 +131,6 @@ class ParentEntity {
/**
* @Entity
- * @DiscriminatorValue("child")
*/
class ChildEntity extends ParentEntity {
/**
diff --git a/tests/Doctrine/Tests/ORM/Mapping/ClassMetadataTest.php b/tests/Doctrine/Tests/ORM/Mapping/ClassMetadataTest.php
index f8835254b..1477c0ec5 100644
--- a/tests/Doctrine/Tests/ORM/Mapping/ClassMetadataTest.php
+++ b/tests/Doctrine/Tests/ORM/Mapping/ClassMetadataTest.php
@@ -38,7 +38,7 @@ class ClassMetadataTest extends \Doctrine\Tests\OrmTestCase
$this->assertTrue($cm->reflClass instanceof \ReflectionClass);
$this->assertEquals('Doctrine\Tests\Models\CMS\CmsUser', $cm->name);
$this->assertEquals('UserParent', $cm->rootEntityName);
- $this->assertEquals(array('One', 'Two', 'Three'), $cm->subClasses);
+ $this->assertEquals(array('Doctrine\Tests\Models\CMS\One', 'Doctrine\Tests\Models\CMS\Two', 'Doctrine\Tests\Models\CMS\Three'), $cm->subClasses);
$this->assertEquals(array('UserParent'), $cm->parentClasses);
$this->assertEquals('UserRepository', $cm->getCustomRepositoryClass());
$this->assertEquals(array('name' => 'disc', 'type' => 'integer', 'fieldName' => 'disc'), $cm->discriminatorColumn);
diff --git a/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php b/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php
index 182c0d441..aae29e47f 100644
--- a/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php
+++ b/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php
@@ -296,15 +296,16 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
// "Get all persons who have $person as a friend."
// Tough one: Many-many self-referencing ("friends") with class table inheritance
- $q3 = $this->_em->createQuery('SELECT p.id FROM Doctrine\Tests\Models\Company\CompanyPerson p WHERE :param MEMBER OF p.friends');
+ $this->_em->getConfiguration()->setAllowPartialObjects(false);
+ $q3 = $this->_em->createQuery('SELECT p FROM Doctrine\Tests\Models\Company\CompanyPerson p WHERE :param MEMBER OF p.friends');
$person = new \Doctrine\Tests\Models\Company\CompanyPerson;
$this->_em->getClassMetadata(get_class($person))->setIdentifierValues($person, 101);
$q3->setParameter('param', $person);
-
$this->assertEquals(
- 'SELECT c0_.id AS id0, c0_.discr AS discr1 FROM company_persons c0_ LEFT JOIN company_employees c1_ ON c0_.id = c1_.id LEFT JOIN company_managers c2_ ON c0_.id = c2_.id WHERE EXISTS (SELECT 1 FROM company_persons_friends c3_ INNER JOIN company_persons c4_ ON c3_.person_id = c0_.id WHERE c3_.friend_id = c4_.id AND c4_.id = ?)',
+ 'SELECT c0_.id AS id0, c0_.name AS name1, c1_.title AS title2, c2_.salary AS salary3, c2_.department AS department4, c0_.discr AS discr5, c0_.spouse_id AS spouse_id6 FROM company_persons c0_ LEFT JOIN company_managers c1_ ON c0_.id = c1_.id LEFT JOIN company_employees c2_ ON c0_.id = c2_.id WHERE EXISTS (SELECT 1 FROM company_persons_friends c3_ INNER JOIN company_persons c4_ ON c3_.person_id = c0_.id WHERE c3_.friend_id = c4_.id AND c4_.id = ?)',
$q3->getSql()
);
+ $this->_em->getConfiguration()->setAllowPartialObjects(true);
}
public function testSupportsCurrentDateFunction()