aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib
diff options
context:
space:
mode:
authorSean Griffin <sean@seantheprogrammer.com>2016-01-12 14:34:42 -0700
committerSean Griffin <sean@seantheprogrammer.com>2016-01-12 14:38:25 -0700
commit5d41cb3bfd6b19833261622ce5d339b1e580bd8b (patch)
tree46ed63b4dd8f07e9b13abb0987eb3afe41962b1d /activerecord/lib
parent858b9652ced5438127e6c6404bf3f9cae9699985 (diff)
downloadrails-5d41cb3bfd6b19833261622ce5d339b1e580bd8b.tar.gz
rails-5d41cb3bfd6b19833261622ce5d339b1e580bd8b.tar.bz2
rails-5d41cb3bfd6b19833261622ce5d339b1e580bd8b.zip
Change `WhereClause#merge` to same named columns on diff tables
While the predicates are an arel equality node where the left side is a full arel attribute, the binds just have the name of the column and nothing else. This means that while splitting the predicates can include the table as a factor, the binds cannot. It's entirely possible that we might be able to have the bind params carry a bit more information (I don't believe the name is used for anything but logging), and that is probably a worthwhile change to make in the future. However the simplest (and likely slightly faster) solution is to simply use the indices of the conflicts in both cases. This means that we only have to compute the collision space once, instead of twice even though we're doing an additional array iteration. Regardless, this method isn't a performance hotspot. Close #22823. [Ben Woosley & Sean Griffin]
Diffstat (limited to 'activerecord/lib')
-rw-r--r--activerecord/lib/active_record/relation/where_clause.rb21
1 files changed, 10 insertions, 11 deletions
diff --git a/activerecord/lib/active_record/relation/where_clause.rb b/activerecord/lib/active_record/relation/where_clause.rb
index 2c2d6cfa47..e39dbac0d5 100644
--- a/activerecord/lib/active_record/relation/where_clause.rb
+++ b/activerecord/lib/active_record/relation/where_clause.rb
@@ -18,9 +18,10 @@ module ActiveRecord
end
def merge(other)
+ conflict_indices = indices_of_predicates_referenced_by(other).to_set
WhereClause.new(
- predicates_unreferenced_by(other) + other.predicates,
- non_conflicting_binds(other) + other.binds,
+ non_conflicting(predicates, conflict_indices) + other.predicates,
+ non_conflicting(binds, conflict_indices) + other.binds,
)
end
@@ -97,20 +98,18 @@ module ActiveRecord
private
- def predicates_unreferenced_by(other)
- predicates.reject do |n|
+ def indices_of_predicates_referenced_by(other)
+ predicates.each_with_index.select do |(n, _)|
equality_node?(n) && other.referenced_columns.include?(n.left)
- end
+ end.map(&:last)
end
- def equality_node?(node)
- node.respond_to?(:operator) && node.operator == :==
+ def non_conflicting(values, conflict_indices)
+ values.reject.with_index { |_, i| conflict_indices.include?(i) }
end
- def non_conflicting_binds(other)
- conflicts = referenced_columns & other.referenced_columns
- conflicts.map! { |node| node.name.to_s }
- binds.reject { |attr| conflicts.include?(attr.name) }
+ def equality_node?(node)
+ node.respond_to?(:operator) && node.operator == :==
end
def inverted_predicates