Fix #41417 Handle Relations with having referencing aliased selects in #include? #41419
Relations that have aliased select values AND a having clause that references an aliased select value would generate an error when
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 additional condition that skips the simplified
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
The text was updated successfully, but these errors were encountered:
@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.
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.