aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/test/cases
diff options
context:
space:
mode:
authorMaxime Lapointe <hunter_spawn@hotmail.com>2016-08-17 11:16:36 -0400
committerMaxime Lapointe <hunter_spawn@hotmail.com>2017-06-20 20:47:22 -0400
commit249ddd0c39e6f24145ae1150d4c8eec9f11219b1 (patch)
tree841ff60580940f95da883d97c127bc9d5f6d0e92 /activerecord/test/cases
parent0787727cd65d820df78c9cd71ac9f145c9834762 (diff)
downloadrails-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.rb23
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