activerecord-import 1.4.1 → 2.2.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.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yaml +73 -15
  3. data/.gitignore +4 -0
  4. data/.rubocop.yml +10 -7
  5. data/.rubocop_todo.yml +10 -16
  6. data/CHANGELOG.md +77 -1
  7. data/Dockerfile +23 -0
  8. data/Gemfile +20 -18
  9. data/README.markdown +46 -7
  10. data/Rakefile +5 -0
  11. data/activerecord-import.gemspec +4 -0
  12. data/benchmarks/benchmark.rb +3 -5
  13. data/benchmarks/lib/base.rb +8 -5
  14. data/benchmarks/lib/cli_parser.rb +9 -7
  15. data/docker-compose.yml +34 -0
  16. data/gemfiles/7.1.gemfile +3 -0
  17. data/gemfiles/7.2.gemfile +3 -0
  18. data/gemfiles/8.0.gemfile +3 -0
  19. data/lib/activerecord-import/active_record/adapters/trilogy_adapter.rb +8 -0
  20. data/lib/activerecord-import/adapters/abstract_adapter.rb +6 -5
  21. data/lib/activerecord-import/adapters/mysql_adapter.rb +24 -18
  22. data/lib/activerecord-import/adapters/postgresql_adapter.rb +26 -18
  23. data/lib/activerecord-import/adapters/sqlite3_adapter.rb +29 -23
  24. data/lib/activerecord-import/adapters/trilogy_adapter.rb +7 -0
  25. data/lib/activerecord-import/base.rb +4 -0
  26. data/lib/activerecord-import/import.rb +64 -36
  27. data/lib/activerecord-import/value_sets_parser.rb +1 -0
  28. data/lib/activerecord-import/version.rb +1 -1
  29. data/lib/activerecord-import.rb +0 -1
  30. data/test/adapters/janus_mysql2.rb +3 -0
  31. data/test/adapters/janus_trilogy.rb +11 -0
  32. data/test/adapters/mysql2_proxy.rb +3 -0
  33. data/test/adapters/postgresql_proxy.rb +3 -0
  34. data/test/adapters/trilogy.rb +11 -0
  35. data/test/database.yml.sample +21 -0
  36. data/test/github/database.yml +19 -2
  37. data/test/import_test.rb +15 -39
  38. data/test/janus_mysql2/import_test.rb +8 -0
  39. data/test/janus_trilogy/import_test.rb +7 -0
  40. data/test/jdbcmysql/import_test.rb +3 -3
  41. data/test/jdbcpostgresql/import_test.rb +2 -2
  42. data/test/jdbcsqlite3/import_test.rb +2 -2
  43. data/test/makara_postgis/import_test.rb +2 -2
  44. data/test/models/author.rb +9 -0
  45. data/test/models/bike_maker.rb +1 -0
  46. data/test/models/book.rb +10 -3
  47. data/test/models/composite_book.rb +19 -0
  48. data/test/models/composite_chapter.rb +12 -0
  49. data/test/models/customer.rb +14 -4
  50. data/test/models/order.rb +13 -4
  51. data/test/models/tag.rb +6 -1
  52. data/test/models/tag_alias.rb +7 -1
  53. data/test/models/topic.rb +6 -0
  54. data/test/models/widget.rb +10 -3
  55. data/test/mysql2/import_test.rb +3 -3
  56. data/test/mysql2_makara/import_test.rb +3 -3
  57. data/test/mysql2_proxy/import_test.rb +6 -0
  58. data/test/mysqlspatial2/import_test.rb +3 -3
  59. data/test/postgis/import_test.rb +2 -2
  60. data/test/postgresql/import_test.rb +2 -2
  61. data/test/postgresql_proxy/import_test.rb +6 -0
  62. data/test/schema/generic_schema.rb +4 -1
  63. data/test/schema/jdbcpostgresql_schema.rb +1 -1
  64. data/test/schema/postgis_schema.rb +1 -1
  65. data/test/schema/postgresql_schema.rb +35 -4
  66. data/test/sqlite3/import_test.rb +2 -2
  67. data/test/support/active_support/test_case_extensions.rb +1 -5
  68. data/test/support/mysql/import_examples.rb +6 -8
  69. data/test/support/postgresql/import_examples.rb +49 -53
  70. data/test/support/shared_examples/on_duplicate_key_update.rb +67 -10
  71. data/test/support/shared_examples/recursive_import.rb +106 -1
  72. data/test/test_helper.rb +13 -22
  73. data/test/trilogy/import_test.rb +7 -0
  74. data/test/value_sets_bytes_parser_test.rb +1 -1
  75. data/test/value_sets_records_parser_test.rb +1 -1
  76. metadata +37 -9
  77. data/gemfiles/4.2.gemfile +0 -4
  78. data/gemfiles/5.0.gemfile +0 -4
  79. data/gemfiles/5.1.gemfile +0 -4
  80. data/lib/activerecord-import/mysql2.rb +0 -9
  81. data/lib/activerecord-import/postgresql.rb +0 -9
  82. data/lib/activerecord-import/sqlite3.rb +0 -9
