diff options
Diffstat (limited to 'activerecord/lib/active_record/relation/where_clause.rb')
-rw-r--r-- | activerecord/lib/active_record/relation/where_clause.rb | 36 |
1 files changed, 35 insertions, 1 deletions
diff --git a/activerecord/lib/active_record/relation/where_clause.rb b/activerecord/lib/active_record/relation/where_clause.rb index b39fc1fed1..cd6da052a9 100644 --- a/activerecord/lib/active_record/relation/where_clause.rb +++ b/activerecord/lib/active_record/relation/where_clause.rb @@ -1,6 +1,6 @@ module ActiveRecord class Relation - class WhereClause + class WhereClause # :nodoc: attr_reader :parts, :binds def initialize(parts, binds) @@ -15,6 +15,13 @@ module ActiveRecord ) end + def merge(other) + WhereClause.new( + parts_unreferenced_by(other) + other.parts, + non_conflicting_binds(other) + other.binds, + ) + end + def ==(other) other.is_a?(WhereClause) && parts == other.parts && @@ -24,6 +31,33 @@ module ActiveRecord def self.empty new([], []) end + + protected + + def referenced_columns + @referenced_columns ||= begin + equality_nodes = parts.select { |n| equality_node?(n) } + Set.new(equality_nodes, &:left) + end + end + + private + + def parts_unreferenced_by(other) + parts.reject do |n| + equality_node?(n) && other.referenced_columns.include?(n.left) + end + end + + def equality_node?(node) + node.respond_to?(:operator) && node.operator == :== + end + + def non_conflicting_binds(other) + conflicts = referenced_columns & other.referenced_columns + conflicts.map! { |node| node.name.to_s } + binds.reject { |col, _| conflicts.include?(col.name) } + end end end end |