aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/relation/merger.rb
diff options
context:
space:
mode:
authorAaron Patterson <aaron.patterson@gmail.com>2013-05-21 11:01:25 -0700
committerAaron Patterson <aaron.patterson@gmail.com>2013-05-21 11:01:25 -0700
commitac70ec64138765ddd2a7c5e0130243e6df98cf2d (patch)
tree3cc3eb3ee81e314fbd60dcabafda0aa40850b382 /activerecord/lib/active_record/relation/merger.rb
parentf47b4236e089b07cb683ee9b7ff8b06111a0ec10 (diff)
parentf3ebbeae6eb647767ccd49e25821b1ba33923596 (diff)
downloadrails-ac70ec64138765ddd2a7c5e0130243e6df98cf2d.tar.gz
rails-ac70ec64138765ddd2a7c5e0130243e6df98cf2d.tar.bz2
rails-ac70ec64138765ddd2a7c5e0130243e6df98cf2d.zip
Merge branch 'bindwhere'
* bindwhere: avoid creating a set if no where values are removed remove bind values for where clauses that were removed push partitioning up so bind elimination can get the removed wheres push partion logic down and initialization logic up partition the where values so we can access the removed ones
Diffstat (limited to 'activerecord/lib/active_record/relation/merger.rb')
-rw-r--r--activerecord/lib/active_record/relation/merger.rb40
1 files changed, 20 insertions, 20 deletions
diff --git a/activerecord/lib/active_record/relation/merger.rb b/activerecord/lib/active_record/relation/merger.rb
index 98afeb8cc5..c114ea0c0d 100644
--- a/activerecord/lib/active_record/relation/merger.rb
+++ b/activerecord/lib/active_record/relation/merger.rb
@@ -99,8 +99,15 @@ module ActiveRecord
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
@@ -123,34 +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 merged_wheres
- rhs_wheres = values[:where] || []
- lhs_wheres = relation.where_values
+ def filter_binds(lhs_binds, removed_wheres)
+ return lhs_binds if removed_wheres.empty?
- if rhs_wheres.empty? || lhs_wheres.empty?
- lhs_wheres + rhs_wheres
- else
- reject_overwrites(lhs_wheres, rhs_wheres) + rhs_wheres
- 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 reject_overwrites(lhs_wheres, rhs_wheres)
+ # 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 }
- lhs_wheres.reject do |w|
+ lhs_wheres.partition do |w|
w.respond_to?(:operator) && w.operator == :== && seen.include?(w.left)
end
end