From 0aef63b350c0ea1ff59fbb6b9ce9b3eec3aaa5eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lu=C3=ADs=20Cobucci?= Date: Sun, 30 Apr 2017 18:50:37 +0200 Subject: [PATCH] Fix quoting also when using inheritance --- .../AbstractEntityInheritancePersister.php | 6 +- .../Entity/JoinedSubclassPersister.php | 34 +++------- .../Entity/SingleTablePersister.php | 11 ++-- lib/Doctrine/ORM/Query/SqlWalker.php | 5 +- tests/Doctrine/Tests/Models/Quote/Address.php | 5 +- tests/Doctrine/Tests/Models/Quote/City.php | 27 ++++++++ .../Tests/Models/Quote/FullAddress.php | 17 +++++ .../ORM/Functional/Ticket/GH6402Test.php | 64 ++++++++++++++----- .../ORM/Query/SelectSqlGenerationTest.php | 12 ++-- .../Doctrine/Tests/OrmFunctionalTestCase.php | 20 ++++-- 10 files changed, 137 insertions(+), 64 deletions(-) create mode 100644 tests/Doctrine/Tests/Models/Quote/City.php create mode 100644 tests/Doctrine/Tests/Models/Quote/FullAddress.php diff --git a/lib/Doctrine/ORM/Persisters/Entity/AbstractEntityInheritancePersister.php b/lib/Doctrine/ORM/Persisters/Entity/AbstractEntityInheritancePersister.php index 6052c63e5..79472b50c 100644 --- a/lib/Doctrine/ORM/Persisters/Entity/AbstractEntityInheritancePersister.php +++ b/lib/Doctrine/ORM/Persisters/Entity/AbstractEntityInheritancePersister.php @@ -82,16 +82,18 @@ abstract class AbstractEntityInheritancePersister extends BasicEntityPersister /** * @param string $tableAlias * @param string $joinColumnName + * @param string $quotedColumnName + * * @param string $type * * @return string */ - protected function getSelectJoinColumnSQL($tableAlias, $joinColumnName, $type) + protected function getSelectJoinColumnSQL($tableAlias, $joinColumnName, $quotedColumnName, $type) { $columnAlias = $this->getSQLColumnAlias($joinColumnName); $this->currentPersisterContext->rsm->addMetaResult('r', $columnAlias, $joinColumnName, false, $type); - return $tableAlias . '.' . $joinColumnName . ' AS ' . $columnAlias; + return $tableAlias . '.' . $quotedColumnName . ' AS ' . $columnAlias; } } diff --git a/lib/Doctrine/ORM/Persisters/Entity/JoinedSubclassPersister.php b/lib/Doctrine/ORM/Persisters/Entity/JoinedSubclassPersister.php index 8fe679ad4..6c09b604a 100644 --- a/lib/Doctrine/ORM/Persisters/Entity/JoinedSubclassPersister.php +++ b/lib/Doctrine/ORM/Persisters/Entity/JoinedSubclassPersister.php @@ -462,21 +462,14 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister ? $this->getSQLTableAlias($mapping['inherited']) : $baseTableAlias; - foreach ($mapping['targetToSourceKeyColumns'] as $srcColumn) { - $className = isset($mapping['inherited']) - ? $mapping['inherited'] - : $this->class->name; - - $targetClass = $this->em->getClassMetadata($mapping['targetEntity']); + $targetClass = $this->em->getClassMetadata($mapping['targetEntity']); + foreach ($mapping['joinColumns'] as $joinColumn) { $columnList[] = $this->getSelectJoinColumnSQL( $tableAlias, - $srcColumn, - PersisterHelper::getTypeOfColumn( - $mapping['sourceToTargetKeyColumns'][$srcColumn], - $targetClass, - $this->em - ) + $joinColumn['name'], + $this->quoteStrategy->getJoinColumnName($joinColumn, $this->class, $this->platform), + PersisterHelper::getTypeOfColumn($joinColumn['referencedColumnName'], $targetClass, $this->em) ); } } @@ -510,21 +503,14 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister continue; } - foreach ($mapping['targetToSourceKeyColumns'] as $srcColumn) { - $className = isset($mapping['inherited']) - ? $mapping['inherited'] - : $subClass->name; - - $targetClass = $this->em->getClassMetadata($mapping['targetEntity']); + $targetClass = $this->em->getClassMetadata($mapping['targetEntity']); + foreach ($mapping['joinColumns'] as $joinColumn) { $columnList[] = $this->getSelectJoinColumnSQL( $tableAlias, - $srcColumn, - PersisterHelper::getTypeOfColumn( - $mapping['sourceToTargetKeyColumns'][$srcColumn], - $targetClass, - $this->em - ) + $joinColumn['name'], + $this->quoteStrategy->getJoinColumnName($joinColumn, $subClass, $this->platform), + PersisterHelper::getTypeOfColumn($joinColumn['referencedColumnName'], $targetClass, $this->em) ); } } diff --git a/lib/Doctrine/ORM/Persisters/Entity/SingleTablePersister.php b/lib/Doctrine/ORM/Persisters/Entity/SingleTablePersister.php index ff1d29652..4b8352b35 100644 --- a/lib/Doctrine/ORM/Persisters/Entity/SingleTablePersister.php +++ b/lib/Doctrine/ORM/Persisters/Entity/SingleTablePersister.php @@ -89,15 +89,12 @@ class SingleTablePersister extends AbstractEntityInheritancePersister $targetClass = $this->em->getClassMetadata($assoc['targetEntity']); - foreach ($assoc['targetToSourceKeyColumns'] as $srcColumn) { + foreach ($assoc['joinColumns'] as $joinColumn) { $columnList[] = $this->getSelectJoinColumnSQL( $tableAlias, - $srcColumn, - PersisterHelper::getTypeOfColumn( - $assoc['sourceToTargetKeyColumns'][$srcColumn], - $targetClass, - $this->em - ) + $joinColumn['name'], + $this->quoteStrategy->getJoinColumnName($joinColumn, $subClass, $this->platform), + PersisterHelper::getTypeOfColumn($joinColumn['referencedColumnName'], $targetClass, $this->em) ); } } diff --git a/lib/Doctrine/ORM/Query/SqlWalker.php b/lib/Doctrine/ORM/Query/SqlWalker.php index 310034e69..b39280b39 100644 --- a/lib/Doctrine/ORM/Query/SqlWalker.php +++ b/lib/Doctrine/ORM/Query/SqlWalker.php @@ -764,7 +764,7 @@ class SqlWalker implements TreeWalker $columnAlias = $this->getSQLColumnAlias($columnName); $columnType = PersisterHelper::getTypeOfColumn($joinColumn['referencedColumnName'], $targetClass, $this->em); - $quotedColumnName = $this->quoteStrategy->getJoinColumnName($joinColumn, $class, $this->platform); + $quotedColumnName = $this->quoteStrategy->getJoinColumnName($joinColumn, $class, $this->platform); $sqlSelectExpressions[] = $sqlTableAlias . '.' . $quotedColumnName . ' AS ' . $columnAlias; $this->rsm->addMetaResult($dqlAlias, $columnAlias, $columnName, $isIdentifier, $columnType); @@ -793,7 +793,8 @@ class SqlWalker implements TreeWalker $columnAlias = $this->getSQLColumnAlias($columnName); $columnType = PersisterHelper::getTypeOfColumn($joinColumn['referencedColumnName'], $targetClass, $this->em); - $sqlSelectExpressions[] = $sqlTableAlias . '.' . $columnName . ' AS ' . $columnAlias; + $quotedColumnName = $this->quoteStrategy->getJoinColumnName($joinColumn, $subClass, $this->platform); + $sqlSelectExpressions[] = $sqlTableAlias . '.' . $quotedColumnName . ' AS ' . $columnAlias; $this->rsm->addMetaResult($dqlAlias, $columnAlias, $columnName, $subClass->isIdentifier($columnName), $columnType); } diff --git a/tests/Doctrine/Tests/Models/Quote/Address.php b/tests/Doctrine/Tests/Models/Quote/Address.php index 58e303f13..42beaf2a4 100644 --- a/tests/Doctrine/Tests/Models/Quote/Address.php +++ b/tests/Doctrine/Tests/Models/Quote/Address.php @@ -5,6 +5,9 @@ namespace Doctrine\Tests\Models\Quote; /** * @Entity * @Table(name="`quote-address`") + * @InheritanceType("SINGLE_TABLE") + * @DiscriminatorColumn(name="type", type="string") + * @DiscriminatorMap({"simple" = Address::class, "full" = FullAddress::class}) */ class Address { @@ -51,4 +54,4 @@ class Address return $this->user; } -} \ No newline at end of file +} diff --git a/tests/Doctrine/Tests/Models/Quote/City.php b/tests/Doctrine/Tests/Models/Quote/City.php new file mode 100644 index 000000000..74503ea08 --- /dev/null +++ b/tests/Doctrine/Tests/Models/Quote/City.php @@ -0,0 +1,27 @@ +name = $name; + } +} diff --git a/tests/Doctrine/Tests/Models/Quote/FullAddress.php b/tests/Doctrine/Tests/Models/Quote/FullAddress.php new file mode 100644 index 000000000..b73cda5bd --- /dev/null +++ b/tests/Doctrine/Tests/Models/Quote/FullAddress.php @@ -0,0 +1,17 @@ +useModelSet('quote'); - try { - $this->setUpEntitySchema([ - Address::class, - Group::class, - Phone::class, - User::class, - ]); - } catch (\Exception $exception) { - } + parent::setUp(); } public function testFind() @@ -40,8 +34,28 @@ class GH6402Test extends OrmFunctionalTestCase { $id = $this->createAddress(); - $addresses = $this->_em->createQuery("SELECT a FROM " . Address::class . " a WHERE a.id = :id") - ->setParameter("id", $id) + $addresses = $this->_em->createQuery('SELECT a FROM ' . Address::class . ' a WHERE a.id = :id') + ->setParameter('id', $id) + ->getResult(); + + self::assertCount(1, $addresses); + self::assertNotNull($addresses[0]->user); + } + + public function testFindWithSubClass() + { + $id = $this->createFullAddress(); + + $address = $this->_em->find(FullAddress::class, $id); + self::assertNotNull($address->user); + } + + public function testQueryWithSubClass() + { + $id = $this->createFullAddress(); + + $addresses = $this->_em->createQuery('SELECT a FROM ' . FullAddress::class . ' a WHERE a.id = :id') + ->setParameter('id', $id) ->getResult(); self::assertCount(1, $addresses); @@ -49,18 +63,34 @@ class GH6402Test extends OrmFunctionalTestCase } private function createAddress() + { + $address = new Address(); + $address->zip = 'bar'; + + $this->persistAddress($address); + + return $address->id; + } + + private function createFullAddress() + { + $address = new FullAddress(); + $address->zip = 'bar'; + $address->city = new City('London'); + + $this->persistAddress($address); + + return $address->id; + } + + private function persistAddress(Address $address) { $user = new User(); $user->name = "foo"; - - $address = new Address(); - $address->zip = "bar"; $user->setAddress($address); $this->_em->persist($user); $this->_em->flush(); $this->_em->clear(); - - return $address->id; } } diff --git a/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php b/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php index b6bdce323..b674c5d38 100644 --- a/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php +++ b/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php @@ -39,8 +39,7 @@ class SelectSqlGenerationTest extends OrmTestCase * @param array $queryHints * @param array $queryParams */ - public function assertSqlGeneration($dqlToBeTested, $sqlToBeConfirmed, array $queryHints = [], array $queryParams = [] - ) + public function assertSqlGeneration($dqlToBeTested, $sqlToBeConfirmed, array $queryHints = [], array $queryParams = []) { try { $query = $this->_em->createQuery($dqlToBeTested); @@ -78,8 +77,7 @@ class SelectSqlGenerationTest extends OrmTestCase * @param array $queryHints * @param array $queryParams */ - public function assertInvalidSqlGeneration($dqlToBeTested, $expectedException, array $queryHints = [], array $queryParams = [] - ) + public function assertInvalidSqlGeneration($dqlToBeTested, $expectedException, array $queryHints = [], array $queryParams = []) { $this->expectException($expectedException); @@ -892,7 +890,7 @@ class SelectSqlGenerationTest extends OrmTestCase } /** - * @expectedException Doctrine\ORM\Query\QueryException + * @expectedException \Doctrine\ORM\Query\QueryException */ public function testOrderBySupportsSingleValuedPathExpressionInverseSide() { @@ -1991,7 +1989,7 @@ class SelectSqlGenerationTest extends OrmTestCase { $this->assertSqlGeneration( 'SELECT u, a FROM Doctrine\Tests\Models\Quote\User u JOIN u.address a', - 'SELECT q0_."user-id" AS userid_0, q0_."user-name" AS username_1, q1_."address-id" AS addressid_2, q1_."address-zip" AS addresszip_3 FROM "quote-user" q0_ INNER JOIN "quote-address" q1_ ON q0_."address-id" = q1_."address-id"' + 'SELECT q0_."user-id" AS userid_0, q0_."user-name" AS username_1, q1_."address-id" AS addressid_2, q1_."address-zip" AS addresszip_3, q1_.type AS type_4 FROM "quote-user" q0_ INNER JOIN "quote-address" q1_ ON q0_."address-id" = q1_."address-id" AND q1_.type IN (\'simple\', \'full\')' ); $this->assertSqlGeneration( @@ -2006,7 +2004,7 @@ class SelectSqlGenerationTest extends OrmTestCase $this->assertSqlGeneration( 'SELECT a, u FROM Doctrine\Tests\Models\Quote\Address a JOIN a.user u', - 'SELECT q0_."address-id" AS addressid_0, q0_."address-zip" AS addresszip_1, q1_."user-id" AS userid_2, q1_."user-name" AS username_3 FROM "quote-address" q0_ INNER JOIN "quote-user" q1_ ON q0_."user-id" = q1_."user-id"' + 'SELECT q0_."address-id" AS addressid_0, q0_."address-zip" AS addresszip_1, q1_."user-id" AS userid_2, q1_."user-name" AS username_3, q0_.type AS type_4 FROM "quote-address" q0_ INNER JOIN "quote-user" q1_ ON q0_."user-id" = q1_."user-id" WHERE q0_.type IN (\'simple\', \'full\')' ); $this->assertSqlGeneration( diff --git a/tests/Doctrine/Tests/OrmFunctionalTestCase.php b/tests/Doctrine/Tests/OrmFunctionalTestCase.php index c1445eaec..2ff2c347c 100644 --- a/tests/Doctrine/Tests/OrmFunctionalTestCase.php +++ b/tests/Doctrine/Tests/OrmFunctionalTestCase.php @@ -225,6 +225,8 @@ abstract class OrmFunctionalTestCase extends OrmTestCase ], 'quote' => [ Models\Quote\Address::class, + Models\Quote\City::class, + Models\Quote\FullAddress::class, Models\Quote\Group::class, Models\Quote\NumericEntity::class, Models\Quote\Phone::class, @@ -480,10 +482,20 @@ abstract class OrmFunctionalTestCase extends OrmTestCase } if (isset($this->_usedModelSets['quote'])) { - $conn->executeUpdate('DELETE FROM ' . $platform->quoteIdentifier("quote-address")); - $conn->executeUpdate('DELETE FROM ' . $platform->quoteIdentifier("quote-group")); - $conn->executeUpdate('DELETE FROM ' . $platform->quoteIdentifier("quote-phone")); - $conn->executeUpdate('DELETE FROM ' . $platform->quoteIdentifier("quote-user")); + $conn->executeUpdate( + sprintf( + 'UPDATE %s SET %s = NULL', + $platform->quoteIdentifier("quote-address"), + $platform->quoteIdentifier('user-id') + ) + ); + + $conn->executeUpdate('DELETE FROM ' . $platform->quoteIdentifier('quote-users-groups')); + $conn->executeUpdate('DELETE FROM ' . $platform->quoteIdentifier('quote-group')); + $conn->executeUpdate('DELETE FROM ' . $platform->quoteIdentifier('quote-phone')); + $conn->executeUpdate('DELETE FROM ' . $platform->quoteIdentifier('quote-user')); + $conn->executeUpdate('DELETE FROM ' . $platform->quoteIdentifier('quote-address')); + $conn->executeUpdate('DELETE FROM ' . $platform->quoteIdentifier('quote-city')); } if (isset($this->_usedModelSets['vct_onetoone'])) {