You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A while ago, doctrine/dbal@0db36a9 stopped implementing type-specific handling when quoting values (Statement::quote()). Moreover, it explicitly added a string type hint. When trying to upgrade to dbal v4 / orm v3 we noticed that this breaks single table inheritance when configuring integers as discriminator values as briefly outlined in #9921.
In that case, SqlWalker passes an integer to Connection::quote() when generating the discriminator column SQL condition:
I guess since we can no longer rely on doctrine/dbal to resolve the parameters for us doctrine/orm needs to somehow consider the discriminator column's type and preprocess the SQL parameters accordingly.
Current behavior
When configuring integers as discriminator values Doctrine triggers a type error whenever the application generates queries;
[TypeError] Doctrine\DBAL\Connection::quote(): Argument #1 ($value) must be of type string, int given, called in /var/www/html/vendor/doctrine/orm/src/Query/SqlWalker.php on line 387
How to reproduce
Here are two functional test that demonstrate the bug:
DiscriminatorColumn(type: 'integer')
<?phpdeclare(strict_types=1);
namespaceDoctrine\Tests\ORM\Functional\Ticket;
useDoctrine\ORM\MappingasORM;
useDoctrine\Tests\OrmFunctionalTestCase;
useGenerator;
usePHPUnit\Framework\Attributes\DataProvider;
class IntegerDiscriminatorValueTest extends OrmFunctionalTestCase
{
protectedfunctionsetUp(): void
{
parent::setUp();
$this->setUpEntitySchema([
IntegerBaseClass::class,
IntegerFooEntity::class,
IntegerBarEntity::class,
]);
}
publicstaticfunctiondqlStatements(): Generator
{
yield ['SELECT e FROM ' . IntegerBaseClass::class . ' e', '/WHERE g0_.type IN \(1, 2\)$/'];
yield ['SELECT e FROM ' . IntegerFooEntity::class . ' e', '/WHERE g0_.type IN \(1\)$/'];
yield ['SELECT e FROM ' . IntegerBarEntity::class . ' e', '/WHERE g0_.type IN \(2\)$/'];
}
#[DataProvider('dqlStatements')]
publicfunctiontestIntegerDiscriminatorValue(string$dql, string$expectedDiscriminatorValues): void
{
$query = $this->_em->createQuery($dql);
$sql = $query->getSQL();
self::assertMatchesRegularExpression($expectedDiscriminatorValues, $sql);
}
}
#[ORM\Entity]
#[ORM\Table(name: 'integer_discriminator')]
#[ORM\InheritanceType('SINGLE_TABLE')]
#[ORM\DiscriminatorColumn(name: 'type', type: 'integer')]
#[ORM\DiscriminatorMap([
1 => IntegerFooEntity::class,
2 => IntegerBarEntity::class,
])]
class IntegerBaseClass
{
#[ORM\Id]
#[ORM\GeneratedValue(strategy: 'IDENTITY')]
#[ORM\Column(type: 'integer')]
privateint|null$id = null;
}
#[ORM\Entity]
class IntegerFooEntity extends IntegerBaseClass
{
}
#[ORM\Entity]
class IntegerBarEntity extends IntegerBaseClass
{
}
DiscriminatorColumn(type: 'string')
<?phpdeclare(strict_types=1);
namespaceDoctrine\Tests\ORM\Functional\Ticket;
useDoctrine\ORM\MappingasORM;
useDoctrine\Tests\OrmFunctionalTestCase;
useGenerator;
usePHPUnit\Framework\Attributes\DataProvider;
class StringIntegerEnumDiscriminatorValueTest extends OrmFunctionalTestCase
{
protectedfunctionsetUp(): void
{
parent::setUp();
$this->setUpEntitySchema([
IntegerBaseClass::class,
IntegerFooEntity::class,
IntegerBarEntity::class,
]);
}
publicstaticfunctiondqlStatements(): Generator
{
yield ['SELECT e FROM ' . IntegerBaseClass::class . ' e', '/WHERE g0_.type IN \(\'1\', \'2\'\)$/'];
yield ['SELECT e FROM ' . IntegerFooEntity::class . ' e', '/WHERE g0_.type IN \(\'1\'\)$/'];
yield ['SELECT e FROM ' . IntegerBarEntity::class . ' e', '/WHERE g0_.type IN \(\'2\'\)$/'];
}
#[DataProvider('dqlStatements')]
publicfunctiontestIntegerDiscriminatorValue(string$dql, string$expectedDiscriminatorValues): void
{
$query = $this->_em->createQuery($dql);
$sql = $query->getSQL();
self::assertMatchesRegularExpression($expectedDiscriminatorValues, $sql);
}
}
#[ORM\Entity]
#[ORM\Table(name: 'numeric_string_discriminator')]
#[ORM\InheritanceType('SINGLE_TABLE')]
#[ORM\DiscriminatorColumn(name: 'type', type: 'string')]
#[ORM\DiscriminatorMap([
'1' => EnumFooEntity::class,
'2' => EnumBarEntity::class,
])]
class EnumBaseClass
{
#[ORM\Id]
#[ORM\GeneratedValue(strategy: 'IDENTITY')]
#[ORM\Column(type: 'integer')]
privateint|null$id = null;
}
#[ORM\Entity]
class EnumFooEntity extends IntegerBaseClass
{
}
#[ORM\Entity]
class EnumBarEntity extends IntegerBaseClass
{
}
Expected behavior
When configuring a discriminator column of type integer I'd expect all queries to contain unquoted parameters: WHERE type IN (1, 2)
However, If I changed the type to string I'd like to see the parameters to be quoted instead even if the discriminator values contain numeric strings: WHERE type IN ('1', '2'). This should cover use cases where people are forced to base the inheritance on enums such as ENUM('1','2','3')..
Bug Report
Summary
A while ago, doctrine/dbal@0db36a9 stopped implementing type-specific handling when quoting values (
Statement::quote()
). Moreover, it explicitly added astring
type hint. When trying to upgrade to dbal v4 / orm v3 we noticed that this breaks single table inheritance when configuring integers as discriminator values as briefly outlined in #9921.In that case,
SqlWalker
passes an integer toConnection::quote()
when generating the discriminator column SQL condition:orm/src/Query/SqlWalker.php
Line 387 in c3cc0fd
orm/src/Query/SqlWalker.php
Line 2250 in c3cc0fd
This results in a type error.
I guess since we can no longer rely on
doctrine/dbal
to resolve the parameters for usdoctrine/orm
needs to somehow consider the discriminator column's type and preprocess the SQL parameters accordingly.Current behavior
When configuring integers as discriminator values Doctrine triggers a type error whenever the application generates queries;
How to reproduce
Here are two functional test that demonstrate the bug:
DiscriminatorColumn(type: 'integer')
DiscriminatorColumn(type: 'string')
Expected behavior
When configuring a discriminator column of type
integer
I'd expect all queries to contain unquoted parameters:WHERE type IN (1, 2)
Example
However, If I changed the type to
string
I'd like to see the parameters to be quoted instead even if the discriminator values contain numeric strings:WHERE type IN ('1', '2')
. This should cover use cases where people are forced to base the inheritance on enums such asENUM('1','2','3').
.The text was updated successfully, but these errors were encountered: