Context
You looked at the queries, which are identical but the values are not. If you look at those, you can see that it's doing a "'Anonymous' LIKE 'en'"...
The reason is one of the dark places of the database layer, ensuring unique placeholders, which is done by recursively precompiling queries and passing around a shared object/state that returns a unique ID every time it's called for each query.
This works all fine until we get to the very special and dark case of UserSelection::entityQueryAlter() which manually compiles a query condition and passes the global default connection and the current query in for the placeholder ID stuff. Combine this with the count query, which is really a nested selected and we're now inside the inner query, which is *not* the one that was used for the compilation, the outer query would be, so we re-start the placer ID counter and get a _0 placeholder. That is the same as the language condition is using, so we re-use that placeholder and use the first value instead of the one that we're adding.
A possible workaround might be to preg_replace() the placeholder with one that is unique, but that's ugly (not that the whole piece of code there isn't already ugly). I suggest you get Crell and DamZ in here, because AFAIK they came up with all this preExecute() fun (I was involved too, but not as much as they).
Problem/Motivation
As per @Crell (in #2144377-135: Entity reference autocomplete lists entity labels only in current content language), pre-compiling a query is not supported and need to be fixed in UserSelection::entityQueryAlter
Proposed resolution
Prosed solution hints from @Crell on IRC:
01:22 Crell: That plugin needs to get the DB connection injected properly.
01:22 Crell: And then not use db_and()/db_or().
01:22 Crell: And then not precompile the string and hope it works.
01:23 Crell: Actually… Hm, can you get the connection from the $query?
01:23 Crell: I could see an argument that you may need to.
01:24 Crell: And this is that argument. Because there is, or at least there was an issue to add, methods to the connection for and/or so that the functions were not necessary.
Remaining tasks
User interface changes
API changes
Comment | File | Size | Author |
---|---|---|---|
#49 | reroll_diff_2259323_40-49.txt | 4.87 KB | ankithashetty |
#49 | 2259323-49.patch | 5.72 KB | ankithashetty |
| |||
#40 | interdiff-40.txt | 785 bytes | amateescu |
#40 | 2259323-40.patch | 5.43 KB | amateescu |
Comments
Comment #1
vijaycs85Comment #2
vijaycs85Comment #3
sunComment #4
BerdirThe connection handling is not the problem here. It is a problem on it's own, but not the reason for this problem.
The *$query* object is the one responsible for ensuring unique placeholders, but the $query that we have here already is a subquery and there is no way to get to the actual parent query within the alter hook as the alter hook is invoked for every subquery separately.
I really have no idea how to fix this other making the hack even crazier and replacing the dynamic placeholder with preg_replace() with one that we can be fairly sure to be unique.. or build a LIKE condition query on our own, but that's not easy as we need to consider database backend specific handling like PostgreSQL's ILIKE.
Comment #5
Crell CreditAttribution: Crell commentedBerdir: Why is that necessary?
From a quick glance at the code, I don't quite get why it's even an issue. Don't use condition(). Use where(), which lets you put in whatever arbitrary SQL fragment you want and let the placeholders get compiled later as normal. Why wouldn't that work?
Comment #6
BerdirBecause we're talking about a LIKE condition (dynamic operator actually), which needs that ESCAPE stuff, needs to use ILIKE on PostgreSQL and so on.. we'd end up rebuilding quite a bit of the code in Condition::compile() and don't have access to the information we need from there (like Condition::mapConditionOperator()).
The only doable workaround that I can think of currently would be to match and replace the dynamic placeholder string with something that we know to be unique.
I'm wondering why we made the unique placeholder stuff part of the query object and not the connection? We could for example reset it after every executed query if we're worried about generating high numbers... Would make this much easier...
Comment #7
Gábor HojtsyCan we somehow move forward with this one? #2144377: Entity reference autocomplete lists entity labels only in current content language has been postponed forever on this :(
Comment #8
Crell CreditAttribution: Crell commentedI *think* we made it part of the query so that each query would reset the counter, not due to an aversion to big numbers but to make the variation in the query string less. The query string has to be byte-identical in order for it to be reused by the database or driver and not recompiled.
That said, in practice I think we found that the query cache was basically useless, at least on MySQL. I don't know that it actually matters anymore. I do not know how invasive it would be to move the placeholder logic to the connection, but I'm open to trying it. It would be an API change, but one that affects only DB driver authors of whom there are about 4. :-) I feel that's safe to make up until RC, but can be overruled.
Comment #9
Gábor HojtsySo I guess the extent of API change required here would only make this possible if done before the beta? Or we need to live with some broken core features for a while.
Comment #10
Crell CreditAttribution: Crell commentedIMO, this is contained enough that it can happen up to RC. I defer to Dratchipott, however.
Comment #11
amateescu CreditAttribution: amateescu commentedOr we could store the anonymous name in the database and remove the need for that dark magic sub-query? User entities are a translatable entity type after all and we can make the form at
config/people/accounts
update the name field for user 0.But that's only based on the assumption that we don't store the anonymous user name in the db for historical reasons, before having translatable entities... I hope @Gábor can answer this better :)
Comment #12
Gábor HojtsyWell, usernames are not supposed to be translatable even though user entities are. It would be a nightmare that if you are on /de/user, you would need to log in using your German username while on /fr/user you would need to log in with your French name. The only thing translatable among user base fields currently is the signature.
Comment #13
amateescu CreditAttribution: amateescu commentedRight, then how about doing the matching for the anonymous user in php instead of the db query. Too hacky? :)
Comment #14
amateescu CreditAttribution: amateescu commentedAnswering to myself.. yes, too hacky because some other code might rely on the query instead of the output of
SelectionInterface::getReferenceableEntities()
. I'm out of simple solutions so we're back to waiting on the "Needs committer feedback" tag...Comment #15
xjmLet's get an updated summary for committers to give feedback on. :) Could use a beta evaluation: Why is it major? What is the impact of fixing this bug? Are there multiple solutions possible? What is the disruption introduced by making the change between betas (impact on contrib code, scope of change needed in core, sites running on betas, etc.)?
Comment #16
xjmRe-tag I guess when ready.
Comment #17
amateescu CreditAttribution: amateescu for Pfizer, Inc. commentedThe code to keep this optimization while moving the counter to the Connection object is quite trivial :)
Comment #19
amateescu CreditAttribution: amateescu for Pfizer, Inc. commentedNow with less silliness.
Comment #20
amateescu CreditAttribution: amateescu for Pfizer, Inc. commented#notmyday
Comment #23
dawehnerWhy do we not use the same method name as on the query object itself?
Comment #24
amateescu CreditAttribution: amateescu for Pfizer, Inc. commentedNo real reason, it just sounded better.
Comment #26
amateescu CreditAttribution: amateescu for Pfizer, Inc. commentedLet's try this.
Comment #29
amateescu CreditAttribution: amateescu for Pfizer, Inc. commentedYay unit tests!
Comment #31
amateescu CreditAttribution: amateescu for Pfizer, Inc. commentedRerolled.
Comment #38
andypostReroll & fix comment in connection
Comment #40
amateescu CreditAttribution: amateescu for Pfizer, Inc. commentedFixed those fails.
Comment #41
andypost@amateescu I'd like to rtbc it but still needs summary update, extra tests not needed I guess
Comment #48
larowlanComment #49
ankithashettyRerolled patch in #40, thanks!
Comment #52
smustgrave CreditAttribution: smustgrave at Mobomo commentedThis issue is being reviewed by the kind folks in Slack, #needs-review-queue-initiative. We are working to keep the size of Needs Review queue [2700+ issues] to around 400 (1 month or less), following Review a patch or merge request as a guide.
This was tagged for issue summary update and tests from what I can still need to happen
Did not test yet.