Skip to content

Commit

Permalink
Implemented support to entities with association marked as @id suppor…
Browse files Browse the repository at this point in the history
…t in many situations. Fixed DDC-1435.
  • Loading branch information
guilhermeblanco committed Oct 29, 2011
1 parent 3745e94 commit 0ec2cc5
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 29 deletions.
72 changes: 55 additions & 17 deletions lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php
Expand Up @@ -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.
*/
Expand Down Expand Up @@ -1904,6 +1904,42 @@ public function getName()
return $this->name;
}

/**
* 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.
Expand All @@ -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'];
}

/**
Expand Down
20 changes: 8 additions & 12 deletions lib/Doctrine/ORM/Query/SqlWalker.php
Expand Up @@ -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;
}
}
Expand All @@ -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;
}
}
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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']);
Expand Down Expand Up @@ -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 . ' = ?';
}
}

Expand Down
1 change: 1 addition & 0 deletions tests/Doctrine/Tests/Models/DDC117/DDC117Article.php
Expand Up @@ -9,6 +9,7 @@ class DDC117Article
{
/** @Id @Column(type="integer", name="article_id") @GeneratedValue */
private $id;

/** @Column */
private $title;

Expand Down
11 changes: 11 additions & 0 deletions tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php
Expand Up @@ -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)"
);
}
}


Expand Down

1 comment on commit 0ec2cc5

@beberlei
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.