activerecord-import 1.4.1 → 1.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yaml +20 -3
  3. data/.rubocop.yml +4 -4
  4. data/.rubocop_todo.yml +6 -16
  5. data/CHANGELOG.md +19 -1
  6. data/Dockerfile +23 -0
  7. data/Gemfile +6 -6
  8. data/README.markdown +19 -4
  9. data/benchmarks/benchmark.rb +3 -3
  10. data/benchmarks/lib/base.rb +2 -2
  11. data/benchmarks/lib/cli_parser.rb +1 -1
  12. data/docker-compose.yml +34 -0
  13. data/gemfiles/7.1.gemfile +3 -0
  14. data/lib/activerecord-import/adapters/abstract_adapter.rb +6 -5
  15. data/lib/activerecord-import/adapters/mysql_adapter.rb +24 -18
  16. data/lib/activerecord-import/adapters/postgresql_adapter.rb +26 -18
  17. data/lib/activerecord-import/adapters/sqlite3_adapter.rb +29 -23
  18. data/lib/activerecord-import/import.rb +39 -22
  19. data/lib/activerecord-import/value_sets_parser.rb +1 -0
  20. data/lib/activerecord-import/version.rb +1 -1
  21. data/test/database.yml.sample +2 -0
  22. data/test/jdbcmysql/import_test.rb +3 -3
  23. data/test/jdbcpostgresql/import_test.rb +2 -2
  24. data/test/jdbcsqlite3/import_test.rb +2 -2
  25. data/test/makara_postgis/import_test.rb +2 -2
  26. data/test/models/bike_maker.rb +1 -0
  27. data/test/models/book.rb +1 -1
  28. data/test/models/customer.rb +6 -4
  29. data/test/models/order.rb +6 -4
  30. data/test/models/tag_alias.rb +3 -1
  31. data/test/models/topic.rb +5 -0
  32. data/test/mysql2/import_test.rb +3 -3
  33. data/test/mysql2_makara/import_test.rb +3 -3
  34. data/test/mysqlspatial2/import_test.rb +3 -3
  35. data/test/postgis/import_test.rb +2 -2
  36. data/test/postgresql/import_test.rb +2 -2
  37. data/test/schema/generic_schema.rb +4 -1
  38. data/test/schema/jdbcpostgresql_schema.rb +1 -1
  39. data/test/schema/postgis_schema.rb +1 -1
  40. data/test/schema/postgresql_schema.rb +1 -4
  41. data/test/sqlite3/import_test.rb +2 -2
  42. data/test/support/shared_examples/on_duplicate_key_update.rb +39 -10
  43. data/test/support/shared_examples/recursive_import.rb +1 -1
  44. data/test/test_helper.rb +3 -3
  45. data/test/value_sets_bytes_parser_test.rb +1 -1
  46. data/test/value_sets_records_parser_test.rb +1 -1
  47. metadata +9 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1b9c717d31cf5a4012568c9d8497947466408be7fef5610fba9143f7a911ed7c
4
- data.tar.gz: 925bc5f645152eeb09f9583e9d50b9be67c4bfa8049c303571f82649262e4d5b
3
+ metadata.gz: f8b122b955b4a926db451a6a3ef72405ade6d69b54876bccb9ea51680486b328
4
+ data.tar.gz: 3af5c65f25ffb54d338d012aab4f3608513071287c8a759f3ba678850a81f6e0
5
5
  SHA512:
6
- metadata.gz: 409d66e4d4e6e9ac31940cea097837d76c93cbeb4b95461323afc6a5f2ace736f945705e5ef33f2a851bb92c13c27e19ffbc14c7e776a0366f1d76091cafd51f
7
- data.tar.gz: 6a0eaa48b85f7b1863dfb2b04c3c193a5e7e1108084556ba1b25fa303bccb40f62dd706ec8d4b5c3394239f167eb1807dfff4fe292edc1e4ad550719a9a63446
6
+ metadata.gz: 638f6a8062713b07b1c2ebe866fa647c254d42e594c0fa056b5a710bcd9a2560b2217db73a89f5804c9fc1a71d5de05fc98625771e6225e9e148f58048618079
7
+ data.tar.gz: 806d66d95034276b0daec9c6c207b8a6187ec0950a44b312267aeef4d491b1c9f5e036641df35950296180f124315fc220e9af5d5b4d4057278176dcf667b1c3
@@ -20,19 +20,33 @@ jobs:
20
20
  fail-fast: false
