aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
authorAaron Patterson <aaron.patterson@gmail.com>2013-10-10 14:46:15 -0700
committerAaron Patterson <aaron.patterson@gmail.com>2013-10-10 14:46:15 -0700
commit223082e588af59cb35108ce2a2d742dcecf72cc6 (patch)
tree209ef28b8fa133bf927e89c5785562af8a921a16 /activerecord
parentd20ccb7e632665b6661e82ae450e8180e3c085f9 (diff)
downloadrails-223082e588af59cb35108ce2a2d742dcecf72cc6.tar.gz
rails-223082e588af59cb35108ce2a2d742dcecf72cc6.tar.bz2
rails-223082e588af59cb35108ce2a2d742dcecf72cc6.zip
merge JoinDependency as outer joins
Merge JoinDependency objects as outer joins
Diffstat (limited to 'activerecord')
-rw-r--r--activerecord/lib/active_record/associations/join_dependency.rb30
-rw-r--r--activerecord/lib/active_record/relation/query_methods.rb2
2 files changed, 31 insertions, 1 deletions
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