Browse files

Implemented support to entities with association marked as @Id suppor…

…t in many situations. Fixed DDC-1435.
  • Loading branch information...
1 parent 3745e94 commit 0ec2cc557f51d6240396689e36101f62d84d2a38 @guilhermeblanco guilhermeblanco committed Oct 29, 2011
View
72 lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php
@@ -1111,25 +1111,25 @@ public function getColumnNames(array $fieldNames = null)
*/
public function getIdentifierColumnNames()
{
- if ($this->isIdentifierComposite) {
- $columnNames = array();
- foreach ($this->identifier as $idField) {
- if (isset($this->associationMappings[$idField])) {
- // no composite pk as fk entity assumption:
- $columnNames[] = $this->associationMappings[$idField]['joinColumns'][0]['name'];
- } else {
- $columnNames[] = $this->fieldMappings[$idField]['columnName'];
- }
+ $columnNames = array();
+
+ foreach ($this->identifier as $idProperty) {
+ if (isset($this->fieldMappings[$idProperty])) {
+ $columnNames[] = $this->fieldMappings[$idProperty]['columnName'];
+
+ continue;
}
- return $columnNames;
- } else if(isset($this->fieldMappings[$this->identifier[0]])) {
- return array($this->fieldMappings[$this->identifier[0]]['columnName']);
- } else {
- // no composite pk as fk entity assumption:
- return array($this->associationMappings[$this->identifier[0]]['joinColumns'][0]['name']);
+
+ // Association defined as Id field
+ $joinColumns = $this->associationMappings[$idProperty]['joinColumns'];
+ $assocColumnNames = array_map(function ($joinColumn) { return $joinColumn['name']; }, $joinColumns);
+
+ $columnNames = array_merge($columnNames, $assocColumnNames);
}
+
+ return $columnNames;
}
-
+
/**
* Sets the type of Id generator to use for the mapped class.
*/
@@ -1905,6 +1905,42 @@ public function getName()
}
/**
+ * Gets the (possibly quoted) identifier column names for safe use in an SQL statement.
+ *
+ * @param AbstractPlatform $platform
+ * @return array
+ */
+ public function getQuotedIdentifierColumnNames($platform)
+ {
+ $quotedColumnNames = array();
+
+ foreach ($this->identifier as $idProperty) {
+ if (isset($this->fieldMappings[$idProperty])) {
+ $quotedColumnNames[] = isset($this->fieldMappings[$idProperty]['quoted'])
+ ? $platform->quoteIdentifier($this->fieldMappings[$idProperty]['columnName'])
+ : $this->fieldMappings[$idProperty]['columnName'];
+
+ continue;
+ }
+
+ // Association defined as Id field
+ $joinColumns = $this->associationMappings[$idProperty]['joinColumns'];
+ $assocQuotedColumnNames = array_map(
+ function ($joinColumn) {
+ return isset($joinColumn['quoted'])
+ ? $platform->quoteIdentifier($joinColumn['name'])
+ : $joinColumn['name'];
+ },
+ $joinColumns
+ );
+
+ $quotedColumnNames = array_merge($quotedColumnNames, $assocQuotedColumnNames);
+ }
+
+ return $quotedColumnNames;
+ }
+
+ /**
* Gets the (possibly quoted) column name of a mapped field for safe use
* in an SQL statement.
*
@@ -1914,7 +1950,9 @@ public function getName()
*/
public function getQuotedColumnName($field, $platform)
{
- return isset($this->fieldMappings[$field]['quoted']) ? $platform->quoteIdentifier($this->fieldMappings[$field]['columnName']) : $this->fieldMappings[$field]['columnName'];
+ return isset($this->fieldMappings[$field]['quoted'])
+ ? $platform->quoteIdentifier($this->fieldMappings[$field]['columnName'])
+ : $this->fieldMappings[$field]['columnName'];
}
/**
View
20 lib/Doctrine/ORM/Query/SqlWalker.php
@@ -248,10 +248,9 @@ private function _generateClassTableInheritanceJoins($class, $dqlAlias)
$sql .= 'JOIN ' . $parentClass->getQuotedTableName($this->_platform) . ' ' . $tableAlias . ' ON ';
$first = true;
- foreach ($class->identifier as $idField) {
+ foreach ($class->getQuotedIdentifierColumnNames($this->_platform) as $columnName) {
if ($first) $first = false; else $sql .= ' AND ';
- $columnName = $class->getQuotedColumnName($idField, $this->_platform);
$sql .= $baseTableAlias . '.' . $columnName . ' = ' . $tableAlias . '.' . $columnName;
}
}
@@ -264,10 +263,9 @@ private function _generateClassTableInheritanceJoins($class, $dqlAlias)
$sql .= ' LEFT JOIN ' . $subClass->getQuotedTableName($this->_platform) . ' ' . $tableAlias . ' ON ';
$first = true;
- foreach ($class->identifier as $idField) {
+ foreach ($class->getQuotedIdentifierColumnNames($this->_platform) as $columnName) {
if ($first) $first = false; else $sql .= ' AND ';
- $columnName = $class->getQuotedColumnName($idField, $this->_platform);
$sql .= $baseTableAlias . '.' . $columnName . ' = ' . $tableAlias . '.' . $columnName;
}
}
@@ -1346,8 +1344,8 @@ public function walkSimpleSelectExpression($simpleSelectExpression)
$tableAlias = $this->getSQLTableAlias($class->getTableName(), $expr);
$sqlParts = array();
- foreach ($class->identifier as $identifier) {
- $sqlParts[] = $tableAlias . '.' . $class->getQuotedColumnName($identifier, $this->_platform);
+ foreach ($class->getQuotedIdentifierColumnNames($this->_platform) as $columnName) {
+ $sqlParts[] = $tableAlias . '.' . $columnName;
}
$sql .= implode(', ', $sqlParts);
@@ -1634,12 +1632,11 @@ public function walkCollectionMemberExpression($collMemberExpr)
$sql .= ' AND ';
$first = true;
- foreach ($targetClass->identifier as $idField) {
+ foreach ($targetClass->getQuotedIdentifierColumnNames($this->_platform) as $targetColumnName) {
if ($first) $first = false; else $sql .= ' AND ';
$this->_parserResult->addParameterMapping($dqlParamKey, $this->_sqlParamIndex++);
- $sql .= $targetTableAlias . '.'
- . $targetClass->getQuotedColumnName($idField, $this->_platform) . ' = ?';
+ $sql .= $targetTableAlias . '.' . $targetColumnName . ' = ?';
}
} else { // many-to-many
$targetClass = $this->_em->getClassMetadata($assoc['targetEntity']);
@@ -1684,12 +1681,11 @@ public function walkCollectionMemberExpression($collMemberExpr)
$sql .= ' AND ';
$first = true;
- foreach ($targetClass->identifier as $idField) {
+ foreach ($targetClass->getQuotedIdentifierColumnNames($this->_platform) as $targetColumnName) {
if ($first) $first = false; else $sql .= ' AND ';
$this->_parserResult->addParameterMapping($dqlParamKey, $this->_sqlParamIndex++);
- $sql .= $targetTableAlias . '.'
- . $targetClass->getQuotedColumnName($idField, $this->_platform) . ' = ?';
+ $sql .= $targetTableAlias . '.' . $targetColumnName . ' = ?';
}
}
View
1 tests/Doctrine/Tests/Models/DDC117/DDC117Article.php
@@ -9,6 +9,7 @@ class DDC117Article
{
/** @Id @Column(type="integer", name="article_id") @GeneratedValue */
private $id;
+
/** @Column */
private $title;
View
11 tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php
@@ -1268,6 +1268,17 @@ public function testSelfReferenceWithOneToOneDoesNotDuplicateAlias()
array(Query::HINT_FORCE_PARTIAL_LOAD => false)
);
}
+
+ /**
+ * @group DDC-1435
+ */
+ public function testForeignKeyAsPrimaryKeySubselect()
+ {
+ $this->assertSqlGeneration(
+ "SELECT s FROM Doctrine\Tests\Models\DDC117\DDC117Article s WHERE EXISTS (SELECT r FROM Doctrine\Tests\Models\DDC117\DDC117Reference r WHERE r.source = s)",
+ "SELECT d0_.article_id AS article_id0, d0_.title AS title1 FROM DDC117Article d0_ WHERE EXISTS (SELECT d1_.source_id, d1_.target_id FROM DDC117Reference d1_ WHERE d1_.source_id = d0_.article_id)"
+ );
+ }
}

1 comment on commit 0ec2cc5

@beberlei
Doctrine member

Good refactoring. I was thinking to shortcut it again, but then the loop with isset and continue for the "default" case of 1 column is probably the fastest solution anyways.

Please sign in to comment.