activerecord-import 1.1.0 → 1.4.1
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 +107 -0
- data/.rubocop.yml +74 -8
- data/Brewfile +3 -1
- data/CHANGELOG.md +38 -3
- data/Gemfile +5 -7
- data/README.markdown +13 -12
- data/Rakefile +2 -0
- data/activerecord-import.gemspec +4 -3
- data/benchmarks/benchmark.rb +7 -1
- data/benchmarks/lib/base.rb +2 -0
- data/benchmarks/lib/cli_parser.rb +3 -1
- 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/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 +2 -0
- data/gemfiles/6.1.gemfile +3 -0
- 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 +2 -0
- 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 +3 -1
- data/lib/activerecord-import/adapters/postgresql_adapter.rb +41 -30
- data/lib/activerecord-import/adapters/sqlite3_adapter.rb +8 -8
- data/lib/activerecord-import/base.rb +3 -1
- data/lib/activerecord-import/import.rb +62 -32
- 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 +2 -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 +45 -2
- data/test/jdbcmysql/import_test.rb +2 -0
- data/test/jdbcpostgresql/import_test.rb +2 -0
- data/test/jdbcsqlite3/import_test.rb +2 -0
- data/test/makara_postgis/import_test.rb +2 -0
- data/test/models/account.rb +2 -0
- data/test/models/alarm.rb +2 -0
- data/test/models/animal.rb +2 -0
- data/test/models/bike_maker.rb +2 -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 +2 -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 +2 -0
- data/test/mysql2_makara/import_test.rb +2 -0
- data/test/mysqlspatial2/import_test.rb +2 -0
- data/test/postgis/import_test.rb +2 -0
- data/test/postgresql/import_test.rb +2 -0
- data/test/schema/generic_schema.rb +33 -0
- data/test/schema/jdbcpostgresql_schema.rb +2 -0
- data/test/schema/mysql2_schema.rb +2 -0
- data/test/schema/postgis_schema.rb +2 -0
- data/test/schema/postgresql_schema.rb +2 -0
- data/test/schema/sqlite3_schema.rb +2 -0
- data/test/schema/version.rb +2 -0
- data/test/sqlite3/import_test.rb +2 -0
- 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 +65 -2
- data/test/support/shared_examples/on_duplicate_key_ignore.rb +2 -0
- data/test/support/shared_examples/on_duplicate_key_update.rb +2 -0
- data/test/support/shared_examples/recursive_import.rb +23 -1
- data/test/support/sqlite3/import_examples.rb +2 -1
- data/test/synchronize_test.rb +2 -0
- data/test/test_helper.rb +19 -2
- data/test/value_sets_bytes_parser_test.rb +2 -0
- data/test/value_sets_records_parser_test.rb +2 -0
- metadata +25 -15
- data/.travis.yml +0 -76
- data/gemfiles/3.2.gemfile +0 -2
- data/gemfiles/4.0.gemfile +0 -2
- data/gemfiles/4.1.gemfile +0 -2
data/test/models/account.rb
CHANGED
data/test/models/alarm.rb
CHANGED
data/test/models/animal.rb
CHANGED
data/test/models/bike_maker.rb
CHANGED
data/test/models/book.rb
CHANGED
data/test/models/car.rb
CHANGED
data/test/models/card.rb
ADDED
data/test/models/chapter.rb
CHANGED
data/test/models/deck.rb
ADDED
data/test/models/dictionary.rb
CHANGED
data/test/models/discount.rb
CHANGED
data/test/models/end_note.rb
CHANGED
data/test/models/group.rb
CHANGED
data/test/models/promotion.rb
CHANGED
data/test/models/question.rb
CHANGED
data/test/models/rule.rb
CHANGED
data/test/models/tag.rb
CHANGED
data/test/models/topic.rb
CHANGED
data/test/models/user.rb
CHANGED
data/test/models/user_token.rb
CHANGED
data/test/models/vendor.rb
CHANGED
data/test/models/widget.rb
CHANGED
data/test/mysql2/import_test.rb
CHANGED
data/test/postgis/import_test.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
ActiveRecord::Schema.define do
|
|
2
4
|
create_table :schema_info, force: :cascade do |t|
|
|
3
5
|
t.integer :version, unique: true
|
|
@@ -52,6 +54,20 @@ ActiveRecord::Schema.define do
|
|
|
52
54
|
t.string :name
|
|
53
55
|
end
|
|
54
56
|
|
|
57
|
+
create_table :cards, force: :cascade do |t|
|
|
58
|
+
t.string :name
|
|
59
|
+
t.string :deck_type
|
|
60
|
+
t.integer :deck_id
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
create_table :decks, force: :cascade do |t|
|
|
64
|
+
t.string :name
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
create_table :playing_cards, force: :cascade do |t|
|
|
68
|
+
t.string :name
|
|
69
|
+
end
|
|
70
|
+
|
|
55
71
|
create_table :books, force: :cascade do |t|
|
|
56
72
|
t.string :title, null: false
|
|
57
73
|
t.string :publisher, null: false, default: 'Default Publisher'
|
|
@@ -190,5 +206,22 @@ ActiveRecord::Schema.define do
|
|
|
190
206
|
PRIMARY KEY (tag_id, publisher_id)
|
|
191
207
|
);
|
|
192
208
|
).split.join(' ').strip
|
|
209
|
+
|
|
210
|
+
create_table :tag_aliases, force: :cascade do |t|
|
|
211
|
+
t.integer :tag_id, null: false
|
|
212
|
+
t.integer :parent_id, null: false
|
|
213
|
+
t.string :alias, null: false
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
create_table :customers, force: :cascade do |t|
|
|
218
|
+
t.integer :account_id
|
|
219
|
+
t.string :name
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
create_table :orders, force: :cascade do |t|
|
|
223
|
+
t.integer :account_id
|
|
224
|
+
t.integer :customer_id
|
|
225
|
+
t.integer :amount
|
|
193
226
|
end
|
|
194
227
|
end
|
data/test/schema/version.rb
CHANGED
data/test/sqlite3/import_test.rb
CHANGED
data/test/support/assertions.rb
CHANGED
data/test/support/factories.rb
CHANGED
data/test/support/generate.rb
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
class ActiveSupport::TestCase
|
|
2
|
-
def Build(*args) # rubocop:disable
|
|
4
|
+
def Build(*args) # rubocop:disable Naming/MethodName
|
|
3
5
|
n = args.shift if args.first.is_a?(Numeric)
|
|
4
6
|
factory = args.shift
|
|
5
7
|
factory_bot_args = args.shift || {}
|
|
@@ -13,7 +15,7 @@ class ActiveSupport::TestCase
|
|
|
13
15
|
end
|
|
14
16
|
end
|
|
15
17
|
|
|
16
|
-
def Generate(*args) # rubocop:disable
|
|
18
|
+
def Generate(*args) # rubocop:disable Naming/MethodName
|
|
17
19
|
n = args.shift if args.first.is_a?(Numeric)
|
|
18
20
|
factory = args.shift
|
|
19
21
|
factory_bot_args = args.shift || {}
|
|
@@ -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 }
|
|
@@ -150,6 +153,34 @@ def should_support_postgresql_import_functionality
|
|
|
150
153
|
end
|
|
151
154
|
end
|
|
152
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
|
+
|
|
153
184
|
context "setting model attributes" do
|
|
154
185
|
let(:code) { 'abc' }
|
|
155
186
|
let(:discount) { 0.10 }
|
|
@@ -179,6 +210,14 @@ def should_support_postgresql_import_functionality
|
|
|
179
210
|
assert_equal updated_promotion.discount, discount
|
|
180
211
|
end
|
|
181
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
|
|
182
221
|
end
|
|
183
222
|
end
|
|
184
223
|
end
|
|
@@ -281,7 +320,7 @@ def should_support_postgresql_import_functionality
|
|
|
281
320
|
end
|
|
282
321
|
|
|
283
322
|
describe "with binary field" do
|
|
284
|
-
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') }
|
|
285
324
|
it "imports the correct values for binary fields" do
|
|
286
325
|
alarms = [Alarm.new(device_id: 1, alarm_type: 1, status: 1, secret_key: binary_value)]
|
|
287
326
|
assert_difference "Alarm.count", +1 do
|
|
@@ -290,6 +329,30 @@ def should_support_postgresql_import_functionality
|
|
|
290
329
|
assert_equal(binary_value, Alarm.first.secret_key)
|
|
291
330
|
end
|
|
292
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
|
|
293
356
|
end
|
|
294
357
|
|
|
295
358
|
def should_support_postgresql_upsert_functionality
|
|
@@ -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) }
|
|
@@ -176,7 +178,7 @@ def should_support_recursive_import
|
|
|
176
178
|
end
|
|
177
179
|
end
|
|
178
180
|
|
|
179
|
-
# 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
|
|
180
182
|
# columns, keys, etc isn't generated for child associations when doing recursive import
|
|
181
183
|
if ActiveRecord::Base.connection.supports_on_duplicate_key_update?
|
|
182
184
|
describe "on_duplicate_key_update" do
|
|
@@ -190,6 +192,26 @@ def should_support_recursive_import
|
|
|
190
192
|
end
|
|
191
193
|
end
|
|
192
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
|
|
193
215
|
end
|
|
194
216
|
end
|
|
195
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__))
|
|
@@ -49,15 +52,29 @@ FileUtils.mkdir_p 'log'
|
|
|
49
52
|
ActiveRecord::Base.logger = Logger.new("log/test.log")
|
|
50
53
|
ActiveRecord::Base.logger.level = Logger::DEBUG
|
|
51
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
|
+
|
|
52
61
|
if ENV['AR_VERSION'].to_f >= 6.0
|
|
53
|
-
yaml_config =
|
|
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
|
|
54
67
|
config = ActiveRecord::DatabaseConfigurations::HashConfig.new("test", adapter, yaml_config)
|
|
55
68
|
ActiveRecord::Base.configurations.configurations << config
|
|
56
69
|
else
|
|
57
70
|
ActiveRecord::Base.configurations["test"] = YAML.load_file(test_dir.join("database.yml"))[adapter]
|
|
58
71
|
end
|
|
59
72
|
|
|
60
|
-
ActiveRecord
|
|
73
|
+
if ActiveRecord.respond_to?(:default_timezone)
|
|
74
|
+
ActiveRecord.default_timezone = :utc
|
|
75
|
+
else
|
|
76
|
+
ActiveRecord::Base.default_timezone = :utc
|
|
77
|
+
end
|
|
61
78
|
|
|
62
79
|
require "activerecord-import"
|
|
63
80
|
ActiveRecord::Base.establish_connection :test
|