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 #41417 Handle Relations with having referencing aliased selects in #include? #41419
Fix #41417 Handle Relations with having referencing aliased selects in #include? #41419
Conversation
04ae412
to
1f4e053
Compare
Tests are broken on postgresql. Can you take a look? |
@rafaelfranca yeah I just saw this too and had a look into it. Based on what I can tell, using an alias in a HAVING statement is actually technically outside the SQL spec. Mysql and sqlite seem to allow it no problems, but postgresql does not. I guess it just seems to actually follow the spec more closely (info). I'm not sure what the best course forward here is. I came across this problem because I use MySQL in one of my Rails apps that has one of these queries, and it worked fine until I updated to Rails 6.1.1. So I guess technically it's a 'regression' of sorts, but it does seem clear that this query probably never would've worked in postgresql in the first place. |
I think we only need to skip the new test you added in the postgresql adapter. |
So should I just add something like: skip if current_adapter?(:PostgreSQLAdapter) at the beginning of the test? Or is there a different way of doing it that is preferred? Seems to work (2 assertions less and 1 skip for postgresql):
|
- skips optimised exists? query for relations that have a having clause Relations that have aliased select values AND a having clause that references an aliased select value would generate an error when #include? was called, due to an optimisation that would generate call #exists? on the relation instead, which effectively alters the select values of the query (and thus removes the aliased select values), but leaves the having clause intact. Because the having clause is then referencing an aliased column that is no longer present in the simplified query, an ActiveRecord::InvalidStatement error was raised. An sample query affected by this problem: Author.select('COUNT(*) as total_posts', 'authors.*') .joins(:posts) .group(:id) .having('total_posts > 2') .include?(Author.first) This change adds an addition check to the condition that skips the simplified #exists? query, which simply checks for the presence of a having clause.
1f4e053
to
644d694
Compare
That is good enough. |
Rightio, just pushed again with the skip for postgres, hopefully the tests should pass now. |
…clude-with-having Fix #41417 Handle Relations with having referencing aliased selects in #include?
Thanks heaps for the quick review and feedback! 😊 |
Skips optimised
#exists?
query in#include?
for relations that have a having clause.Summary
Relations that have aliased select values AND a having clause that references an aliased select value would generate an error when
#include?
was called, due to an optimisation that would generate call#exists?
on the relation instead, which effectively alters the select values of the query (and thus removes the aliased select values), but leaves the having clause intact. Because the having clause is then referencing an aliased column that is no longer present in the simplified query, anActiveRecord::InvalidStatement
error was raised.An sample query affected by this problem:
This change adds an additional condition that skips the simplified
#exists?
query, which simply checks for the presence of a having clause.Other Information
Not all Relations that have a having clause actually trigger this problem. It's specifically the ones that have aliased select values AND where the having clause references an aliased select value.
The change does however skip the optimised
#exists?
query for all relations that have a having clause. I attempted to find a decent way to detect when aliased select values where included in the relation, and when the having clause was referencing these aliases, and while I could actually do it for the specific example of query above, it involved effectively parsing SQL, and based on what I've read in other discussion in different issues, this is strongly discouraged. So I figured in this case maybe the pragmatic path is just to skip the optimisation introduced in 166b63e for all relations that use a having condition. This way at least the problem for this very specific type of query is resolved, even if it means that a slightly broader group of queries are exempted from the optimisation as a result.Fixes #41417