activerecord-import 1.0.2 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/test.yaml +113 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +74 -8
- data/.rubocop_todo.yml +6 -16
- data/Brewfile +3 -1
- data/CHANGELOG.md +115 -3
- data/Gemfile +12 -10
- data/LICENSE +21 -56
- data/README.markdown +71 -60
- data/Rakefile +2 -0
- data/activerecord-import.gemspec +6 -5
- data/benchmarks/benchmark.rb +10 -4
- data/benchmarks/lib/base.rb +4 -2
- data/benchmarks/lib/cli_parser.rb +4 -2
- data/benchmarks/lib/float.rb +2 -0
- data/benchmarks/lib/mysql2_benchmark.rb +2 -0
- data/benchmarks/lib/output_to_csv.rb +2 -0
- data/benchmarks/lib/output_to_html.rb +4 -2
- data/benchmarks/models/test_innodb.rb +2 -0
- data/benchmarks/models/test_memory.rb +2 -0
- data/benchmarks/models/test_myisam.rb +2 -0
- data/benchmarks/schema/{mysql_schema.rb → mysql2_schema.rb} +2 -0
- data/gemfiles/4.2.gemfile +2 -0
- data/gemfiles/5.0.gemfile +2 -0
- data/gemfiles/5.1.gemfile +2 -0
- data/gemfiles/5.2.gemfile +2 -0
- data/gemfiles/6.0.gemfile +4 -1
- data/gemfiles/6.1.gemfile +4 -1
- data/gemfiles/7.0.gemfile +4 -0
- data/lib/activerecord-import/active_record/adapters/abstract_adapter.rb +2 -0
- data/lib/activerecord-import/active_record/adapters/jdbcmysql_adapter.rb +6 -4
- data/lib/activerecord-import/active_record/adapters/jdbcpostgresql_adapter.rb +2 -0
- data/lib/activerecord-import/active_record/adapters/jdbcsqlite3_adapter.rb +2 -0
- data/lib/activerecord-import/active_record/adapters/mysql2_adapter.rb +2 -0
- data/lib/activerecord-import/active_record/adapters/postgresql_adapter.rb +2 -0
- data/lib/activerecord-import/active_record/adapters/seamless_database_pool_adapter.rb +2 -0
- data/lib/activerecord-import/active_record/adapters/sqlite3_adapter.rb +2 -0
- data/lib/activerecord-import/adapters/abstract_adapter.rb +14 -5
- data/lib/activerecord-import/adapters/em_mysql2_adapter.rb +2 -0
- data/lib/activerecord-import/adapters/mysql2_adapter.rb +2 -0
- data/lib/activerecord-import/adapters/mysql_adapter.rb +33 -25
- data/lib/activerecord-import/adapters/postgresql_adapter.rb +69 -56
- data/lib/activerecord-import/adapters/sqlite3_adapter.rb +39 -39
- data/lib/activerecord-import/base.rb +10 -2
- data/lib/activerecord-import/import.rb +143 -62
- data/lib/activerecord-import/mysql2.rb +2 -0
- data/lib/activerecord-import/postgresql.rb +2 -0
- data/lib/activerecord-import/sqlite3.rb +2 -0
- data/lib/activerecord-import/synchronize.rb +3 -1
- data/lib/activerecord-import/value_sets_parser.rb +5 -0
- data/lib/activerecord-import/version.rb +3 -1
- data/lib/activerecord-import.rb +3 -1
- data/test/adapters/jdbcmysql.rb +2 -0
- data/test/adapters/jdbcpostgresql.rb +2 -0
- data/test/adapters/jdbcsqlite3.rb +2 -0
- data/test/adapters/makara_postgis.rb +2 -0
- data/test/adapters/mysql2.rb +2 -0
- data/test/adapters/mysql2_makara.rb +2 -0
- data/test/adapters/mysql2spatial.rb +2 -0
- data/test/adapters/postgis.rb +2 -0
- data/test/adapters/postgresql.rb +2 -0
- data/test/adapters/postgresql_makara.rb +2 -0
- data/test/adapters/seamless_database_pool.rb +2 -0
- data/test/adapters/spatialite.rb +2 -0
- data/test/adapters/sqlite3.rb +2 -0
- data/test/{travis → github}/database.yml +3 -1
- data/test/import_test.rb +93 -2
- data/test/jdbcmysql/import_test.rb +5 -3
- data/test/jdbcpostgresql/import_test.rb +4 -2
- data/test/jdbcsqlite3/import_test.rb +4 -2
- data/test/makara_postgis/import_test.rb +4 -2
- data/test/models/account.rb +2 -0
- data/test/models/alarm.rb +2 -0
- data/test/models/animal.rb +8 -0
- data/test/models/bike_maker.rb +3 -0
- data/test/models/book.rb +2 -0
- data/test/models/car.rb +2 -0
- data/test/models/card.rb +5 -0
- data/test/models/chapter.rb +2 -0
- data/test/models/customer.rb +8 -0
- data/test/models/deck.rb +8 -0
- data/test/models/dictionary.rb +2 -0
- data/test/models/discount.rb +2 -0
- data/test/models/end_note.rb +2 -0
- data/test/models/group.rb +2 -0
- data/test/models/order.rb +8 -0
- data/test/models/playing_card.rb +4 -0
- data/test/models/promotion.rb +2 -0
- data/test/models/question.rb +2 -0
- data/test/models/rule.rb +2 -0
- data/test/models/tag.rb +3 -0
- data/test/models/tag_alias.rb +5 -0
- data/test/models/topic.rb +7 -0
- data/test/models/user.rb +2 -0
- data/test/models/user_token.rb +2 -0
- data/test/models/vendor.rb +2 -0
- data/test/models/widget.rb +2 -0
- data/test/mysql2/import_test.rb +5 -3
- data/test/mysql2_makara/import_test.rb +5 -3
- data/test/mysqlspatial2/import_test.rb +5 -3
- data/test/postgis/import_test.rb +4 -2
- data/test/postgresql/import_test.rb +4 -2
- data/test/schema/generic_schema.rb +34 -0
- data/test/schema/jdbcpostgresql_schema.rb +3 -1
- data/test/schema/mysql2_schema.rb +2 -0
- data/test/schema/postgis_schema.rb +3 -1
- data/test/schema/postgresql_schema.rb +16 -0
- data/test/schema/sqlite3_schema.rb +2 -0
- data/test/schema/version.rb +2 -0
- data/test/sqlite3/import_test.rb +4 -2
- data/test/support/active_support/test_case_extensions.rb +2 -0
- data/test/support/assertions.rb +2 -0
- data/test/support/factories.rb +2 -0
- data/test/support/generate.rb +4 -2
- data/test/support/mysql/import_examples.rb +2 -1
- data/test/support/postgresql/import_examples.rb +96 -2
- data/test/support/shared_examples/on_duplicate_key_ignore.rb +2 -0
- data/test/support/shared_examples/on_duplicate_key_update.rb +50 -9
- data/test/support/shared_examples/recursive_import.rb +32 -1
- data/test/support/sqlite3/import_examples.rb +2 -1
- data/test/synchronize_test.rb +2 -0
- data/test/test_helper.rb +30 -5
- data/test/value_sets_bytes_parser_test.rb +3 -1
- data/test/value_sets_records_parser_test.rb +3 -1
- metadata +27 -16
- data/.travis.yml +0 -70
- data/gemfiles/3.2.gemfile +0 -2
- data/gemfiles/4.0.gemfile +0 -2
- data/gemfiles/4.1.gemfile +0 -2
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
#
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
def should_support_postgresql_import_functionality
|
|
3
4
|
should_support_recursive_import
|
|
4
5
|
|
|
@@ -102,6 +103,8 @@ def should_support_postgresql_import_functionality
|
|
|
102
103
|
books.first.id.to_s
|
|
103
104
|
end
|
|
104
105
|
end
|
|
106
|
+
let(:true_returning_value) { ENV['AR_VERSION'].to_f >= 5.0 ? true : 't' }
|
|
107
|
+
let(:false_returning_value) { ENV['AR_VERSION'].to_f >= 5.0 ? false : 'f' }
|
|
105
108
|
|
|
106
109
|
it "creates records" do
|
|
107
110
|
assert_difference("Book.count", +1) { result }
|
|
@@ -116,6 +119,26 @@ def should_support_postgresql_import_functionality
|
|
|
116
119
|
assert_equal [%w(King It)], result.results
|
|
117
120
|
end
|
|
118
121
|
|
|
122
|
+
context "when given an empty array" do
|
|
123
|
+
let(:result) { Book.import([], returning: %w(title)) }
|
|
124
|
+
|
|
125
|
+
setup { result }
|
|
126
|
+
|
|
127
|
+
it "returns empty arrays for ids and results" do
|
|
128
|
+
assert_equal [], result.ids
|
|
129
|
+
assert_equal [], result.results
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
context "when a returning column is a serialized attribute" do
|
|
134
|
+
let(:vendor) { Vendor.new(hours: { monday: '8-5' }) }
|
|
135
|
+
let(:result) { Vendor.import([vendor], returning: %w(hours)) }
|
|
136
|
+
|
|
137
|
+
it "creates records" do
|
|
138
|
+
assert_difference("Vendor.count", +1) { result }
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
119
142
|
context "when primary key and returning overlap" do
|
|
120
143
|
let(:result) { Book.import(books, returning: %w(id title)) }
|
|
121
144
|
|
|
@@ -130,6 +153,34 @@ def should_support_postgresql_import_functionality
|
|
|
130
153
|
end
|
|
131
154
|
end
|
|
132
155
|
|
|
156
|
+
context "when returning is raw sql" do
|
|
157
|
+
let(:result) { Book.import(books, returning: "title, (xmax = '0') AS inserted") }
|
|
158
|
+
|
|
159
|
+
setup { result }
|
|
160
|
+
|
|
161
|
+
it "returns ids" do
|
|
162
|
+
assert_equal [book_id], result.ids
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
it "returns specified columns" do
|
|
166
|
+
assert_equal [['It', true_returning_value]], result.results
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
context "when returning contains raw sql" do
|
|
171
|
+
let(:result) { Book.import(books, returning: [:title, "id, (xmax = '0') AS inserted"]) }
|
|
172
|
+
|
|
173
|
+
setup { result }
|
|
174
|
+
|
|
175
|
+
it "returns ids" do
|
|
176
|
+
assert_equal [book_id], result.ids
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
it "returns specified columns" do
|
|
180
|
+
assert_equal [['It', book_id, true_returning_value]], result.results
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
|
|
133
184
|
context "setting model attributes" do
|
|
134
185
|
let(:code) { 'abc' }
|
|
135
186
|
let(:discount) { 0.10 }
|
|
@@ -159,6 +210,14 @@ def should_support_postgresql_import_functionality
|
|
|
159
210
|
assert_equal updated_promotion.discount, discount
|
|
160
211
|
end
|
|
161
212
|
end
|
|
213
|
+
|
|
214
|
+
context 'returning raw sql' do
|
|
215
|
+
let(:returning_columns) { [:discount, "(xmax = '0') AS inserted"] }
|
|
216
|
+
|
|
217
|
+
it "sets custom model attributes" do
|
|
218
|
+
assert_equal updated_promotion.inserted, false_returning_value
|
|
219
|
+
end
|
|
220
|
+
end
|
|
162
221
|
end
|
|
163
222
|
end
|
|
164
223
|
end
|
|
@@ -249,8 +308,19 @@ def should_support_postgresql_import_functionality
|
|
|
249
308
|
end
|
|
250
309
|
end
|
|
251
310
|
|
|
311
|
+
describe "with enum field" do
|
|
312
|
+
let(:vendor_type) { "retailer" }
|
|
313
|
+
it "imports the correct values for enum fields" do
|
|
314
|
+
vendor = Vendor.new(name: 'Vendor 1', vendor_type: vendor_type)
|
|
315
|
+
assert_difference "Vendor.count", +1 do
|
|
316
|
+
Vendor.import [vendor]
|
|
317
|
+
end
|
|
318
|
+
assert_equal(vendor_type, Vendor.first.vendor_type)
|
|
319
|
+
end
|
|
320
|
+
end
|
|
321
|
+
|
|
252
322
|
describe "with binary field" do
|
|
253
|
-
let(:binary_value) { "\xE0'c\xB2\xB0\xB3Bh\\\xC2M\xB1m\\I\xC4r".force_encoding('ASCII-8BIT') }
|
|
323
|
+
let(:binary_value) { "\xE0'c\xB2\xB0\xB3Bh\\\xC2M\xB1m\\I\xC4r".dup.force_encoding('ASCII-8BIT') }
|
|
254
324
|
it "imports the correct values for binary fields" do
|
|
255
325
|
alarms = [Alarm.new(device_id: 1, alarm_type: 1, status: 1, secret_key: binary_value)]
|
|
256
326
|
assert_difference "Alarm.count", +1 do
|
|
@@ -259,6 +329,30 @@ def should_support_postgresql_import_functionality
|
|
|
259
329
|
assert_equal(binary_value, Alarm.first.secret_key)
|
|
260
330
|
end
|
|
261
331
|
end
|
|
332
|
+
|
|
333
|
+
unless ENV["SKIP_COMPOSITE_PK"]
|
|
334
|
+
describe "with composite foreign keys" do
|
|
335
|
+
let(:account_id) { 555 }
|
|
336
|
+
let(:customer) { Customer.new(account_id: account_id, name: "foo") }
|
|
337
|
+
let(:order) { Order.new(account_id: account_id, amount: 100, customer: customer) }
|
|
338
|
+
|
|
339
|
+
it "imports and correctly maps foreign keys" do
|
|
340
|
+
assert_difference "Customer.count", +1 do
|
|
341
|
+
Customer.import [customer]
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
assert_difference "Order.count", +1 do
|
|
345
|
+
Order.import [order]
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
db_customer = Customer.last
|
|
349
|
+
db_order = Order.last
|
|
350
|
+
|
|
351
|
+
assert_equal db_customer.orders.last, db_order
|
|
352
|
+
assert_not_equal db_order.customer_id, nil
|
|
353
|
+
end
|
|
354
|
+
end
|
|
355
|
+
end
|
|
262
356
|
end
|
|
263
357
|
|
|
264
358
|
def should_support_postgresql_upsert_functionality
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
def should_support_basic_on_duplicate_key_update
|
|
2
4
|
describe "#import" do
|
|
3
5
|
extend ActiveSupport::TestCase::ImportAssertions
|
|
@@ -24,7 +26,7 @@ def should_support_basic_on_duplicate_key_update
|
|
|
24
26
|
User.import(updated_users, on_duplicate_key_update: [:name])
|
|
25
27
|
assert User.count == updated_users.length
|
|
26
28
|
User.all.each_with_index do |user, i|
|
|
27
|
-
assert_equal user.name, users[i].name
|
|
29
|
+
assert_equal user.name, "#{users[i].name} Rothschild"
|
|
28
30
|
assert_equal 1, user.lock_version
|
|
29
31
|
end
|
|
30
32
|
end
|
|
@@ -48,7 +50,7 @@ def should_support_basic_on_duplicate_key_update
|
|
|
48
50
|
User.import(columns, updated_values, on_duplicate_key_update: [:name])
|
|
49
51
|
assert User.count == updated_values.length
|
|
50
52
|
User.all.each_with_index do |user, i|
|
|
51
|
-
assert_equal user.name, users[i].name
|
|
53
|
+
assert_equal user.name, "#{users[i].name} Rothschild"
|
|
52
54
|
assert_equal 1, user.lock_version
|
|
53
55
|
end
|
|
54
56
|
end
|
|
@@ -70,9 +72,19 @@ def should_support_basic_on_duplicate_key_update
|
|
|
70
72
|
User.import(updated_values, on_duplicate_key_update: [:name])
|
|
71
73
|
assert User.count == updated_values.length
|
|
72
74
|
User.all.each_with_index do |user, i|
|
|
73
|
-
assert_equal user.name, users[i].name
|
|
75
|
+
assert_equal user.name, "#{users[i].name} Rothschild"
|
|
74
76
|
assert_equal 1, user.lock_version
|
|
75
77
|
end
|
|
78
|
+
updated_values2 = User.all.map do |user|
|
|
79
|
+
user.name += ' jr.'
|
|
80
|
+
{ id: user.id, name: user.name }
|
|
81
|
+
end
|
|
82
|
+
User.import(updated_values2, on_duplicate_key_update: [:name])
|
|
83
|
+
assert User.count == updated_values2.length
|
|
84
|
+
User.all.each_with_index do |user, i|
|
|
85
|
+
assert_equal user.name, "#{users[i].name} Rothschild jr."
|
|
86
|
+
assert_equal 2, user.lock_version
|
|
87
|
+
end
|
|
76
88
|
end
|
|
77
89
|
|
|
78
90
|
it 'upsert optimistic lock columns other than lock_version by model' do
|
|
@@ -92,7 +104,7 @@ def should_support_basic_on_duplicate_key_update
|
|
|
92
104
|
Account.import(updated_accounts, on_duplicate_key_update: [:id, :name])
|
|
93
105
|
assert Account.count == updated_accounts.length
|
|
94
106
|
Account.all.each_with_index do |user, i|
|
|
95
|
-
assert_equal user.name, accounts[i].name
|
|
107
|
+
assert_equal user.name, "#{accounts[i].name} Rothschild"
|
|
96
108
|
assert_equal 1, user.lock
|
|
97
109
|
end
|
|
98
110
|
end
|
|
@@ -116,7 +128,7 @@ def should_support_basic_on_duplicate_key_update
|
|
|
116
128
|
Account.import(columns, updated_values, on_duplicate_key_update: [:name])
|
|
117
129
|
assert Account.count == updated_values.length
|
|
118
130
|
Account.all.each_with_index do |user, i|
|
|
119
|
-
assert_equal user.name, accounts[i].name
|
|
131
|
+
assert_equal user.name, "#{accounts[i].name} Rothschild"
|
|
120
132
|
assert_equal 1, user.lock
|
|
121
133
|
end
|
|
122
134
|
end
|
|
@@ -138,7 +150,7 @@ def should_support_basic_on_duplicate_key_update
|
|
|
138
150
|
Account.import(updated_values, on_duplicate_key_update: [:name])
|
|
139
151
|
assert Account.count == updated_values.length
|
|
140
152
|
Account.all.each_with_index do |user, i|
|
|
141
|
-
assert_equal user.name, accounts[i].name
|
|
153
|
+
assert_equal user.name, "#{accounts[i].name} Rothschild"
|
|
142
154
|
assert_equal 1, user.lock
|
|
143
155
|
end
|
|
144
156
|
end
|
|
@@ -160,10 +172,11 @@ def should_support_basic_on_duplicate_key_update
|
|
|
160
172
|
Bike::Maker.import(updated_makers, on_duplicate_key_update: [:name])
|
|
161
173
|
assert Bike::Maker.count == updated_makers.length
|
|
162
174
|
Bike::Maker.all.each_with_index do |maker, i|
|
|
163
|
-
assert_equal maker.name, makers[i].name
|
|
175
|
+
assert_equal maker.name, "#{makers[i].name} bikes"
|
|
164
176
|
assert_equal 1, maker.lock_version
|
|
165
177
|
end
|
|
166
178
|
end
|
|
179
|
+
|
|
167
180
|
it 'update the lock_version of models separated by namespaces by array' do
|
|
168
181
|
makers = [
|
|
169
182
|
Bike::Maker.new(name: 'Yamaha'),
|
|
@@ -183,7 +196,7 @@ def should_support_basic_on_duplicate_key_update
|
|
|
183
196
|
Bike::Maker.import(columns, updated_values, on_duplicate_key_update: [:name])
|
|
184
197
|
assert Bike::Maker.count == updated_values.length
|
|
185
198
|
Bike::Maker.all.each_with_index do |maker, i|
|
|
186
|
-
assert_equal maker.name, makers[i].name
|
|
199
|
+
assert_equal maker.name, "#{makers[i].name} bikes"
|
|
187
200
|
assert_equal 1, maker.lock_version
|
|
188
201
|
end
|
|
189
202
|
end
|
|
@@ -205,7 +218,7 @@ def should_support_basic_on_duplicate_key_update
|
|
|
205
218
|
Bike::Maker.import(updated_values, on_duplicate_key_update: [:name])
|
|
206
219
|
assert Bike::Maker.count == updated_values.length
|
|
207
220
|
Bike::Maker.all.each_with_index do |maker, i|
|
|
208
|
-
assert_equal maker.name, makers[i].name
|
|
221
|
+
assert_equal maker.name, "#{makers[i].name} bikes"
|
|
209
222
|
assert_equal 1, maker.lock_version
|
|
210
223
|
end
|
|
211
224
|
end
|
|
@@ -304,6 +317,34 @@ def should_support_basic_on_duplicate_key_update
|
|
|
304
317
|
should_support_on_duplicate_key_update
|
|
305
318
|
should_update_fields_mentioned
|
|
306
319
|
end
|
|
320
|
+
|
|
321
|
+
context "using column aliases" do
|
|
322
|
+
let(:columns) { %w( id title author_name author_email_address parent_id ) }
|
|
323
|
+
let(:update_columns) { %w(title author_email_address parent_id) }
|
|
324
|
+
|
|
325
|
+
context "with column aliases in column list" do
|
|
326
|
+
let(:columns) { %w( id name author_name author_email_address parent_id ) }
|
|
327
|
+
should_support_on_duplicate_key_update
|
|
328
|
+
should_update_fields_mentioned
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
context "with column aliases in update columns list" do
|
|
332
|
+
let(:update_columns) { %w(name author_email_address parent_id) }
|
|
333
|
+
should_support_on_duplicate_key_update
|
|
334
|
+
should_update_fields_mentioned
|
|
335
|
+
end
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
if ENV['AR_VERSION'].to_i >= 6.0
|
|
339
|
+
context "using ignored columns" do
|
|
340
|
+
let(:columns) { %w( id title author_name author_email_address parent_id priority ) }
|
|
341
|
+
let(:values) { [[99, "Book", "John Doe", "john@doe.com", 17, 1]] }
|
|
342
|
+
let(:update_columns) { %w(name author_email_address parent_id priority) }
|
|
343
|
+
let(:updated_values) { [[99, "Book - 2nd Edition", "Author Should Not Change", "johndoe@example.com", 57, 2]] }
|
|
344
|
+
should_support_on_duplicate_key_update
|
|
345
|
+
should_update_fields_mentioned
|
|
346
|
+
end
|
|
347
|
+
end
|
|
307
348
|
end
|
|
308
349
|
|
|
309
350
|
context "with a table that has a non-standard primary key" do
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
def should_support_recursive_import
|
|
2
4
|
describe "importing objects with associations" do
|
|
3
5
|
let(:new_topics) { Build(num_topics, :topic_with_book) }
|
|
@@ -138,6 +140,15 @@ def should_support_recursive_import
|
|
|
138
140
|
books.each do |book|
|
|
139
141
|
assert_equal book.topic_id, second_new_topic.id
|
|
140
142
|
end
|
|
143
|
+
|
|
144
|
+
books.each { |book| book.topic_id = nil }
|
|
145
|
+
assert_no_difference "Book.count", books.size do
|
|
146
|
+
Book.import books, validate: false, on_duplicate_key_update: [:topic_id]
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
books.each do |book|
|
|
150
|
+
assert_equal book.topic_id, nil
|
|
151
|
+
end
|
|
141
152
|
end
|
|
142
153
|
|
|
143
154
|
unless ENV["SKIP_COMPOSITE_PK"]
|
|
@@ -167,7 +178,7 @@ def should_support_recursive_import
|
|
|
167
178
|
end
|
|
168
179
|
end
|
|
169
180
|
|
|
170
|
-
# If adapter supports on_duplicate_key_update, it is only applied to top level models so that SQL with invalid
|
|
181
|
+
# If adapter supports on_duplicate_key_update and specific columns are specified, it is only applied to top level models so that SQL with invalid
|
|
171
182
|
# columns, keys, etc isn't generated for child associations when doing recursive import
|
|
172
183
|
if ActiveRecord::Base.connection.supports_on_duplicate_key_update?
|
|
173
184
|
describe "on_duplicate_key_update" do
|
|
@@ -181,6 +192,26 @@ def should_support_recursive_import
|
|
|
181
192
|
end
|
|
182
193
|
end
|
|
183
194
|
end
|
|
195
|
+
|
|
196
|
+
context "when :all fields are updated" do
|
|
197
|
+
setup do
|
|
198
|
+
Topic.import new_topics, recursive: true
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
it "updates associated objects" do
|
|
202
|
+
new_author_name = 'Richard Bachman'
|
|
203
|
+
topic = new_topics.first
|
|
204
|
+
topic.books.each do |book|
|
|
205
|
+
book.author_name = new_author_name
|
|
206
|
+
end
|
|
207
|
+
assert_nothing_raised do
|
|
208
|
+
Topic.import new_topics, recursive: true, on_duplicate_key_update: :all
|
|
209
|
+
end
|
|
210
|
+
Topic.find(topic.id).books.each do |book|
|
|
211
|
+
assert_equal new_author_name, book.author_name
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
end
|
|
184
215
|
end
|
|
185
216
|
end
|
|
186
217
|
|
data/test/synchronize_test.rb
CHANGED
data/test/test_helper.rb
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'pathname'
|
|
4
|
+
require 'rake'
|
|
2
5
|
test_dir = Pathname.new File.dirname(__FILE__)
|
|
3
6
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
|
4
7
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
|
@@ -21,7 +24,7 @@ if ActiveSupport::VERSION::STRING < "4.0"
|
|
|
21
24
|
require 'mocha/test_unit'
|
|
22
25
|
else
|
|
23
26
|
require 'active_support/testing/autorun'
|
|
24
|
-
require "mocha/
|
|
27
|
+
require "mocha/minitest"
|
|
25
28
|
end
|
|
26
29
|
|
|
27
30
|
require 'timecop'
|
|
@@ -48,8 +51,30 @@ adapter = ENV["ARE_DB"] || "sqlite3"
|
|
|
48
51
|
FileUtils.mkdir_p 'log'
|
|
49
52
|
ActiveRecord::Base.logger = Logger.new("log/test.log")
|
|
50
53
|
ActiveRecord::Base.logger.level = Logger::DEBUG
|
|
51
|
-
|
|
52
|
-
ActiveRecord
|
|
54
|
+
|
|
55
|
+
if ActiveRecord.respond_to?(:use_yaml_unsafe_load)
|
|
56
|
+
ActiveRecord.use_yaml_unsafe_load = true
|
|
57
|
+
elsif ActiveRecord::Base.respond_to?(:use_yaml_unsafe_load)
|
|
58
|
+
ActiveRecord::Base.use_yaml_unsafe_load = true
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
if ENV['AR_VERSION'].to_f >= 6.0
|
|
62
|
+
yaml_config = if Gem::Version.new(Psych::VERSION) >= Gem::Version.new('3.2.1')
|
|
63
|
+
YAML.safe_load_file(test_dir.join("database.yml"), aliases: true)[adapter]
|
|
64
|
+
else
|
|
65
|
+
YAML.load_file(test_dir.join("database.yml"))[adapter]
|
|
66
|
+
end
|
|
67
|
+
config = ActiveRecord::DatabaseConfigurations::HashConfig.new("test", adapter, yaml_config)
|
|
68
|
+
ActiveRecord::Base.configurations.configurations << config
|
|
69
|
+
else
|
|
70
|
+
ActiveRecord::Base.configurations["test"] = YAML.load_file(test_dir.join("database.yml"))[adapter]
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
if ActiveRecord.respond_to?(:default_timezone)
|
|
74
|
+
ActiveRecord.default_timezone = :utc
|
|
75
|
+
else
|
|
76
|
+
ActiveRecord::Base.default_timezone = :utc
|
|
77
|
+
end
|
|
53
78
|
|
|
54
79
|
require "activerecord-import"
|
|
55
80
|
ActiveRecord::Base.establish_connection :test
|
|
@@ -59,7 +84,7 @@ ActiveSupport::Notifications.subscribe(/active_record.sql/) do |_, _, _, _, hsh|
|
|
|
59
84
|
end
|
|
60
85
|
|
|
61
86
|
require "factory_bot"
|
|
62
|
-
Dir[File.dirname(__FILE__)
|
|
87
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].sort.each { |file| require file }
|
|
63
88
|
|
|
64
89
|
# Load base/generic schema
|
|
65
90
|
require test_dir.join("schema/version")
|
|
@@ -67,7 +92,7 @@ require test_dir.join("schema/generic_schema")
|
|
|
67
92
|
adapter_schema = test_dir.join("schema/#{adapter}_schema.rb")
|
|
68
93
|
require adapter_schema if File.exist?(adapter_schema)
|
|
69
94
|
|
|
70
|
-
Dir[File.dirname(__FILE__)
|
|
95
|
+
Dir["#{File.dirname(__FILE__)}/models/*.rb"].sort.each { |file| require file }
|
|
71
96
|
|
|
72
97
|
# Prevent this deprecation warning from breaking the tests.
|
|
73
98
|
Rake::FileList.send(:remove_method, :import)
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: activerecord-import
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0
|
|
4
|
+
version: 1.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Zach Dennis
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2023-08-21 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activerecord
|
|
@@ -16,14 +16,14 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - ">="
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '
|
|
19
|
+
version: '4.2'
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - ">="
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '
|
|
26
|
+
version: '4.2'
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: rake
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -45,10 +45,10 @@ executables: []
|
|
|
45
45
|
extensions: []
|
|
46
46
|
extra_rdoc_files: []
|
|
47
47
|
files:
|
|
48
|
+
- ".github/workflows/test.yaml"
|
|
48
49
|
- ".gitignore"
|
|
49
50
|
- ".rubocop.yml"
|
|
50
51
|
- ".rubocop_todo.yml"
|
|
51
|
-
- ".travis.yml"
|
|
52
52
|
- Brewfile
|
|
53
53
|
- CHANGELOG.md
|
|
54
54
|
- Gemfile
|
|
@@ -67,16 +67,14 @@ files:
|
|
|
67
67
|
- benchmarks/models/test_innodb.rb
|
|
68
68
|
- benchmarks/models/test_memory.rb
|
|
69
69
|
- benchmarks/models/test_myisam.rb
|
|
70
|
-
- benchmarks/schema/
|
|
71
|
-
- gemfiles/3.2.gemfile
|
|
72
|
-
- gemfiles/4.0.gemfile
|
|
73
|
-
- gemfiles/4.1.gemfile
|
|
70
|
+
- benchmarks/schema/mysql2_schema.rb
|
|
74
71
|
- gemfiles/4.2.gemfile
|
|
75
72
|
- gemfiles/5.0.gemfile
|
|
76
73
|
- gemfiles/5.1.gemfile
|
|
77
74
|
- gemfiles/5.2.gemfile
|
|
78
75
|
- gemfiles/6.0.gemfile
|
|
79
76
|
- gemfiles/6.1.gemfile
|
|
77
|
+
- gemfiles/7.0.gemfile
|
|
80
78
|
- lib/activerecord-import.rb
|
|
81
79
|
- lib/activerecord-import/active_record/adapters/abstract_adapter.rb
|
|
82
80
|
- lib/activerecord-import/active_record/adapters/jdbcmysql_adapter.rb
|
|
@@ -114,6 +112,7 @@ files:
|
|
|
114
112
|
- test/adapters/spatialite.rb
|
|
115
113
|
- test/adapters/sqlite3.rb
|
|
116
114
|
- test/database.yml.sample
|
|
115
|
+
- test/github/database.yml
|
|
117
116
|
- test/import_test.rb
|
|
118
117
|
- test/jdbcmysql/import_test.rb
|
|
119
118
|
- test/jdbcpostgresql/import_test.rb
|
|
@@ -121,18 +120,25 @@ files:
|
|
|
121
120
|
- test/makara_postgis/import_test.rb
|
|
122
121
|
- test/models/account.rb
|
|
123
122
|
- test/models/alarm.rb
|
|
123
|
+
- test/models/animal.rb
|
|
124
124
|
- test/models/bike_maker.rb
|
|
125
125
|
- test/models/book.rb
|
|
126
126
|
- test/models/car.rb
|
|
127
|
+
- test/models/card.rb
|
|
127
128
|
- test/models/chapter.rb
|
|
129
|
+
- test/models/customer.rb
|
|
130
|
+
- test/models/deck.rb
|
|
128
131
|
- test/models/dictionary.rb
|
|
129
132
|
- test/models/discount.rb
|
|
130
133
|
- test/models/end_note.rb
|
|
131
134
|
- test/models/group.rb
|
|
135
|
+
- test/models/order.rb
|
|
136
|
+
- test/models/playing_card.rb
|
|
132
137
|
- test/models/promotion.rb
|
|
133
138
|
- test/models/question.rb
|
|
134
139
|
- test/models/rule.rb
|
|
135
140
|
- test/models/tag.rb
|
|
141
|
+
- test/models/tag_alias.rb
|
|
136
142
|
- test/models/topic.rb
|
|
137
143
|
- test/models/user.rb
|
|
138
144
|
- test/models/user_token.rb
|
|
@@ -163,12 +169,11 @@ files:
|
|
|
163
169
|
- test/support/sqlite3/import_examples.rb
|
|
164
170
|
- test/synchronize_test.rb
|
|
165
171
|
- test/test_helper.rb
|
|
166
|
-
- test/travis/database.yml
|
|
167
172
|
- test/value_sets_bytes_parser_test.rb
|
|
168
173
|
- test/value_sets_records_parser_test.rb
|
|
169
|
-
homepage:
|
|
174
|
+
homepage: https://github.com/zdennis/activerecord-import
|
|
170
175
|
licenses:
|
|
171
|
-
-
|
|
176
|
+
- MIT
|
|
172
177
|
metadata: {}
|
|
173
178
|
post_install_message:
|
|
174
179
|
rdoc_options: []
|
|
@@ -178,15 +183,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
178
183
|
requirements:
|
|
179
184
|
- - ">="
|
|
180
185
|
- !ruby/object:Gem::Version
|
|
181
|
-
version:
|
|
186
|
+
version: 2.4.0
|
|
182
187
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
183
188
|
requirements:
|
|
184
189
|
- - ">="
|
|
185
190
|
- !ruby/object:Gem::Version
|
|
186
191
|
version: '0'
|
|
187
192
|
requirements: []
|
|
188
|
-
|
|
189
|
-
rubygems_version: 2.7.8
|
|
193
|
+
rubygems_version: 3.0.3.1
|
|
190
194
|
signing_key:
|
|
191
195
|
specification_version: 4
|
|
192
196
|
summary: Bulk insert extension for ActiveRecord
|
|
@@ -205,6 +209,7 @@ test_files:
|
|
|
205
209
|
- test/adapters/spatialite.rb
|
|
206
210
|
- test/adapters/sqlite3.rb
|
|
207
211
|
- test/database.yml.sample
|
|
212
|
+
- test/github/database.yml
|
|
208
213
|
- test/import_test.rb
|
|
209
214
|
- test/jdbcmysql/import_test.rb
|
|
210
215
|
- test/jdbcpostgresql/import_test.rb
|
|
@@ -212,18 +217,25 @@ test_files:
|
|
|
212
217
|
- test/makara_postgis/import_test.rb
|
|
213
218
|
- test/models/account.rb
|
|
214
219
|
- test/models/alarm.rb
|
|
220
|
+
- test/models/animal.rb
|
|
215
221
|
- test/models/bike_maker.rb
|
|
216
222
|
- test/models/book.rb
|
|
217
223
|
- test/models/car.rb
|
|
224
|
+
- test/models/card.rb
|
|
218
225
|
- test/models/chapter.rb
|
|
226
|
+
- test/models/customer.rb
|
|
227
|
+
- test/models/deck.rb
|
|
219
228
|
- test/models/dictionary.rb
|
|
220
229
|
- test/models/discount.rb
|
|
221
230
|
- test/models/end_note.rb
|
|
222
231
|
- test/models/group.rb
|
|
232
|
+
- test/models/order.rb
|
|
233
|
+
- test/models/playing_card.rb
|
|
223
234
|
- test/models/promotion.rb
|
|
224
235
|
- test/models/question.rb
|
|
225
236
|
- test/models/rule.rb
|
|
226
237
|
- test/models/tag.rb
|
|
238
|
+
- test/models/tag_alias.rb
|
|
227
239
|
- test/models/topic.rb
|
|
228
240
|
- test/models/user.rb
|
|
229
241
|
- test/models/user_token.rb
|
|
@@ -254,6 +266,5 @@ test_files:
|
|
|
254
266
|
- test/support/sqlite3/import_examples.rb
|
|
255
267
|
- test/synchronize_test.rb
|
|
256
268
|
- test/test_helper.rb
|
|
257
|
-
- test/travis/database.yml
|
|
258
269
|
- test/value_sets_bytes_parser_test.rb
|
|
259
270
|
- test/value_sets_records_parser_test.rb
|
data/.travis.yml
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
language: ruby
|
|
2
|
-
cache: bundler
|
|
3
|
-
rvm:
|
|
4
|
-
- 2.5.5
|
|
5
|
-
|
|
6
|
-
env:
|
|
7
|
-
global:
|
|
8
|
-
# https://github.com/discourse/discourse/blob/master/.travis.yml
|
|
9
|
-
- RUBY_GC_MALLOC_LIMIT=50000000
|
|
10
|
-
matrix:
|
|
11
|
-
- AR_VERSION=5.1
|
|
12
|
-
- AR_VERSION=5.2
|
|
13
|
-
- AR_VERSION=6.0
|
|
14
|
-
|
|
15
|
-
matrix:
|
|
16
|
-
include:
|
|
17
|
-
- rvm: 2.3.8
|
|
18
|
-
env: AR_VERSION=3.2
|
|
19
|
-
- rvm: 2.3.8
|
|
20
|
-
env: AR_VERSION=4.0
|
|
21
|
-
- rvm: 2.3.8
|
|
22
|
-
env: AR_VERSION=4.1
|
|
23
|
-
- rvm: 2.3.8
|
|
24
|
-
env: AR_VERSION=4.2
|
|
25
|
-
- rvm: 2.3.8
|
|
26
|
-
env: AR_VERSION=5.0
|
|
27
|
-
|
|
28
|
-
fast_finish: true
|
|
29
|
-
|
|
30
|
-
addons:
|
|
31
|
-
postgresql: "9.5"
|
|
32
|
-
apt:
|
|
33
|
-
sources:
|
|
34
|
-
- travis-ci/sqlite3
|
|
35
|
-
- mysql-5.7-trusty
|
|
36
|
-
packages:
|
|
37
|
-
- sqlite3
|
|
38
|
-
- mysql-server
|
|
39
|
-
- mysql-client
|
|
40
|
-
- postgresql-9.5-postgis-2.3
|
|
41
|
-
|
|
42
|
-
before_install:
|
|
43
|
-
- gem update --system
|
|
44
|
-
- sudo mysql -e "use mysql; update user set authentication_string=PASSWORD('') where User='root'; update user set plugin='mysql_native_password';FLUSH PRIVILEGES;"
|
|
45
|
-
- sudo mysql_upgrade
|
|
46
|
-
- sudo service mysql restart
|
|
47
|
-
|
|
48
|
-
before_script:
|
|
49
|
-
- mysql -e 'create database activerecord_import_test;'
|
|
50
|
-
- psql -c 'create database activerecord_import_test;' -U postgres
|
|
51
|
-
- psql activerecord_import_test -c 'create extension if not exists hstore;' -U postgres
|
|
52
|
-
- psql -c 'create extension if not exists postgis;' -U postgres
|
|
53
|
-
- psql -c 'create extension if not exists "uuid-ossp";' -U postgres
|
|
54
|
-
- cp test/travis/database.yml test/database.yml
|
|
55
|
-
|
|
56
|
-
script:
|
|
57
|
-
- bundle exec rake test:mysql2
|
|
58
|
-
- bundle exec rake test:mysql2_makara
|
|
59
|
-
- bundle exec rake test:mysql2spatial
|
|
60
|
-
- bundle exec rake test:postgis
|
|
61
|
-
- bundle exec rake test:postgresql
|
|
62
|
-
- bundle exec rake test:postgresql_makara
|
|
63
|
-
- bundle exec rake test:seamless_database_pool
|
|
64
|
-
- bundle exec rake test:spatialite
|
|
65
|
-
- bundle exec rake test:sqlite3
|
|
66
|
-
- bundle exec rubocop
|
|
67
|
-
|
|
68
|
-
dist: trusty
|
|
69
|
-
|
|
70
|
-
sudo: required
|
data/gemfiles/3.2.gemfile
DELETED