diff --git a/lib/Doctrine/ORM/Query/SqlWalker.php b/lib/Doctrine/ORM/Query/SqlWalker.php index 0a6cde95b..d16d9ff60 100644 --- a/lib/Doctrine/ORM/Query/SqlWalker.php +++ b/lib/Doctrine/ORM/Query/SqlWalker.php @@ -732,14 +732,19 @@ class SqlWalker implements TreeWalker $joinTableAlias = $this->getSqlTableAlias($joinTable['name'], $joinedDqlAlias); $sql .= $assoc->getQuotedJoinTableName($this->_platform) . ' ' . $joinTableAlias . ' ON '; + $first = true; if ($relation->isOwningSide) { foreach ($assoc->relationToSourceKeyColumns as $relationColumn => $sourceColumn) { + if ( ! $first) $sql .= ' AND '; else $first = false; + $sql .= $sourceTableAlias . '.' . $sourceClass->getQuotedColumnName($sourceClass->fieldNames[$sourceColumn], $this->_platform) . ' = ' . $joinTableAlias . '.' . $relationColumn; } } else { foreach ($assoc->relationToTargetKeyColumns as $relationColumn => $targetColumn) { + if ( ! $first) $sql .= ' AND '; else $first = false; + $sql .= $sourceTableAlias . '.' . $targetClass->getQuotedColumnName($targetClass->fieldNames[$targetColumn], $this->_platform) . ' = ' . $joinTableAlias . '.' . $relationColumn; @@ -751,14 +756,19 @@ class SqlWalker implements TreeWalker ? ' LEFT JOIN ' : ' INNER JOIN '; $sql .= $targetTableName . ' ' . $targetTableAlias . ' ON '; + $first = true; if ($relation->isOwningSide) { foreach ($assoc->relationToTargetKeyColumns as $relationColumn => $targetColumn) { + if ( ! $first) $sql .= ' AND '; else $first = false; + $sql .= $targetTableAlias . '.' . $targetClass->getQuotedColumnName($targetClass->fieldNames[$targetColumn], $this->_platform) . ' = ' . $joinTableAlias . '.' . $relationColumn; } } else { foreach ($assoc->relationToSourceKeyColumns as $relationColumn => $sourceColumn) { + if ( ! $first) $sql .= ' AND '; else $first = false; + $sql .= $targetTableAlias . '.' . $sourceClass->getQuotedColumnName($sourceClass->fieldNames[$sourceColumn], $this->_platform) . ' = ' . $joinTableAlias . '.' . $relationColumn; diff --git a/tests/Doctrine/Tests/Models/Navigation/NavCountry.php b/tests/Doctrine/Tests/Models/Navigation/NavCountry.php new file mode 100644 index 000000000..fd3755260 --- /dev/null +++ b/tests/Doctrine/Tests/Models/Navigation/NavCountry.php @@ -0,0 +1,39 @@ +name = $name; + } + + public function getId() { + return $this->id; + } + + public function getName() { + return $this->name; + } +} \ No newline at end of file diff --git a/tests/Doctrine/Tests/Models/Navigation/NavPhotos.php b/tests/Doctrine/Tests/Models/Navigation/NavPhotos.php new file mode 100644 index 000000000..b1ce1fa25 --- /dev/null +++ b/tests/Doctrine/Tests/Models/Navigation/NavPhotos.php @@ -0,0 +1,48 @@ +poi = $poi; + $this->file = $file; + } + + public function getId() { + return $this->id; + } + + public function getPointOfInterest() { + return $this->poi; + } + + public function getFile() { + return $this->file; + } +} \ No newline at end of file diff --git a/tests/Doctrine/Tests/Models/Navigation/NavPointOfInterest.php b/tests/Doctrine/Tests/Models/Navigation/NavPointOfInterest.php new file mode 100644 index 000000000..f212e68e2 --- /dev/null +++ b/tests/Doctrine/Tests/Models/Navigation/NavPointOfInterest.php @@ -0,0 +1,56 @@ +lat = $lat; + $this->long = $long; + $this->name = $name; + $this->country = $country; + } + + public function getLong() { + return $this->long; + } + + public function getLat() { + return $this->lat; + } + + public function getName() { + return $this->name; + } + + public function getCountry() { + return $this->country; + } +} \ No newline at end of file diff --git a/tests/Doctrine/Tests/Models/Navigation/NavTour.php b/tests/Doctrine/Tests/Models/Navigation/NavTour.php new file mode 100644 index 000000000..5a58017aa --- /dev/null +++ b/tests/Doctrine/Tests/Models/Navigation/NavTour.php @@ -0,0 +1,61 @@ +name = $name; + $this->pois = new \Doctrine\Common\Collections\ArrayCollection; + } + + public function addPointOfInterest(NavPointOfInterest $poi) + { + $this->pois[] = $poi; + } + + public function getPointOfInterests() + { + return $this->pois; + } + + public function getName() + { + return $this->name; + } + + public function getId() + { + return $this->id; + } +} \ No newline at end of file diff --git a/tests/Doctrine/Tests/ORM/Functional/AllTests.php b/tests/Doctrine/Tests/ORM/Functional/AllTests.php index a3191b886..fa301beb9 100644 --- a/tests/Doctrine/Tests/ORM/Functional/AllTests.php +++ b/tests/Doctrine/Tests/ORM/Functional/AllTests.php @@ -45,6 +45,7 @@ class AllTests $suite->addTestSuite('Doctrine\Tests\ORM\Functional\ManyToManySelfReferentialAssociationTest'); $suite->addTestSuite('Doctrine\Tests\ORM\Functional\OrderedCollectionTest'); $suite->addTestSuite('Doctrine\Tests\ORM\Functional\OrderedJoinedTableInheritanceCollectionTest'); + $suite->addTestSuite('Doctrine\Tests\ORM\Functional\CompositePrimaryKeyTest'); $suite->addTestSuite('Doctrine\Tests\ORM\Functional\ReferenceProxyTest'); $suite->addTestSuite('Doctrine\Tests\ORM\Functional\LifecycleCallbackTest'); $suite->addTestSuite('Doctrine\Tests\ORM\Functional\StandardEntityPersisterTest'); diff --git a/tests/Doctrine/Tests/ORM/Functional/CompositePrimaryKeyTest.php b/tests/Doctrine/Tests/ORM/Functional/CompositePrimaryKeyTest.php new file mode 100644 index 000000000..7eced1b84 --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Functional/CompositePrimaryKeyTest.php @@ -0,0 +1,95 @@ +useModelSet('navigation'); + parent::setUp(); + } + + public function putGermanysBrandenburderTor() + { + $country = new NavCountry("Germany"); + $this->_em->persist($country); + $poi = new NavPointOfInterest(100, 200, "Brandenburger Tor", $country); + $this->_em->persist($poi); + $this->_em->flush(); + $this->_em->clear(); + } + + public function putTripAroundEurope() + { + $poi = $this->_em->find('Doctrine\Tests\Models\Navigation\NavPointOfInterest', array('lat' => 100, 'long' => 200)); + + $tour = new NavTour("Trip around Europe"); + $tour->addPointOfInterest($poi); + + $this->_em->persist($tour); + $this->_em->flush(); + $this->_em->clear(); + + return $tour; + } + + public function testPersistCompositePkEntity() + { + $this->putGermanysBrandenburderTor(); + + $poi = $this->_em->find('Doctrine\Tests\Models\Navigation\NavPointOfInterest', array('lat' => 100, 'long' => 200)); + + $this->assertType('Doctrine\Tests\Models\Navigation\NavPointOfInterest', $poi); + $this->assertEquals(100, $poi->getLat()); + $this->assertEquals(200, $poi->getLong()); + $this->assertEquals('Brandenburger Tor', $poi->getName()); + } + + public function testManyToManyCompositeRelation() + { + $this->putGermanysBrandenburderTor(); + $tour = $this->putTripAroundEurope(); + + $tour = $this->_em->find('Doctrine\Tests\Models\Navigation\NavTour', $tour->getId()); + + $this->assertEquals(1, count($tour->getPointOfInterests())); + } + + public function testCompositeDqlEagerFetching() + { + $this->putGermanysBrandenburderTor(); + $this->putTripAroundEurope(); + + $dql = 'SELECT t, p, c FROM Doctrine\Tests\Models\Navigation\NavTour t ' . + 'INNER JOIN t.pois p INNER JOIN p.country c'; + $tours = $this->_em->createQuery($dql)->getResult(); + + $this->assertEquals(1, count($tours)); + + $pois = $tours[0]->getPointOfInterests(); + + $this->assertEquals(1, count($pois)); + $this->assertEquals('Brandenburger Tor', $pois[0]->getName()); + } + + public function testCompositeCollectionMemberExpression() + { + $this->markTestSkipped('How to test this?'); + + $this->putGermanysBrandenburderTor(); + $this->putTripAroundEurope(); + + $dql = 'SELECT t FROM Doctrine\Tests\Models\Navigation\NavTour t, Doctrine\Tests\Models\Navigation\NavPointOfInterest p ' . + 'WHERE p MEMBER OF t.pois'; + $tours = $this->_em->createQuery($dql) + ->getResult(); + + $this->assertEquals(1, count($tours)); + } +} \ No newline at end of file