Skip to content

Conversation

mpdude
Copy link
Contributor

@mpdude mpdude commented Oct 7, 2025

This PR fixes the Criteria matching API for IN and NIN conditions with values that are arrays, by making sure that type information for the matched field is passed to the DBAL level correctly.

Passing the right parameter type to DBAL is important to make sure parameter conversions are applied before matching at the database level.

Memory-based collections (ArrayCollections or initialized collection fields) would perform matching on the objects in memory where no type conversion to the database representation is required, giving correct results.

But uninitialized collections that have their conditions evaluated at the database level need to convert parameter values to the database representation before performing the comparison.

One extra challenge is that the DBAL type system does currently not support array-valued parameters for custom types. Only a limited list of types is supported.

I discussed this with @morozov at the Doctrine Hackathon and came to the conclusion that it would be best to work around this limitation at the ORM level. Thus, this fix recognizes array-valued parameters and creates multiple placeholders (like ?, ?, ?) for them, flattening out the arrays in the parameter list and repeating the type information for each one of them.

Previous stalled attempt to fix this was in #11897.

…ype conversions

This PR fixes the `Criteria` matching API for `IN` and `NIN` conditions with values that are arrays, by making sure that type information for the matched field is passed to the DBAL level correctly.

Passing the right parameter type to DBAL is important to make sure parameter conversions are applied before matching at the database level.

Memory-based collections (`ArrayCollection`s or initialized collection fields) would perform matching on the objects in memory where no type conversion to the database representation is required, giving correct results.

But uninitialized collections that have their conditions evaluated at the database level need to convert parameter values to the database representation before performing the comparison.

One extra challenge is that the DBAL type system does currently not support array-valued parameters for custom types. Only a [limited list of types](https://www.doctrine-project.org/projects/doctrine-dbal/en/4.2/reference/data-retrieval-and-manipulation.html#list-of-parameters-conversion) is supported.

I discussed this with @morozov at the Doctrine Hackathon and came to the conclusion that it would be best to work around this limitation at the ORM level. Thus, this fix recognizes array-valued parameters and creates multiple placeholders (like `?, ?, ?`) for them, flattening out the arrays in the parameter list and repeating the type information for each one of them.

Previous stalled attempt to fix this was in doctrine#11897.
@mpdude mpdude force-pushed the criteria-matching-custom-type-retry branch from f6d4c47 to bd86a47 Compare October 8, 2025 21:13
morozov
morozov previously approved these changes Oct 9, 2025
Copy link
Member

@morozov morozov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good from the DBAL perspective 👍

@greg0ire
Copy link
Member

The commits would need to be squashed either by you or the person who merges.


$matching = new OwningManyToManyEntity();
$matching->id2 = 'first';
$matching->field = 'match this';
Copy link
Member

@greg0ire greg0ire Oct 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I asked Claude how this test had to do with conversion, and when I understood, how to make it more obvious, it suggested to add comments here and below. There are other suggestions but this is the one I think would be the most appropriate.

Suggested change
$matching->field = 'match this';
$matching->field = 'match this'; // stored as 'zngpu guvf'

Comment on lines +62 to +63
yield [Criteria::expr()->eq('field', 'match this')];
yield [Criteria::expr()->in('field', ['match this'])];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
yield [Criteria::expr()->eq('field', 'match this')];
yield [Criteria::expr()->in('field', ['match this'])];
yield [Criteria::expr()->eq('field', 'match this')]; // should convert to 'zngpu guvf'
yield [Criteria::expr()->in('field', ['match this'])]; // should convert to ['zngpu guvf']

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you agree, please do the same for the other test

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants