mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Child joins should be aliased when merging relations
Rails 5.2 does not alias child joins, causing an error about duplicated table/fields: Example: Using some code like: `Post.joins(:author, :categorizations).merge(Author.select(:id)).merge(Categorization.joins(:author))` *Before this fix:* ` SELECT ... FROM "posts" INNER JOIN "authors" ON ... INNER JOIN "authors" ON ... ` *After this fix:* ` SELECT ... FROM "posts" INNER JOIN "authors" ON ... INNER JOIN "authors" "authors_categorizations" ON ... ` Before 5.2, Rails aliased the joins, but wrongfully transformed them into a LEFT OUTER JOIN. This fix will keep them as INNER JOINS, but make sure child joins are aliased, to avoid errors.
This commit is contained in:
parent
d0d3e96492
commit
fd689d9fb1
2 changed files with 27 additions and 2 deletions
|
@ -88,7 +88,7 @@ module ActiveRecord
|
|||
walk join_root, oj.join_root
|
||||
else
|
||||
oj.join_root.children.flat_map { |child|
|
||||
make_join_constraints(oj.join_root, child, join_type)
|
||||
make_join_constraints(oj.join_root, child, join_type, true)
|
||||
}
|
||||
end
|
||||
}
|
||||
|
|
|
@ -5,10 +5,11 @@ require "models/post"
|
|||
require "models/comment"
|
||||
require "models/author"
|
||||
require "models/rating"
|
||||
require "models/categorization"
|
||||
|
||||
module ActiveRecord
|
||||
class RelationTest < ActiveRecord::TestCase
|
||||
fixtures :posts, :comments, :authors, :author_addresses, :ratings
|
||||
fixtures :posts, :comments, :authors, :author_addresses, :ratings, :categorizations
|
||||
|
||||
def test_construction
|
||||
relation = Relation.new(FakeKlass, table: :b)
|
||||
|
@ -223,6 +224,30 @@ module ActiveRecord
|
|||
assert_equal manual_comments_on_post_that_have_author.size, merged_authors_with_commented_posts_relation.to_a.size
|
||||
end
|
||||
|
||||
def test_relation_merging_with_merged_symbol_joins_is_aliased
|
||||
categorizations_with_authors = Categorization.joins(:author)
|
||||
queries = capture_sql { Post.joins(:author, :categorizations).merge(Author.select(:id)).merge(categorizations_with_authors).to_a }
|
||||
|
||||
nb_inner_join = queries.sum { |sql| sql.scan(/INNER\s+JOIN/i).size }
|
||||
assert_equal 3, nb_inner_join, "Wrong amount of INNER JOIN in query"
|
||||
|
||||
# using `\W` as the column separator
|
||||
assert queries.any? { |sql| %r[INNER\s+JOIN\s+#{Author.quoted_table_name}\s+\Wauthors_categorizations\W]i.match?(sql) }, "Should be aliasing the child INNER JOINs in query"
|
||||
end
|
||||
|
||||
def test_relation_with_merged_joins_aliased_works
|
||||
categorizations_with_authors = Categorization.joins(:author)
|
||||
posts_with_joins_and_merges = Post.joins(:author, :categorizations)
|
||||
.merge(Author.select(:id)).merge(categorizations_with_authors)
|
||||
|
||||
author_with_posts = Author.joins(:posts).ids
|
||||
categorizations_with_author = Categorization.joins(:author).ids
|
||||
posts_with_author_and_categorizations = Post.joins(:categorizations).where(author_id: author_with_posts, categorizations: { id: categorizations_with_author }).ids
|
||||
|
||||
assert_equal posts_with_author_and_categorizations.size, posts_with_joins_and_merges.count
|
||||
assert_equal posts_with_author_and_categorizations.size, posts_with_joins_and_merges.to_a.size
|
||||
end
|
||||
|
||||
def test_relation_merging_with_joins_as_join_dependency_pick_proper_parent
|
||||
post = Post.create!(title: "haha", body: "huhu")
|
||||
comment = post.comments.create!(body: "hu")
|
||||
|
|
Loading…
Reference in a new issue