@@ -16,7 +16,7 @@ class BenchmarkBase
16
16
  end
17
17
  end
18
18
 
19
- # Returns an OpenStruct which contains two attritues, +description+ and +tms+ after performing an
19
+ # Returns a struct which contains two attritues, +description+ and +tms+ after performing an
20
20
  # actual benchmark.
21
21
  #
22
22
  # == PARAMETERS
@@ -24,18 +24,21 @@ class BenchmarkBase
24
24
  # * blk - the block of code to benchmark
25
25
  #
26
26
  # == RETURNS
27
- # An OpenStruct object with the following attributes:
27
+ # A struct 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
+
31
+ BmStruct = Struct.new( :description, :tms, :failed, keyword_init: true )
32
+
33
+ def bm( description, &block )
31
34
  tms = nil
32
35
  puts "Benchmarking #{description}"
33
36
 
34
- Benchmark.bm { |x| tms = x.report { yield } }
37
+ Benchmark.bm { |x| tms = x.report(&block) }
35
38
  delete_all
36
39
  failed = false
37
40
 
38
- OpenStruct.new description: description, tms: tms, failed: failed
41
+ BmStruct.new( description: description, tms: tms, failed: failed )
39
42
  end
40
43
 
41
44
  # Given a model class (ie: Topic), and an array of columns and value sets
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'optparse'
4
- require 'ostruct'
5
4
 
6
5
  #
7
6
  # == PARAMETERS
@@ -10,7 +9,7 @@ require 'ostruct'
10
9
  # * t - the table types to test. ie: myisam, innodb, memory, temporary, etc.
11
10
  #
12
11
  module BenchmarkOptionParser
13
- BANNER = "Usage: ruby #{$0} [options]\nSee ruby #{$0} -h for more options."
12
+ BANNER = "Usage: ruby #{$0} [options]\nSee ruby #{$0} -h for more options.".freeze
14
13
 
15
14
  def self.print_banner
16
15
  puts BANNER
@@ -29,7 +28,7 @@ module BenchmarkOptionParser
29
28
  print_valid_table_types( options, prefix: " " )
30
29
  end
31
30
 
32
- # TODO IMPLEMENT THIS
31
+ # TODO: IMPLEMENT THIS
33
32
  def self.print_valid_table_types( options, hsh = { prefix: '' } )
34
33
  if !options.table_types.keys.empty?
35
34
  options.table_types.keys.sort.each { |type| puts hsh[:prefix].to_s + type.to_s }
@@ -38,8 +37,11 @@ module BenchmarkOptionParser
38
37
  end
39
38
  end
40
39
 
40
+ OptionsStruct = Struct.new( :adapter, :table_types, :delete_on_finish, :number_of_objects, :outputs,
41
+ :benchmark_all_types, keyword_init: true )
42
+ OutputStruct = Struct.new( :format, :filename, keyword_init: true )
41
43
  def self.parse( args )
