[DDC-2240] Inconsistent querying for parameter type (from ClassMetadata) between using Find/FindBy and DoctrineQL Created: 11/Jan/13 Updated: 08/Feb/13 Resolved: 13/Jan/13 |
|
| Status: | Resolved |
| Project: | Doctrine 2 - ORM |
| Component/s: | DQL |
| Affects Version/s: | 2.3.1 |
| Fix Version/s: | None |
| Security Level: | All |
| Type: | Bug | Priority: | Major |
| Reporter: | Slavik Derevyanko | Assignee: | Benjamin Eberlei |
| Resolution: | Duplicate | Votes: | 0 |
| Labels: | ClassMetadata, dql | ||
| Attachments: |
|
||||||||
| Issue Links: |
|
||||||||
| Description |
|
Hi, I have stumbled on a problem were querying the same data with different methods (findBy and DQL) retrieves different results. I have extended the Doctrine\DBAL\Types\DateTimeType with my own type which I attach. It is important, as the single purpose of convertToDatabaseValue() is to perform conversion of the incoming DateTime to the UTC timezone prior to conversion to string, Example: as you see, DateTime object is created without DateTimeZone set, which makes it employ the server's default timezone (say EST). Entity has this property registered as:
And this datatype is registered with Doctrine through Symfony2 configuration: Whenever I query the DB, prior to SQL generation, DateTime is getting converted to UTC by UTCDateTimeType#convertToDatabaseValue(), and becomes: $entity = $em->getRepository('BVDPetroleumBundle:FuelCardTransaction')->findOneBy(array('id' => $id, 'processed_datetime' => new \DateTime('2011-03-10 23:58:37'))); But, when the DQL is used to issue the same query: $queryBuilder = $em->createQueryBuilder() Doctrine\DBAL\Types\DateTimeType#convertToDatabaseValue() is getting executed for 'processed_datetime', instead of and the conversion doesn't happen, so the query doesn't return the result, that really exists in DB. I attach two methods traces, so it's easier to identify the problem: whenever the findBy is used, and whenever the DQL is used. The reason it succeeds when used with findBy methods: The reason it fails with DQL: The $types (which has 'datetime' instead of 'utcdatetime') array is getting formed in in Doctrine\ORM\Query#processParameterMappings($paramMappings) in Doctrine\ORM\AbstractQuery#processParameterValue($value) for object of class DateTime I would expect this to be executed: but it's not, and the DateTime is returned out of it, and in Doctrine\ORM\Query\processParameterMappings $type is getting set to $parameter->getType() ('datetime') Please confirm/contradict the issue. Right now for workaround, whenever I use DQL, have to explicitly set the timezone of DateTime prior to issuing a query. From Russia with love, |
| Comments |
| Comment by Slavik Derevyanko [ 11/Jan/13 ] |
|
I realized, that with DQL, and that it's possible to set the type as a third parameter: $queryBuilder = $em->createQueryBuilder() It seems, this is worth noting in the documentation. |
| Comment by Benjamin Eberlei [ 12/Jan/13 ] |
|
Verified, but I don't know how to fix it without breaking BC. As a workaround you can convert the value yourself in your code, not the nicest solution, but when wrapped in a function call of your own, it shouldn't be to invasive. Guilherme Blanco any idea what to do? |
| Comment by Guilherme Blanco [ 12/Jan/13 ] |
|
There's a way currently to fix this issue. Currently, setParameter only accepts key, value, type as arguments, creating its own Query\Parameter. Ideally, any Type could convert back and forth from DB to PHP value. During a query, the algorithm should apply also. But if we do this change, we will introduce a BC break. To solve the issue, you'll have to create your own Parameter. From the Doctrine perspective, we only need to support $key to be a class too. If it's a class, replace the value in the collection of parameters. This is the required change in our codebase. All you have to do is create a class that extends Query\Parameter, then apply your required changes when doing getValue or during object construction. Then use the method I mentioned to inject an ArrayCollection of Parameters and everything will work. =) |
| Comment by Benjamin Eberlei [ 13/Jan/13 ] |
|
Same as |
| Comment by Benjamin Eberlei [ 08/Feb/13 ] |
|
A related Github Pull-Request [GH-574] was opened |
| Comment by Slavik Derevyanko [ 08/Feb/13 ] |
|
Great, thanks! |