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.
- checksums.yaml +4 -4
- data/.github/workflows/test.yaml +20 -3
- data/.rubocop.yml +4 -4
- data/.rubocop_todo.yml +6 -16
- data/CHANGELOG.md +19 -1
- data/Dockerfile +23 -0
- data/Gemfile +6 -6
- data/README.markdown +19 -4
- data/benchmarks/benchmark.rb +3 -3
- data/benchmarks/lib/base.rb +2 -2
- data/benchmarks/lib/cli_parser.rb +1 -1
- data/docker-compose.yml +34 -0
- data/gemfiles/7.1.gemfile +3 -0
- 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/database.yml.sample +2 -0
- 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/book.rb +1 -1
- data/test/models/customer.rb +6 -4
- data/test/models/order.rb +6 -4
- data/test/models/tag_alias.rb +3 -1
- 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 +4 -1
- data/test/schema/jdbcpostgresql_schema.rb +1 -1
- data/test/schema/postgis_schema.rb +1 -1
- data/test/schema/postgresql_schema.rb +1 -4
- data/test/sqlite3/import_test.rb +2 -2
- data/test/support/shared_examples/on_duplicate_key_update.rb +39 -10
- data/test/support/shared_examples/recursive_import.rb +1 -1
- 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 +9 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f8b122b955b4a926db451a6a3ef72405ade6d69b54876bccb9ea51680486b328
|
4
|
+
data.tar.gz: 3af5c65f25ffb54d338d012aab4f3608513071287c8a759f3ba678850a81f6e0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 638f6a8062713b07b1c2ebe866fa647c254d42e594c0fa056b5a710bcd9a2560b2217db73a89f5804c9fc1a71d5de05fc98625771e6225e9e148f58048618079
|
7
|
+
data.tar.gz: 806d66d95034276b0daec9c6c207b8a6187ec0950a44b312267aeef4d491b1c9f5e036641df35950296180f124315fc220e9af5d5b4d4057278176dcf667b1c3
|
data/.github/workflows/test.yaml
CHANGED
@@ -20,19 +20,33 @@ jobs:
|
|
20
20
|
fail-fast: false
|
21
21
|
matrix:
|
22
22
|
ruby:
|
23
|
-
- 3.
|
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@
|
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@
|
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/
|
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,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
|
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'
|
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"
|
35
|
-
gem "activerecord-jdbcmysql-adapter"
|
36
|
-
gem "activerecord-jdbcpostgresql-adapter"
|
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.
|
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
|
|
@@ -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).
|
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 }
|
data/docker-compose.yml
ADDED
@@ -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:
|
@@ -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
|