42
- options = OpenStruct.new(
44
+ options = OptionsStruct.new(
43
45
  adapter: 'mysql2',
44
46
  table_types: {},
45
47
  delete_on_finish: true,
@@ -81,12 +83,12 @@ module BenchmarkOptionParser
81
83
 
82
84
  # print results in CSV format
83
85
  opts.on( "--to-csv [String]", "Print results in a CSV file format" ) do |filename|
84
- options.outputs << OpenStruct.new( format: 'csv', filename: filename)
86
+ options.outputs << OutputStruct.new( format: 'csv', filename: filename)
85
87
  end
86
88
 
87
89
  # print results in HTML format
88
90
  opts.on( "--to-html [String]", "Print results in HTML format" ) do |filename|
89
- options.outputs << OpenStruct.new( format: 'html', filename: filename )
91
+ options.outputs << OutputStruct.new( format: 'html', filename: filename )
90
92
  end
91
93
  end # end opt.parse!
92
94
 
@@ -100,7 +102,7 @@ module BenchmarkOptionParser
100
102
  end
101
103
 
102
104
  options.number_of_objects = [1000] if options.number_of_objects.empty?
103
- options.outputs = [OpenStruct.new( format: 'html', filename: 'benchmark.html')] if options.outputs.empty?
105
+ options.outputs = [OutputStruct.new( format: 'html', filename: 'benchmark.html')] if options.outputs.empty?
104
106
 
105
107
  print_options( options )
106
108
 
@@ -0,0 +1,34 @@
1
+ version: "3.5"
2
+
3
+ services:
4
+ mysql:
5
+ platform: linux/x86_64
6
+ image: mysql:5.7
7
+ volumes:
8
+ - mysql-data:/var/lib/mysql
9
+ ports:
10
+ - "3306:3306"
11
+
12
+ postgresql:
13
+ image: postgres:latest
14
+ volumes:
15
+ - postgresql-data:/var/lib/postgresql/data
16
+ ports:
17
+ - "5432:5432"
18
+
19
+ app:
20
+ build:
21
+ context: .
22
+ environment:
23
+ DB_HOST: mysql
24
+ AR_VERSION: 7.0
25
+ volumes:
26
+ - .:/usr/src/app
27
+ depends_on:
28
+ - mysql
29
+ - postgresql
30
+ command: tail -f /dev/null
31
+
32
+ volumes:
33
+ mysql-data:
34
+ postgresql-data:
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ gem 'activerecord', '~> 7.1.0'
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ gem 'activerecord', '~> 7.2.0'
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ gem 'activerecord', '~> 8.0.0'
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_record/connection_adapters/trilogy_adapter"
4
+ require "activerecord-import/adapters/trilogy_adapter"
5
+
6
+ class ActiveRecord::ConnectionAdapters::TrilogyAdapter
7
+ include ActiveRecord::Import::TrilogyAdapter
8
+ end
@@ -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 = if sql.is_a?( String )
13
- [sql, '']
14
- elsif sql.is_a?( Array )
15
- [sql.shift, sql.join( ' ' )]
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 = if sql.is_a?( String )
17
- [sql, '']
18
- elsif sql.is_a?( Array )
19
- [sql.shift, sql.join( ' ' )]
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.size + post_sql.size
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 NO_MAX_PACKET == max || total_bytes <= max || options[:force_single_insert]
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.first
89
- locking_column = args.last
90
- if arg.is_a?( Array )
91
- sql << sql_for_on_duplicate_key_update_as_array( table_name, locking_column, arg )
92
- elsif arg.is_a?( Hash )
93
- sql << sql_for_on_duplicate_key_update_as_hash( table_name, locking_column, arg )
94
- elsif arg.is_a?( String )
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
- qc = quote_column_name( column )
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
- qc1 = quote_column_name( column1 )
114
- qc2 = quote_column_name( column2 )
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 = if sql.is_a?( String )
16
- [sql, '']
17
- elsif sql.is_a?( Array )
18
- [sql.shift, sql.join( ' ' )]
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
- if arg.is_a?( Hash )
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
- elsif arg.is_a?( Array )
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
- if columns.is_a?( Array )
155
- sql << sql_for_on_duplicate_key_update_as_array( table_name, locking_column, columns )
156
- elsif columns.is_a?( Hash )
157
- sql << sql_for_on_duplicate_key_update_as_hash( table_name, locking_column, columns )
158
- elsif columns.is_a?( String )
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
- qc = quote_column_name( column )
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
- qc1 = quote_column_name( column1 )
181
- qc2 = quote_column_name( column2 )
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 = '(' + Array( conflict_target ).reject( &:blank? ).join( ', ' ) + ') '
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 = if sql.is_a?( String )
28
- [sql, '']
29
- elsif sql.is_a?( Array )
30
- [sql.shift, sql.join( ' ' )]
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
- if supports_on_duplicate_key_update?
60
- # Options :recursive and :on_duplicate_key_ignore are mutually exclusive
61
- if (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] )
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
- if arg.is_a?( Hash )
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
- elsif arg.is_a?( Array )
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
- if columns.is_a?( Array )
118
- sql << sql_for_on_duplicate_key_update_as_array( table_name, locking_column, columns )
119
- elsif columns.is_a?( Hash )
120
- sql << sql_for_on_duplicate_key_update_as_hash( table_name, locking_column, columns )
121
- elsif columns.is_a?( String )
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
- qc = quote_column_name( column )
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
- qc1 = quote_column_name( column1 )
144
- qc2 = quote_column_name( column2 )
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 = '(' + Array( conflict_target ).reject( &:blank? ).join( ', ' ) + ') '
161
+ sql = "(#{Array( conflict_target ).reject( &:blank? ).join( ', ' )}) "
156
162
  sql += "WHERE #{index_predicate} " if index_predicate
157
163
  sql
158
164
  end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "activerecord-import/adapters/mysql_adapter"
4
+
5
+ module ActiveRecord::Import::TrilogyAdapter
6
+ include ActiveRecord::Import::MysqlAdapter
7
+ end
@@ -11,11 +11,15 @@ module ActiveRecord::Import
11
11
  case adapter
12
12
  when 'mysql2_makara' then 'mysql2'
13
13
  when 'mysql2spatial' then 'mysql2'
14
+ when 'mysql2_proxy' then 'mysql2'
15
+ when 'janus_mysql2' then 'mysql2'
14
16
  when 'spatialite' then 'sqlite3'
15
17
  when 'postgresql_makara' then 'postgresql'
18
+ when 'postgresql_proxy' then 'postgresql'
16
19
  when 'makara_postgis' then 'postgresql'
17
20
  when 'postgis' then 'postgresql'
18
21
  when 'cockroachdb' then 'postgresql'
22
+ when 'janus_trilogy' then 'trilogy'
19
23
  else adapter
20
24
  end
21
25
  end