From 9ce9ae2818379574f784f22dc1c183015ab6a018 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Sat, 3 Feb 2024 19:18:18 +0100 Subject: [PATCH 1/3] Update branches in README --- README.md | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index a128c1f1e9c..c8e009fd5a5 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ -| [3.0.x][3.0] | [2.19.x][2.19] | [2.18.x][2.18] | -|:----------------:|:----------------:|:----------:| -| [![Build status][3.0 image]][3.0] | [![Build status][2.19 image]][2.19] | [![Build status][2.18 image]][2.18] | -| [![Coverage Status][3.0 coverage image]][3.0 coverage]| [![Coverage Status][2.19 coverage image]][2.19 coverage] | [![Coverage Status][2.18 coverage image]][2.18 coverage] | +| [4.0.x][4.0] | [3.1.x][3.1] | [3.0.x][3.0] | [2.19.x][2.19] | [2.18.x][2.18] | +|:------------------------------------------------------:|:------------------------------------------------------:|:-------------------------------------------------------:|:--------------------------------------------------------:|:---------------------------------------------------------:| +| [![Build status][4.0 image]][4.0] | [![Build status][3.1 image]][3.1] | [![Build status][3.0 image]][3.0] | [![Build status][2.19 image]][2.19] | [![Build status][2.18 image]][2.18] | +| [![Coverage Status][4.0 coverage image]][4.0 coverage] | [![Coverage Status][3.1 coverage image]][3.1 coverage] | [![Coverage Status][3.0 coverage image]][3.0 coverage] | [![Coverage Status][2.19 coverage image]][2.19 coverage] | [![Coverage Status][2.18 coverage image]][2.18 coverage] | [

πŸ‡ΊπŸ‡¦ UKRAINE NEEDS YOUR HELP NOW!

](https://www.doctrine-project.org/stop-war.html) @@ -18,6 +18,14 @@ without requiring unnecessary code duplication. * [Documentation](https://www.doctrine-project.org/projects/doctrine-orm/en/stable/index.html) + [4.0 image]: https://github.com/doctrine/orm/actions/workflows/continuous-integration.yml/badge.svg?branch=4.0.x + [4.0]: https://github.com/doctrine/orm/tree/4.0.x + [4.0 coverage image]: https://codecov.io/gh/doctrine/orm/branch/4.0.x/graph/badge.svg + [4.0 coverage]: https://codecov.io/gh/doctrine/orm/branch/4.0.x + [3.1 image]: https://github.com/doctrine/orm/actions/workflows/continuous-integration.yml/badge.svg?branch=3.1.x + [3.1]: https://github.com/doctrine/orm/tree/3.1.x + [3.1 coverage image]: https://codecov.io/gh/doctrine/orm/branch/3.1.x/graph/badge.svg + [3.1 coverage]: https://codecov.io/gh/doctrine/orm/branch/3.1.x [3.0 image]: https://github.com/doctrine/orm/actions/workflows/continuous-integration.yml/badge.svg?branch=3.0.x [3.0]: https://github.com/doctrine/orm/tree/3.0.x [3.0 coverage image]: https://codecov.io/gh/doctrine/orm/branch/3.0.x/graph/badge.svg From 6f98147d093bc594199c98eb49af71fc558ca1f9 Mon Sep 17 00:00:00 2001 From: Michael Skvortsov Date: Sun, 4 Feb 2024 01:11:40 +0200 Subject: [PATCH 2/3] Ignore subclasses without discriminatorValue when generating discriminator column condition SQL (#11200) After commit https://github.com/doctrine/orm/commit/4e8e3ef30b3d214640883aec5a17896afc006116 when `\Doctrine\ORM\Query\SqlWalker` generates dicsriminator column condition SQL (method `\Doctrine\ORM\Query\SqlWalker::generateDiscriminatorColumnConditionSQL`) it adds an empty string to the list of possible values if the inheritance hierarchy contains a non-root abstract class. When the discriminator column is implemented with a custom type in PostgreSQL (equivalent of Enum) the query fails because the type cannot have a value of an empty string. It boils down to the fact that `\Doctrine\ORM\Mapping\ClassMetadataInfo::$subClasses` contains an abstract class and in its Metadata the value of `\Doctrine\ORM\Mapping\ClassMetadataInfo::$discriminatorValue` is `null`. #### Previous behavior In version 2.14.1 `\Doctrine\ORM\Mapping\ClassMetadataInfo::$subClasses` does not contain an abstract class. Fixes #11199, fixes #11177, fixes #10846. --------- Co-authored-by: Michael Skvortsov Co-authored-by: Matthias Pigulla --- src/Query/SqlWalker.php | 24 +++-- .../ORM/Functional/Ticket/GH11199Test.php | 96 +++++++++++++++++++ 2 files changed, 114 insertions(+), 6 deletions(-) create mode 100644 tests/Tests/ORM/Functional/Ticket/GH11199Test.php diff --git a/src/Query/SqlWalker.php b/src/Query/SqlWalker.php index f3d0ab794c0..70971459340 100644 --- a/src/Query/SqlWalker.php +++ b/src/Query/SqlWalker.php @@ -471,6 +471,10 @@ private function generateDiscriminatorColumnConditionSQL(array $dqlAliases): str continue; } + $sqlTableAlias = $this->useSqlTableAliases + ? $this->getSQLTableAlias($class->getTableName(), $dqlAlias) . '.' + : ''; + $conn = $this->em->getConnection(); $values = []; @@ -479,14 +483,22 @@ private function generateDiscriminatorColumnConditionSQL(array $dqlAliases): str } foreach ($class->subClasses as $subclassName) { - $values[] = $conn->quote($this->em->getClassMetadata($subclassName)->discriminatorValue); - } + $subclassMetadata = $this->em->getClassMetadata($subclassName); - $sqlTableAlias = $this->useSqlTableAliases - ? $this->getSQLTableAlias($class->getTableName(), $dqlAlias) . '.' - : ''; + // Abstract entity classes show up in the list of subClasses, but may be omitted + // from the discriminator map. In that case, they have a null discriminator value. + if ($subclassMetadata->discriminatorValue === null) { + continue; + } - $sqlParts[] = $sqlTableAlias . $class->getDiscriminatorColumn()['name'] . ' IN (' . implode(', ', $values) . ')'; + $values[] = $conn->quote($subclassMetadata->discriminatorValue); + } + + if ($values !== []) { + $sqlParts[] = $sqlTableAlias . $class->getDiscriminatorColumn()['name'] . ' IN (' . implode(', ', $values) . ')'; + } else { + $sqlParts[] = '1=0'; // impossible condition + } } $sql = implode(' AND ', $sqlParts); diff --git a/tests/Tests/ORM/Functional/Ticket/GH11199Test.php b/tests/Tests/ORM/Functional/Ticket/GH11199Test.php new file mode 100644 index 00000000000..cac299e12b8 --- /dev/null +++ b/tests/Tests/ORM/Functional/Ticket/GH11199Test.php @@ -0,0 +1,96 @@ +setUpEntitySchema([ + GH11199Root::class, + GH11199Parent::class, + GH11199Foo::class, + GH11199Baz::class, + GH11199AbstractLeaf::class, + ]); + } + + public function dqlStatements(): Generator + { + yield ['SELECT e FROM ' . GH11199Root::class . ' e', "/WHERE g0_.asset_type IN \('root', 'foo', 'baz'\)$/"]; + yield ['SELECT e FROM ' . GH11199Parent::class . ' e', "/WHERE g0_.asset_type IN \('foo'\)$/"]; + yield ['SELECT e FROM ' . GH11199Foo::class . ' e', "/WHERE g0_.asset_type IN \('foo'\)$/"]; + yield ['SELECT e FROM ' . GH11199Baz::class . ' e', "/WHERE g0_.asset_type IN \('baz'\)$/"]; + yield ['SELECT e FROM ' . GH11199AbstractLeaf::class . ' e', '/WHERE 1=0/']; + } + + /** + * @dataProvider dqlStatements + */ + public function testGH11199(string $dql, string $expectedDiscriminatorValues): void + { + $query = $this->_em->createQuery($dql); + $sql = $query->getSQL(); + + self::assertMatchesRegularExpression($expectedDiscriminatorValues, $sql); + } +} + +/** + * @ORM\Entity() + * @ORM\Table(name="gh11199") + * @ORM\InheritanceType("SINGLE_TABLE") + * @ORM\DiscriminatorColumn(name="asset_type", type="string") + * @ORM\DiscriminatorMap({ + * "root" = "\Doctrine\Tests\ORM\Functional\Ticket\GH11199Root", + * "foo" = "\Doctrine\Tests\ORM\Functional\Ticket\GH11199Foo", + * "baz" = "\Doctrine\Tests\ORM\Functional\Ticket\GH11199Baz", + * }) + */ +class GH11199Root +{ + /** + * @ORM\Id + * @ORM\GeneratedValue(strategy="IDENTITY") + * @ORM\Column(type="integer") + * + * @var int|null + */ + private $id = null; +} + +/** + * @ORM\Entity() + */ +abstract class GH11199Parent extends GH11199Root +{ +} + +/** + * @ORM\Entity() + */ +class GH11199Foo extends GH11199Parent +{ +} + +/** + * @ORM\Entity() + */ +class GH11199Baz extends GH11199Root +{ +} + +/** + * @ORM\Entity() + */ +abstract class GH11199AbstractLeaf extends GH11199Root +{ +} From 40fbbf4429b0d66517244051237a2bd0616a7a13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Paris?= Date: Sun, 4 Feb 2024 17:41:45 +0100 Subject: [PATCH 3/3] Point link to correct upgrade guide (#11220) --- docs/en/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/index.rst b/docs/en/index.rst index a7979cb1a70..0236d9968c8 100644 --- a/docs/en/index.rst +++ b/docs/en/index.rst @@ -96,7 +96,7 @@ Tutorials Changelogs ---------- -* `Upgrade `_ +* `Upgrade `_ Cookbook --------