activerecord-import 1.1.0 → 1.4.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|