Problem/Motivation
As title says - Incorrect filter group OR behavior, INNER JOIN
instead of expected LEFT JOIN
From @SoulReceiver #139 comment
Steps to reproduce
- Install Drupal
- Create an article with the tag 'test'
- Create a view of articles and add 'Tags' as an exposed filter with 'Is one of', twice, using OR operator
- Set both filters to 'test'
- Confirm there are no results, when you should expect the test article to appear
I note that it works as expected if the exposed filters are set to 'Is all of'.
From @pameeela #121 comment
Proposed resolution
- Use
INNER JOIN
only if the join is not for filter group with OR operator - Add tests to replicate the bug and check the fix.
Remaining tasks
---
User interface changes
---
API changes
---
Data model changes
---
Release notes snippet
---
Original summary D7
I have a view, in code, which uses two groups of ANDed filters, with group behaviour OR. Since updating to views 3.5 (from 3.3+173-dev), the filter OR no longer works correctly - I am getting only the nodes that match the second filter group, not nodes that match either group. There is nothing very special about the filters, which operate on node type, status, nid and taxonomy terms. Aggregation is enabled.
I am pulling values from view arguments and supplying those to the filters in hook_views_query_alter(), but if I disable that and use static filter values in the view the OR still fails as above, so I don't think that is the problem.
The relevant query in 3.3 used a LEFT JOIN, this has changed to INNER JOIN in 3.5. See the second join in each query below.
7.x-3.3+173-dev:
SELECT DISTINCT node.title AS node_title, node.nid AS nid, COUNT(field_data_field_related_article.field_related_article_tid) AS field_data_field_related_article_field_related_article_tid, COUNT(field_data_field_related_article.delta) AS field_data_field_related_article_delta, COUNT(field_data_field_related_article.language) AS field_data_field_related_article_language, COUNT(field_data_field_related_article.bundle) AS field_data_field_related_article_bundle
FROM
{node} node
INNER JOIN {field_data_field_related_article} field_data_field_related_article ON node.nid = field_data_field_related_article.entity_id AND (field_data_field_related_article.entity_type = 'node' AND field_data_field_related_article.deleted = '0')
LEFT JOIN {field_data_field_related_delivery} field_data_field_related_delivery ON node.nid = field_data_field_related_delivery.entity_id AND (field_data_field_related_delivery.entity_type = 'node' AND field_data_field_related_delivery.deleted = '0')
INNER JOIN {node_access} na ON na.nid = node.nid
WHERE (( (node.status = '1') AND (node.type IN ('article', 'programme')) AND (node.nid != '68') AND (field_data_field_related_article.field_related_article_tid IN ('54')) )OR( (node.status = '1') AND (node.type IN ('article', 'programme')) AND (node.nid != '68') AND (field_data_field_related_delivery.field_related_delivery_value IN ('distance')) ))AND(( (na.gid = '0') AND (na.realm = 'all') )OR( (na.gid = '0') AND (na.realm = 'domain_site') )OR( (na.gid = '3') AND (na.realm = 'domain_id') ))AND (na.grant_view >= '1')
GROUP BY node_title, nid
ORDER BY node_title ASC
7.x-3.5:
SELECT DISTINCT node.title AS node_title, node.nid AS nid, COUNT(field_data_field_related_article.field_related_article_tid) AS field_data_field_related_article_field_related_article_tid, COUNT(field_data_field_related_article.delta) AS field_data_field_related_article_delta, COUNT(field_data_field_related_article.language) AS field_data_field_related_article_language, COUNT(field_data_field_related_article.bundle) AS field_data_field_related_article_bundle
FROM
{node} node
INNER JOIN {field_data_field_related_article} field_data_field_related_article ON node.nid = field_data_field_related_article.entity_id AND (field_data_field_related_article.entity_type = 'node' AND field_data_field_related_article.deleted = '0')
INNER JOIN {field_data_field_related_delivery} field_data_field_related_delivery ON node.nid = field_data_field_related_delivery.entity_id AND (field_data_field_related_delivery.entity_type = 'node' AND field_data_field_related_delivery.deleted = '0')
INNER JOIN {node_access} na ON na.nid = node.nid
WHERE (( (node.status = '1') AND (node.type IN ('article', 'programme')) AND (node.nid != '68') AND (field_data_field_related_article.field_related_article_tid IN ('54')) )OR( (node.status = '1') AND (node.type IN ('article', 'programme')) AND (node.nid != '68') AND (field_data_field_related_delivery.field_related_delivery_value IN ('distance')) ))AND(( (na.gid = '0') AND (na.realm = 'all') )OR( (na.gid = '0') AND (na.realm = 'domain_site') )OR( (na.gid = '3') AND (na.realm = 'domain_id') ))AND (na.grant_view >= '1')
GROUP BY node_title, nid
ORDER BY node_title ASC
Comment | File | Size | Author |
---|
Issue fork drupal-1766338
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
- 1766338-incorrect-filter-group changes, plain diff MR !4081
Comments
Comment #1
John Pitcairn CreditAttribution: John Pitcairn commented7.x-3.3 also produces a LEFT JOIN, and so does 7.x-3.0. This behavior in 7.x-3.4 and 7.x-3.5 appears to be a regression?
The commit that changed the behavior is:
commit 994acb299405ff0651706c020cf5d4e6d689e8b3
Author: Daniel Wehner
Date: Fri Aug 17 13:11:59 2012 +0200
Issue #1494884: Use many_to_one for the field_list filter
Comment #2
Ravenight CreditAttribution: Ravenight commentedI can report the group by function is not working too. I upgraded from 7-3.3 to 7-3.5 and my views with simple grouping by month no longer group.Code: (group by is not included in the query)
Grouping should be on the node.created field and is setup to do so in the settings.
Okay my issue was caused by theme developer and simplehtmldom modules. When these are both enabled, the group by is not inserted into the query. I turned them off and views 7-3.5 started working as it had been.
Comment #3
John Pitcairn CreditAttribution: John Pitcairn commentedThis issue is not about SQL GROUP BY
It is about creating views filter OR groups, which should use LEFT JOIN for the optional filter field tables, but now use INNER JOIN.
Comment #4
mariusart CreditAttribution: mariusart commentedHi. I've the same problem.
how i can resolve it?
thanks
Comment #5
xenophyle CreditAttribution: xenophyle commentedI have the same problem and have temporarily plugged the hole by changing includes/handlers.inc line 896 in function ensure_my_table() from
to
I haven't had time to text extensively, but it hasn't broken any of my other views so far.
EDIT: This isn't meant as a long-term solution. I just wanted to post a quick fix that worked in my case. If you use this, you should at least check that your other views work as expected. In summary, use at your own risk.
Comment #6
John Pitcairn CreditAttribution: John Pitcairn commentedI'm staying at 3.3+dev for now.
I'm pretty sure doing what you have may have unintended consequences somewhere. The commit that broke things simply changes the parent class for this specific handler.
I'll roll a patch that just reverts the commit from #1494884: Why is there no "is all of" operator for select list filters?, but if anyone is relying on that new behavior, the patch will revert that too.
Comment #7
John Pitcairn CreditAttribution: John Pitcairn commentedHere's the patch as above. It applies to 7.x-3.x-dev or 7.x-3.5.
Marking needs review to hopefully attract a little attention, but my feeling is that simply reverting may not be the way to go since others will be using the new filter behavior. That needs to be fixed so it doesn't break filter grouping.
Comment #8
Jorrit CreditAttribution: Jorrit commentedIt works for me, however: all list-based views have to be re-edited and saved after the patch commit.
Comment #9
liquidcms CreditAttribution: liquidcms commentedi had the same issue when going from 3.3 to 3.5; but saw a few different things
- i have now an INNER join where there used to be a LEFT (as reported)
- also have and AND in my WHEREwhere the OR used to be
- the OR'ed filter groups, even though they showed correctly in the views admin form; when i go to rearrange, even though i see a 2nd filter group; all of the filters are in the first group (hence the AND). moving them to the 2nd group and re-saving fixes the AND back to an OR
the incorrect inner join is being used with a boolean field; if that makes any difference.. trying patch out now.
Comment #10
liquidcms CreditAttribution: liquidcms commentedthe fix in #5 fixes for me; not sure what the patch #7 is about; doesn't seem to be related to this issue.
Comment #11
Jorrit CreditAttribution: Jorrit commentedPatch 7 also worked for me, I overlooked patch 5. I will try it tomorrow. I think it is better to have a patch that changes as little as possible.
Comment #12
John Pitcairn CreditAttribution: John Pitcairn commented@liquidcms: Patch #7 simply reverts the bad commit that produced the incorrect behaviour. The changes made in that commit were very simple, do a single thing, affect a single file (changing the filter handler class inheritance) and are easily reversible. If the patch at #7 does not fix the issue for anyone, then they probably have a different issue.
The change in #5 (there is no patch there) will force a LEFT JOIN even where it is known to be safe to use INNER JOIN. The bad commit did not touch include/handlers.inc - I do not think attempting to patch it there is appropriate, there is nothing broken there to fix.
@Jorrit: I think it is better to have a patch that fixes only the broken filter handler.
Comment #13
liquidcms CreditAttribution: liquidcms commentedyes, patch in #7 works as well (changes from #5 reverted)
Comment #14
Mark_L6n CreditAttribution: Mark_L6n commentedThe patch in #7 works for me as well.
Comment #15
John Pitcairn CreditAttribution: John Pitcairn commentedI'm going to re-open #1494884: Why is there no "is all of" operator for select list filters?, in the hope that it will generate some discussion.
We probably can't expect this patch to be committed as-is since it will break the new feature introduced in that issue.
Comment #16
Taxoman CreditAttribution: Taxoman commentedSee also:
#1601036: Views: Use LEFT JOIN not INNER, and the issue it is marked as a duplicate of:
#1781744: Draft and Needs review pages are broken
Comment #17
hass CreditAttribution: hass commentedIs the workbench issue now a views bug? Cannot review on mobile :-(
Comment #18
hass CreditAttribution: hass commentedComment #19
John Pitcairn CreditAttribution: John Pitcairn commentedI don't think this is a critical views bug.
Comment #20
hass CreditAttribution: hass commentedIf a large number of valid views is broken and several modules I think it is.
Comment #21
Mark_L6n CreditAttribution: Mark_L6n commentedI'd agree with hass...since this likely breaks a huge number of views, I don't understand why it wouldn't be 'critical'.
Comment #22
John Pitcairn CreditAttribution: John Pitcairn commentedSet it back to critical then. Somebody further up the food chain will probably yell at you ;-)
Comment #23
Mark_L6n CreditAttribution: Mark_L6n commentedOK :-) Apologies to you guys working so hard on putting Views in core (my favorite of the many pieces of good news for D8).
As a summary, this issue is causing views with a SQL query containing a logical structure as simple as the following to not work correctly:
Given such a basic structure, it's likely that a huge number of views are not working correctly, so the priority has been changed to critical.
Comment #24
drewish CreditAttribution: drewish commentedYeah, this is definitely a critical bug. It basically broke a bunch of our views.
Comment #25
Preston McMurry CreditAttribution: Preston McMurry commentedI made the #7 patch some weeks ago, and everything worked.
A few weeks pass ...
... and view is back to old bad behavior. Checked patch, and it is still in place:
Not sure what else might be going on ...
-----
edit #1: I looked at the current dev release ( http://ftp.drupal.org/files/projects/views-7.x-3.x-dev.zip ) and it contains the unpatched code.
Comment #26
John Pitcairn CreditAttribution: John Pitcairn commentedThis patch has not been committed to dev, you'll need to re-patch every time you update.
Comment #27
Preston McMurry CreditAttribution: Preston McMurry commentedHave not updated, just trying to find code that works. See #24. Patch still in place, but error has returned regardless.
Also tried code from the 3.3 release ( http://drupal.org/node/1451068 ) and it failed as well. Probably because the function name is different than in the patch.
Comment #28
John Pitcairn CreditAttribution: John Pitcairn commentedIf the example you posted at #25 is the current module code you are running, then it isn't patched. Many-to-one is the new, faulty behaviour.
Comment #29
Preston McMurry CreditAttribution: Preston McMurry commentedAgh. You are correct. That was a whole day wasted because someone on else on the project team unwisely fiddled my previously applied (and functional) patch.
Comment #30
dealancer CreditAttribution: dealancer commentedApplied, but I am still having this issue again.
Comment #31
dawehnerSo I totally see all your points that the initial in #1494884: Why is there no "is all of" operator for select list filters? change was wrong
though I'm wondering how much we would break by moving it back.
At the same time we then probably would need some code for converting new created views back, similar like the current init() code does it and maybe even add support for "is all of". What do you think?
Comment #32
John Pitcairn CreditAttribution: John Pitcairn commentedI have never yet needed to use the "is all of" operator so I don't personally care what happens to that. But I guess we are now far enough down the track that there needs to be a way to continue to support it without breaking anything else, so yeah.
Comment #33
magtak CreditAttribution: magtak commentedThis also occurs in 6.x-2.16. Should we await a solution? To avoid hacking/patching I changed my model a bit.
Comment #34
runeasgar CreditAttribution: runeasgar commentedsubscribe.. this is crippling a view that I need for a site I'm building. I don't think it's possible to build the view without this working properly.
Comment #35
jacquelynfisher CreditAttribution: jacquelynfisher commentedI agree with runeasgar. This issue is breaking a view that is needed for a site that is almost ready to go live.
Comment #36
sorin.eugen CreditAttribution: sorin.eugen commentedFor the issue with INNER JOIN instead of LEFT JOIN, without adding the patch in #7, you can select the Reduce duplicates checkbox from the first field in OR group filter and will transform your query to LEFT JOIN.
For more info check handlers.inc at line 890:
if ($this->handler->operator == 'or' && empty($this->handler->options['reduce_duplicates']))
which makes your query use INNER JOIN, so checking the reduce duplicates option takes you to line 960, using LEFT JOIN.
EDIT: You still need to export your views to code.
Comment #37
klausiPatch from #7 works for me as interim solution in my drush make file.
As @dawehner said in #31 we cannot commit this as is => needs work.
I have no idea how to resolve this appropriately as I don't have the big picture of implications, so ideas welcome.
Comment #38
John Pitcairn CreditAttribution: John Pitcairn commentedVersion should be dev. Patch at #7 still works for 7.x-3.7 I think.
Comment #39
skesslerI applied the patch in #7 against 7.x-3.7 and it is not working for me.
I had thought this was an issue with Field Collections but it may be this issue. I had opened this up as #1993298: Views does not work with OR .
Comment #40
John Pitcairn CreditAttribution: John Pitcairn commentedIf the patch applies it should work, unless your problem is elsewhere.
Comment #41
trapper-1 CreditAttribution: trapper-1 commented#36 works for me
racked my brain on this for many hours thinking "usually my brain/logic is wrong, not the program"....after switching around my logical operators several different ways I broke down to digging into the SQL. Quickly found this issue of 'inner join' and this helpful article.
Comment #42
lgomezma CreditAttribution: lgomezma commentedPatch #7 worked for me too. I think this should be included in the next release.
Comment #43
John Pitcairn CreditAttribution: John Pitcairn commented@Igomezma: this patch will never be included in any release. See #31 and #32.
Comment #44
p0832414 CreditAttribution: p0832414 commentedPatch #7 saved my day. Thank you !
Comment #45
skyredwang#36 works for me
Comment #46
ikeigenwijs CreditAttribution: ikeigenwijs commentedI do not like to hack the module,
if the patch works it should be added to dev.
My solution witch worked for my situation is to negate the query.
instead of
Contentype=A or B
And
Tax_contentA= value1
or
Tax_contentB=value2
I made
Contentype=A or B
And
Tax_contentA not one of (all the other values except value1)
And
Tax_contentB not one of (all the other values except value2)
Which came out as a query with Left join and works
Comment #47
kdmarks CreditAttribution: kdmarks commented#36 worked for me. Thank you so much for the fix.
Comment #48
Kimberley_p CreditAttribution: Kimberley_p commented#36 sorted it our for me
Comment #49
jmoruziThought I was going crazy because I couldn't figure out why my filter wasn't working, but #36 worked for me as well. Thanks sorin.eugen.
Comment #50
DanChadwick CreditAttribution: DanChadwick commentedFixing the many-to-one helper (used by the many-to-one filter) will be nontrivial. It seems riddled with INNER joins, none of which will work when the filter group operator is OR or when the inter-filter group operator is OR. There are also "summary joins", which use INNER and I'm unsure about.
I wish I could offer a patch, but after looking at it for a couple of hours, it's clear that someone that really understands the architecture of how joins are determined needs to do this. In the interim, I'm using the reduce duplicates workaround.
Comment #51
tim.plunkett#935984: or filter uses inner join for optional fields thus excluding expected results was marked a duplicate of this, but that was about terms (the bug I'm seeing) not fields per-se (the bug described here).
Comment #52
John Pitcairn CreditAttribution: John Pitcairn commentedPatch at #7 still works with 7.x-3.8 for me, reverting the changes committed in #1494884: Why is there no "is all of" operator for select list filters?. I have no "reduce duplicates" checkbox available for any of the filters.
Comment #53
geerlingguy CreditAttribution: geerlingguy commentedJust wanted to note that this bit me too, noticed the INNER JOIN was excluding half the results, and just checking the "Reduce Duplicates" box on the boolean field that changed the query from LEFT to INNER switched it back to a LEFT JOIN, and all was well. See also (on Drupal Answers): Changing an inner join to a left join in views 3.3?
Comment #54
idebr CreditAttribution: idebr commentedI found another workaround when I was working around this bug.
Inner join:
Node status = 1
Node promoted = 1
AND
Field value = 1 OR
Field is empty
Left Join:
Node status = 1
Node promoted = 1
AND
Field is empty OR
Field value = 1
Comment #55
BrightBoldThanks sorin.eugen for the workaround in #36. I used "reduce duplicates" on the field that was causing the problem and that fixed it. That's much easier than continuing to have to remember to re-patch Views every time I upgrade!
Comment #56
JonMcL CreditAttribution: JonMcL commentedI just applied to 7.x-3.8 and it fixed the issue for me. This seems like a truly critical (regression) bug. I know the maintainers are probably focused on D8. Has anyone tested if this is not an issue in D8 or does it need to be fixed there first?
Comment #57
liquidcms CreditAttribution: liquidcms commentedThe patch in #7 has always worked for me; but i just made a simple filter arrangement today as: http://screencast.com/t/2awrl0pfbo
and i was getting inner join (broken)
until i did the solution in #36 and set Reduce Duplicates on one of the filters.
Comment #58
Simon Georges CreditAttribution: Simon Georges at Makina Corpus commented#36 worked for me as well, thanks for the tip.
Comment #59
dbazuin CreditAttribution: dbazuin at LimoenGroen commentedThe workaround from #46 did work for me.
I must add it did needed some experimenting with the order of the filter items and groups to get it working.
Comment #60
JayDarnellI would be interested in a long term solution for this issue as well. Based on everything I've read here I'm hesitant to build a complex view where this issue would ultimately arise and apply patches that may not work long term.
Comment #61
tobiberlinAfter applying the patch I had to refactor some of my views - usually those which used a field as a filter. When I opened the views administration page of such a view an error occurred:
Additionally in preview it was stating that there is not a valid operator. When opening the settings of this filter no operator was chosen. I needed to re-activate the "Is one of" or another operator and the errors disappeared.
Best,
Tobias
Comment #62
roynilanjan CreditAttribution: roynilanjan commentedpatch #7 is not a proper solution according to view architecture, it basically tries to by-pass the views_handler_filter_many_to_one instead tries to use the views_handler_filter_in_operator, which is basically parent class of views_handler_filter_many_to_one. problem is mentioned in #5, this is the actual reason to get the INNER join in the query
Comment #63
John Pitcairn CreditAttribution: John Pitcairn commented@roynilanjan patch #7 is not a solution because it simply reverts the git commit that caused this issue. The
views_handler_filter_field_list
handler was previously a child of theviews_handler_filter_in_operator
class. The patch corrects the grouping behaviour (by reverting) but makes no attempt to update any existing views using list fields as a filter.The patch was intended as a short-term fix to restore correct OR group behaviour, but now we are 3 years on with no real fix in sight...
Comment #64
matthew.lavoie CreditAttribution: matthew.lavoie commentedAfter spending far too many hours trying to figure out what was wrong, and finally searching through the issue queue, I found this. I was able to use the workaround in #36 to get the View I am trying to build to work as expected.
Seems kind of absurd we're going on three years to resolve what seems to be a simple regression...
Comment #65
realgiucas CreditAttribution: realgiucas commented#36 seems to work for me too
Comment #66
Nicolas Bouteille CreditAttribution: Nicolas Bouteille commentedworkaround in #36 works for me but I have to check the Reduce duplicates checkbox on all filters that propose it (some don't), and I have do do it for filters in all of my 3 groups.
Comment #67
John Pitcairn CreditAttribution: John Pitcairn commentedPatch at #7 still applies to Views 7.x-3.14
Comment #68
mattew CreditAttribution: mattew commentedHi,
I encountered the same issue when trying to filter on list fields which are not mandatory (could be empty) so the IN clause could not works and the INNER JOIN reduce the results to entities which HAVE data existing in the fields...
My case was :
some other exposed filters...
AND
field1 is one of a OR b (Exposed, Allow multiple selections)
AND
field2 is one of x OR y (Exposed, Allow multiple selections)
Result: nothing, usage of INNER JOIN, etc.
My solution came from #46 (thanks!), and I came to something like:
some exposed filters...
AND
field1 is one of a OR b (Exposed, Allow multiple selections)
OR
field1 is not one of a AND b (both options selected in the filter params)
AND
field2 is one of x OR y (Exposed, Allow multiple selections)
OR
field2 is not one of x AND y (both options selected in the filter params)
It's quite complicated, but it works...
Note: I also tried "field1 is empty" for the second test in the OR clause, but without success, all entities were shown regardless of exposed filters values.
Comment #69
jenlamptonI'm running Views 7.x-3.14 and I don't understand how to apply the recommended work-around in #36. There is no "reduce duplicates" checkbox on the filter settings. Does this only apply to views that are using aggregation?
My view is a simple one as described in #23, with an OR being counteracted by the INNER JOIN in the query.
I'm hesitant to use the patch in #7 because it's been years since that feature went in. Reverting it now may break I-don't-know-how-many other views on the site.
Can someone explain again why the solution in #5 is not the right approach? I understand that was not the file that was changed the day that everything broke, but that doesn't mean it is not the place for a solution today.
The following code comment is present:
It sounds like we are using inner joins here even when we know we can't. Is there a way we can expand the logic to properly determine if the JOIN should be INNER or LEFT? Perhaps adding a check to see if any of the filters are using OR instead of AND?
Attaching a patch based on #5, but leaving as NW since I expect this will cause a minor performance regression. Still better than broken views IMHO.
Comment #70
rliAgree with @jenlampton. The comment in the code apparently indicated that we can NOT use INNER join.
Applying the patch in #69 fixed the issue temporarily.
Comment #71
John Pitcairn CreditAttribution: John Pitcairn commented@jenlampton: No, I wouldn't use #7 unless you have been using it consistently since then and know you have no views that use the "new" handler.
Comment #72
susannecoates CreditAttribution: susannecoates as a volunteer commented@jenlampton Your patch views-critical_inner_vs_left_join-1766338-69 worked for me, Thanks!
Comment #73
pifagorSelected checkbox "Reduce duplicates", the image given me to realize the request because LEFT JOIN and not INNER JOIN because.
Comment #74
jenlamptonPatch still applies cleanly to 7.x-3.15.
Comment #75
brulain CreditAttribution: brulain commented5 years later, the patch still works : what's the police doing ?
Comment #76
jenlamptonPatch in #69 still applies cleanly to 7.x-3.16.
Comment #77
luenemannAgreeing with @jenlampton. The use of "INNER JOIN" here is a false optimization.
My issue is the following (stripped down example):
OR
-Is one of
-1
Possible Solutions:
Is none of
-0
- negate the conditionReduce duplicates - checked
I guess the query optimization is based on the assumption that the relationship of fields and nodes is consistent. Meaning there is a value row in the field table for every node of a given type. But Drupal allows this inconsistency.
I've tried to finde the introduction of this optimization and found #248749: Consider Use of Inner Joins for Taxonomy Filters . It was introduced in views-6.x-2.0-alpha5 (http://cgit.drupalcode.org/views/commit/?id=1f4cbd4).
It was intended for taxonomy filters but now applies to "boolean" filters as well (by #1494884: Why is there no "is all of" operator for select list filters?).
I've checked it - the false assumption of consistency applies to taxonomy filters as well...
Is this optimization still in views for Drupal 8? The use case above with a boolean field is no issue in D8 (so with less options to select from...).
So how to get patch #1766338-69: Incorrect filter group OR behavior, LEFT JOIN changed to INNER JOIN applied to views?
IHMO the issue title is misleading - its an old bug, not a regression...
Can someone help to rephrase it?
Comment #78
luenemannI've checked my Issue from #77 on D8 with a
List (text)
ansTaxonomy Term
field. And it still doesn't work there.#2559961: ManyToOneHelper ignores group configuration for some cases Mentions this one
Comment #79
jibranMoving it to Drupal core as per #2559961-22: ManyToOneHelper ignores group configuration for some cases.
Comment #81
jenlamptonPatch in #69 still applies cleanly to 7.x-3.17.
Comment #82
jenlamptonPatch in #69 still applies cleanly to 7.x-3.18.
Comment #83
ckaotik@jenlampton Regarding this, isn't this only a problem when using OR conjunctions? Can't we simply check for this, e.g.
Comment #84
ckaotikI've attached a patch against 8.4 for my suggestion above. Reviews and better ideas are welcome :)
Also added the "Needs tests" tag.
Comment #85
adam-delaney CreditAttribution: adam-delaney at The University of Iowa commentedPatch #7 worked for 7.x-3.x. Thanks for the fix.
Comment #86
andyanderso CreditAttribution: andyanderso as a volunteer commented@jenlampton Thanks for the patch in #69. I think your solution is right-on, and I don't think that there is a large enough performance hit for this not to be included in the next release. THANK YOU!
Comment #88
alison#84 applied cleanly for me on 8.4.5, but did not fix the problem -- below is the query generated by my view, before and after the patch at #84 -- it looks like, one of the JOINs changed, but the the "AND" did not change to an "OR":
pre-patch...
post-patch...
(...)
For comparison, here's the same query using the patch at #29 over on #2559961: ManyToOneHelper ignores group configuration for some cases -- see the nested "OR" in the last part of the WHERE clause:
(...)
Bottom line for *me* is that I'm all set for now, using #29 from the aforementioned issue, but I figured I'd still share my test results over here!
Comment #89
ckaotik@alisonjo2786 Thanks for the feedback and the example queries!
I think that issue (#2559961: ManyToOneHelper ignores group configuration for some cases) and this one are actually different problems, and depending on the use case, you would need fixes for both, i.e. have both the
INNER JOIN
change to aLEFT JOIN
(this issue) and apply theOR
/AND
operator as defined in the filter group.Have you tried using both patches at once?
Disecting your query generated with issue 2559961, the simplified
WHERE
structure is this:This uses an
INNER JOIN {taxonomy_index} taxonomy_index
.The
WHERE
query part from #84 would be this (reordered and re-indented):This one uses a
LEFT JOIN {taxonomy_index} taxonomy_index
.In your case this should not make a difference, but if you weren't joining with the same table for both
OR
connected conditions, the result would most likely still be wrong if only one table has a JOIN partner. Then the whole query would fail, instead of just one of the ORs.Basically, this issue's patch only handles the LEFT vs. INNER JOIN logic, whereas the other one only handles the AND vs. OR condition logic.
Using one fix without the other still produces unexpected results.
I've also added #2580265: entity query nested conditions must use LEFT joins when any of the parent condition groups is using OR as a related issue, this is getting quite messy.
Comment #90
stellarvisions CreditAttribution: stellarvisions commentedDo we still need to apply patch #69 to views 7.x-3.20? looks like yes but checking.
[ I patched by had because the line numbers have changed, but a simple patch]
Comment #91
andyanderso CreditAttribution: andyanderso commentedIt does look like this problem still exists, but the patch in #69 no longer applies. We will have to do some digging to see how to make it apply.
Comment #92
andyanderso CreditAttribution: andyanderso as a volunteer commentedI re-did the patch using the same change as jenlampton in #69 - THANK YOU for creating the original. It would be great to get this into the next views release.
Comment #94
John Pitcairn CreditAttribution: John Pitcairn commentedNot sure why testbot is complaining includes/handlers.inc is missing for 7.x. Let's try this one.
Comment #96
John Pitcairn CreditAttribution: John Pitcairn commentedWeird. Patch works against current 7.x-dev and 7.x-3.20.
Comment #97
luenemannThis issue moved to Drupal Core (see #79 #1766338-79: Incorrect filter group OR behavior, LEFT JOIN changed to INNER JOIN)
Drupal 7 does not contain Views.
I think testbot tries to apply the patch to drupal-core. That fails because there is no Views module.
I think the current strategy is to fix d8-views first and to backport the solution to d7-views.
Comment #98
ckaotikI agree, let's get this fixed in D8 so we can backport to D7!
Marking as Needs Review for the only D8 patch we have, in #84 (the problems mentioned in #88 are most likely due to interactions with #2559961: ManyToOneHelper ignores group configuration for some cases).
Comment #100
specky_rum CreditAttribution: specky_rum commentedfwiw I have a view with grouped filters in the following structure:
I applied the patch in #84 but I also needed the one from here: https://www.drupal.org/project/drupal/issues/2559961#comment-12715853. Together these 2 patches resolved the issue and the view is returning the correct results.
This on D8.6.7
Comment #101
jenlamptonThe patch in #94 still applies cleanly to views 7.x-3.22. Thank you to @John Pitcairn and @andyanderso for re-applying the patch! Sad it wasn't included in the last release, fingers crossed it'll go into the next one!
Comment #102
andyanderso CreditAttribution: andyanderso as a volunteer commented+1 to including it in the next 7.x release.
Comment #103
jenlamptonThe patch in #94 still applies cleanly to views 7.x-3.23. RTBC for D7.
@DamienMcKenna would it be useful to create a separate non-core issue for D7 (for tests) or do you prefer to stick to a single issue?
Comment #104
tmin CreditAttribution: tmin commented+1 to include this in the next release (since apparently it didn't make it to 3.23).
It's a straightforward regression and everyone is more hesitant to apply crucial security updates if there is a possibility for listings in their website to break.
Comment #105
sagesolutions CreditAttribution: sagesolutions commentedI had an issue that with taxonomy terms, the join is still using inner. See https://www.drupal.org/project/drupal/issues/2559961#comment-13291136
I updated the patch to exclude inner joins on taxonomy terms. Please review!
Comment #106
sagesolutions CreditAttribution: sagesolutions commentedMoved parenthesis to correct location in patch. Please review this one!
Comment #107
LendudeHaving a hardcoded reference to the 'taxonomy_index_tid' plugin in the ManyToOneHelper sounds less than ideal. Is there no other way to detect that this is needed?
Comment #108
sagesolutions CreditAttribution: sagesolutions commented@Lendude,
The only time I see is using the INNER join is when one (or more) of the fields are taxonomy terms. If its not a taxonomy term, then it will use the LEFT join.
Ideally it should check if is an OR grouping in the group, or any parent group, but I don't see a way to do that.
Comment #109
mlncn CreditAttribution: mlncn as a volunteer and at Agaric for Drutopia, Find It Cambridge, Cambridge, Massachusetts Family Policy Council commentedAgreed that ideally we don't have hardcoded corrections, but until another way is contrived, let's not let the perfect be the enemy of the good and get this needed fix in.
Comment #110
Heisen-blueLike @specky_rum, I had to also apply the patch from ManyToOneHelper ignores group configuration for some cases. It works perfectly now :)
Drupal 8.7.5
Comment #111
pifagorWe need to update the core version to the current one
Comment #112
pifagorComment #113
Krzysztof DomańskiThe reason that the problem is related to taxonomy filter may be that this filter allows you to select "Reduce duplicates". Other filters do not have this setting.
https://git.drupalcode.org/project/drupal/blob/8.8.x/core/modules/views/src/ManyToOneHelper.php#L160.
See also https://www.drupal.org/project/drupal/issues/2559961#comment-13347356
Comment #115
jenlamptonThe patch in #94 still applies cleanly to views 7.x-3.24.
Comment #116
phjouI had a similar bug on my SQL request from the view with Drupal 8.8.
My filters were like this:
(Condition 1 AND Condition 2) OR (Condition 3 AND condition 4)
And views just translate it like this:
(condition 4 AND Condition 1 AND Condition 2) OR (Condition 3)
I just checked the ""Reduce duplicates" option on my condition 4 and the SQL query was good again... Weird behaviour.
Comment #117
tmin CreditAttribution: tmin at Lawspot for Lawspot commentedVerifying that the patch in #94 cleanly applies in 7.x-3.24.
Since it's been way too long and the current issue is becoming a beast where the solved D7 part gets left behind for no good reason, I suppose that we move to the "duplicate" issue for D7 which can be found here.
It's been 8 years since this issue has been created and even though I'm all for backporting the eventual solution that may be found for D8, I'd prefer if we don't keep an obvious bug in the D7 branch and force users to re-apply patches on every Views update.
I'm updating this issue in the Views issue queue with the patch found in #94.
Please continue the discussion there for the 7.x branch of the issue and if there is a solution in the 8.x branch we'll see what we're going to do about backporting it.
Comment #118
jenlamptonI've added an additional check for grouping to the patch from #94 and posted an updated patch in the other issue. Noting here for those that were following this issue for a Drupal 7 fix.
Comment #121
pameeela CreditAttribution: pameeela commentedI'm closing #2935113: No results when using the same vocab twice as exposed filter as a duplicate and I believe that it has a more concise set of steps to reproduce this, but I haven't been following this issue so I don't want to make major changes to the issue summary.
The steps are:
I note that it works as expected if the exposed filters are set to 'Is all of'.
Comment #124
wranvaud CreditAttribution: wranvaud commentedPatch #106 work for me together with https://www.drupal.org/project/drupal/issues/2559961#comment-13860069
Comment #128
liquidcms CreditAttribution: liquidcms commentedI have a simple view with a filter to filter out based on 2 options in a list field (field_campaign_type). But as this was added after content was created; many nodes simply have the value as NULL.
With filter as: published AND (field = 'option A' OR field is empty)
This doesn't work at all as the OR isn't used in the query. Adding the "reduce duplicates" option to the 2 ORed filters seemed to fix in that it added the OR into the WHERE clause. But then, when setting some of my nodes to 'option B', those still show up as well. I see the query has an AND added to one of the LEFT JOINs:
LEFT JOIN node__field_campaign_type node__field_campaign_type_value_0 ON node_field_data.nid = node__field_campaign_type_value_0.entity_id AND node__field_campaign_type_value_0.field_campaign_type_value = '0'
removing the "AND node__field_campaign_type_value_0.field_campaign_type_value = '0'" and the view works as expected.
Comment #132
vasikenew MR available
the condition to use
INNER
for join: Only if there is no group with OR operator.LEFT JOIN
it's by default.However this will not work without the solution for https://www.drupal.org/project/drupal/issues/2559961
which means that it can be really tested.
And a scenario to reproduce.
1. Create 2 taxonomies
and add some terms
2. Create 2 taxonomy term reference fields
And create different content
3. Create a view with 2 filters for those 2 fields
4. Play with
AND
andOR
operators for those filtersAgain the patch from https://www.drupal.org/project/drupal/issues/2559961 it's needed in terms to get the right results.
p.s. i have no idea why those 2 issues were separated.
Comment #133
vasikeTests available on related ticket MR
please check
https://www.drupal.org/project/drupal/issues/2559961#comment-15085241
Comment #134
smustgrave CreditAttribution: smustgrave at Mobomo commentedIf this ticket isn't going to add tests and be dependent on another. Then it should be postponed.
But even then I think the tests should be different, as the tests on #2559961: ManyToOneHelper ignores group configuration for some cases should be testing that issue. If the tests are testing the same thing then these tickets would be dups of each other.
Comment #136
vasikeAs the solution and tests are in the MR of the related issue ... i would say this is kind of duplicate.
closed also the MR ... test can't be added without the solution from related issue.
Comment #137
SoulReceiver CreditAttribution: SoulReceiver at Full Fat Things commentedThis is still an issue, but applying the code in the merge request worked very nicely. Can this be rereviewed?
Comment #138
smustgrave CreditAttribution: smustgrave at Mobomo commentedAs is the MR can't be merged as it's closed and No test coverage
If this ticket were to continue issue summary would have to be updated to standard template.
But would see if related issue that this was closed for solves the issue, depending on core version you are on.
Comment #139
SoulReceiver CreditAttribution: SoulReceiver at Full Fat Things commentedCurrently running Drupal 10.2.4, and when creating a View and adding an OR condition of two taxonomy fields, the resulting JOIN's on these tables remains as an INNER rather than a LEFT:
Comment #141
vasikeIt seems the changes for this issue were not included in the related issue commits.
So i re-opened the MR and added the tests code from there.
i think we are back to review.
Comment #142
longwaveThanks for reviving this and adding some tests.
However, the tests pass with or without the change, see https://git.drupalcode.org/issue/drupal-1766338/-/jobs/1278007 - so are they testing the correct thing?
Comment #143
vasike@longwave thank you for the "guidance"
Also @SoulReceiver comments helped.
i remembered some things about this issue.
indeed the previous tests added tried for the related issue which actually solved this specific case when we have multiple "Has taxonomy term" filters.
And this multiple uses will bring "LEFT JOIN" from the second filter .. which means the tests will pass anyway.
The trick ... having the second taxonomy filter as "field filter". It still uses the "
taxonomy_index_tid
" filter plugin so, I think we're still in the right place and (+) it adds and extra test for taxonomy fields.Also removed some tests that weren't that relevant here.
https://git.drupalcode.org/issue/drupal-1766338/-/jobs/1304700
I'm more than aware it's not the perfect/complete solution for the fix ... but at least it could save the day.
To save the (Views Filter Grouping) Universe ... I think another issue is needed ... starting maybe with some kernel tests about those FIlters GROUPING JOINS.
p.s. Views and tests needs a lot of efforts ... still
Comment #144
smustgrave CreditAttribution: smustgrave at Mobomo commentedCan the issue summary be updated using standard template.
Original issue appears to have been written for D7.
Comment #145
vasikeSummary updated.
Comment #146
smustgrave CreditAttribution: smustgrave at Mobomo commentedIssue summary appears much better
Ran test-only feature
So shows coverage.
Manually testing following the steps I believe I am seeing the issue.
I probably would of just used one filter selecting the multiple options but maybe can understand scenarios were you would do it this way.
Change to ManyToOneHelper makes sense.
12 years wow, good job on this one!
Comment #147
alexpottI've tried to credit people who helped move this issue on and have been thanked on the issue for their contributions. Obviously with so many comments this can be hard to get right - hopefully I have. Please let me know if I've not.
Comment #148
alexpottCommitted and pushed 0dac7cab32 to 11.x and 1c95773ffe to 10.3.x and c1c3ae32ca to 10.2.x. Thanks!