diff options
author | Maxime Lapointe <hunter_spawn@hotmail.com> | 2016-08-17 11:16:36 -0400 |
---|---|---|
committer | Maxime Lapointe <hunter_spawn@hotmail.com> | 2017-06-20 20:47:22 -0400 |
commit | 249ddd0c39e6f24145ae1150d4c8eec9f11219b1 (patch) | |
tree | 841ff60580940f95da883d97c127bc9d5f6d0e92 /activerecord/test/cases | |
parent | 0787727cd65d820df78c9cd71ac9f145c9834762 (diff) | |
download | rails-249ddd0c39e6f24145ae1150d4c8eec9f11219b1.tar.gz rails-249ddd0c39e6f24145ae1150d4c8eec9f11219b1.tar.bz2 rails-249ddd0c39e6f24145ae1150d4c8eec9f11219b1.zip |
Keep INNER JOIN when merging relations
Doing `Author.joins(:posts).merge(Post.joins(:comments))` does this
`SELECT ... INNER JOIN posts ON... LEFT OUTER JOIN comments ON...`
instead of doing
`SELECT ... INNER JOIN posts ON... INNER JOIN comments ON...`.
This behavior is unexpected and makes little sense as, basically, doing
`Post.joins(:comments)` means I want posts that have comments. Turning
it to a LEFT JOIN means I want posts and join the comments data, if
any.
We can see this problem directly in the existing tests.
The test_relation_merging_with_merged_joins_as_symbols only does joins
from posts to comments to ratings while the ratings fixture isn't
loaded, but the count is non-zero.
Diffstat (limited to 'activerecord/test/cases')
-rw-r--r-- | activerecord/test/cases/relation_test.rb | 23 |
1 files changed, 21 insertions, 2 deletions
diff --git a/activerecord/test/cases/relation_test.rb b/activerecord/test/cases/relation_test.rb index 5fb32270b7..73ce1cda27 100644 --- a/activerecord/test/cases/relation_test.rb +++ b/activerecord/test/cases/relation_test.rb @@ -6,7 +6,7 @@ require "models/rating" module ActiveRecord class RelationTest < ActiveRecord::TestCase - fixtures :posts, :comments, :authors, :author_addresses + fixtures :posts, :comments, :authors, :author_addresses, :ratings FakeKlass = Struct.new(:table_name, :name) do extend ActiveRecord::Delegation::DelegateCache @@ -224,7 +224,26 @@ module ActiveRecord def test_relation_merging_with_merged_joins_as_symbols special_comments_with_ratings = SpecialComment.joins(:ratings) posts_with_special_comments_with_ratings = Post.group("posts.id").joins(:special_comments).merge(special_comments_with_ratings) - assert_equal({ 2 => 1, 4 => 3, 5 => 1 }, authors(:david).posts.merge(posts_with_special_comments_with_ratings).count) + assert_equal({ 4 => 2 }, authors(:david).posts.merge(posts_with_special_comments_with_ratings).count) + end + + def test_relation_merging_with_merged_symbol_joins_keeps_inner_joins + queries = capture_sql { authors_with_commented_posts = Author.joins(:posts).merge(Post.joins(:comments)).to_a } + + nb_inner_join = queries.sum { |sql| sql.scan(/INNER\s+JOIN/i).size } + assert_equal 2, nb_inner_join, "Wrong amount of INNER JOIN in query" + assert queries.none? { |sql| /LEFT\s+(OUTER)?\s+JOIN/i.match?(sql) }, "Shouldn't have any LEFT JOIN in query" + end + + def test_relation_merging_with_merged_symbol_joins_has_correct_size_and_count + # Has one entry per comment + merged_authors_with_commented_posts_relation = Author.joins(:posts).merge(Post.joins(:comments)) + + post_ids_with_author = Post.joins(:author).pluck(:id) + manual_comments_on_post_that_have_author = Comment.where(post_id: post_ids_with_author).pluck(:id) + + assert_equal manual_comments_on_post_that_have_author.size, merged_authors_with_commented_posts_relation.count + 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_joins_as_join_dependency_pick_proper_parent |