21
21
  matrix:
22
22
  ruby:
23
- - 3.1
23
+ - 3.2
24
24
  env:
25
+ - AR_VERSION: '7.1'
26
+ RUBYOPT: --enable-frozen-string-literal
25
27
  - AR_VERSION: '7.0'
26
28
  RUBYOPT: --enable-frozen-string-literal
27
29
  - AR_VERSION: 6.1
28
30
  RUBYOPT: --enable-frozen-string-literal
29
31
  include:
32
+ - ruby: 3.1
33
+ env:
34
+ AR_VERSION: '7.1'
35
+ - ruby: 3.1
36
+ env:
37
+ AR_VERSION: '7.0'
38
+ - ruby: 3.1
39
+ env:
40
+ AR_VERSION: 6.1
30
41
  - ruby: '3.0'
31
42
  env:
32
43
  AR_VERSION: '7.0'
33
44
  - ruby: '3.0'
34
45
  env:
35
46
  AR_VERSION: 6.1
47
+ - ruby: jruby
48
+ env:
49
+ AR_VERSION: '7.0'
36
50
  - ruby: 2.7
37
51
  env:
38
52
  AR_VERSION: '7.0'
@@ -42,6 +56,9 @@ jobs:
42
56
  - ruby: 2.7
43
57
  env:
44
58
  AR_VERSION: '6.0'
59
+ - ruby: jruby-9.3.10.0
60
+ env:
61
+ AR_VERSION: '6.1'
45
62
  - ruby: 2.6
46
63
  env:
47
64
  AR_VERSION: 5.2
@@ -59,7 +76,7 @@ jobs:
59
76
  AR_VERSION: ${{ matrix.env.AR_VERSION }}
60
77
  DB_DATABASE: activerecord_import_test
61
78
  steps:
62
- - uses: actions/checkout@v2
79
+ - uses: actions/checkout@v4
63
80
  - uses: ruby/setup-ruby@v1
64
81
  with:
65
82
  ruby-version: ${{ matrix.ruby }}
@@ -98,7 +115,7 @@ jobs:
98
115
  env:
99
116
  AR_VERSION: '7.0'
100
117
  steps:
101
- - uses: actions/checkout@v2
118
+ - uses: actions/checkout@v4
102
119
  - uses: ruby/setup-ruby@v1
103
120
  with:
104
121
  ruby-version: 2.7
data/.rubocop.yml CHANGED
@@ -66,10 +66,10 @@ Style/SymbolArray:
66
66
  Style/TrailingCommaInArrayLiteral:
67
67
  Enabled: false
68
68
 
69
- Layout/AlignArguments:
69
+ Layout/ArgumentAlignment:
70
70
  Enabled: false
71
71
 
72
- Layout/AlignParameters:
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/IndentHeredoc:
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/UncommunicativeMethodParamName:
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 2016-03-17 18:14:55 -0700 using RuboCop version 0.38.0.
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: 4
22
- # Cop supports --auto-correct.
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
- # Cop supports --auto-correct.
31
- # Configuration parameters: Keywords.
32
- # Keywords: TODO, FIXME, OPTIMIZE, HACK, REVIEW
33
- Style/CommentAnnotation:
24
+ Style/CombinableLoops:
34
25
  Exclude:
35
- - 'benchmarks/lib/cli_parser.rb'
36
- - 'lib/activerecord-import/import.rb'
26
+ - 'test/support/shared_examples/recursive_import.rb'
data/CHANGELOG.md CHANGED
@@ -1,8 +1,26 @@
1
+ ## Changes in 1.5.1
2
+
3
+ ### Fixes
4
+
5
+ * Stop memoizing schema_columns_hash so dynamic schema changes are picked up. Thanks to @koshigoe via \##812.
6
+
7
+ ## Changes in 1.5.0
8
+
9
+ ### New Features
10
+
11
+ * Add Rails 7.1 support. Thanks to @gucki via \##807.
12
+ * Add support for alias attributes. Thanks to @leonidkroka via \##799.
13
+
14
+ ### Fixes
15
+
16
+ * Support for multi-byte column names when splitting queries. Thanks to @TakuyaKurimoto via \##801.
17
+ * Fix issue with track_validation_failures when import models. Thanks to @OtaYohihiro via \##798.
18
+
1
19
  ## Changes in 1.4.1
