aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/test
diff options
context:
space:
mode:
authorBob Lail <bob.lailfamily@gmail.com>2019-04-04 07:35:04 -0500
committerBob Lail <bob.lailfamily@gmail.com>2019-04-08 08:01:40 -0500
commitc24efdbd2720bd4d936a3ffab0c22af0a718d2f1 (patch)
treee3f234d04ca0c06847c236b5c959aeb8af1e1953 /activerecord/test
parentbf1494a1018a0bdc50dac4e87fdbf4b6b03083fa (diff)
downloadrails-c24efdbd2720bd4d936a3ffab0c22af0a718d2f1.tar.gz
rails-c24efdbd2720bd4d936a3ffab0c22af0a718d2f1.tar.bz2
rails-c24efdbd2720bd4d936a3ffab0c22af0a718d2f1.zip
When skipping duplicates in bulk insert on MySQL, avoid assigning id when not specified
If `id` is an `AUTONUMBER` column, then my former strategy here of assigning `no_op_column` to an arbitrary column would fail in this specific scenario: 1. `model.columns.first` is an AUTONUMBER column 2. `model.columns.first` is not assigned in the insert attributes I added three tests: the first test covers the actual error; the second test documents that this _isn't_ a problem when a value is given for the AUTONUMBER column and the third test ensures that this no-op strategy isn't secretly doing an UPSERT.
Diffstat (limited to 'activerecord/test')
-rw-r--r--activerecord/test/cases/insert_all_test.rb38
1 files changed, 38 insertions, 0 deletions
diff --git a/activerecord/test/cases/insert_all_test.rb b/activerecord/test/cases/insert_all_test.rb
index fc25701c80..61fbda1f0f 100644
--- a/activerecord/test/cases/insert_all_test.rb
+++ b/activerecord/test/cases/insert_all_test.rb
@@ -104,6 +104,44 @@ class InsertAllTest < ActiveRecord::TestCase
end
end
+ def test_insert_all_with_skip_duplicates_and_autonumber_id_not_given
+ skip unless supports_insert_on_duplicate_skip?
+
+ assert_difference "Book.count", 1 do
+ # These two books are duplicates according to an index on %i[author_id name]
+ # but their IDs are not specified so they will be assigned different IDs
+ # by autonumber. We will get an exception from MySQL if we attempt to skip
+ # one of these records by assigning its ID.
+ Book.insert_all [
+ { author_id: 8, name: "Refactoring" },
+ { author_id: 8, name: "Refactoring" }
+ ]
+ end
+ end
+
+ def test_insert_all_with_skip_duplicates_and_autonumber_id_given
+ skip unless supports_insert_on_duplicate_skip?
+
+ assert_difference "Book.count", 1 do
+ Book.insert_all [
+ { id: 200, author_id: 8, name: "Refactoring" },
+ { id: 201, author_id: 8, name: "Refactoring" }
+ ]
+ end
+ end
+
+ def test_skip_duplicates_strategy_does_not_secretly_upsert
+ skip unless supports_insert_on_duplicate_skip?
+
+ book = Book.create!(author_id: 8, name: "Refactoring", format: "EXPECTED")
+
+ assert_no_difference "Book.count" do
+ Book.insert(author_id: 8, name: "Refactoring", format: "UNEXPECTED")
+ end
+
+ assert_equal "EXPECTED", book.reload.format
+ end
+
def test_insert_all_will_raise_if_duplicates_are_skipped_only_for_a_certain_conflict_target
skip unless supports_insert_on_duplicate_skip? && supports_insert_conflict_target?