You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Build a query that uses .count(:all) and .group(...) with a custom .select("... AS alias") and a .order(:alias)
It seems ActiveRecord when calling .count(:all) will remove from the SELECT the alias column and everything else but the primary key, however it keeps the ORDER BY alias. To execute COUNT(...), the ORDER BY is kind of irrelevant, it should probably be removed.
Note: It ain't specific to Postgres. Error is present with SQLite too.
# frozen_string_literal: truerequire"bundler/inline"# Toggle this to test with SQLiteuse_postgres=falsegemfile(true)dosource"https://rubygems.org"git_source(:github){ |repo| "https://github.com/#{repo}.git"}gem"rails","7.1.3.2"gem"database_cleaner"ifuse_postgresgem"pg"elsegem"sqlite3"endendrequire"active_record"require"minitest/autorun"require"logger"require"database_cleaner"ifuse_postgresActiveRecord::Base.establish_connection(adapter: "postgresql",host: "localhost",database: "dev",username: "dev",password: "dev",port: 5437)elseActiveRecord::Base.establish_connection(adapter: "sqlite3",database: ":memory:")endActiveRecord::Base.logger=Logger.new($stdout)ActiveRecord::Schema.definedocreate_table:conversations,force: truedo |t| # rubocop:disable Style/SymbolProct.timestampsendcreate_table:messages,force: truedo |t|
t.references:conversationt.timestampsendendclassConversation < ActiveRecord::Base# rubocop:disable Rails/ApplicationRecordhas_many:messages,dependent: :destroyendclassMessage < ActiveRecord::Base# rubocop:disable Rails/ApplicationRecordbelongs_to:conversationendDatabaseCleaner.strategy=:truncationclassBugTest < Minitest::TestclassSuccessException < StandardError;enddefsetupDatabaseCleaner.startConversation.create!.tapdo |conversation|
Message.create!(conversation: conversation)Message.create!(conversation: conversation)Message.create!(conversation: conversation)endenddefteardownDatabaseCleaner.cleanenddefassert_not_raise(&block)assert_raises(SuccessException)doblock.callraiseSuccessExceptionendenddefsql_nowifActiveRecord::Base.connection_db_config.adapter == "sqlite3""DATE('NOW')"else"NOW()"endenddefbase_queryConversation.select("conversations.*","COUNT(messages.id) AS messages_count","#{sql_now} AS last_activity_at").left_joins(:messages).group(:id)enddeftest_it_should_work_with_aliased_order_byquery=base_query.order("last_activity_at DESC")assert_not_raise{query.count(:all)}enddeftest_it_demonstrates_that_non_aliased_order_by_workquery=base_query.order(Arel.sql("#{sql_now} DESC"))assert_not_raise{query.count(:all)}enddeftest_without_order_by_it_always_workquery=base_query# .order("last_activity_at DESC")assert_not_raise{query.count(:all)}endend
Expected behavior
This query should work
Conversation.select("conversations.*","COUNT(messages.id) AS messages_count","NOW() AS last_activity_at").left_joins(:messages).order(:last_activity_at).group(:id)
Expected query
SELECT
COUNT(*) AS "count_all",
"conversations"."id" AS "conversations_id"
FROM "conversations"
LEFT OUTER JOIN "messages" ON "messages"."conversation_id" = "conversations"."id"
GROUP BY "conversations"."id"
-- WITHOUT THIS
-- ORDER BY last_activity_at DESC
Actual behavior
ActiveRecord::StatementInvalid <"PG::UndefinedColumn: ERROR: column \"last_activity_at\" does not exist
SELECT
COUNT(*) AS "count_all",
"conversations"."id" AS "conversations_id"
FROM "conversations"
LEFT OUTER JOIN "messages" ON "messages"."conversation_id" = "conversations"."id"
GROUP BY "conversations"."id"
ORDER BY last_activity_at DESC
System configuration
Rails version: 7.1.3.2
Ruby version: 3.0.0
The text was updated successfully, but these errors were encountered:
Steps to reproduce
Build a query that uses
.count(:all)
and.group(...)
with a custom.select("... AS alias")
and a.order(:alias)
It seems ActiveRecord when calling
.count(:all)
will remove from the SELECT thealias
column and everything else but the primary key, however it keeps theORDER BY alias
. To executeCOUNT(...)
, theORDER BY
is kind of irrelevant, it should probably be removed.ActiveRecord seems to already clear ORDER BY for some specific scenario as seen here: https://github.com/rails/rails/blob/main/activerecord/lib/active_record/relation/calculations.rb#L240 however in my scenario, the
has_include(...)
returns false and goes straight toperform_calculation(operation, column_name)
Here https://github.com/rails/rails/blob/main/activerecord/lib/active_record/relation/calculations.rb#L536 select values are redefined, maybe we should simply add
Test code
Note: It ain't specific to Postgres. Error is present with SQLite too.
Expected behavior
This query should work
Expected query
Actual behavior
System configuration
Rails version: 7.1.3.2
Ruby version: 3.0.0
The text was updated successfully, but these errors were encountered: