Skip to content

Commit

Permalink
merge doesn't allow to overwrite partially matching nodes
Browse files Browse the repository at this point in the history
This makes `merge rewhere: true` follow the original `merge`'s behavior.
  • Loading branch information
kamipo committed May 27, 2020
1 parent 817389d commit 844106e
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 5 deletions.
18 changes: 13 additions & 5 deletions activerecord/lib/active_record/relation/where_clause.rb
Expand Up @@ -101,13 +101,12 @@ def contradiction?
end

def extract_attributes
attrs = []
predicates.each do |node|
Arel.fetch_attribute(node) { |attr| attrs << attr } || begin
attrs << node.left if node.equality? && node.left.is_a?(Arel::Predications)
predicates.each_with_object([]) do |node, attrs|
attr = extract_attribute(node) || begin
node.left if node.equality? && node.left.is_a?(Arel::Predications)
end
attrs << attr if attr
end
attrs
end

protected
Expand All @@ -121,6 +120,15 @@ def referenced_columns
end

private
def extract_attribute(node)
attr_node = nil
Arel.fetch_attribute(node) do |attr|
return if attr_node&.!= attr # all attr nodes should be the same
attr_node = attr
end
attr_node
end

def equalities(predicates)
equalities = []

Expand Down
15 changes: 15 additions & 0 deletions activerecord/test/cases/relation/merging_test.rb
Expand Up @@ -36,6 +36,11 @@ def test_merge_in_clause

assert_equal [mary, bob], david_and_mary.merge(mary_and_bob, rewhere: true)
assert_equal [david, mary], mary_and_bob.merge(david_and_mary, rewhere: true)

david_and_bob = Author.where(id: david).or(Author.where(name: "Bob"))

assert_equal [david], david_and_mary.merge(david_and_bob)
assert_equal [david], david_and_mary.merge(david_and_bob, rewhere: true)
end

def test_merge_between_clause
Expand All @@ -61,6 +66,11 @@ def test_merge_between_clause

assert_equal [mary, bob], david_and_mary.merge(mary_and_bob, rewhere: true)
assert_equal [david, mary], mary_and_bob.merge(david_and_mary, rewhere: true)

david_and_bob = Author.where(id: david).or(Author.where(name: "Bob"))

assert_equal [david], david_and_mary.merge(david_and_bob)
assert_equal [david], david_and_mary.merge(david_and_bob, rewhere: true)
end

def test_merge_or_clause
Expand All @@ -86,6 +96,11 @@ def test_merge_or_clause

assert_equal [mary, bob], david_and_mary.merge(mary_and_bob, rewhere: true)
assert_equal [david, mary], mary_and_bob.merge(david_and_mary, rewhere: true)

david_and_bob = Author.where(id: david).or(Author.where(name: "Bob"))

assert_equal [david], david_and_mary.merge(david_and_bob)
assert_equal [david], david_and_mary.merge(david_and_bob, rewhere: true)
end

def test_merge_not_in_clause
Expand Down

0 comments on commit 844106e

Please sign in to comment.