Skip to content

Commit f7bc844

Browse files
Merge pull request rails#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
2 parents 2947e5b + 3bf867d commit f7bc844

File tree

2 files changed

+17
-3
lines changed

2 files changed

+17
-3
lines changed

activerecord/lib/active_record/insert_all.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@ def initialize(model, inserts, on_duplicate:, update_only: nil, returning: nil,
2323
@keys = @inserts.first.keys
2424
end
2525

26-
configure_on_duplicate_update_logic
27-
2826
if model.scope_attributes?
2927
@scope_attributes = model.scope_attributes
3028
@keys |= @scope_attributes.keys
@@ -35,8 +33,8 @@ def initialize(model, inserts, on_duplicate:, update_only: nil, returning: nil,
3533
@returning = false if @returning == []
3634

3735
@unique_by = find_unique_index_for(@unique_by)
38-
@on_duplicate = :skip if @on_duplicate == :update && updatable_columns.empty?
3936

37+
configure_on_duplicate_update_logic
4038
ensure_valid_options_for_connection!
4139
end
4240

@@ -135,6 +133,8 @@ def configure_on_duplicate_update_logic
135133
elsif custom_update_sql_provided?
136134
@update_sql = on_duplicate
137135
@on_duplicate = :update
136+
elsif @on_duplicate == :update && updatable_columns.empty?
137+
@on_duplicate = :skip
138138
end
139139
end
140140

activerecord/test/cases/insert_all_test.rb

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

742+
def test_upsert_all_updates_using_provided_sql_and_unique_by
743+
skip unless supports_insert_on_duplicate_update? && supports_insert_conflict_target?
744+
745+
book = books(:rfr)
746+
assert_equal "proposed", book.status
747+
748+
Book.upsert_all(
749+
[{ name: book.name, author_id: book.author_id }],
750+
unique_by: [:name, :author_id],
751+
on_duplicate: Arel.sql("status = 2")
752+
)
753+
assert_equal "published", book.reload.status
754+
end
755+
742756
def test_upsert_all_with_unique_by_fails_cleanly_for_adapters_not_supporting_insert_conflict_target
743757
skip if supports_insert_conflict_target?
744758

0 commit comments

Comments
 (0)