Skip to content

Commit

Permalink
merge JoinDependency as outer joins
Browse files Browse the repository at this point in the history
Merge JoinDependency objects as outer joins
  • Loading branch information
tenderlove committed Oct 10, 2013
1 parent d20ccb7 commit 223082e
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 1 deletion.
30 changes: 30 additions & 0 deletions activerecord/lib/active_record/associations/join_dependency.rb
Expand Up @@ -85,6 +85,20 @@ def outer_joins
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
Expand Down Expand Up @@ -118,6 +132,22 @@ def instantiate(result_set)

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

Expand Down
2 changes: 1 addition & 1 deletion activerecord/lib/active_record/relation/query_methods.rb
Expand Up @@ -951,7 +951,7 @@ def build_joins(manager, joins)
)

stashed_association_joins.each do |dep|
join_dependency.graft dep.outer_joins
join_dependency.merge_outer_joins! dep
end

joins = join_dependency.join_constraints
Expand Down

0 comments on commit 223082e

Please sign in to comment.