Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

[DDC-719] Fixed issue with Empty and also Size function that were gen…

…erating an incorrect SQL for associations counting.
  • Loading branch information...
commit 35af98260a525a841c05be15f52f8df455000066 1 parent 623c02c
Guilherme Blanco authored
69 lib/Doctrine/ORM/Query/AST/Functions/SizeFunction.php
View
@@ -45,45 +45,66 @@ class SizeFunction extends FunctionNode
*/
public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
{
+ $platform = $sqlWalker->getConnection()->getDatabasePlatform();
$dqlAlias = $this->collectionPathExpression->identificationVariable;
$assocField = $this->collectionPathExpression->field;
$qComp = $sqlWalker->getQueryComponent($dqlAlias);
- $assoc = $qComp['metadata']->associationMappings[$assocField];
- $sql = '';
-
+ $class = $qComp['metadata'];
+ $assoc = $class->associationMappings[$assocField];
+ $sql = 'SELECT COUNT(*) FROM ';
+
if ($assoc->isOneToMany()) {
$targetClass = $sqlWalker->getEntityManager()->getClassMetadata($assoc->targetEntityName);
- $targetAssoc = $targetClass->associationMappings[$assoc->mappedBy];
-
$targetTableAlias = $sqlWalker->getSqlTableAlias($targetClass->table['name']);
- $sourceTableAlias = $sqlWalker->getSqlTableAlias($qComp['metadata']->table['name'], $dqlAlias);
-
- $whereSql = '';
+ $sourceTableAlias = $sqlWalker->getSqlTableAlias($class->table['name'], $dqlAlias);
- foreach ($targetAssoc->targetToSourceKeyColumns as $targetKeyColumn => $sourceKeyColumn) {
- $whereSql .= (($whereSql == '') ? ' WHERE ' : ' AND ')
- . $targetTableAlias . '.' . $sourceKeyColumn . ' = '
- . $sourceTableAlias . '.' . $targetKeyColumn;
- }
+ $sql .= $targetClass->getQuotedTableName($platform) . ' ' . $targetTableAlias . ' WHERE ';
+
+ $owningAssoc = $targetClass->associationMappings[$assoc->mappedBy];
- $tableName = $targetClass->table['name'];
- } else if ($assoc->isManyToMany()) {
- $targetTableAlias = $sqlWalker->getSqlTableAlias($assoc->joinTable['name']);
- $sourceTableAlias = $sqlWalker->getSqlTableAlias($qComp['metadata']->table['name'], $dqlAlias);
+ $first = true;
- $whereSql = '';
+ foreach ($owningAssoc->targetToSourceKeyColumns as $targetColumn => $sourceColumn) {
+ if ($first) $first = false; else $sql .= ' AND ';
- foreach ($assoc->relationToSourceKeyColumns as $targetKeyColumn => $sourceKeyColumn) {
- $whereSql .= (($whereSql == '') ? ' WHERE ' : ' AND ')
- . $targetTableAlias . '.' . $targetKeyColumn . ' = '
- . $sourceTableAlias . '.' . $sourceKeyColumn;
+ $sql .= $targetTableAlias . '.' . $sourceColumn
+ . ' = '
+ . $sourceTableAlias . '.' . $class->getQuotedColumnName($class->fieldNames[$targetColumn], $platform);
}
+ } else { // many-to-many
+ $targetClass = $sqlWalker->getEntityManager()->getClassMetadata($assoc->targetEntityName);
+
+ $owningAssoc = $assoc->isOwningSide ? $assoc : $targetClass->associationMappings[$assoc->mappedBy];
+ $joinTable = $owningAssoc->joinTable;
- $tableName = $assoc->joinTable['name'];
+ // SQL table aliases
+ $joinTableAlias = $sqlWalker->getSqlTableAlias($joinTable['name']);
+ $sourceTableAlias = $sqlWalker->getSqlTableAlias($class->table['name'], $dqlAlias);
+
+ // join to target table
+ $sql .= $owningAssoc->getQuotedJoinTableName($platform) . ' ' . $joinTableAlias . ' WHERE ';
+
+ $joinColumns = $assoc->isOwningSide
+ ? $joinTable['joinColumns']
+ : $joinTable['inverseJoinColumns'];
+
+ $first = true;
+
+ foreach ($joinColumns as $joinColumn) {
+ if ($first) $first = false; else $sql .= ' AND ';
+
+ $sourceColumnName = $class->getQuotedColumnName(
+ $class->fieldNames[$joinColumn['referencedColumnName']], $platform
+ );
+
+ $sql .= $joinTableAlias . '.' . $joinColumn['name']
+ . ' = '
+ . $sourceTableAlias . '.' . $sourceColumnName;
+ }
}
- return '(SELECT COUNT(*) FROM ' . $tableName . ' ' . $targetTableAlias . $whereSql . ')';
+ return '(' . $sql . ')';
}
/**
4 lib/Doctrine/ORM/Query/SqlWalker.php
View
@@ -1393,7 +1393,7 @@ public function walkCollectionMemberExpression($collMemberExpr)
$targetClass = $this->_em->getClassMetadata($assoc->targetEntityName);
$owningAssoc = $assoc->isOwningSide ? $assoc : $targetClass->associationMappings[$assoc->mappedBy];
- $joinTable = $assoc->isOwningSide ? $assoc->joinTable : $owningAssoc->joinTable;
+ $joinTable = $owningAssoc->joinTable;
// SQL table aliases
$joinTableAlias = $this->getSqlTableAlias($joinTable['name']);
@@ -1401,7 +1401,7 @@ public function walkCollectionMemberExpression($collMemberExpr)
$sourceTableAlias = $this->getSqlTableAlias($class->table['name'], $dqlAlias);
// join to target table
- $sql .= $assoc->getQuotedJoinTableName($this->_platform)
+ $sql .= $owningAssoc->getQuotedJoinTableName($this->_platform)
. ' ' . $joinTableAlias . ' INNER JOIN '
. $targetClass->getQuotedTableName($this->_platform)
. ' ' . $targetTableAlias . ' ON ';
107 tests/Doctrine/Tests/ORM/Functional/Ticket/DDC719Test.php
View
@@ -0,0 +1,107 @@
+<?php
+
+namespace Doctrine\Tests\ORM\Functional\Ticket;
+
+require_once __DIR__ . '/../../../TestInit.php';
+
+class DDC719Test extends \Doctrine\Tests\OrmFunctionalTestCase
+{
+ protected function setUp()
+ {
+ parent::setUp();
+ //$this->_em->getConnection()->getConfiguration()->setSQLLogger(new \Doctrine\DBAL\Logging\EchoSQLLogger);
+ $this->_schemaTool->createSchema(array(
+ $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC719Group'),
+ ));
+ }
+
+ public function testIsEmptySqlGeneration()
+ {
+ $q = $this->_em->createQuery('SELECT g, c FROM Doctrine\Tests\ORM\Functional\Ticket\DDC719Group g LEFT JOIN g.children c WHERE g.parents IS EMPTY');
+
+ $this->assertEquals('SELECT g0_.name AS name0, g0_.description AS description1, g0_.id AS id2, g1_.name AS name3, g1_.description AS description4, g1_.id AS id5 FROM groups g0_ LEFT JOIN groups_groups g2_ ON g0_.id = g2_.parent_id LEFT JOIN groups g1_ ON g1_.id = g2_.child_id WHERE (SELECT COUNT(*) FROM groups_groups g3_ WHERE g3_.child_id = g0_.id) = 0', $q->getSQL());
+ }
+}
+
+/**
+ * @MappedSuperclass
+ */
+class Entity
+{
+ /**
+ * @Id @GeneratedValue
+ * @Column(type="integer")
+ */
+ protected $id;
+
+ public function getId() { return $this->id; }
+}
+
+/**
+ * @Entity
+ * @Table(name="groups")
+ */
+class DDC719Group extends Entity {
+ /** @Column(type="string", nullable=false) */
+ protected $name;
+
+ /** @Column(type="string", nullable=true) */
+ protected $description;
+
+ /**
+ * @ManyToMany(targetEntity="DDC719Group", inversedBy="parents")
+ * @JoinTable(name="groups_groups",
+ * joinColumns={@JoinColumn(name="parent_id", referencedColumnName="id")},
+ * inverseJoinColumns={@JoinColumn(name="child_id", referencedColumnName="id")}
+ * )
+ */
+ protected $children = NULL;
+
+ /**
+ * @ManyToMany(targetEntity="DDC719Group", mappedBy="children")
+ */
+ protected $parents = NULL;
+
+ /**
+ * construct
+ */
+ public function __construct() {
+ parent::__construct();
+
+ $this->channels = new ArrayCollection();
+ $this->children = new ArrayCollection();
+ $this->parents = new ArrayCollection();
+ }
+
+ /**
+ * adds group as new child
+ *
+ * @param Group $child
+ * @todo check against endless recursion
+ * @todo check if the group is already member of the group
+ */
+ public function addGroup(Group $child) {
+ $this->children->add($child);
+ }
+
+ /**
+ * adds channel as new child
+ *
+ * @param Channel $child
+ * @todo check if the channel is already member of the group
+ */
+ public function addChannel(Channel $child) {
+ $this->channels->add($child);
+ }
+
+ /**
+ * getter & setter
+ */
+ public function getName() { return $this->name; }
+ public function setName($name) { $this->name = $name; }
+ public function getDescription() { return $this->description; }
+ public function setDescription($description) { $this->description = $description; }
+ public function getChildren() { return $this->children; }
+ public function getParents() { return $this->parents; }
+ public function getChannels() { return $this->channels; }
+}
Please sign in to comment.
Something went wrong with that request. Please try again.