New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Handle removed parameters by tree walker in Paginator #7328
Handle removed parameters by tree walker in Paginator #7328
Conversation
I didn't even know that we allowed subqueries in the |
Why do you think it is a problem ? |
Mostly because the hydration process doesn't consider it, nor we have tests for it AFAIK |
Subselects are supported by design, we even have Subselect node and Parser method. We also do have tests for it https://github.com/doctrine/doctrine2/blob/ce1e3250b4bea05dc0c7a4ed09a6fb05e21705d6/tests/Doctrine/Tests/ORM/Functional/QueryTest.php#L701 and it's pretty widely used. |
Hmm, interesting - fairly sure that subselects were never allowed in the |
It is also documented on the DQL page : https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/dql-doctrine-query-language.html#clauses |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Test case should be added
} | ||
|
||
/** | ||
* Remove unused parameters from $query |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Method should be named in way this comment is not needed. How about unbindUnusedQueryParams
You're right but I don't know how to test it ... I'd like to mock the Paginator and test that the method unbindUnusedQueryParams is called and test the method itself but how can I do it due to its private accessibility ? |
Yeah all pagination tests are currently functional ones. I will try to help you create unit test for this. But if my effort stalls, just create another functional one, similar like this one https://github.com/doctrine/doctrine2/blob/ce1e3250b4bea05dc0c7a4ed09a6fb05e21705d6/tests/Doctrine/Tests/ORM/Functional/PaginationTest.php#L567-L575 Btw test shouldn't just assert working of unbindUnusedQueryParams, but rationalize it. This means it should assert there is either no exception thrown when query is being executed, or count of paramMappings matches count of parameters, basically same as is done here https://github.com/doctrine/doctrine2/blob/ce1e3250b4bea05dc0c7a4ed09a6fb05e21705d6/lib/Doctrine/ORM/Query.php#L309-L315 |
@ostrolucky thank you for your help |
I've replaced your test with unit one, hopefully you don't mind. @Ocramius can you have a look? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall, patch seems fine. There is one left problem that needs to be verified, which is a query like following:
SELECT f FROM Foo f WHERE f.foo = :foo
with bound parameters:
[
'foo' => 'foo',
'bar' => 'bar',
];
This kind of parameter binding is invalid: would the paginator make it valid because of the automatically removed parameters?
FROM Doctrine\\Tests\\Models\\CMS\\CmsUser u | ||
WHERE u.id = :paramInWhere" | ||
); | ||
$query->setParameters(compact('paramInWhere', 'paramInSubSelect')); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's please never ever ever ever use compact
:-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So @Majkl578 can you add it to forbidden functions in CS standard? I was careful in not introducing any new violations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah it's because 2.6 is locked to version 1
Any particular reason for that?
$abstractHydrator->method('hydrateAll')->willReturn([$returnedIds]); | ||
$connection->expects($this->exactly(3))->method('executeQuery'); | ||
|
||
for ($invocationIndex=0; $invocationIndex<2; $invocationIndex++) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this is repeated only 2 times, repeating the expects()
is OK
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So what's the general rule when to duplicate code and when to put it to loop? 3 time repeat?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a loop done for 2 iterations - seems easier to read with explicit at(0)
at(1)
, at(2)
$paginator = (new Paginator($query, true))->setUseOutputWalkers(false); | ||
|
||
$abstractHydrator->method('hydrateAll')->willReturn([$returnedIds]); | ||
$connection->expects($this->exactly(3))->method('executeQuery'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that exactly
, any
, at
and such are static methods
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Asserts as well
Probably yes. Doesn't seem worth it to me to add extra logic to deal with such edge case though. |
Well, I'd still expect a test that either expects an exception or just runs regardless of bound parameters :-) This is just to prevent regressions btw. |
@plfort I have changed your patch to only strip extra params if there is LimitSubqueryWalker or CountWalker used, as only these strip out select statements. Is that ok? I have also added tests which deal with edge case @Ocramius suggested. Dealing with that more correctly might be by moving such logic directly into Parser, instead of in |
Absolutely 👍 |
bump @Ocramius |
@ostrolucky can you merge this to |
v2.6.3 [![Build Status](https://travis-ci.org/doctrine/doctrine2.svg?branch=v2.6.3)](https://travis-ci.org/doctrine/doctrine2) This release provides fixes for many things, specially: - Regression in commit order calculation - BC-break in `EntityManager#find()` using optimistic lock outside of transaction - PHP 7.3 compatibility issues -------------------------------------------- - Total issues resolved: **8** - Total pull requests resolved: **26** - Total contributors: **26** Documentation ------------- - [7472: fix incorrect phpdoc typehint](doctrine#7472) thanks to @seferov - [7465: Fixes tiny typo in the 'Working with DateTime instances' documentation](doctrine#7465) thanks to @unguul - [7444: Fixed URLs of doctrine-mapping.xsd in docs](doctrine#7444) thanks to @Naitsirch - [7441: $hydrationMode throughout can be a string as well as int (for custom modes)](doctrine#7441) thanks to @asgrim - [7435: Fix a typo on Documentation](doctrine#7435) thanks to @oguzdumanoglu - [7434: Removed FAQ paragraph stating public variables are disallowed](doctrine#7434) thanks to @Naitsirch and @flaushi - [7423: Update association-mapping.rst](doctrine#7423) thanks to @ThomasLandauer - [7421: JIRA to Github issues on Limitations and Known Issues](doctrine#7421) thanks to @seferov - [7412: Some formatting improvements](doctrine#7412) thanks to @ThomasLandauer - [7411: Autoload error when following the Getting Started Guide](doctrine#7411) thanks to @ThomasLandauer - [7401: &doctrine#91;docs&doctrine#93; Fix docblock in `inheritance-mapping.rst`](doctrine#7401) thanks to @bobdenotter - [7397: Update getting-started.rst](doctrine#7397) thanks to @eibt - [7394: Class 'Doctrine\Common\Persistence\Mapping\Driver\AnnotationDriver' not found](doctrine#7394) thanks to @ekosynth - [7378: Typo fix](doctrine#7378) thanks to @BenMorel - [7377: Fix query andX doctype](doctrine#7377) thanks to @sserbin - [7374: Deprecation message in documentation for YAML](doctrine#7374) thanks to @SenseException and @iltar - [7360: Document getPartialReference() properly](doctrine#7360) thanks to @lcobucci Bug --- - [7471: Fix parameter value processing for objects with unloaded metadata](doctrine#7471) thanks to @alcaeus - [7367: Fix for BC break in 2.6.2 when calling EM::find() with LockMode::OPTIMISTIC outside of a TX](doctrine#7367) thanks to @timdev - [7328: Handle removed parameters by tree walker in Paginator](doctrine#7328) thanks to @plfort - [7325: Make code php 7.3 lint-compatible](doctrine#7325) thanks to @paxal - [7317: &doctrine#91;XML&doctrine#93; Fix default value of many-to-many order-by to ASC](doctrine#7317) thanks to @alexdenvir - [7260: Fix the handling of circular references in the commit order calculator](doctrine#7260) thanks to @stof - [6830: fix applying column options on foreign key columns](doctrine#6830) thanks to @Tobion Improvement ----------- - [7428: CI: Test against PHP 7.3](doctrine#7428) thanks to @Majkl578 - [7363: Fix compatibility with phan](doctrine#7363) thanks to @philippe-unitiz - [7345: Correct DOMDocument constructor in test](doctrine#7345) thanks to @guilliamxavier - [7307: Fix remaining usages of deprecated ClassLoader and Inflector from doctrine/common](doctrine#7307) thanks to @Majkl578 and @simonwelsh
There is a bug introduced in #6820 (my bad)
Given this code :
The resulting subquery in the Paginator will look like this :
The query is OK but the parameter 'paramB' is still binded to the query, causing a "tooManyParameters" exception.
Edit: I don't really know how to test this behaviour ...