From 223082e588af59cb35108ce2a2d742dcecf72cc6 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 10 Oct 2013 14:46:15 -0700 Subject: merge JoinDependency as outer joins Merge JoinDependency objects as outer joins --- .../active_record/associations/join_dependency.rb | 30 ++++++++++++++++++++++ .../lib/active_record/relation/query_methods.rb | 2 +- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/associations/join_dependency.rb b/activerecord/lib/active_record/associations/join_dependency.rb index bc235cf63d..a25a061fc0 100644 --- a/activerecord/lib/active_record/associations/join_dependency.rb +++ b/activerecord/lib/active_record/associations/join_dependency.rb @@ -85,6 +85,20 @@ module ActiveRecord nodes end + def merge_outer_joins!(other) + left = join_root + right = other.join_root + + if left.match? right + merge_node left, right + else + # If the roots aren't the same, then deep copy the RHS to the LHS + left.children.concat right.children.map { |node| + deep_copy left, node + } + end + end + def join_constraints join_root.flat_map(&:join_constraints) end @@ -118,6 +132,22 @@ module ActiveRecord private + def merge_node(left, right) + intersection, missing = right.children.map { |node1| + [left.children.find { |node2| node1.match? node2 }, node1] + }.partition(&:first) + + intersection.each { |l,r| merge_node l, r } + + left.children.concat missing.map { |_,node| deep_copy left, node } + end + + def deep_copy(parent, node) + dup = build_join_association(node.reflection, parent, Arel::OuterJoin) + dup.children.concat node.children.map { |n| deep_copy dup, n } + dup + end + def find_node(target_node) stack = target_node.parents << target_node diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 364c7ec418..9c9690215a 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -951,7 +951,7 @@ module ActiveRecord ) stashed_association_joins.each do |dep| - join_dependency.graft dep.outer_joins + join_dependency.merge_outer_joins! dep end joins = join_dependency.join_constraints -- cgit v1.2.3