activerecord-import 1.0.2 → 1.7.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 +151 -0
- data/.gitignore +5 -0
- data/.rubocop.yml +74 -8
- data/.rubocop_todo.yml +10 -16
- data/Brewfile +3 -1
- data/CHANGELOG.md +138 -3
- data/Dockerfile +23 -0
- data/Gemfile +24 -14
- data/LICENSE +21 -56
- data/README.markdown +108 -60
- data/Rakefile +3 -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/docker-compose.yml +34 -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/gemfiles/7.1.gemfile +3 -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/active_record/adapters/trilogy_adapter.rb +8 -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/adapters/trilogy_adapter.rb +7 -0
- data/lib/activerecord-import/base.rb +10 -2
- data/lib/activerecord-import/import.rb +162 -65
- 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 +2 -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/adapters/trilogy.rb +9 -0
- data/test/database.yml.sample +7 -0
- data/test/{travis → github}/database.yml +7 -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/author.rb +7 -0
- data/test/models/bike_maker.rb +3 -0
- data/test/models/book.rb +7 -2
- data/test/models/car.rb +2 -0
- data/test/models/card.rb +5 -0
- data/test/models/chapter.rb +2 -0
- data/test/models/composite_book.rb +19 -0
- data/test/models/composite_chapter.rb +9 -0
- data/test/models/customer.rb +18 -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 +17 -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 +9 -1
- data/test/models/tag_alias.rb +11 -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 +37 -1
- 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 +47 -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 +108 -2
- data/test/support/shared_examples/on_duplicate_key_ignore.rb +2 -0
- data/test/support/shared_examples/on_duplicate_key_update.rb +78 -9
- data/test/support/shared_examples/recursive_import.rb +98 -1
- data/test/support/sqlite3/import_examples.rb +2 -1
- data/test/synchronize_test.rb +2 -0
- data/test/test_helper.rb +33 -6
- data/test/trilogy/import_test.rb +7 -0
- data/test/value_sets_bytes_parser_test.rb +3 -1
- data/test/value_sets_records_parser_test.rb +3 -1
- metadata +42 -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
data/test/models/vendor.rb
CHANGED
data/test/models/widget.rb
CHANGED
data/test/mysql2/import_test.rb
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
require File.expand_path(File.dirname(__FILE__)
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../test_helper")
|
|
4
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../support/assertions")
|
|
5
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../support/mysql/import_examples")
|
|
4
6
|
|
|
5
7
|
should_support_mysql_import_functionality
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require File.expand_path(File.dirname(__FILE__)
|
|
4
|
-
|
|
3
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../test_helper")
|
|
4
|
+
|
|
5
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../support/assertions")
|
|
6
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../support/mysql/import_examples")
|
|
5
7
|
|
|
6
8
|
should_support_mysql_import_functionality
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require File.expand_path(File.dirname(__FILE__)
|
|
4
|
-
|
|
3
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../test_helper")
|
|
4
|
+
|
|
5
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../support/assertions")
|
|
6
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../support/mysql/import_examples")
|
|
5
7
|
|
|
6
8
|
should_support_mysql_import_functionality
|
data/test/postgis/import_test.rb
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../test_helper")
|
|
4
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../support/postgresql/import_examples")
|
|
3
5
|
|
|
4
6
|
should_support_postgresql_import_functionality
|
|
5
7
|
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../test_helper")
|
|
4
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../support/postgresql/import_examples")
|
|
3
5
|
|
|
4
6
|
should_support_postgresql_import_functionality
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
ActiveRecord::Schema.define do
|
|
2
4
|
create_table :schema_info, force: :cascade do |t|
|
|
3
|
-
t.integer :version
|
|
5
|
+
t.integer :version
|
|
4
6
|
end
|
|
7
|
+
add_index :schema_info, :version, unique: true
|
|
8
|
+
|
|
5
9
|
SchemaInfo.create version: SchemaInfo::VERSION
|
|
6
10
|
|
|
7
11
|
create_table :group, force: :cascade do |t|
|
|
@@ -20,6 +24,7 @@ ActiveRecord::Schema.define do
|
|
|
20
24
|
t.boolean :approved, default: '1'
|
|
21
25
|
t.integer :replies_count
|
|
22
26
|
t.integer :parent_id
|
|
27
|
+
t.integer :priority, default: 0
|
|
23
28
|
t.string :type
|
|
24
29
|
t.datetime :created_at
|
|
25
30
|
t.datetime :created_on
|
|
@@ -52,6 +57,20 @@ ActiveRecord::Schema.define do
|
|
|
52
57
|
t.string :name
|
|
53
58
|
end
|
|
54
59
|
|
|
60
|
+
create_table :cards, force: :cascade do |t|
|
|
61
|
+
t.string :name
|
|
62
|
+
t.string :deck_type
|
|
63
|
+
t.integer :deck_id
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
create_table :decks, force: :cascade do |t|
|
|
67
|
+
t.string :name
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
create_table :playing_cards, force: :cascade do |t|
|
|
71
|
+
t.string :name
|
|
72
|
+
end
|
|
73
|
+
|
|
55
74
|
create_table :books, force: :cascade do |t|
|
|
56
75
|
t.string :title, null: false
|
|
57
76
|
t.string :publisher, null: false, default: 'Default Publisher'
|
|
@@ -190,5 +209,22 @@ ActiveRecord::Schema.define do
|
|
|
190
209
|
PRIMARY KEY (tag_id, publisher_id)
|
|
191
210
|
);
|
|
192
211
|
).split.join(' ').strip
|
|
212
|
+
|
|
213
|
+
create_table :tag_aliases, force: :cascade do |t|
|
|
214
|
+
t.integer :tag_id, null: false
|
|
215
|
+
t.integer :parent_id, null: false
|
|
216
|
+
t.string :alias, null: false
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
create_table :customers, force: :cascade do |t|
|
|
221
|
+
t.integer :account_id
|
|
222
|
+
t.string :name
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
create_table :orders, force: :cascade do |t|
|
|
226
|
+
t.integer :account_id
|
|
227
|
+
t.integer :customer_id
|
|
228
|
+
t.integer :amount
|
|
193
229
|
end
|
|
194
230
|
end
|
|
@@ -1,10 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
ActiveRecord::Schema.define do
|
|
2
4
|
execute('CREATE extension IF NOT EXISTS "hstore";')
|
|
3
5
|
execute('CREATE extension IF NOT EXISTS "pgcrypto";')
|
|
4
6
|
execute('CREATE extension IF NOT EXISTS "uuid-ossp";')
|
|
5
7
|
|
|
8
|
+
# create ENUM if it does not exist yet
|
|
9
|
+
begin
|
|
10
|
+
execute('CREATE TYPE vendor_type AS ENUM (\'wholesaler\', \'retailer\');')
|
|
11
|
+
rescue ActiveRecord::StatementInvalid
|
|
12
|
+
execute('ALTER TYPE vendor_type ADD VALUE IF NOT EXISTS \'wholesaler\';')
|
|
13
|
+
execute('ALTER TYPE vendor_type ADD VALUE IF NOT EXISTS \'retailer\';')
|
|
14
|
+
end
|
|
15
|
+
|
|
6
16
|
create_table :vendors, id: :uuid, force: :cascade do |t|
|
|
7
17
|
t.string :name, null: true
|
|
18
|
+
t.text :hours
|
|
8
19
|
t.text :preferences
|
|
9
20
|
|
|
10
21
|
if t.respond_to?(:json)
|
|
@@ -29,6 +40,8 @@ ActiveRecord::Schema.define do
|
|
|
29
40
|
t.text :json_data
|
|
30
41
|
end
|
|
31
42
|
|
|
43
|
+
t.column :vendor_type, :vendor_type
|
|
44
|
+
|
|
32
45
|
t.datetime :created_at
|
|
33
46
|
t.datetime :updated_at
|
|
34
47
|
end
|
|
@@ -44,4 +57,38 @@ ActiveRecord::Schema.define do
|
|
|
44
57
|
end
|
|
45
58
|
|
|
46
59
|
add_index :alarms, [:device_id, :alarm_type], unique: true, where: 'status <> 0'
|
|
60
|
+
|
|
61
|
+
unless ENV["SKIP_COMPOSITE_PK"]
|
|
62
|
+
create_table :authors, force: :cascade do |t|
|
|
63
|
+
t.string :name
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
execute %(
|
|
67
|
+
DROP SEQUENCE IF EXISTS composite_book_id_seq CASCADE;
|
|
68
|
+
CREATE SEQUENCE composite_book_id_seq
|
|
69
|
+
AS integer
|
|
70
|
+
START WITH 1
|
|
71
|
+
INCREMENT BY 1
|
|
72
|
+
NO MINVALUE
|
|
73
|
+
NO MAXVALUE
|
|
74
|
+
CACHE 1;
|
|
75
|
+
|
|
76
|
+
DROP TABLE IF EXISTS composite_books;
|
|
77
|
+
CREATE TABLE composite_books (
|
|
78
|
+
id bigint DEFAULT nextval('composite_book_id_seq'::regclass) NOT NULL,
|
|
79
|
+
title character varying,
|
|
80
|
+
author_id bigint
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
ALTER TABLE ONLY composite_books ADD CONSTRAINT fk_rails_040a418131 FOREIGN KEY (author_id) REFERENCES authors(id);
|
|
84
|
+
).split.join(' ').strip
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
create_table :composite_chapters, force: :cascade do |t|
|
|
88
|
+
t.string :title
|
|
89
|
+
t.integer :composite_book_id, null: false
|
|
90
|
+
t.integer :author_id, null: false
|
|
91
|
+
t.datetime :created_at
|
|
92
|
+
t.datetime :updated_at
|
|
93
|
+
end
|
|
47
94
|
end
|
data/test/schema/version.rb
CHANGED
data/test/sqlite3/import_test.rb
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../test_helper")
|
|
4
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../support/sqlite3/import_examples")
|
|
3
5
|
|
|
4
6
|
should_support_sqlite3_import_functionality
|
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 }
|
|
@@ -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,42 @@ 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
|
+
|
|
355
|
+
it "should import models with auto-incrementing ID successfully" do
|
|
356
|
+
author = Author.create!(name: "Foo Barson")
|
|
357
|
+
|
|
358
|
+
books = []
|
|
359
|
+
2.times do |i|
|
|
360
|
+
books << CompositeBook.new(author_id: author.id, title: "book #{i}")
|
|
361
|
+
end
|
|
362
|
+
assert_difference "CompositeBook.count", +2 do
|
|
363
|
+
CompositeBook.import books
|
|
364
|
+
end
|
|
365
|
+
end
|
|
366
|
+
end
|
|
367
|
+
end
|
|
262
368
|
end
|
|
263
369
|
|
|
264
370
|
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,11 +218,39 @@ 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
|
|
212
225
|
end
|
|
226
|
+
|
|
227
|
+
context 'with locking disabled' do
|
|
228
|
+
it 'does not update the lock_version' do
|
|
229
|
+
users = [
|
|
230
|
+
User.new(name: 'Salomon'),
|
|
231
|
+
User.new(name: 'Nathan')
|
|
232
|
+
]
|
|
233
|
+
User.import(users)
|
|
234
|
+
assert User.count == users.length
|
|
235
|
+
User.all.each do |user|
|
|
236
|
+
assert_equal 0, user.lock_version
|
|
237
|
+
end
|
|
238
|
+
updated_users = User.all.map do |user|
|
|
239
|
+
user.name += ' Rothschild'
|
|
240
|
+
user
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
ActiveRecord::Base.lock_optimistically = false # Disable locking
|
|
244
|
+
User.import(updated_users, on_duplicate_key_update: [:name])
|
|
245
|
+
ActiveRecord::Base.lock_optimistically = true # Enable locking
|
|
246
|
+
|
|
247
|
+
assert User.count == updated_users.length
|
|
248
|
+
User.all.each_with_index do |user, i|
|
|
249
|
+
assert_equal user.name, "#{users[i].name} Rothschild"
|
|
250
|
+
assert_equal 0, user.lock_version
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
end
|
|
213
254
|
end
|
|
214
255
|
|
|
215
256
|
context "with :on_duplicate_key_update" do
|
|
@@ -304,6 +345,34 @@ def should_support_basic_on_duplicate_key_update
|
|
|
304
345
|
should_support_on_duplicate_key_update
|
|
305
346
|
should_update_fields_mentioned
|
|
306
347
|
end
|
|
348
|
+
|
|
349
|
+
context "using column aliases" do
|
|
350
|
+
let(:columns) { %w( id title author_name author_email_address parent_id ) }
|
|
351
|
+
let(:update_columns) { %w(title author_email_address parent_id) }
|
|
352
|
+
|
|
353
|
+
context "with column aliases in column list" do
|
|
354
|
+
let(:columns) { %w( id name author_name author_email_address parent_id ) }
|
|
355
|
+
should_support_on_duplicate_key_update
|
|
356
|
+
should_update_fields_mentioned
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
context "with column aliases in update columns list" do
|
|
360
|
+
let(:update_columns) { %w(name author_email_address parent_id) }
|
|
361
|
+
should_support_on_duplicate_key_update
|
|
362
|
+
should_update_fields_mentioned
|
|
363
|
+
end
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
if ENV['AR_VERSION'].to_i >= 6.0
|
|
367
|
+
context "using ignored columns" do
|
|
368
|
+
let(:columns) { %w( id title author_name author_email_address parent_id priority ) }
|
|
369
|
+
let(:values) { [[99, "Book", "John Doe", "john@doe.com", 17, 1]] }
|
|
370
|
+
let(:update_columns) { %w(name author_email_address parent_id priority) }
|
|
371
|
+
let(:updated_values) { [[99, "Book - 2nd Edition", "Author Should Not Change", "johndoe@example.com", 57, 2]] }
|
|
372
|
+
should_support_on_duplicate_key_update
|
|
373
|
+
should_update_fields_mentioned
|
|
374
|
+
end
|
|
375
|
+
end
|
|
307
376
|
end
|
|
308
377
|
|
|
309
378
|
context "with a table that has a non-standard primary key" do
|