Problem/Motivation
If you have a dbtng condition which was already used on another query the placeholder counter is getting mixed up. This is very easy to reproduce when you try to reuse a subquery object with two select objects where the latter have a different number of conditions.
Proposed resolution
The idea is to force a rebuild of the condition string, when the outer query object has changed.
Remaining tasks
In general the patch isn't working yet and some reviews of people would help as well
User interface changes
No changes
API changes
No changes, just fixes the bug
Original report by [dereine]
Let's asume you have a subquery with a db_or().
The first condition in the subquery takes the value of the next condition of the main query.
The easiest way to reproduce it is to use views.
Download the latest version, add a relationship "terms from node" and add a filter with depth filter and select depth > 0
Additional add a filter for the node.type and if you enable query display under admin/structure/views/settings you will see this
SELECT node.created AS node_created, node.nid AS nid
...
WHERE ( (tn.tid = 'article') OR (th1.tid = '1') OR (th2.tid = '1') OR (th3.tid = '1') OR (th4.tid = '1') OR (th5.tid = '1') ))) AND (node.type IN ('article')) ))
Comment | File | Size | Author |
---|---|---|---|
#86 | 1112854_86.patch | 17.53 KB | chx |
#85 | 1112854_85.patch | 1.97 KB | chx |
#80 | 1112854_80.patch | 15.03 KB | chx |
#75 | 1112854-subquery-conditions.patch | 15.03 KB | Damien Tournoud |
#73 | test_view.txt | 5.26 KB | ryne.andal |
Comments
Comment #1
stefd CreditAttribution: stefd commentedSame issue here, also from Views (so this might be a Views issue... I'll post something on the Views issue list and refer to this issue).
In my case, a sample query shows that :db_condition_placeholder_1 and :db_condition_placeholder_2 are used twice in the query, which I believe is not supposed to happen:
The query ends up having "tn.tid = 'destination'" which doesn't make sense ('destination' is actually the node type).
I am slowing learning the art of Drupal debugging, but I think I traced the issue to the following comment in includes/database/select.inc, function __toString, around line 1500:
So, maybe __toString() *is* called somewhere before getArguments().
Hope this helps.
Comment #2
Damien Tournoud CreditAttribution: Damien Tournoud commentedIt's really an issue in Views.
Views reuses the same subquery twice, once for the count query and once for the query. This is unsupported.
The issue can be easily demonstrated by applying this:
... which is obviously not a real fix. I leave fixing Views as an exercice for the reader :)
Comment #3
stefd CreditAttribution: stefd commentedI confirm that the above change (#2) by Damien fixes my issue.
Unfortunately, I don't have the knowledge to offer a proper patch, so I'll leave that to the professionals ;)
Merci Damien.
Comment #4
dawehnerSo what about this?
Comment #5
stefd CreditAttribution: stefd commentedYes, I can confirm that the patch in #4 fixes my issue also.
Thanks dereine.
Comment #6
dawehnerAs discussed with crell, berdir, merlinofchaos this seems to be an issue of core.
__clone should take care about conditions,fields, and joins.
Comment #7
BerdirPatch looks good to me. We already do that with UNION's for example, it's just wrong that we don't do that for other SelectQuery instances.
Now, I guess the only thing that's missing here is a test :)
Comment #8
Damien Tournoud CreditAttribution: Damien Tournoud commentedThis solves the issue in Views, but only by chance. It does for only one reason: Views uses the same subquery object to build two queries, but it runs one of them through
SelectQuery::countQuery()
which clone the second query object.After the patch, you still cannot reuse the same subquery object to build two queries when you don't clone one of them. This is very very ugly :) We should rather make sure we force the query and all its conditions to rebuild itself when the source object is changed. One way of doing that would be to store the SPL Hash of the $queryPlaceholder and make sure we rebuild if ->compile() is called with a different object.
Comment #9
Damien Tournoud CreditAttribution: Damien Tournoud commentedComment #10
bryancasler CreditAttribution: bryancasler commentedsubscribe
Comment #11
Anonymous (not verified) CreditAttribution: Anonymous commentedSubscribe
Comment #12
yellowhousedesign CreditAttribution: yellowhousedesign commentedsubscribe
Comment #13
jpstrikesback CreditAttribution: jpstrikesback commentedsubscribe
Comment #14
Adam S CreditAttribution: Adam S commentedsubscribe
Comment #15
Liam Mitchell CreditAttribution: Liam Mitchell commentedBecause this has been tagged D8 I have opened a issue in Views for a workaround until this is fixed: #1201908: Taxonomy filter with depth generating incorrect results because of core subquery bug
In my case it affects the taxonomy (with depth filter) as above. I have attached dereine's first patch there.
Comment #16
ryne.andal CreditAttribution: ryne.andal commentedsubscribing
Comment #17
Anonymous (not verified) CreditAttribution: Anonymous commentedsub
Comment #18
jhodgdonI just saw a very similar issue crop up in a Views Taxonomy with depth argument (or whatever they're called now in D7), along with a node access module. The query that Views ended up running had the taxonomy term ID mixed up with the node access gid, due to (I believe) duplicate use of placeholder arguments.
Probably the next thing to do would be to write a test...
Comment #19
Audrius Vaitonis CreditAttribution: Audrius Vaitonis commentedsubscribe
Comment #20
bryancasler CreditAttribution: bryancasler commentedThis issue over here was marked as a duplicate #972934: Contextual filter "Content: User posted or commented" argument does not work
Comment #21
Thomas_M CreditAttribution: Thomas_M commentedanother duplicate here #1223320: Filter "Has Taxonomy Term (with Depth)" and contextual filters
PS: solved with the patch above
Comment #22
jhodgdonJust a note that after applying patch in #4 to Views and #6 to Core, Views is working OK. Today I was seeing the problem when I used a Taxonomy filter along with a Language filter - the taxonomy term ID was getting set to 'en' instead of the number it was supposed to be.
Comment #23
joelstein CreditAttribution: joelstein commentedThis issue may also be the cause of #1202416: Search is not working with node access turned on.
Comment #24
Anonymous (not verified) CreditAttribution: Anonymous commentedPatch in #6 does not solves the problem with Views.
Subscribe
Comment #25
jhodgdonSee #22. You need to patch Views as well as Drupal Core. At least, that worked for me.
Comment #26
Anonymous (not verified) CreditAttribution: Anonymous commentedOk. Now i've applied both patchs, and sadly, they dont fix the problem in my case. :( Must wait for the real patch....
Comment #27
bryancasler CreditAttribution: bryancasler commentedI just applied the patch in #4 to Views 7.x-3.x-dev from 2011-06-26 and the patch in #6 to Drupal 7.4
The views argument "Content: User posted or commented" is still broken. Just wanted to test it so I could give feedback.
Here is a screenshot of the arguments setup http://awesomescreenshot.com/0b7id7id0
Comment #28
Anonymous (not verified) CreditAttribution: Anonymous commentedI can't understand almost nothing of DBTNG code, but may be a tip for the causing of the bug, may be $queryPlaceholder is the problem? it seems the same instance is being used on querys and subquerys, causing both of them having :db_condition_placeholder_0 on them, and later being replaced with the same values (WRONG!)
Hope this can be fixed soon on D7! Cant be so hard for somebody with knowledge of the code.
Comment #29
chx CreditAttribution: chx commentedJavier, as one of the people who could fix this, I am back in Hungary to help my brother with a 2.5yrs old and a newborn. Meanwhile I need to work to earn a living. Think again about "not hard".
Comment #30
jhodgdonI am going to raise the status of this issue to Major.
I have worked on a total of two Drupal 7 site build projects so far. Both involved Views. Both ran into this issue when making slightly complex queries. For me, this is a "blocker" -- it makes me think Drupal 7 is not ready for real time use, because the nearly-core-everyone-needs module Views that we all rely on cannot be used effectively without hacking core and/or Views.
Comment #31
ryne.andal CreditAttribution: ryne.andal commentedCompletely agree with #30. Makes Drupal 6 look more attractive for many situations.
Comment #32
dawehner@ javier.alejandr..
You could always help indirect by helping somewhere else in the community.
For example choose one random module and help out the issues there, try to reproduce the bugs etc.
THIS will motivate people to work on it...
I think it's not a point that this is a bad bug, as this affects a lot of people.
Comment #33
dawehnerCan someone provide an easy to use reproduction?
I couldn't reproduce it with the linked issues. Maybe this issue is not that major.
Comment #35
dawehnerA better actual hopefull working version.
Comment #36
ryne.andal CreditAttribution: ryne.andal commentedI can break views by adding a relationship: content: taxonomy terms on node
Adding a contextual filter: Taxonomy term: name - allow multiple filter values to work together
Comment #37
dawehnerMake it as easy as possible and provide a reusable export. It's not hard.
Comment #38
ryne.andal CreditAttribution: ryne.andal commentedSorry, I didn't realize you wanted a views export. Don't be rude.
Add a couple of arguments to the preview, and voila!
Comment #39
dawehnerSorry, didn't meant to be but if you ask this too often it kinds of annoy yourself.
Comment #41
bryancasler CreditAttribution: bryancasler commented@dereine, the post #972934: Contextual filter "Content: User posted or commented" argument does not work was marked as a duplicate of this one. Here is a views export using that argument.
http://drupal.org/files/issues/48584310_1.txt
Comment #42
Anonymous (not verified) CreditAttribution: Anonymous commented#35 didnt work for me. Look at the :db_condition_placeholder_5
Comment #43
tj2653 CreditAttribution: tj2653 commenteddereine has seen this, but for the benefit of others, here is my working sample illustrating the bug, along with SQL queries and my views export:
http://drupal.org/node/1228280
Comment #44
chx CreditAttribution: chx commentedIn the name of readability I have deleted and attached those Views exports. Please be considerate and do not copypaste into a complicated bug report such long things.
Comment #45
bryancasler CreditAttribution: bryancasler commentedPlease be considerate and ask me to change my post next time, I'm obviously as active as I can be in this conversation. I do agree with your concern of readability, but ascetics is not a reason to change someone else's post. I've gone ahead and re-edited my post to include a pastebin link.
Comment #46
Anonymous (not verified) CreditAttribution: Anonymous commentedThere is some place where to learn about DBTNG code, so i can get the idea behind it and try to help fixing this? Thank you
Comment #47
chx CreditAttribution: chx commentedComment #48
ryne.andal CreditAttribution: ryne.andal commentedHow can I help with this issue? This is a major roadblock for us and would love for it to be resolved.
Comment #49
catchThere's a patch in #35, it fails 5 of Drupal's automated tests, but it still might fix this issue.
So you could read http://drupal.org/patch/apply, and try it out on your system to see if it fixes the bug for you or not.
If it does, then it's mainly a matter of trying to fix the 5 test failures and some additional review of the code in order to get it actually committed and into the next 7.x point release (or the one after, since they're monthly at the moment).
Comment #50
dawehnerAdding a tag which will be required.
Comment #51
Anonymous (not verified) CreditAttribution: Anonymous commentedsubscribe.
Comment #52
ryne.andal CreditAttribution: ryne.andal commentedNevermind, #33 and #35 are close together and I misclicked.
A test view in a clean dev environment still fails when using a term relationship and term name contextual filters just as I had included in my view export.
Another note - attached image is irrelevant and I don't know how to take it off...sorry!
Comment #53
chx CreditAttribution: chx commentedAfter considering the subtle but crippling effects for several days I deem this critical. I will fix it this week. Edit: provided the Views expotrs above indeed break stuff.
Comment #54
Damien Tournoud CreditAttribution: Damien Tournoud commentedUntested patch, implementing the basics of what I think we need.
Comment #56
chx CreditAttribution: chx commentedHow does this differ from
If the only place you change the unique identifier is the constructor and clone then i fail to see the difference.
spl_object_hash()
-- has terrible documentation. I updated http://drupal4hu.com/node/224 which explains it better. debug_zval_dump() will show the dataspl_object_hash
creates a hash fromphp -r 'class foo{};$x = new foo; $x = new foo; debug_zval_dump($x);'
results inobject(foo)#2 ...
and that(foo)#2
is whatspl_object_hash
encodes.Comment #57
dawehnerHere is a quick rerole of #54
Comment #59
Anonymous (not verified) CreditAttribution: Anonymous commented#57: uniq_id(TRUE) is not found. In php manual i see uniqid() function, not uniq_id
Testing, it stills generates querys as i posted on #42:
Comment #60
Damien Tournoud CreditAttribution: Damien Tournoud commentedRegarding
spl_object_hash()
: those hashs can and *are* reused. We just cannot rely on them here.Comment #61
dawehnerOkay this time with the right php function.
Comment #63
Anonymous (not verified) CreditAttribution: Anonymous commented@dereine: you attached the exact same patch in #61 (as #57)
Anyway, I' ve replaced uniq_id(TRUE) with uniqid() to test it (as I commented on #59) but it still doesnt fix the problem.
Comment #64
chx CreditAttribution: chx commentedDamien, you are right. Those hashes are reused. How dumb of PHP!
Comment #65
chx CreditAttribution: chx commentedRerolled, ran database tests. Ran the view from #59 seemed OK. Edit: please disregard this comment.
Comment #66
bryancasler CreditAttribution: bryancasler commentedPatch is 0 bytes
Comment #67
Anonymous (not verified) CreditAttribution: Anonymous commentedThere is no way to avoid 0 bytes attachments ? Please, attach the real patch so i can test it!!! :)
Comment #68
chx CreditAttribution: chx commentedSorry. There's no real patch. As said: please ignore. The only reason I got passes is because i failed to apply the patch i thought i did.
Comment #69
franzComment #70
franzFixed the patch, let's see how test plays.
Also, the proper arguments for http://www.php.net/manual/en/function.uniqid.php are $prefix and $more_entropy. We might use $prefix for something, but I left it as '' for now.
Comment #71
franzComment #73
ryne.andal CreditAttribution: ryne.andal commentedThe patch in #70 doesn't solve the issue with the attached view timing out when an argument is supplied for the contextual filter.
Comment #74
Anonymous (not verified) CreditAttribution: Anonymous commented#70 produces #59 exact same query (buggy) in my case.
Comment #75
Damien Tournoud CreditAttribution: Damien Tournoud commentedWe had a comment (by myself) in the code that this was going to bite us in the ass one day.
Note to self: the whole
SelectQueryExtender
needs to be reviewed, it is full of BS right now.Comment #76
Anonymous (not verified) CreditAttribution: Anonymous commented@Damien: I' m using D7.7. Can i apply that #75 patch on it? Or which version must i get ? Thanks
Comment #77
chx CreditAttribution: chx commentedjavier, what about trying 7.7? if the patch applies, good. Otherwise, may I recommend http://drupal.org/node/707484 ? Thanks for helping to test.
Comment #78
Anonymous (not verified) CreditAttribution: Anonymous commented@Damien: Kudos to you!!! It is working for me on a clean D 7.7 + patch on #75.
Comment #79
jhodgdonThe docs need some work in this patch [leaving status at Needs Review so that people will continue to test the functionality though] [but PLEASE don't commit this patch until the docs are cleaned up!]
a)
Should be "Checks whether a condition..."
b)
Should be "Returns a unique..." Note: this line appears twice in the patch, wrong both times.
c) Some functions with no doc:
There are quite a few others without doc. EVERY function/method needs a docblock starting with /**.
Comment #80
chx CreditAttribution: chx commentedThe functions without doc are doxygen'd in the interface. Based on testing passed and #76 reporting it works with Views, this is ready. Note that there is quite some cleanup required around this topic but this is a critical to be fixed ASAP
Edit: I only fixed grammar mistakes pointed out by jhodgdon. Thanks for reviewing our critical!
Comment #81
jhodgdonAccording to the (proposed? accepted?) "docs gate", we're not supposed to be committing patches without complete docs, or with docs that don't meet our standards.
http://drupal.org/node/1203498
So I would appreciate it if someone who has time could address #79 (if I had time to do it, I'd make a new patch, but alas, not today...). All functions and methods are supposed to be documented -- no exceptions.
We have standards for how to document ones that are implementations of interfaces. See
http://drupal.org/node/1354
for standards.
Comment #82
chx CreditAttribution: chx commentedI addressed #79 a) and b) because it's valid. However, most of SelectQuery, for example, is already not doxygen'd because it comes from SelectQueryInterface. If this is not enough please open an issue to fix DBTNG docs. That's a change of standards -- I am not against it -- but I am against it blocking this critical. See http://api.drupal.org/api/drupal/includes--database--select.inc/class/Se... for eg.
Comment #83
chx CreditAttribution: chx commentedOn further investigation i see a lot of Implements QueryConditionInterface::compile(). already so -- what can I say? Let's reroll this with those.
Comment #84
chx CreditAttribution: chx commentedWe are not going to add all the doxygen for select.inc in this issue. I fixed the rest of the files IMO. I am adding a test , however. Filed #1255524: select.inc needs more doxygen for select.inc.
Comment #85
chx CreditAttribution: chx commentedTest-only, will fail.
Comment #86
chx CreditAttribution: chx commentedThis one, OTOH, passes because it includes Damien's fixes. Edit: Doxygen fixes are also included but I did not and will not touch select.inc doxygen as said above. There's dozens upon dozens of methods needing to be doxygen'd already.
Comment #86.0
chx CreditAttribution: chx commentedAdd an issue summary
Comment #87
dawehnerLooking at the patch, it looks fine.
Additional it fixes on of the views queries from above.
Comment #88
jhodgdonDocs are much closer, thanks! I wouldn't hold up this patch for the doc fixes at this point either. Thanks!
Comment #89
jhodgdonDo we know whether this patch fixes #1202416: Search is not working with node access turned on too?
Comment #90
xjmI confirmed that #1202416: Search is not working with node access turned on is resolved by the patch here. Since this is critical, jhogdon suggested this should go in first and then we add a test for the other as a followup.
Comment #91
chx CreditAttribution: chx commentedI called this critical because it surely messes up lots.
Comment #92
chx CreditAttribution: chx commentedAlso note the patch applies to D7.x cleanly.
Comment #93
webchickIt's 3am in London, and so I'm not sure I totally understand what's going on here, but this has sign-off from the right people and fixes a critical problem with Views.
Committed and pushed to 8.x and 7.x.
Comment #94
chx CreditAttribution: chx commentedThat's dedication! Thanks so much!
Comment #95.0
(not verified) CreditAttribution: commentedDescribed the way I understand the issue
Comment #97
Aleksander Belov CreditAttribution: Aleksander Belov commentedGuys, sorry to resurrect such an old topic but this does not seem to be fixed, I still have problems with cloning an already executed query with subqueries. Drupal 7.
This is an illustration of my query structure with argument placeholder counters applied by '$this->getArguments();', as it processes arguments one by one in the program flow:
:0 (main query)
:1
:2
-- :3 (subquery)
-- :4
After it has been executed, in my program flow I clone whole query and add one more condition to the outer query. The outer query gets marked as changed, but inner query is not! During the next $query->execute() the "$this->getArguments();" counts the placeholders correctly before the subquery starts. Since the subquery is not changed, it gets skipped, and placeholder counter continues where it was, producing wrong placeholder numbers:
:0 (main query)
:1
:2
-- :3 (subquery)
-- :4
:3 (main query continues, producing same placeholder number as in skipped inner query. Should be :5)
I have manually applied the second part of #6, which seems to solve the problem:
Does it make any sense? Should we apply this part of patch here to D7 as well?
Comment #98
Aleksander Belov CreditAttribution: Aleksander Belov commented