2
20
 
3
21
  ### Fixes
4
22
 
5
- * Fix importing models that have required belongs_to associations and use composite primary keys. Thanks to @thoughtbot-summer vi \##783.
23
+ * Fix importing models that have required belongs_to associations and use composite primary keys. Thanks to @thoughtbot-summer via \##783.
6
24
 
7
25
  ## Changes in 1.4.0
8
26
 
data/Dockerfile ADDED
@@ -0,0 +1,23 @@
1
+ # Use the official Ruby 3.2 image as a base image
2
+ ARG RUBY_VERSION=3.2
3
+ FROM ruby:${RUBY_VERSION}-bullseye
4
+
5
+ # Set the working directory
6
+ WORKDIR /usr/src/app
7
+
8
+ # Install system packages
9
+ RUN apt-get update -qq && \
10
+ apt-get install -y default-mysql-client postgresql postgresql-contrib vim && \
11
+ apt-get clean
12
+
13
+ # Set environment variables
14
+ ENV AR_VERSION=7.0
15
+
16
+ # Copy all files
17
+ COPY . .
18
+
19
+ # Move sample database.yml and install gems
20
+ RUN mv test/database.yml.sample test/database.yml && \
21
+ bundle install
22
+
23
+ CMD ["irb"]
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', '~> 0.71.0'
18
+ gem 'rubocop'
19
19
  gem 'rake'
20
20
  end
21
21
 
@@ -31,16 +31,16 @@ end
31
31
  platforms :jruby do
32
32
  gem "jdbc-mysql"
33
33
  gem "jdbc-postgres"
34
- gem "activerecord-jdbcsqlite3-adapter", "~> 1.3"
35
- gem "activerecord-jdbcmysql-adapter", "~> 1.3"
36
- gem "activerecord-jdbcpostgresql-adapter", "~> 1.3"
34
+ gem "activerecord-jdbcsqlite3-adapter"
35
+ gem "activerecord-jdbcmysql-adapter"
36
+ gem "activerecord-jdbcpostgresql-adapter"
37
37
  end
38
38
 
39
39
  # Support libs
40
40
  gem "factory_bot"
41
41
  gem "timecop"
42
42
  gem "chronic"
43
- gem "mocha", "~> 1.3.0"
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.12.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
- NOTE: This only works with PostgreSQL and ActiveRecord objects. This won't work with
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
- NOTE: If you are using ActiveRecord 7.0 or later, please use `ActiveRecord.default_timezone` instead.
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: These instructions will only work if you are using version 0.2.0 or higher.
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
 
@@ -624,6 +626,19 @@ AR_VERSION=7.0 bundle exec rake test:postgresql test:sqlite3 test:mysql2
624
626
 
625
627
  Once you have pushed up your changes, you can find your CI results [here](https://github.com/zdennis/activerecord-import/actions).
626
628
 
629
+ #### Docker Setup
630
+
631
+ Before you begin, make sure you have [Docker](https://www.docker.com/products/docker-desktop/) and [Docker Compose](https://docs.docker.com/compose/) installed on your machine. If you don't, you can install both via Homebrew using the following command:
632
+
633
+ ```bash
634
+ brew install docker && brew install docker-compose
635
+ ```
636
+ ##### Steps
637
+
638
+ 1. In your terminal run `docker-compose up --build`
639
+ 1. In another tab/window run `docker-compose exec app bash`
640
+ 1. In that same terminal run the mysql2 test by running `bundle exec rake test:mysql2`
641
+
627
642
  ## Issue Triage [![Open Source Helpers](https://www.codetriage.com/zdennis/activerecord-import/badges/users.svg)](https://www.codetriage.com/zdennis/activerecord-import)
628
643
 
629
644
  You can triage issues which may include reproducing bug reports or asking for vital information, such as version numbers or reproduction instructions. If you would like to start triaging issues, one easy way to get started is to [subscribe to activerecord-import on CodeTriage](https://www.codetriage.com/zdennis/activerecord-import).
@@ -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__) + "/models/*.rb"].each { |file| require 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..-1].downcase
57
- clazz = Object.const_get( clazz_str + "Benchmark" )
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|
@@ -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 { yield } }
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 }
@@ -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'
@@ -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