Skip to content
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

Fix filter query when using "OR" conditions #1358

Merged
merged 1 commit into from
Mar 29, 2021

Conversation

phansys
Copy link
Member

@phansys phansys commented Mar 20, 2021

Subject

Fix filter query when using "OR" conditions.

I am targeting this branch, because these changes respect BC.

Rework of #925, keeping BC.
Fixes sonata-project/SonataAdminBundle#2850.
Fixes sonata-project/SonataAdminBundle#3368.
Fixes sonata-project/SonataAdminBundle#5569.

Changelog

### Fixed
- Resulting `WHERE` clause from `Filter::applyWhere()` when using `OR` conditions on queries that already have previous conditions.

To do

  • Find a way to tell the filter it must add the AND WHERE clause for first time without using a static variable;
  • Add tests.

@phansys
Copy link
Member Author

phansys commented Mar 21, 2021

We could evaluate if in the next major, we could provide the Xor expression used for the search from the datagrid at the AdminBundle.
By now, I think we could rely in this workaround.
@VincentLanglet, since you was experiencing this issue, could you please test these changes in a real project?

@phansys phansys requested a review from VincentLanglet March 21, 2021 17:06
Copy link
Member

@VincentLanglet VincentLanglet left a comment

Choose a reason for hiding this comment

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

If I understand correctly.

If you've add a where(Foo) is the configure query.
And you're using a filter1 with AND, a filter3 with OR, a filter2 with AND and a filter4 with OR.

You will get where Foo AND filter1,
then where Foo AND filter1 AND (filter3)
then where Foo AND filter1 AND (filter3) AND filter2
then where Foo AND filter1 AND (filter3 OR filter4) AND filter2

So what you're calling a root filter condition, could more related to the Or. getOrFilterCondition ? Same for the marker.

Would it be possible to add test unit ?

@phansys
Copy link
Member Author

phansys commented Mar 21, 2021

So what you're calling a root filter condition, could more related to the Or. getOrFilterCondition ? Same for the marker.

Let's say you have the following datagrid query:

SELECT ...
FROM model m
WHERE
    m.enabled = true
    AND m.updated_at IS NULL
;

The changes introduced in this PR will perform these actions:

  1. Add an AND condition inside the WHERE clause, using what I called, a marker, enclosed with parentheses:
SELECT ...
FROM model m
WHERE
    m.enabled = true
    AND m.updated_at IS NULL
    AND (
        "sonata_admin.datagrid.filter_query.marker" IS NULL
    )
;
  1. This marker is used later for all the filters to identify the AND group where the OR conditions must be placed:
SELECT ...
FROM model m
WHERE
    m.enabled = true
    AND m.updated_at IS NULL
    AND (
        "sonata_admin.datagrid.filter_query.marker" IS NULL
        OR m.name LIKE "%my search criteria%"
        OR m.lastname LIKE "%my search criteria%"
    )
;

Would it be possible to add test unit ?

Yes, that's in my To Do list, but I'd like to confirm if the results are the expected in other real project before spending time on them. In my case, it is working fine, but please let me know if you have chance to check it on your side.
Thank you in advance.

@VincentLanglet
Copy link
Member

Yes, so the method getRootCondition is returning the part

    (
        "sonata_admin.datagrid.filter_query.marker" IS NULL
        OR m.name LIKE "%my search criteria"
        OR m.lastname LIKE "%my search criteria"
    )

I don't consider this as the root condition, but only the one related to OrFilter.

@phansys
Copy link
Member Author

phansys commented Mar 21, 2021

I don't consider this as the root condition, but only the one related to OrFilter.

Since getRootCondition() is declared in the class Filter, I feel naming it getOrFilterCondition() like a redundancy, but I have no problem with that change. My main concern is about the behavior and how it's working.

@VincentLanglet
Copy link
Member

My main concern is about the behavior and how it's working.

I will try to use this in the week, but since we've overridden the default search behavior I need some work/time.

@phansys phansys force-pushed the pr_925 branch 3 times, most recently from bef6f82 to b1972ec Compare March 23, 2021 02:14
@phansys phansys marked this pull request as ready for review March 23, 2021 02:28
@phansys phansys requested review from VincentLanglet and a team March 23, 2021 02:28
@phansys phansys force-pushed the pr_925 branch 3 times, most recently from cc1df5c to 7cc1086 Compare March 23, 2021 19:32
@phansys phansys requested review from VincentLanglet and a team March 23, 2021 21:20
@phansys phansys force-pushed the pr_925 branch 2 times, most recently from b27e3e9 to f680e97 Compare March 26, 2021 12:07
@phansys phansys changed the title Attempt to fix filter query Fix filter query when using "OR" conditions Mar 26, 2021
@phansys phansys force-pushed the pr_925 branch 3 times, most recently from 656d079 to 0025e97 Compare March 26, 2021 12:24
@phansys
Copy link
Member Author

phansys commented Mar 26, 2021

@sonata-project/contributors, could you please review?
I'd like to make a release including this fix.

franmomu
franmomu previously approved these changes Mar 27, 2021
src/Filter/Filter.php Outdated Show resolved Hide resolved
tests/Filter/FilterTest.php Outdated Show resolved Hide resolved
Copy link
Member

@VincentLanglet VincentLanglet left a comment

Choose a reason for hiding this comment

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

I still didn't find time to try this.

Does someone did ?

*/
private function addOrParameter(BaseProxyQueryInterface $query, $parameter): void
{
$adminCode = $this->getOption('admin_code');
Copy link
Member Author

Choose a reason for hiding this comment

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

Even if we usually will use the admin code which a filter belongs to as value for this option, I think we could use a more agnostic name, since this option has no actual relation with an admin code; it's just a grouping identifier used to know which filters must share the same condition.
WDYT about "group" or something similar?

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