-
Notifications
You must be signed in to change notification settings - Fork 21.6k
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
resolving includes() is severly broken: #count works, #sum is broken #22422
Comments
Can you please create a standard reproduction script using one of the templates available here? |
I've added the reproduction script for the issue above in https://gist.github.com/aidanharan/a4003a10d7cdada717b5 The issue is present in at least versions 5.0.0.beta3, 4.2.5.2 and 4.1.14.2. |
It may not be the intended use, but I've personally used things like |
This issue has been automatically marked as stale because it has not been commented on for at least The resources of the Rails team are limited, and so we are asking for your help. If you can still reproduce this error on the Thank you for all your contributions. |
This issue has been automatically closed because of inactivity. If you can still reproduce this error on the Thank you for all your contributions. |
Hi, this is still an issue in Rails 6. To repro: # frozen_string_literal: true
require "bundler/inline"
gemfile(true) do
source "https://rubygems.org"
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
# Activate the gem you are reporting the issue against.
gem "activerecord", "6.0.0"
gem "sqlite3"
end
require "active_record"
require "minitest/autorun"
require "logger"
# This connection will do for database-independent bug reports.
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
ActiveRecord::Base.logger = Logger.new(STDOUT)
ActiveRecord::Schema.define do
create_table :expenses, force: true do |t|
t.integer :amount
end
create_table :users_expenses, force: true do |t|
t.integer :expense_id
t.integer :amount
end
end
class Expense < ActiveRecord::Base
has_many :users_expenses, dependent: :destroy
end
class UsersExpense < ActiveRecord::Base
belongs_to :expense
end
class BugTest < Minitest::Test
def setup
expense = Expense.create!(amount: 10)
expense.users_expenses << UsersExpense.create!(amount: 5)
expense.users_expenses << UsersExpense.create!(amount: 5)
another_expense = Expense.create!(amount: 10)
another_expense.users_expenses << UsersExpense.create!(amount: 5)
another_expense.users_expenses << UsersExpense.create!(amount: 5)
end
def teardown
Expense.destroy_all
end
def test_sum_with_includes
assert_equal 20, Expense.all.includes(:users_expenses).sum(:amount) # NOK
end
def test_sum_without_includes
assert_equal 20, Expense.all.sum(:amount) # OK
end
def test_ampersand_sum_with_includes
assert_equal 20, Expense.all.includes(:users_expenses).sum(&:amount) # OK
end
def test_ampersand_sum_without_includes
assert_equal 20, Expense.all.sum(&:amount) # OK
end
end
Should I open new issue? |
I have a query, aka ActiveRelation.
I have a base table (disks) with a lot of other tables attached to it (i.e. tracks)
I now build a query based only on the Disk table:
But when I use includes():
-- sql: select count(*) from disk where(available is true)
-- sql: select sum(price) from disk LEFT OUTER JOIN tracks ON ... where(available is true)
-- which results in sum([disk x tracks] price)
I believe this is a severly wrong behaviour.
I suspect there must be some place in ActiveRecord that tries to optimize fetches in a bad way.
I looks to me, like sometimes the engine tries to optimize includes()
by folding in the includes into a single query by using left outer joins.
This leads to a lot of really unpredictable behaviour thorughout the framework.
(you stumble around that whenever you use includes() .. can't find my previous bug report on that)
I'd like to suggest:
To my understanding, #includes is only a hint to improve the query strategy to avoid nxm fetches, but it should never alter the semantics of the query.
But currently (as of activerecord 4.2.5) some weird optimization really breaks the semantics of the query in a really bad way.
I'd like to suggest that #includes MUST NOT change the query, but MAY be used to trigger additional queries to prefetch related tables.
While not related to this bug, I could think of an even better optimization.
I believe that the includes() should only be fetched on demand.
I'll make up a new issue for this
The text was updated successfully, but these errors were encountered: