activerecord-import 1.4.1 → 1.5.0
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 +7 -1
- data/.rubocop.yml +4 -4
- data/.rubocop_todo.yml +6 -16
- data/CHANGELOG.md +13 -1
- data/Gemfile +3 -3
- data/README.markdown +6 -4
- data/benchmarks/benchmark.rb +3 -3
- data/benchmarks/lib/base.rb +2 -2
- data/benchmarks/lib/cli_parser.rb +1 -1
- data/lib/activerecord-import/adapters/abstract_adapter.rb +6 -5
- data/lib/activerecord-import/adapters/mysql_adapter.rb +24 -18
- data/lib/activerecord-import/adapters/postgresql_adapter.rb +26 -18
- data/lib/activerecord-import/adapters/sqlite3_adapter.rb +29 -23
- data/lib/activerecord-import/import.rb +39 -22
- data/lib/activerecord-import/value_sets_parser.rb +1 -0
- data/lib/activerecord-import/version.rb +1 -1
- data/test/jdbcmysql/import_test.rb +3 -3
- data/test/jdbcpostgresql/import_test.rb +2 -2
- data/test/jdbcsqlite3/import_test.rb +2 -2
- data/test/makara_postgis/import_test.rb +2 -2
- data/test/models/bike_maker.rb +1 -0
- data/test/models/topic.rb +5 -0
- data/test/mysql2/import_test.rb +3 -3
- data/test/mysql2_makara/import_test.rb +3 -3
- data/test/mysqlspatial2/import_test.rb +3 -3
- data/test/postgis/import_test.rb +2 -2
- data/test/postgresql/import_test.rb +2 -2
- data/test/schema/generic_schema.rb +1 -0
- data/test/schema/jdbcpostgresql_schema.rb +1 -1
- data/test/schema/postgis_schema.rb +1 -1
- data/test/sqlite3/import_test.rb +2 -2
- data/test/support/shared_examples/on_duplicate_key_update.rb +39 -10
- data/test/test_helper.rb +3 -3
- data/test/value_sets_bytes_parser_test.rb +1 -1
- data/test/value_sets_records_parser_test.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 866dd09466fbda981329e13916e89986cb47d65259f0889b8a3b53aeca1aee32
|
4
|
+
data.tar.gz: 258a0d2fc34bbb928500e2f8a83df4f5bdc8901c25e2e123a569c56d587d3f53
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 989562e1fb64d669a96211c6b80df5b89d8a43aa38575ec6706d0633b405983a63849bd5fb78d4031ed7e4b2c239192f62d4b3d9e720f4c474cd3801600d11ef
|
7
|
+
data.tar.gz: 22e6ccbb750bb7851930d98c2b90f496c759d35503c8c1e58b841f4a928a283c486caec3f22cb57e6948b6960e6fff2a598499f0670f59b281e321dded20c183
|
data/.github/workflows/test.yaml
CHANGED
@@ -20,13 +20,19 @@ jobs:
|
|
20
20
|
fail-fast: false
|
21
21
|
matrix:
|
22
22
|
ruby:
|
23
|
-
- 3.
|
23
|
+
- 3.2
|
24
24
|
env:
|
25
25
|
- AR_VERSION: '7.0'
|
26
26
|
RUBYOPT: --enable-frozen-string-literal
|
27
27
|
- AR_VERSION: 6.1
|
28
28
|
RUBYOPT: --enable-frozen-string-literal
|
29
29
|
include:
|
30
|
+
- ruby: 3.1
|
31
|
+
env:
|
32
|
+
AR_VERSION: '7.0'
|
33
|
+
- ruby: 3.1
|
34
|
+
env:
|
35
|
+
AR_VERSION: 6.1
|
30
36
|
- ruby: '3.0'
|
31
37
|
env:
|
32
38
|
AR_VERSION: '7.0'
|
data/.rubocop.yml
CHANGED
@@ -66,10 +66,10 @@ Style/SymbolArray:
|
|
66
66
|
Style/TrailingCommaInArrayLiteral:
|
67
67
|
Enabled: false
|
68
68
|
|
69
|
-
Layout/
|
69
|
+
Layout/ArgumentAlignment:
|
70
70
|
Enabled: false
|
71
71
|
|
72
|
-
Layout/
|
72
|
+
Layout/ParameterAlignment:
|
73
73
|
EnforcedStyle: with_fixed_indentation
|
74
74
|
|
75
75
|
Layout/EndAlignment:
|
@@ -81,7 +81,7 @@ Layout/ElseAlignment:
|
|
81
81
|
Layout/EmptyLineAfterGuardClause:
|
82
82
|
Enabled: false
|
83
83
|
|
84
|
-
Layout/
|
84
|
+
Layout/HeredocIndentation:
|
85
85
|
Enabled: false
|
86
86
|
|
87
87
|
Layout/SpaceInsideParens:
|
@@ -102,7 +102,7 @@ Lint/PercentStringArray:
|
|
102
102
|
Naming/HeredocDelimiterNaming:
|
103
103
|
Enabled: false
|
104
104
|
|
105
|
-
Naming/
|
105
|
+
Naming/MethodParameterName:
|
106
106
|
Enabled: false
|
107
107
|
|
108
108
|
Security/YAMLLoad:
|
data/.rubocop_todo.yml
CHANGED
@@ -1,36 +1,26 @@
|
|
1
1
|
# This configuration was generated by
|
2
2
|
# `rubocop --auto-gen-config`
|
3
|
-
# on
|
3
|
+
# on 2023-02-15 00:58:14 UTC using RuboCop version 1.45.1.
|
4
4
|
# The point is for the user to remove these configuration records
|
5
5
|
# one by one as the offenses are removed from the code base.
|
6
6
|
# Note that changes in the inspected code, or installation of new
|
7
7
|
# versions of RuboCop, may require this file to be generated again.
|
8
8
|
|
9
|
-
# Offense count: 2
|
10
|
-
Lint/HandleExceptions:
|
11
|
-
Exclude:
|
12
|
-
- 'lib/activerecord-import/base.rb'
|
13
|
-
- 'test/import_test.rb'
|
14
|
-
|
15
9
|
# Offense count: 2
|
16
10
|
Lint/RescueException:
|
17
11
|
Exclude:
|
18
12
|
- 'benchmarks/lib/cli_parser.rb'
|
19
13
|
- 'test/import_test.rb'
|
20
14
|
|
21
|
-
# Offense count:
|
22
|
-
#
|
23
|
-
# Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods.
|
15
|
+
# Offense count: 3
|
16
|
+
# This cop supports safe autocorrection (--autocorrect).
|
17
|
+
# Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods.
|
24
18
|
Lint/UnusedMethodArgument:
|
25
19
|
Exclude:
|
26
20
|
- 'lib/activerecord-import/adapters/postgresql_adapter.rb'
|
27
21
|
- 'lib/activerecord-import/import.rb'
|
28
22
|
|
29
23
|
# Offense count: 2
|
30
|
-
|
31
|
-
# Configuration parameters: Keywords.
|
32
|
-
# Keywords: TODO, FIXME, OPTIMIZE, HACK, REVIEW
|
33
|
-
Style/CommentAnnotation:
|
24
|
+
Style/CombinableLoops:
|
34
25
|
Exclude:
|
35
|
-
- '
|
36
|
-
- 'lib/activerecord-import/import.rb'
|
26
|
+
- 'test/support/shared_examples/recursive_import.rb'
|
data/CHANGELOG.md
CHANGED
@@ -1,8 +1,20 @@
|
|
1
|
+
## Changes in 1.5.0
|
2
|
+
|
3
|
+
### New Features
|
4
|
+
|
5
|
+
* Add Rails 7.1 support. Thanks to @gucki via \##807.
|
6
|
+
* Add support for alias attributes. Thanks to @leonidkroka via \##799.
|
7
|
+
|
8
|
+
### Fixes
|
9
|
+
|
10
|
+
* Support for multi-byte column names when splitting queries. Thanks to @TakuyaKurimoto via \##801.
|
11
|
+
* Fix issue with track_validation_failures when import models. Thanks to @OtaYohihiro via \##798.
|
12
|
+
|
1
13
|
## Changes in 1.4.1
|
2
14
|
|
3
15
|
### Fixes
|
4
16
|
|
5
|
-
* Fix importing models that have required belongs_to associations and use composite primary keys. Thanks to @thoughtbot-summer
|
17
|
+
* Fix importing models that have required belongs_to associations and use composite primary keys. Thanks to @thoughtbot-summer via \##783.
|
6
18
|
|
7
19
|
## Changes in 1.4.0
|
8
20
|
|
data/Gemfile
CHANGED
@@ -15,7 +15,7 @@ pg_version = '0.9'
|
|
15
15
|
pg_version = '1.1' if version >= 6.1
|
16
16
|
|
17
17
|
group :development, :test do
|
18
|
-
gem 'rubocop'
|
18
|
+
gem 'rubocop'
|
19
19
|
gem 'rake'
|
20
20
|
end
|
21
21
|
|
@@ -40,7 +40,7 @@ end
|
|
40
40
|
gem "factory_bot"
|
41
41
|
gem "timecop"
|
42
42
|
gem "chronic"
|
43
|
-
gem "mocha", "~> 1.
|
43
|
+
gem "mocha", "~> 2.1.0"
|
44
44
|
|
45
45
|
# Debugging
|
46
46
|
platforms :jruby do
|
@@ -49,7 +49,7 @@ end
|
|
49
49
|
|
50
50
|
platforms :ruby do
|
51
51
|
gem "pry-byebug"
|
52
|
-
gem "pry", "~> 0.
|
52
|
+
gem "pry", "~> 0.14.0"
|
53
53
|
end
|
54
54
|
|
55
55
|
if version >= 4.0
|
data/README.markdown
CHANGED
@@ -245,8 +245,8 @@ Book.import columns, books, batch_size: 2, batch_progress: my_proc
|
|
245
245
|
|
246
246
|
#### Recursive
|
247
247
|
|
248
|
-
|
249
|
-
hashes or arrays as recursive inputs.
|
248
|
+
> **Note**
|
249
|
+
> This only works with PostgreSQL and ActiveRecord objects. This won't work with hashes or arrays as recursive inputs.
|
250
250
|
|
251
251
|
Assume that Books <code>has_many</code> Reviews.
|
252
252
|
|
@@ -434,7 +434,8 @@ Should you wish to specify those columns, you may use the option `timestamps: fa
|
|
434
434
|
However, it is also possible to set just `:created_at` in specific records. In this case despite using `timestamps: true`, `:created_at` will be updated only in records where that field is `nil`. Same rule applies for record associations when enabling the option `recursive: true`.
|
435
435
|
|
436
436
|
If you are using custom time zones, these will be respected when performing imports as well as long as `ActiveRecord::Base.default_timezone` is set, which for practically all Rails apps it is.
|
437
|
-
|
437
|
+
> **Note**
|
438
|
+
> If you are using ActiveRecord 7.0 or later, please use `ActiveRecord.default_timezone` instead.
|
438
439
|
|
439
440
|
### Callbacks
|
440
441
|
|
@@ -506,7 +507,8 @@ This allows an external gem to dynamically add an adapter without the need to ad
|
|
506
507
|
|
507
508
|
### Requiring
|
508
509
|
|
509
|
-
Note
|
510
|
+
> **Note**
|
511
|
+
> These instructions will only work if you are using version 0.2.0 or higher.
|
510
512
|
|
511
513
|
#### Autoloading via Bundler
|
512
514
|
|
data/benchmarks/benchmark.rb
CHANGED
@@ -41,7 +41,7 @@ require File.join(benchmark_dir, "../test/schema/generic_schema")
|
|
41
41
|
adapter_schema = File.join(benchmark_dir, "schema/#{options.adapter}_schema.rb")
|
42
42
|
require adapter_schema if File.exist?(adapter_schema)
|
43
43
|
|
44
|
-
Dir[File.dirname(__FILE__)
|
44
|
+
Dir["#{File.dirname(__FILE__)}/models/*.rb"].sort.each { |file| require file }
|
45
45
|
|
46
46
|
require File.join( benchmark_dir, 'lib', "#{options.adapter}_benchmark" )
|
47
47
|
|
@@ -53,8 +53,8 @@ else
|
|
53
53
|
end
|
54
54
|
|
55
55
|
letter = options.adapter[0].chr
|
56
|
-
clazz_str = letter.upcase + options.adapter[1
|
57
|
-
clazz = Object.const_get( clazz_str
|
56
|
+
clazz_str = letter.upcase + options.adapter[1..].downcase
|
57
|
+
clazz = Object.const_get( "#{clazz_str}Benchmark" )
|
58
58
|
|
59
59
|
benchmarks = []
|
60
60
|
options.number_of_objects.each do |num|
|
data/benchmarks/lib/base.rb
CHANGED
@@ -27,11 +27,11 @@ class BenchmarkBase
|
|
27
27
|
# An OpenStruct object with the following attributes:
|
28
28
|
# * description - the description of the benchmark ran
|
29
29
|
# * tms - a Benchmark::Tms containing the results of the benchmark
|
30
|
-
def bm( description )
|
30
|
+
def bm( description, &block )
|
31
31
|
tms = nil
|
32
32
|
puts "Benchmarking #{description}"
|
33
33
|
|
34
|
-
Benchmark.bm { |x| tms = x.report
|
34
|
+
Benchmark.bm { |x| tms = x.report(&block) }
|
35
35
|
delete_all
|
36
36
|
failed = false
|
37
37
|
|
@@ -29,7 +29,7 @@ module BenchmarkOptionParser
|
|
29
29
|
print_valid_table_types( options, prefix: " " )
|
30
30
|
end
|
31
31
|
|
32
|
-
# TODO IMPLEMENT THIS
|
32
|
+
# TODO: IMPLEMENT THIS
|
33
33
|
def self.print_valid_table_types( options, hsh = { prefix: '' } )
|
34
34
|
if !options.table_types.keys.empty?
|
35
35
|
options.table_types.keys.sort.each { |type| puts hsh[:prefix].to_s + type.to_s }
|
@@ -9,10 +9,11 @@ module ActiveRecord::Import::AbstractAdapter
|
|
9
9
|
def insert_many( sql, values, _options = {}, *args ) # :nodoc:
|
10
10
|
number_of_inserts = 1
|
11
11
|
|
12
|
-
base_sql, post_sql =
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
base_sql, post_sql = case sql
|
13
|
+
when String
|
14
|
+
[sql, '']
|
15
|
+
when Array
|
16
|
+
[sql.shift, sql.join( ' ' )]
|
16
17
|
end
|
17
18
|
|
18
19
|
sql2insert = base_sql + values.join( ',' ) + post_sql
|
@@ -47,7 +48,7 @@ module ActiveRecord::Import::AbstractAdapter
|
|
47
48
|
post_sql_statements = []
|
48
49
|
|
49
50
|
if supports_on_duplicate_key_update? && options[:on_duplicate_key_update]
|
50
|
-
post_sql_statements << sql_for_on_duplicate_key_update( table_name, options[:on_duplicate_key_update], options[:primary_key], options[:locking_column] )
|
51
|
+
post_sql_statements << sql_for_on_duplicate_key_update( table_name, options[:on_duplicate_key_update], options[:model], options[:primary_key], options[:locking_column] )
|
51
52
|
elsif logger && options[:on_duplicate_key_update]
|
52
53
|
logger.warn "Ignoring on_duplicate_key_update because it is not supported by the database."
|
53
54
|
end
|
@@ -13,13 +13,14 @@ module ActiveRecord::Import::MysqlAdapter
|
|
13
13
|
# the number of inserts default
|
14
14
|
number_of_inserts = 0
|
15
15
|
|
16
|
-
base_sql, post_sql =
|
17
|
-
|
18
|
-
|
19
|
-
|
16
|
+
base_sql, post_sql = case sql
|
17
|
+
when String
|
18
|
+
[sql, '']
|
19
|
+
when Array
|
20
|
+
[sql.shift, sql.join( ' ' )]
|
20
21
|
end
|
21
22
|
|
22
|
-
sql_size = QUERY_OVERHEAD + base_sql.
|
23
|
+
sql_size = QUERY_OVERHEAD + base_sql.bytesize + post_sql.bytesize
|
23
24
|
|
24
25
|
# the number of bytes the requested insert statement values will take up
|
25
26
|
values_in_bytes = values.sum(&:bytesize)
|
@@ -33,7 +34,7 @@ module ActiveRecord::Import::MysqlAdapter
|
|
33
34
|
max = max_allowed_packet
|
34
35
|
|
35
36
|
# if we can insert it all as one statement
|
36
|
-
if
|
37
|
+
if max == NO_MAX_PACKET || total_bytes <= max || options[:force_single_insert]
|
37
38
|
number_of_inserts += 1
|
38
39
|
sql2insert = base_sql + values.join( ',' ) + post_sql
|
39
40
|
insert( sql2insert, *args )
|
@@ -85,13 +86,13 @@ module ActiveRecord::Import::MysqlAdapter
|
|
85
86
|
# in +args+.
|
86
87
|
def sql_for_on_duplicate_key_update( table_name, *args ) # :nodoc:
|
87
88
|
sql = ' ON DUPLICATE KEY UPDATE '.dup
|
88
|
-
arg = args
|
89
|
-
|
90
|
-
|
91
|
-
sql << sql_for_on_duplicate_key_update_as_array( table_name, locking_column, arg )
|
92
|
-
|
93
|
-
sql << sql_for_on_duplicate_key_update_as_hash( table_name, locking_column, arg )
|
94
|
-
|
89
|
+
arg, model, _primary_key, locking_column = args
|
90
|
+
case arg
|
91
|
+
when Array
|
92
|
+
sql << sql_for_on_duplicate_key_update_as_array( table_name, model, locking_column, arg )
|
93
|
+
when Hash
|
94
|
+
sql << sql_for_on_duplicate_key_update_as_hash( table_name, model, locking_column, arg )
|
95
|
+
when String
|
95
96
|
sql << arg
|
96
97
|
else
|
97
98
|
raise ArgumentError, "Expected Array or Hash"
|
@@ -99,19 +100,24 @@ module ActiveRecord::Import::MysqlAdapter
|
|
99
100
|
sql
|
100
101
|
end
|
101
102
|
|
102
|
-
def sql_for_on_duplicate_key_update_as_array( table_name, locking_column, arr ) # :nodoc:
|
103
|
+
def sql_for_on_duplicate_key_update_as_array( table_name, model, locking_column, arr ) # :nodoc:
|
103
104
|
results = arr.map do |column|
|
104
|
-
|
105
|
+
original_column_name = model.attribute_alias?( column ) ? model.attribute_alias( column ) : column
|
106
|
+
qc = quote_column_name( original_column_name )
|
105
107
|
"#{table_name}.#{qc}=VALUES(#{qc})"
|
106
108
|
end
|
107
109
|
increment_locking_column!(table_name, results, locking_column)
|
108
110
|
results.join( ',' )
|
109
111
|
end
|
110
112
|
|
111
|
-
def sql_for_on_duplicate_key_update_as_hash( table_name, locking_column, hsh ) # :nodoc:
|
113
|
+
def sql_for_on_duplicate_key_update_as_hash( table_name, model, locking_column, hsh ) # :nodoc:
|
112
114
|
results = hsh.map do |column1, column2|
|
113
|
-
|
114
|
-
|
115
|
+
original_column1_name = model.attribute_alias?( column1 ) ? model.attribute_alias( column1 ) : column1
|
116
|
+
qc1 = quote_column_name( original_column1_name )
|
117
|
+
|
118
|
+
original_column2_name = model.attribute_alias?( column2 ) ? model.attribute_alias( column2 ) : column2
|
119
|
+
qc2 = quote_column_name( original_column2_name )
|
120
|
+
|
115
121
|
"#{table_name}.#{qc1}=VALUES( #{qc2} )"
|
116
122
|
end
|
117
123
|
increment_locking_column!(table_name, results, locking_column)
|
@@ -12,10 +12,11 @@ module ActiveRecord::Import::PostgreSQLAdapter
|
|
12
12
|
ids = []
|
13
13
|
results = []
|
14
14
|
|
15
|
-
base_sql, post_sql =
|
16
|
-
|
17
|
-
|
18
|
-
|
15
|
+
base_sql, post_sql = case sql
|
16
|
+
when String
|
17
|
+
[sql, '']
|
18
|
+
when Array
|
19
|
+
[sql.shift, sql.join( ' ' )]
|
19
20
|
end
|
20
21
|
|
21
22
|
sql2insert = base_sql + values.join( ',' ) + post_sql
|
@@ -110,13 +111,14 @@ module ActiveRecord::Import::PostgreSQLAdapter
|
|
110
111
|
# Add a column to be updated on duplicate key update
|
111
112
|
def add_column_for_on_duplicate_key_update( column, options = {} ) # :nodoc:
|
112
113
|
arg = options[:on_duplicate_key_update]
|
113
|
-
|
114
|
+
case arg
|
115
|
+
when Hash
|
114
116
|
columns = arg.fetch( :columns ) { arg[:columns] = [] }
|
115
117
|
case columns
|
116
118
|
when Array then columns << column.to_sym unless columns.include?( column.to_sym )
|
117
119
|
when Hash then columns[column.to_sym] = column.to_sym
|
118
120
|
end
|
119
|
-
|
121
|
+
when Array
|
120
122
|
arg << column.to_sym unless arg.include?( column.to_sym )
|
121
123
|
end
|
122
124
|
end
|
@@ -132,7 +134,7 @@ module ActiveRecord::Import::PostgreSQLAdapter
|
|
132
134
|
# Returns a generated ON CONFLICT DO UPDATE statement given the passed
|
133
135
|
# in +args+.
|
134
136
|
def sql_for_on_duplicate_key_update( table_name, *args ) # :nodoc:
|
135
|
-
arg, primary_key, locking_column = args
|
137
|
+
arg, model, primary_key, locking_column = args
|
136
138
|
arg = { columns: arg } if arg.is_a?( Array ) || arg.is_a?( String )
|
137
139
|
return unless arg.is_a?( Hash )
|
138
140
|
|
@@ -151,11 +153,12 @@ module ActiveRecord::Import::PostgreSQLAdapter
|
|
151
153
|
end
|
152
154
|
|
153
155
|
sql << "#{conflict_target}DO UPDATE SET "
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
156
|
+
case columns
|
157
|
+
when Array
|
158
|
+
sql << sql_for_on_duplicate_key_update_as_array( table_name, model, locking_column, columns )
|
159
|
+
when Hash
|
160
|
+
sql << sql_for_on_duplicate_key_update_as_hash( table_name, model, locking_column, columns )
|
161
|
+
when String
|
159
162
|
sql << columns
|
160
163
|
else
|
161
164
|
raise ArgumentError, 'Expected :columns to be an Array or Hash'
|
@@ -166,19 +169,24 @@ module ActiveRecord::Import::PostgreSQLAdapter
|
|
166
169
|
sql
|
167
170
|
end
|
168
171
|
|
169
|
-
def sql_for_on_duplicate_key_update_as_array( table_name, locking_column, arr ) # :nodoc:
|
172
|
+
def sql_for_on_duplicate_key_update_as_array( table_name, model, locking_column, arr ) # :nodoc:
|
170
173
|
results = arr.map do |column|
|
171
|
-
|
174
|
+
original_column_name = model.attribute_alias?( column ) ? model.attribute_alias( column ) : column
|
175
|
+
qc = quote_column_name( original_column_name )
|
172
176
|
"#{qc}=EXCLUDED.#{qc}"
|
173
177
|
end
|
174
178
|
increment_locking_column!(table_name, results, locking_column)
|
175
179
|
results.join( ',' )
|
176
180
|
end
|
177
181
|
|
178
|
-
def sql_for_on_duplicate_key_update_as_hash( table_name, locking_column, hsh ) # :nodoc:
|
182
|
+
def sql_for_on_duplicate_key_update_as_hash( table_name, model, locking_column, hsh ) # :nodoc:
|
179
183
|
results = hsh.map do |column1, column2|
|
180
|
-
|
181
|
-
|
184
|
+
original_column1_name = model.attribute_alias?( column1 ) ? model.attribute_alias( column1 ) : column1
|
185
|
+
qc1 = quote_column_name( original_column1_name )
|
186
|
+
|
187
|
+
original_column2_name = model.attribute_alias?( column2 ) ? model.attribute_alias( column2 ) : column2
|
188
|
+
qc2 = quote_column_name( original_column2_name )
|
189
|
+
|
182
190
|
"#{qc1}=EXCLUDED.#{qc2}"
|
183
191
|
end
|
184
192
|
increment_locking_column!(table_name, results, locking_column)
|
@@ -192,7 +200,7 @@ module ActiveRecord::Import::PostgreSQLAdapter
|
|
192
200
|
if constraint_name.present?
|
193
201
|
"ON CONSTRAINT #{constraint_name} "
|
194
202
|
elsif conflict_target.present?
|
195
|
-
sql =
|
203
|
+
sql = "(#{Array( conflict_target ).reject( &:blank? ).join( ', ' )}) "
|
196
204
|
sql += "WHERE #{index_predicate} " if index_predicate
|
197
205
|
sql
|
198
206
|
end
|
@@ -24,10 +24,11 @@ module ActiveRecord::Import::SQLite3Adapter
|
|
24
24
|
def insert_many( sql, values, _options = {}, *args ) # :nodoc:
|
25
25
|
number_of_inserts = 0
|
26
26
|
|
27
|
-
base_sql, post_sql =
|
28
|
-
|
29
|
-
|
30
|
-
|
27
|
+
base_sql, post_sql = case sql
|
28
|
+
when String
|
29
|
+
[sql, '']
|
30
|
+
when Array
|
31
|
+
[sql.shift, sql.join( ' ' )]
|
31
32
|
end
|
32
33
|
|
33
34
|
value_sets = ::ActiveRecord::Import::ValueSetsRecordsParser.parse(values,
|
@@ -56,11 +57,9 @@ module ActiveRecord::Import::SQLite3Adapter
|
|
56
57
|
def post_sql_statements( table_name, options ) # :nodoc:
|
57
58
|
sql = []
|
58
59
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
sql << sql_for_on_duplicate_key_ignore( options[:on_duplicate_key_ignore] )
|
63
|
-
end
|
60
|
+
# Options :recursive and :on_duplicate_key_ignore are mutually exclusive
|
61
|
+
if supports_on_duplicate_key_update? && ((options[:ignore] || options[:on_duplicate_key_ignore]) && !options[:on_duplicate_key_update])
|
62
|
+
sql << sql_for_on_duplicate_key_ignore( options[:on_duplicate_key_ignore] )
|
64
63
|
end
|
65
64
|
|
66
65
|
sql + super
|
@@ -73,13 +72,14 @@ module ActiveRecord::Import::SQLite3Adapter
|
|
73
72
|
# Add a column to be updated on duplicate key update
|
74
73
|
def add_column_for_on_duplicate_key_update( column, options = {} ) # :nodoc:
|
75
74
|
arg = options[:on_duplicate_key_update]
|
76
|
-
|
75
|
+
case arg
|
76
|
+
when Hash
|
77
77
|
columns = arg.fetch( :columns ) { arg[:columns] = [] }
|
78
78
|
case columns
|
79
79
|
when Array then columns << column.to_sym unless columns.include?( column.to_sym )
|
80
80
|
when Hash then columns[column.to_sym] = column.to_sym
|
81
81
|
end
|
82
|
-
|
82
|
+
when Array
|
83
83
|
arg << column.to_sym unless arg.include?( column.to_sym )
|
84
84
|
end
|
85
85
|
end
|
@@ -95,7 +95,7 @@ module ActiveRecord::Import::SQLite3Adapter
|
|
95
95
|
# Returns a generated ON CONFLICT DO UPDATE statement given the passed
|
96
96
|
# in +args+.
|
97
97
|
def sql_for_on_duplicate_key_update( table_name, *args ) # :nodoc:
|
98
|
-
arg, primary_key, locking_column = args
|
98
|
+
arg, model, primary_key, locking_column = args
|
99
99
|
arg = { columns: arg } if arg.is_a?( Array ) || arg.is_a?( String )
|
100
100
|
return unless arg.is_a?( Hash )
|
101
101
|
|
@@ -114,11 +114,12 @@ module ActiveRecord::Import::SQLite3Adapter
|
|
114
114
|
end
|
115
115
|
|
116
116
|
sql << "#{conflict_target}DO UPDATE SET "
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
117
|
+
case columns
|
118
|
+
when Array
|
119
|
+
sql << sql_for_on_duplicate_key_update_as_array( table_name, model, locking_column, columns )
|
120
|
+
when Hash
|
121
|
+
sql << sql_for_on_duplicate_key_update_as_hash( table_name, model, locking_column, columns )
|
122
|
+
when String
|
122
123
|
sql << columns
|
123
124
|
else
|
124
125
|
raise ArgumentError, 'Expected :columns to be an Array or Hash'
|
@@ -129,19 +130,24 @@ module ActiveRecord::Import::SQLite3Adapter
|
|
129
130
|
sql
|
130
131
|
end
|
131
132
|
|
132
|
-
def sql_for_on_duplicate_key_update_as_array( table_name, locking_column, arr ) # :nodoc:
|
133
|
+
def sql_for_on_duplicate_key_update_as_array( table_name, model, locking_column, arr ) # :nodoc:
|
133
134
|
results = arr.map do |column|
|
134
|
-
|
135
|
+
original_column_name = model.attribute_alias?( column ) ? model.attribute_alias( column ) : column
|
136
|
+
qc = quote_column_name( original_column_name )
|
135
137
|
"#{qc}=EXCLUDED.#{qc}"
|
136
138
|
end
|
137
139
|
increment_locking_column!(table_name, results, locking_column)
|
138
140
|
results.join( ',' )
|
139
141
|
end
|
140
142
|
|
141
|
-
def sql_for_on_duplicate_key_update_as_hash( table_name, locking_column, hsh ) # :nodoc:
|
143
|
+
def sql_for_on_duplicate_key_update_as_hash( table_name, model, locking_column, hsh ) # :nodoc:
|
142
144
|
results = hsh.map do |column1, column2|
|
143
|
-
|
144
|
-
|
145
|
+
original_column1_name = model.attribute_alias?( column1 ) ? model.attribute_alias( column1 ) : column1
|
146
|
+
qc1 = quote_column_name( original_column1_name )
|
147
|
+
|
148
|
+
original_column2_name = model.attribute_alias?( column2 ) ? model.attribute_alias( column2 ) : column2
|
149
|
+
qc2 = quote_column_name( original_column2_name )
|
150
|
+
|
145
151
|
"#{qc1}=EXCLUDED.#{qc2}"
|
146
152
|
end
|
147
153
|
increment_locking_column!(table_name, results, locking_column)
|
@@ -152,7 +158,7 @@ module ActiveRecord::Import::SQLite3Adapter
|
|
152
158
|
conflict_target = args[:conflict_target]
|
153
159
|
index_predicate = args[:index_predicate]
|
154
160
|
if conflict_target.present?
|
155
|
-
sql =
|
161
|
+
sql = "(#{Array( conflict_target ).reject( &:blank? ).join( ', ' )}) "
|
156
162
|
sql += "WHERE #{index_predicate} " if index_predicate
|
157
163
|
sql
|
158
164
|
end
|
@@ -4,17 +4,17 @@ require "ostruct"
|
|
4
4
|
|
5
5
|
module ActiveRecord::Import::ConnectionAdapters; end
|
6
6
|
|
7
|
-
module ActiveRecord::Import
|
7
|
+
module ActiveRecord::Import # :nodoc:
|
8
8
|
Result = Struct.new(:failed_instances, :num_inserts, :ids, :results)
|
9
9
|
|
10
|
-
module ImportSupport
|
11
|
-
def supports_import?
|
10
|
+
module ImportSupport # :nodoc:
|
11
|
+
def supports_import? # :nodoc:
|
12
12
|
true
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
-
module OnDuplicateKeyUpdateSupport
|
17
|
-
def supports_on_duplicate_key_update?
|
16
|
+
module OnDuplicateKeyUpdateSupport # :nodoc:
|
17
|
+
def supports_on_duplicate_key_update? # :nodoc:
|
18
18
|
true
|
19
19
|
end
|
20
20
|
end
|
@@ -73,7 +73,7 @@ module ActiveRecord::Import #:nodoc:
|
|
73
73
|
end
|
74
74
|
|
75
75
|
def valid_model?(model)
|
76
|
-
init_validations(model.class) unless model.
|
76
|
+
init_validations(model.class) unless model.instance_of?(@validator_class)
|
77
77
|
|
78
78
|
validation_context = @options[:validate_with_context]
|
79
79
|
validation_context ||= (model.new_record? ? :create : :update)
|
@@ -85,7 +85,11 @@ module ActiveRecord::Import #:nodoc:
|
|
85
85
|
|
86
86
|
model.run_callbacks(:validation) do
|
87
87
|
if defined?(ActiveSupport::Callbacks::Filters::Environment) # ActiveRecord >= 4.1
|
88
|
-
runner = @validate_callbacks.compile
|
88
|
+
runner = if @validate_callbacks.method(:compile).arity == 0
|
89
|
+
@validate_callbacks.compile
|
90
|
+
else # ActiveRecord >= 7.1
|
91
|
+
@validate_callbacks.compile(nil)
|
92
|
+
end
|
89
93
|
env = ActiveSupport::Callbacks::Filters::Environment.new(model, false, nil)
|
90
94
|
if runner.respond_to?(:call) # ActiveRecord < 5.1
|
91
95
|
runner.call(env)
|
@@ -165,7 +169,7 @@ class ActiveRecord::Associations::CollectionAssociation
|
|
165
169
|
m.public_send "#{reflection.type}=", owner.class.name if reflection.type
|
166
170
|
end
|
167
171
|
|
168
|
-
|
172
|
+
model_klass.bulk_import column_names, models, options
|
169
173
|
|
170
174
|
# supports array of hash objects
|
171
175
|
elsif args.last.is_a?( Array ) && args.last.first.is_a?(Hash)
|
@@ -204,11 +208,11 @@ class ActiveRecord::Associations::CollectionAssociation
|
|
204
208
|
end
|
205
209
|
end
|
206
210
|
|
207
|
-
|
211
|
+
model_klass.bulk_import column_names, array_of_attributes, options
|
208
212
|
|
209
213
|
# supports empty array
|
210
214
|
elsif args.last.is_a?( Array ) && args.last.empty?
|
211
|
-
|
215
|
+
ActiveRecord::Import::Result.new([], 0, [])
|
212
216
|
|
213
217
|
# supports 2-element array and array
|
214
218
|
elsif args.size == 2 && args.first.is_a?( Array ) && args.last.is_a?( Array )
|
@@ -239,7 +243,7 @@ class ActiveRecord::Associations::CollectionAssociation
|
|
239
243
|
end
|
240
244
|
end
|
241
245
|
|
242
|
-
|
246
|
+
model_klass.bulk_import column_names, array_of_attributes, options
|
243
247
|
else
|
244
248
|
raise ArgumentError, "Invalid arguments!"
|
245
249
|
end
|
@@ -574,7 +578,7 @@ class ActiveRecord::Base
|
|
574
578
|
|
575
579
|
if models.first.id.nil?
|
576
580
|
Array(primary_key).each do |c|
|
577
|
-
if column_names.include?(c) &&
|
581
|
+
if column_names.include?(c) && schema_columns_hash[c].type == :uuid
|
578
582
|
column_names.delete(c)
|
579
583
|
end
|
580
584
|
end
|
@@ -697,7 +701,11 @@ class ActiveRecord::Base
|
|
697
701
|
return_obj = if is_validating
|
698
702
|
import_with_validations( column_names, array_of_attributes, options ) do |failed_instances|
|
699
703
|
if models
|
700
|
-
models.
|
704
|
+
models.each_with_index do |m, i|
|
705
|
+
next unless m.errors.any?
|
706
|
+
|
707
|
+
failed_instances << (options[:track_validation_failures] ? [i, m] : m)
|
708
|
+
end
|
701
709
|
else
|
702
710
|
# create instances for each of our column/value sets
|
703
711
|
arr = validations_array_for_column_names_and_attributes( column_names, array_of_attributes )
|
@@ -774,7 +782,10 @@ class ActiveRecord::Base
|
|
774
782
|
def import_without_validations_or_callbacks( column_names, array_of_attributes, options = {} )
|
775
783
|
return ActiveRecord::Import::Result.new([], 0, [], []) if array_of_attributes.empty?
|
776
784
|
|
777
|
-
column_names = column_names.map
|
785
|
+
column_names = column_names.map do |name|
|
786
|
+
original_name = attribute_alias?(name) ? attribute_alias(name) : name
|
787
|
+
original_name.to_sym
|
788
|
+
end
|
778
789
|
scope_columns, scope_values = scope_attributes.to_a.transpose
|
779
790
|
|
780
791
|
unless scope_columns.blank?
|
@@ -786,15 +797,13 @@ class ActiveRecord::Base
|
|
786
797
|
end
|
787
798
|
end
|
788
799
|
|
789
|
-
if finder_needs_type_condition?
|
790
|
-
|
791
|
-
|
792
|
-
array_of_attributes.each { |attrs| attrs << sti_name }
|
793
|
-
end
|
800
|
+
if finder_needs_type_condition? && !column_names.include?(inheritance_column.to_sym)
|
801
|
+
column_names << inheritance_column.to_sym
|
802
|
+
array_of_attributes.each { |attrs| attrs << sti_name }
|
794
803
|
end
|
795
804
|
|
796
805
|
columns = column_names.each_with_index.map do |name, i|
|
797
|
-
column =
|
806
|
+
column = schema_columns_hash[name.to_s]
|
798
807
|
raise ActiveRecord::Import::MissingColumnError.new(name.to_s, i) if column.nil?
|
799
808
|
column
|
800
809
|
end
|
@@ -859,13 +868,13 @@ class ActiveRecord::Base
|
|
859
868
|
model.id = id
|
860
869
|
|
861
870
|
timestamps.each do |attr, value|
|
862
|
-
model.send(attr
|
871
|
+
model.send("#{attr}=", value) if model.send(attr).nil?
|
863
872
|
end
|
864
873
|
end
|
865
874
|
end
|
866
875
|
|
867
876
|
deserialize_value = lambda do |column, value|
|
868
|
-
column =
|
877
|
+
column = schema_columns_hash[column]
|
869
878
|
return value unless column
|
870
879
|
if respond_to?(:type_caster)
|
871
880
|
type = type_for_attribute(column.name)
|
@@ -959,6 +968,14 @@ class ActiveRecord::Base
|
|
959
968
|
end
|
960
969
|
end
|
961
970
|
|
971
|
+
def schema_columns_hash
|
972
|
+
@schema_columns_hash ||= if respond_to?(:ignored_columns) && ignored_columns.any?
|
973
|
+
connection.schema_cache.columns_hash(table_name)
|
974
|
+
else
|
975
|
+
columns_hash
|
976
|
+
end
|
977
|
+
end
|
978
|
+
|
962
979
|
# We are eventually going to call Class.import <objects> so we build up a hash
|
963
980
|
# of class => objects to import.
|
964
981
|
def find_associated_objects_for_import(associated_objects_by_class, model)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require File.expand_path(File.dirname(__FILE__)
|
4
|
-
require File.expand_path(File.dirname(__FILE__)
|
5
|
-
require File.expand_path(File.dirname(__FILE__)
|
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")
|
6
6
|
|
7
7
|
should_support_mysql_import_functionality
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require File.expand_path(File.dirname(__FILE__)
|
4
|
-
require File.expand_path(File.dirname(__FILE__)
|
3
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../test_helper")
|
4
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../support/postgresql/import_examples")
|
5
5
|
|
6
6
|
should_support_postgresql_import_functionality
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require File.expand_path(File.dirname(__FILE__)
|
4
|
-
require File.expand_path(File.dirname(__FILE__)
|
3
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../test_helper")
|
4
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../support/sqlite3/import_examples")
|
5
5
|
|
6
6
|
should_support_sqlite3_import_functionality
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require File.expand_path(File.dirname(__FILE__)
|
4
|
-
require File.expand_path(File.dirname(__FILE__)
|
3
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../test_helper")
|
4
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../support/postgresql/import_examples")
|
5
5
|
|
6
6
|
should_support_postgresql_import_functionality
|
7
7
|
|
data/test/models/bike_maker.rb
CHANGED
data/test/models/topic.rb
CHANGED
@@ -1,6 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Topic < ActiveRecord::Base
|
4
|
+
if ENV['AR_VERSION'].to_i >= 6.0
|
5
|
+
self.ignored_columns = [:priority]
|
6
|
+
end
|
7
|
+
alias_attribute :name, :title
|
8
|
+
|
4
9
|
validates_presence_of :author_name
|
5
10
|
validates :title, numericality: { only_integer: true }, on: :context_test
|
6
11
|
validates :title, uniqueness: true
|
data/test/mysql2/import_test.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require File.expand_path(File.dirname(__FILE__)
|
4
|
-
require File.expand_path(File.dirname(__FILE__)
|
5
|
-
require File.expand_path(File.dirname(__FILE__)
|
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")
|
6
6
|
|
7
7
|
should_support_mysql_import_functionality
|
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require File.expand_path(File.dirname(__FILE__)
|
3
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../test_helper")
|
4
4
|
|
5
|
-
require File.expand_path(File.dirname(__FILE__)
|
6
|
-
require File.expand_path(File.dirname(__FILE__)
|
5
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../support/assertions")
|
6
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../support/mysql/import_examples")
|
7
7
|
|
8
8
|
should_support_mysql_import_functionality
|
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require File.expand_path(File.dirname(__FILE__)
|
3
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../test_helper")
|
4
4
|
|
5
|
-
require File.expand_path(File.dirname(__FILE__)
|
6
|
-
require File.expand_path(File.dirname(__FILE__)
|
5
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../support/assertions")
|
6
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../support/mysql/import_examples")
|
7
7
|
|
8
8
|
should_support_mysql_import_functionality
|
data/test/postgis/import_test.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require File.expand_path(File.dirname(__FILE__)
|
4
|
-
require File.expand_path(File.dirname(__FILE__)
|
3
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../test_helper")
|
4
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../support/postgresql/import_examples")
|
5
5
|
|
6
6
|
should_support_postgresql_import_functionality
|
7
7
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require File.expand_path(File.dirname(__FILE__)
|
4
|
-
require File.expand_path(File.dirname(__FILE__)
|
3
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../test_helper")
|
4
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../support/postgresql/import_examples")
|
5
5
|
|
6
6
|
should_support_postgresql_import_functionality
|
data/test/sqlite3/import_test.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require File.expand_path(File.dirname(__FILE__)
|
4
|
-
require File.expand_path(File.dirname(__FILE__)
|
3
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../test_helper")
|
4
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../support/sqlite3/import_examples")
|
5
5
|
|
6
6
|
should_support_sqlite3_import_functionality
|
@@ -26,7 +26,7 @@ def should_support_basic_on_duplicate_key_update
|
|
26
26
|
User.import(updated_users, on_duplicate_key_update: [:name])
|
27
27
|
assert User.count == updated_users.length
|
28
28
|
User.all.each_with_index do |user, i|
|
29
|
-
assert_equal user.name, users[i].name
|
29
|
+
assert_equal user.name, "#{users[i].name} Rothschild"
|
30
30
|
assert_equal 1, user.lock_version
|
31
31
|
end
|
32
32
|
end
|
@@ -50,7 +50,7 @@ def should_support_basic_on_duplicate_key_update
|
|
50
50
|
User.import(columns, updated_values, on_duplicate_key_update: [:name])
|
51
51
|
assert User.count == updated_values.length
|
52
52
|
User.all.each_with_index do |user, i|
|
53
|
-
assert_equal user.name, users[i].name
|
53
|
+
assert_equal user.name, "#{users[i].name} Rothschild"
|
54
54
|
assert_equal 1, user.lock_version
|
55
55
|
end
|
56
56
|
end
|
@@ -72,7 +72,7 @@ def should_support_basic_on_duplicate_key_update
|
|
72
72
|
User.import(updated_values, on_duplicate_key_update: [:name])
|
73
73
|
assert User.count == updated_values.length
|
74
74
|
User.all.each_with_index do |user, i|
|
75
|
-
assert_equal user.name, users[i].name
|
75
|
+
assert_equal user.name, "#{users[i].name} Rothschild"
|
76
76
|
assert_equal 1, user.lock_version
|
77
77
|
end
|
78
78
|
updated_values2 = User.all.map do |user|
|
@@ -82,7 +82,7 @@ def should_support_basic_on_duplicate_key_update
|
|
82
82
|
User.import(updated_values2, on_duplicate_key_update: [:name])
|
83
83
|
assert User.count == updated_values2.length
|
84
84
|
User.all.each_with_index do |user, i|
|
85
|
-
assert_equal user.name, users[i].name
|
85
|
+
assert_equal user.name, "#{users[i].name} Rothschild jr."
|
86
86
|
assert_equal 2, user.lock_version
|
87
87
|
end
|
88
88
|
end
|
@@ -104,7 +104,7 @@ def should_support_basic_on_duplicate_key_update
|
|
104
104
|
Account.import(updated_accounts, on_duplicate_key_update: [:id, :name])
|
105
105
|
assert Account.count == updated_accounts.length
|
106
106
|
Account.all.each_with_index do |user, i|
|
107
|
-
assert_equal user.name, accounts[i].name
|
107
|
+
assert_equal user.name, "#{accounts[i].name} Rothschild"
|
108
108
|
assert_equal 1, user.lock
|
109
109
|
end
|
110
110
|
end
|
@@ -128,7 +128,7 @@ def should_support_basic_on_duplicate_key_update
|
|
128
128
|
Account.import(columns, updated_values, on_duplicate_key_update: [:name])
|
129
129
|
assert Account.count == updated_values.length
|
130
130
|
Account.all.each_with_index do |user, i|
|
131
|
-
assert_equal user.name, accounts[i].name
|
131
|
+
assert_equal user.name, "#{accounts[i].name} Rothschild"
|
132
132
|
assert_equal 1, user.lock
|
133
133
|
end
|
134
134
|
end
|
@@ -150,7 +150,7 @@ def should_support_basic_on_duplicate_key_update
|
|
150
150
|
Account.import(updated_values, on_duplicate_key_update: [:name])
|
151
151
|
assert Account.count == updated_values.length
|
152
152
|
Account.all.each_with_index do |user, i|
|
153
|
-
assert_equal user.name, accounts[i].name
|
153
|
+
assert_equal user.name, "#{accounts[i].name} Rothschild"
|
154
154
|
assert_equal 1, user.lock
|
155
155
|
end
|
156
156
|
end
|
@@ -172,10 +172,11 @@ def should_support_basic_on_duplicate_key_update
|
|
172
172
|
Bike::Maker.import(updated_makers, on_duplicate_key_update: [:name])
|
173
173
|
assert Bike::Maker.count == updated_makers.length
|
174
174
|
Bike::Maker.all.each_with_index do |maker, i|
|
175
|
-
assert_equal maker.name, makers[i].name
|
175
|
+
assert_equal maker.name, "#{makers[i].name} bikes"
|
176
176
|
assert_equal 1, maker.lock_version
|
177
177
|
end
|
178
178
|
end
|
179
|
+
|
179
180
|
it 'update the lock_version of models separated by namespaces by array' do
|
180
181
|
makers = [
|
181
182
|
Bike::Maker.new(name: 'Yamaha'),
|
@@ -195,7 +196,7 @@ def should_support_basic_on_duplicate_key_update
|
|
195
196
|
Bike::Maker.import(columns, updated_values, on_duplicate_key_update: [:name])
|
196
197
|
assert Bike::Maker.count == updated_values.length
|
197
198
|
Bike::Maker.all.each_with_index do |maker, i|
|
198
|
-
assert_equal maker.name, makers[i].name
|
199
|
+
assert_equal maker.name, "#{makers[i].name} bikes"
|
199
200
|
assert_equal 1, maker.lock_version
|
200
201
|
end
|
201
202
|
end
|
@@ -217,7 +218,7 @@ def should_support_basic_on_duplicate_key_update
|
|
217
218
|
Bike::Maker.import(updated_values, on_duplicate_key_update: [:name])
|
218
219
|
assert Bike::Maker.count == updated_values.length
|
219
220
|
Bike::Maker.all.each_with_index do |maker, i|
|
220
|
-
assert_equal maker.name, makers[i].name
|
221
|
+
assert_equal maker.name, "#{makers[i].name} bikes"
|
221
222
|
assert_equal 1, maker.lock_version
|
222
223
|
end
|
223
224
|
end
|
@@ -316,6 +317,34 @@ def should_support_basic_on_duplicate_key_update
|
|
316
317
|
should_support_on_duplicate_key_update
|
317
318
|
should_update_fields_mentioned
|
318
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
|
319
348
|
end
|
320
349
|
|
321
350
|
context "with a table that has a non-standard primary key" do
|
data/test/test_helper.rb
CHANGED
@@ -24,7 +24,7 @@ if ActiveSupport::VERSION::STRING < "4.0"
|
|
24
24
|
require 'mocha/test_unit'
|
25
25
|
else
|
26
26
|
require 'active_support/testing/autorun'
|
27
|
-
require "mocha/
|
27
|
+
require "mocha/minitest"
|
28
28
|
end
|
29
29
|
|
30
30
|
require 'timecop'
|
@@ -84,7 +84,7 @@ ActiveSupport::Notifications.subscribe(/active_record.sql/) do |_, _, _, _, hsh|
|
|
84
84
|
end
|
85
85
|
|
86
86
|
require "factory_bot"
|
87
|
-
Dir[File.dirname(__FILE__)
|
87
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].sort.each { |file| require file }
|
88
88
|
|
89
89
|
# Load base/generic schema
|
90
90
|
require test_dir.join("schema/version")
|
@@ -92,7 +92,7 @@ require test_dir.join("schema/generic_schema")
|
|
92
92
|
adapter_schema = test_dir.join("schema/#{adapter}_schema.rb")
|
93
93
|
require adapter_schema if File.exist?(adapter_schema)
|
94
94
|
|
95
|
-
Dir[File.dirname(__FILE__)
|
95
|
+
Dir["#{File.dirname(__FILE__)}/models/*.rb"].sort.each { |file| require file }
|
96
96
|
|
97
97
|
# Prevent this deprecation warning from breaking the tests.
|
98
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.
|
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
|