diff --git a/README.md b/README.md index 68ea9c2d310..43f72614467 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 diff --git a/docs/en/index.rst b/docs/en/index.rst index 641709b5dec..83071ad9597 100644 --- a/docs/en/index.rst +++ b/docs/en/index.rst @@ -93,7 +93,7 @@ Tutorials Changelogs ---------- -* `Upgrade `_ +* `Upgrade `_ Cookbook -------- diff --git a/src/Query/SqlWalker.php b/src/Query/SqlWalker.php index f6f94347e36..0baf3727e8e 100644 --- a/src/Query/SqlWalker.php +++ b/src/Query/SqlWalker.php @@ -376,6 +376,10 @@ private function generateDiscriminatorColumnConditionSQL(array $dqlAliases): str continue; } + $sqlTableAlias = $this->useSqlTableAliases + ? $this->getSQLTableAlias($class->getTableName(), $dqlAlias) . '.' + : ''; + $conn = $this->em->getConnection(); $values = []; @@ -384,14 +388,22 @@ private function generateDiscriminatorColumnConditionSQL(array $dqlAliases): str } foreach ($class->subClasses as $subclassName) { - $values[] = $conn->quote((string) $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((string) $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..524ff932099 --- /dev/null +++ b/tests/Tests/ORM/Functional/Ticket/GH11199Test.php @@ -0,0 +1,81 @@ +setUpEntitySchema([ + GH11199Root::class, + GH11199Parent::class, + GH11199Foo::class, + GH11199Baz::class, + GH11199AbstractLeaf::class, + ]); + } + + public static 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' => GH11199Root::class, + 'foo' => GH11199Foo::class, + 'baz' => GH11199Baz::class, +])] +class GH11199Root +{ + #[ORM\Id] + #[ORM\GeneratedValue(strategy: 'IDENTITY')] + #[ORM\Column(type: 'integer')] + private int|null $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 +{ +}