Skip to content

Commit edcde0d

Browse files
Merge pull request #49870 from fatkodima/fix-upsert-custom_on_duplicate-and-unique_by
Fix upserting for custom `:on_duplicate` and `:unique_by` consisting of all inserts keys (cherry picked from commit f7bc844)
1 parent 589f72f commit edcde0d

File tree

3 files changed

+22
-3
lines changed

3 files changed

+22
-3
lines changed

activerecord/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
* Fix upserting for custom `:on_duplicate` and `:unique_by` consisting of all
2+
inserts keys.
3+
4+
*fatkodima*
5+
16
* Fix `NoMethodError` when casting a PostgreSQL `money` value that uses a
27
comma as its radix point and has no leading currency symbol. For example,
38
when casting `"3,50"`.

activerecord/lib/active_record/insert_all.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@ def initialize(model, inserts, on_duplicate:, update_only: nil, returning: nil,
1717
disallow_raw_sql!(on_duplicate)
1818
disallow_raw_sql!(returning)
1919

20-
configure_on_duplicate_update_logic
21-
2220
if model.scope_attributes?
2321
@scope_attributes = model.scope_attributes
2422
@keys |= @scope_attributes.keys
@@ -29,8 +27,8 @@ def initialize(model, inserts, on_duplicate:, update_only: nil, returning: nil,
2927
@returning = false if @returning == []
3028

3129
@unique_by = find_unique_index_for(unique_by)
32-
@on_duplicate = :skip if @on_duplicate == :update && updatable_columns.empty?
3330

31+
configure_on_duplicate_update_logic
3432
ensure_valid_options_for_connection!
3533
end
3634

@@ -99,6 +97,8 @@ def configure_on_duplicate_update_logic
9997
elsif custom_update_sql_provided?
10098
@update_sql = on_duplicate
10199
@on_duplicate = :update
100+
elsif @on_duplicate == :update && updatable_columns.empty?
101+
@on_duplicate = :skip
102102
end
103103
end
104104

activerecord/test/cases/insert_all_test.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -664,6 +664,20 @@ def test_upsert_all_updates_using_provided_sql
664664
assert_equal "written", Book.find(2).status
665665
end
666666

667+
def test_upsert_all_updates_using_provided_sql_and_unique_by
668+
skip unless supports_insert_on_duplicate_update? && supports_insert_conflict_target?
669+
670+
book = books(:rfr)
671+
assert_equal "proposed", book.status
672+
673+
Book.upsert_all(
674+
[{ name: book.name, author_id: book.author_id }],
675+
unique_by: [:author_id, :name],
676+
on_duplicate: Arel.sql("status = 2")
677+
)
678+
assert_equal "published", book.reload.status
679+
end
680+
667681
def test_upsert_all_with_unique_by_fails_cleanly_for_adapters_not_supporting_insert_conflict_target
668682
skip if supports_insert_conflict_target?
669683

0 commit comments

Comments
 (0)