diff options
Diffstat (limited to 'activerecord/lib/active_record/relation/merger.rb')
-rw-r--r-- | activerecord/lib/active_record/relation/merger.rb | 49 |
1 files changed, 24 insertions, 25 deletions
diff --git a/activerecord/lib/active_record/relation/merger.rb b/activerecord/lib/active_record/relation/merger.rb index bda7a76330..c114ea0c0d 100644 --- a/activerecord/lib/active_record/relation/merger.rb +++ b/activerecord/lib/active_record/relation/merger.rb @@ -94,15 +94,20 @@ module ActiveRecord []) relation.joins! rest - join_dependency.join_associations.each do |association| - @relation = association.join_relation(relation) - end + @relation = join_dependency.join_relation(relation) end end def merge_multi_values - relation.where_values = merged_wheres - relation.bind_values = merged_binds + lhs_wheres = relation.where_values + rhs_wheres = values[:where] || [] + lhs_binds = relation.bind_values + rhs_binds = values[:bind] || [] + + removed, kept = partition_overwrites(lhs_wheres, rhs_wheres) + + relation.where_values = kept + rhs_wheres + relation.bind_values = filter_binds(lhs_binds, removed) + rhs_binds if values[:reordering] # override any order specified in the original relation @@ -125,33 +130,27 @@ module ActiveRecord end end - def merged_binds - if values[:bind] - (relation.bind_values + values[:bind]).uniq(&:first) - else - relation.bind_values - end - end + def filter_binds(lhs_binds, removed_wheres) + return lhs_binds if removed_wheres.empty? - def merged_wheres - values[:where] ||= [] - - if values[:where].empty? || relation.where_values.empty? - relation.where_values + values[:where] - else - sanitized_wheres + values[:where] - end + set = Set.new removed_wheres.map { |x| x.left.name } + lhs_binds.dup.delete_if { |col,_| set.include? col.name } end # Remove equalities from the existing relation with a LHS which is # present in the relation being merged in. - def sanitized_wheres - seen = Set.new - values[:where].each do |w| - seen << w.left if w.respond_to?(:operator) && w.operator == :== + # returns [things_to_remove, things_to_keep] + def partition_overwrites(lhs_wheres, rhs_wheres) + if lhs_wheres.empty? || rhs_wheres.empty? + return [[], lhs_wheres] + end + + nodes = rhs_wheres.find_all do |w| + w.respond_to?(:operator) && w.operator == :== end + seen = Set.new(nodes) { |node| node.left } - relation.where_values.reject do |w| + lhs_wheres.partition do |w| w.respond_to?(:operator) && w.operator == :== && seen.include?(w.left) end end |