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
+{
+}