Ransack generates redundant left join statements
itsalongstory opened this issue · comments
itsalongstory commented
test_ransack.rb
require 'bundler/inline'
gemfile(true) do
source 'https://rubygems.org'
gem 'activerecord', '~> 7.0', '>= 7.0.6', require: "active_record"
gem 'sqlite3', '~> 1.6', '>= 1.6.3'
gem 'ransack', '~> 4.0'
gem 'minitest', '~> 5.19', require: "minitest/autorun"
end
ActiveRecord::Base.establish_connection(
adapter: "sqlite3",
database: "./test_ransack_search"
)
ActiveRecord::Schema.define do
drop_table(:authors, if_exists: true)
drop_table(:articles, if_exists: true)
drop_table(:comments, if_exists: true)
create_table :authors do |t|
t.string :name
end
create_table :articles do |t|
t.belongs_to :author
t.string :title
end
create_table :comments do |t|
t.belongs_to :article
t.string :content
end
end
class ApplicationRecord < ActiveRecord::Base
primary_abstract_class
def self.ransackable_attributes(auth_object = nil)
authorizable_ransackable_attributes
end
def self.ransackable_associations(auth_object = nil)
authorizable_ransackable_associations
end
end
class Author < ApplicationRecord
has_many :articles
end
class Article < ApplicationRecord
has_many :comments
belongs_to :author
end
class Comment < ApplicationRecord
belongs_to :article
end
class MyTest < Minitest::Test
# success
def test_1
query_params = { article_title_eq: 'abc' }
assert_equal "SELECT \"comments\".* FROM \"comments\" INNER JOIN \"articles\" ON \"articles\".\"id\" = \"comments\".\"article_id\" WHERE \"articles\".\"title\" = 'abc'", Comment.joins(:article).ransack(query_params).result.to_sql
end
# failure
def test_2
query_params = { article_author_name_eq: 'abc' }
assert_equal "SELECT \"comments\".* FROM \"comments\" INNER JOIN \"articles\" ON \"articles\".\"id\" = \"comments\".\"article_id\" INNER JOIN \"authors\" ON \"authors\".\"id\" = \"articles\".\"author_id\" WHERE \"authors\".\"name\" = 'abc'", Comment.joins(article: :author).ransack(query_params).result.to_sql
end
end
deploy@fms-test:~$ ruby test_ransack.rb
Fetching gem metadata from https://gems.ruby-china.com/........
Resolving dependencies...
Using concurrent-ruby 1.2.2
Using minitest 5.19.0
Using i18n 1.14.1
Using bundler 2.4.16
Using tzinfo 2.0.6
Using sqlite3 1.6.3 (x86_64-linux)
Using activesupport 7.0.6
Using activemodel 7.0.6
Using activerecord 7.0.6
Using ransack 4.0.0
-- drop_table(:authors, {:if_exists=>true})
-> 0.0503s
-- drop_table(:articles, {:if_exists=>true})
-> 0.0358s
-- drop_table(:comments, {:if_exists=>true})
-> 0.0358s
-- create_table(:authors)
-> 0.0359s
-- create_table(:articles)
-> 0.0719s
-- create_table(:comments)
-> 0.0717s
Run options: --seed 62497
# Running:
.F
Finished in 0.060084s, 33.2867 runs/s, 33.2867 assertions/s.
1) Failure:
MyTest#test_2 [test_ransack.rb:71]:
--- expected
+++ actual
@@ -1 +1 @@
-"SELECT \"comments\".* FROM \"comments\" INNER JOIN \"articles\" ON \"articles\".\"id\" = \"comments\".\"article_id\" INNER JOIN \"authors\" ON \"authors\".\"id\" = \"articles\".\"author_id\" WHERE \"authors\".\"name\" = 'abc'"
+"SELECT \"comments\".* FROM \"comments\" INNER JOIN \"articles\" ON \"articles\".\"id\" = \"comments\".\"article_id\" INNER JOIN \"authors\" ON \"authors\".\"id\" = \"articles\".\"author_id\" LEFT OUTER JOIN \"authors\" \"authors_articles\" ON \"authors_articles\".\"id\" = \"articles\".\"author_id\" WHERE \"authors\".\"name\" = 'abc'"
2 runs, 2 assertions, 1 failures, 0 errors, 0 skips
itsalongstory commented
In test_2
, ransack generate sql like this:
SELECT
"comments".*
FROM
"comments"
INNER JOIN "articles" ON "articles"."id" = "comments"."article_id"
INNER JOIN "authors" ON "authors"."id" = "articles"."author_id"
LEFT OUTER JOIN "authors" "authors_articles" ON "authors_articles"."id" = "articles"."author_id" -- ?????
WHERE
"authors"."name" = 'abc'
The LEFT OUTER JOIN ...
is redundant, isn't it?
What we need is just like below:
SELECT
"comments".*
FROM
"comments"
INNER JOIN "articles" ON "articles"."id" = "comments"."article_id"
INNER JOIN "authors" ON "authors"."id" = "articles"."author_id"
WHERE
"authors"."name" = 'abc'
H. Can Yıldırım commented
I've noticed the same thing in my application, it brokes some of my SQL calculation. Did you find any solution to this? @itsalongstory
itsalongstory commented
I've noticed the same thing in my application, it brokes some of my SQL calculation. Did you find any solution to this? @itsalongstory
Not yet.