activerecord-jdbc-adapter 60.0-java → 61.0-java

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 807d5401be5ff0aba3877e221cd597609d8b88b7388cd2bde43861565b3e008c
4
- data.tar.gz: ac01cd946ad85a3c4b854d198408f61bff55ddd6a97dd6e3b47ceab20eb78e6a
3
+ metadata.gz: c0f6e1df31960b2169ea7d6c7d664a5d44a3302e0382957842124a0ed1090488
4
+ data.tar.gz: 63a7540994c1ef969cb67702fdf0860ab17f47632b985b9d52f690a5e247ea51
5
5
  SHA512:
6
- metadata.gz: a8e2cbd16ca12f5fcd1403a899ca97328f5887b670789939e3ca83dc9046dff670c75def5e294ad0a19433a528355147f9974cfaac077f838491286f6786af47
7
- data.tar.gz: cc77979db17af2578c841b16d95bf7f7b4203e437fb490016509498c43348486399b046c8b0140795848d6cd44f67e3fa17bd1f6bd16a854bbc3569959bf3522
6
+ metadata.gz: e367ae078f402928bb460a0677e506282deb20c802ccb6d4fafe27fea61717ea64048b6ef4b77b1143da97b56efbe71373b80e2ea870f007a6bcbf394a7be637
7
+ data.tar.gz: fb746f2b1260275e7cb4a7fe6f20c7720f5f23525e5a9ea5ecc852dac7f2141f01d177419ef701b43960ea36c42cb476536f229e575551200d2a5c8cc532c6ab
data/.gitignore CHANGED
@@ -2,6 +2,7 @@
2
2
  *.tgz
3
3
  *~
4
4
  *.log
5
+ /log/
5
6
  patches*
6
7
  *#
7
8
  TAGS
@@ -30,4 +31,4 @@ Gemfile.lock
30
31
  .idea
31
32
  .settings
32
33
  activerecord-jdbc.iml
33
- lib/arjdbc/jdbc/adapter_java.jar
34
+ lib/arjdbc/jdbc/adapter_java.jar
@@ -15,7 +15,7 @@ install:
15
15
 
16
16
  language: ruby
17
17
  rvm:
18
- - jruby-9.2.7.0
18
+ - jruby-9.2.14.0
19
19
  jdk:
20
20
  - openjdk8
21
21
 
@@ -37,8 +37,8 @@ before_script:
37
37
  mysql -e "grant all privileges on activerecord_unittest.* to rails@localhost;" && \
38
38
  mysql -e "grant all privileges on activerecord_unittest2.* to rails@localhost;" && \
39
39
  mysql -e "grant all privileges on inexistent_activerecord_unittest.* to rails@localhost;" && \
40
- mysql -e "CREATE DATABASE activerecord_unittest DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;" && \
41
- mysql -e "CREATE DATABASE activerecord_unittest2 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;" \
40
+ mysql -e "CREATE DATABASE activerecord_unittest DEFAULT CHARACTER SET utf8mb4;" && \
41
+ mysql -e "CREATE DATABASE activerecord_unittest2 DEFAULT CHARACTER SET utf8mb4;" \
42
42
  || true
43
43
  - |
44
44
  [ "$DB" == "postgresql" ] && [ "$TEST_PREFIX" == "rails:" ] && \
@@ -48,7 +48,7 @@ before_script:
48
48
 
49
49
  env:
50
50
  global:
51
- - AR_VERSION="6-0-stable"
51
+ - AR_VERSION="master"
52
52
  matrix:
53
53
  allow_failures:
54
54
  - rvm: jruby-head
@@ -69,6 +69,9 @@ matrix:
69
69
  - addons:
70
70
  postgresql: "10"
71
71
  env: DB=postgresql PREPARED_STATEMENTS=true INSERT_RETURNING=true
72
+ - addons:
73
+ postgresql: "10"
74
+ env: DB=postgresql PREPARED_STATEMENTS=true JRUBY_OPTS=-J-Duser.timezone=America/Detroit
72
75
  - addons:
73
76
  postgresql: "9.4"
74
77
  env: DB=postgresql PREPARED_STATEMENTS=true
@@ -108,18 +111,18 @@ matrix:
108
111
  env: DB=mariadb PREPARED_STATEMENTS=true
109
112
 
110
113
  # Rails test-suite :
111
- - env: DB=mysql2 TEST_PREFIX="rails:" AR_VERSION="6-0-stable" # PS off by default
112
- - env: DB=mysql2 TEST_PREFIX="rails:" AR_VERSION="6-0-stable" PREPARED_STATEMENTS=true
113
- - env: DB=mysql2 TEST_PREFIX="rails:" AR_VERSION="6-0-stable" DRIVER=MariaDB
114
+ - env: DB=mysql2 TEST_PREFIX="rails:" AR_VERSION="6-1-stable" # PS off by default
115
+ - env: DB=mysql2 TEST_PREFIX="rails:" AR_VERSION="6-1-stable" PREPARED_STATEMENTS=true
116
+ - env: DB=mysql2 TEST_PREFIX="rails:" AR_VERSION="6-1-stable" DRIVER=MariaDB
114
117
 
115
118
  - addons:
116
119
  postgresql: "10"
117
- env: DB=postgresql TEST_PREFIX="rails:" AR_VERSION="6-0-stable" # PS on by default
120
+ env: DB=postgresql TEST_PREFIX="rails:" AR_VERSION="6-1-stable" # PS on by default
118
121
  - addons:
119
122
  postgresql: "10"
120
- env: DB=postgresql TEST_PREFIX="rails:" AR_VERSION="6-0-stable" PREPARED_STATEMENTS=false
123
+ env: DB=postgresql TEST_PREFIX="rails:" AR_VERSION="6-1-stable" PREPARED_STATEMENTS=false
121
124
  - addons:
122
125
  postgresql: "9.4"
123
- env: DB=postgresql TEST_PREFIX="rails:" AR_VERSION="6-0-stable" # PS on by default
126
+ env: DB=postgresql TEST_PREFIX="rails:" AR_VERSION="6-1-stable" # PS on by default
124
127
 
125
- - env: DB=sqlite3 TEST_PREFIX="rails:" AR_VERSION="6-0-stable"
128
+ - env: DB=sqlite3 TEST_PREFIX="rails:" AR_VERSION="6-1-stable"
data/Gemfile CHANGED
@@ -59,7 +59,7 @@ end
59
59
 
60
60
  group :rails do
61
61
  group :test do
62
- gem 'minitest', '~> 5.11.3', require: nil
62
+ gem 'minitest', '~> 5.12.2', require: nil
63
63
  gem 'minitest-excludes', '~> 2.0.1', require: nil
64
64
  gem 'minitest-rg', require: nil
65
65
 
data/README.md CHANGED
@@ -23,7 +23,8 @@ Versions are targeted at certain versions of Rails and live on their own branche
23
23
  | 50.x | 5.0.x | 50-stable | 9.1.x | 7 |
24
24
  | 51.x | 5.1.x | 51-stable | 9.1.x | 7 |
25
25
  | 52.x | 5.2.x | 52-stable | 9.1.x | 7 |
26
- | 60.x | 6.0.x | master | 9.2.7 | 8 |
26
+ | 60.x | 6.0.x | 60-stable | 9.2.7 | 8 |
27
+ | 61.x | 6.1.x | master | 9.2.7 | 8 |
27
28
 
28
29
  Note that JRuby 9.1.x is end-of-life. We recommend Java 8 at a minimum for all
29
30
  versions.
@@ -116,8 +117,8 @@ Proceed as with Rails; specify `ActiveRecord` in your Bundle along with the
116
117
  chosen JDBC adapter(s), this time sample *Gemfile* for MySQL:
117
118
 
118
119
  ```ruby
119
- gem 'activerecord', '~> 5.0.6'
120
- gem 'activerecord-jdbcmysql-adapter', :platform => :jruby
120
+ gem 'activerecord', '~> 6.0.3'
121
+ gem 'activerecord-jdbcmysql-adapter', '~> 60.2', :platform => :jruby
121
122
  ```
122
123
 
123
124
  When you `require 'bundler/setup'` everything will be set up for you as expected.
@@ -126,13 +127,13 @@ When you `require 'bundler/setup'` everything will be set up for you as expected
126
127
 
127
128
  Install the needed gems with JRuby, for example:
128
129
 
129
- gem install activerecord -v "~> 5.0.6"
130
- gem install activerecord-jdbc-adapter --ignore-dependencies
130
+ gem install activerecord -v "~> 6.0.3"
131
+ gem install activerecord-jdbc-adapter -v "~> 60.2" --ignore-dependencies
131
132
 
132
133
  If you wish to use the adapter for a specific database, you can install it
133
134
  directly and the (jdbc-) driver gem (dependency) will be installed as well:
134
135
 
135
- jruby -S gem install activerecord-jdbcmysql-adapter
136
+ jruby -S gem install activerecord-jdbcmysql-adapter -v "~> 60.2"
136
137
 
137
138
  Your program should include:
138
139
 
@@ -172,7 +173,7 @@ ask on the #JRuby IRC channel on http://freenode.net/ (try [web-chat][6]).
172
173
  This project was originally written by [Nick Sieger](http://github.com/nicksieger)
173
174
  and [Ola Bini](http://github.com/olabini) with lots of help from the JRuby community.
174
175
  Polished 3.x compatibility and 4.x support (for AR-JDBC >= 1.3.0) was managed by
175
- [Karol Bucek](http://github.com/kares) among others. Support for Rails 6 was
176
+ [Karol Bucek](http://github.com/kares) among others. Support for Rails 6.0 and 6.1 was
176
177
  contributed by [shellyBits GmbH](https://shellybits.ch/)
177
178
 
178
179
  ## License
@@ -41,7 +41,7 @@ Gem::Specification.new do |gem|
41
41
  gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
42
42
  gem.test_files = gem.files.grep(%r{^test/})
43
43
 
44
- gem.add_dependency 'activerecord', '~> 6.0.0'
44
+ gem.add_dependency 'activerecord', '~> 6.1.0'
45
45
 
46
46
  #gem.add_development_dependency 'test-unit', '2.5.4'
47
47
  #gem.add_development_dependency 'test-unit-context', '>= 0.3.0'
@@ -2,5 +2,5 @@ require 'arel/visitors/compat'
2
2
 
3
3
  class Arel::Visitors::PostgreSQL
4
4
  # AREL converts bind argument markers "?" to "$n" for PG, but JDBC wants "?".
5
- remove_method :visit_Arel_Nodes_BindParam if ArJdbc::AR42
5
+ remove_method :bind_block
6
6
  end
@@ -56,6 +56,7 @@ module ArJdbc
56
56
  case exception
57
57
  when SystemExit, SignalException, NoMemoryError then exception
58
58
  when ActiveModel::RangeError, TypeError, RuntimeError then exception
59
+ when ActiveRecord::ConnectionNotEstablished then exception
59
60
  else super
60
61
  end
61
62
  end
@@ -15,14 +15,15 @@ module ArJdbc
15
15
  end
16
16
 
17
17
  materialize_transactions
18
+ mark_transaction_written_if_write(sql)
18
19
 
19
20
  binds = convert_legacy_binds_to_attributes(binds) if binds.first.is_a?(Array)
20
21
 
21
22
  if without_prepared_statement?(binds)
22
- log(sql, name) { @connection.execute_insert(sql) }
23
+ log(sql, name) { @connection.execute_insert_pk(sql, pk) }
23
24
  else
24
25
  log(sql, name, binds) do
25
- @connection.execute_insert(sql, binds)
26
+ @connection.execute_insert_pk(sql, binds, pk)
26
27
  end
27
28
  end
28
29
  end
@@ -35,6 +36,7 @@ module ArJdbc
35
36
  end
36
37
 
37
38
  materialize_transactions
39
+ mark_transaction_written_if_write(sql)
38
40
 
39
41
  binds = convert_legacy_binds_to_attributes(binds) if binds.first.is_a?(Array)
40
42
 
@@ -55,6 +57,7 @@ module ArJdbc
55
57
  end
56
58
 
57
59
  materialize_transactions
60
+ mark_transaction_written_if_write(sql)
58
61
 
59
62
  binds = convert_legacy_binds_to_attributes(binds) if binds.first.is_a?(Array)
60
63
 
@@ -72,6 +75,7 @@ module ArJdbc
72
75
  end
73
76
 
74
77
  materialize_transactions
78
+ mark_transaction_written_if_write(sql)
75
79
 
76
80
  log(sql, name) { @connection.execute(sql) }
77
81
  end
@@ -24,26 +24,26 @@ module ArJdbc
24
24
  # Starts a database transaction.
25
25
  # @override
26
26
  def begin_db_transaction
27
- log('BEGIN TRANSACTION', nil) { @connection.begin }
27
+ log('BEGIN', 'TRANSACTION') { @connection.begin }
28
28
  end
29
29
 
30
30
  # Starts a database transaction.
31
31
  # @param isolation the transaction isolation to use
32
32
  def begin_isolated_db_transaction(isolation)
33
- log("BEGIN ISOLATED TRANSACTION - #{isolation}", nil) { @connection.begin(isolation) }
33
+ log("BEGIN ISOLATED - #{isolation}", 'TRANSACTION') { @connection.begin(isolation) }
34
34
  end
35
35
 
36
36
  # Commits the current database transaction.
37
37
  # @override
38
38
  def commit_db_transaction
39
- log('COMMIT TRANSACTION', nil) { @connection.commit }
39
+ log('COMMIT', 'TRANSACTION') { @connection.commit }
40
40
  end
41
41
 
42
42
  # Rolls back the current database transaction.
43
43
  # Called from 'rollback_db_transaction' in the AbstractAdapter
44
44
  # @override
45
45
  def exec_rollback_db_transaction
46
- log('ROLLBACK TRANSACTION', nil) { @connection.rollback }
46
+ log('ROLLBACK', 'TRANSACTION') { @connection.rollback }
47
47
  end
48
48
 
49
49
  ########################## Savepoint Interface ############################
@@ -55,7 +55,7 @@ module ArJdbc
55
55
  # @since 1.3.0
56
56
  # @extension added optional name parameter
57
57
  def create_savepoint(name = current_savepoint_name)
58
- log("SAVEPOINT #{name}", 'Savepoint') { @connection.create_savepoint(name) }
58
+ log("SAVEPOINT #{name}", 'TRANSACTION') { @connection.create_savepoint(name) }
59
59
  end
60
60
 
61
61
  # Transaction rollback to a given (previously created) save-point.
@@ -64,7 +64,7 @@ module ArJdbc
64
64
  # @param name the save-point name
65
65
  # @extension added optional name parameter
66
66
  def exec_rollback_to_savepoint(name = current_savepoint_name)
67
- log("ROLLBACK TO SAVEPOINT #{name}", 'Savepoint') { @connection.rollback_savepoint(name) }
67
+ log("ROLLBACK TO SAVEPOINT #{name}", 'TRANSACTION') { @connection.rollback_savepoint(name) }
68
68
  end
69
69
 
70
70
  # Release a previously created save-point.
@@ -73,9 +73,22 @@ module ArJdbc
73
73
  # @param name the save-point name
74
74
  # @extension added optional name parameter
75
75
  def release_savepoint(name = current_savepoint_name)
76
- log("RELEASE SAVEPOINT #{name}", 'Savepoint') { @connection.release_savepoint(name) }
76
+ log("RELEASE SAVEPOINT #{name}", 'TRANSACTION') { @connection.release_savepoint(name) }
77
77
  end
78
78
 
79
79
  end
80
80
  end
81
81
  end
82
+
83
+ # patch to avoid the usage of WeakMap
84
+ require 'active_record/connection_adapters/abstract/transaction'
85
+ module ActiveRecord
86
+ module ConnectionAdapters
87
+ class Transaction
88
+ def add_record(record, ensure_finalize = true)
89
+ @records ||= []
90
+ @records << record
91
+ end
92
+ end
93
+ end
94
+ end
@@ -33,10 +33,10 @@ module ActiveRecord
33
33
 
34
34
  include ArJdbc::MySQL
35
35
 
36
- def initialize(connection, logger, connection_parameters, config)
37
- super
36
+ def initialize(connection, logger, connection_options, config)
37
+ superclass_config = config.reverse_merge(prepared_statements: false)
38
+ super(connection, logger, connection_options, superclass_config)
38
39
 
39
- @prepared_statements = false unless config.key?(:prepared_statements)
40
40
  # configure_connection taken care of at ArJdbc::Abstract::Core
41
41
  end
42
42
 
@@ -88,7 +88,7 @@ module ActiveRecord
88
88
 
89
89
  # from MySQL::DatabaseStatements
90
90
  READ_QUERY = ActiveRecord::ConnectionAdapters::AbstractAdapter.build_read_query_regexp(
91
- :begin, :commit, :explain, :select, :set, :show, :release, :savepoint, :rollback, :describe, :desc
91
+ :desc, :describe, :set, :show, :use
92
92
  ) # :nodoc:
93
93
  private_constant :READ_QUERY
94
94
 
@@ -96,6 +96,15 @@ module ActiveRecord
96
96
  !READ_QUERY.match?(sql)
97
97
  end
98
98
 
99
+ def explain(arel, binds = [])
100
+ sql = "EXPLAIN #{to_sql(arel, binds)}"
101
+ start = Concurrent.monotonic_time
102
+ result = exec_query(sql, "EXPLAIN", binds)
103
+ elapsed = Concurrent.monotonic_time - start
104
+
105
+ MySQL::ExplainPrettyPrinter.new.pp(result, elapsed)
106
+ end
107
+
99
108
  # Reloading the type map in abstract/statement_cache.rb blows up postgres
100
109
  def clear_cache!
101
110
  reload_type_map
@@ -179,7 +188,7 @@ module ActiveRecord
179
188
 
180
189
  # defined in MySQL::DatabaseStatements which is not included
181
190
  def default_insert_value(column)
182
- Arel.sql("DEFAULT") unless column.auto_increment?
191
+ super unless column.auto_increment?
183
192
  end
184
193
 
185
194
  # FIXME: optimize insert_fixtures_set by using JDBC Statement.addBatch()/executeBatch()
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
  ArJdbc::ConnectionMethods.module_eval do
3
3
  def mysql_connection(config)
4
+ config = config.deep_dup
4
5
  # NOTE: this isn't "really" necessary but Rails (in tests) assumes being able to :
5
6
  # ActiveRecord::Base.mysql2_connection ActiveRecord::Base.configurations['arunit'].merge(database: ...)
6
7
  config = symbolize_keys_if_necessary(config)
@@ -67,6 +68,7 @@ ArJdbc::ConnectionMethods.module_eval do
67
68
  # with reconnect fail-over sets connection read-only (by default)
68
69
  # properties['failOverReadOnly'] ||= 'false'
69
70
  end
71
+ properties['noDatetimeStringSync'] = true unless properties.key?('noDatetimeStringSync')
70
72
  end
71
73
  if config[:sslkey] || sslcert = config[:sslcert] # || config[:use_ssl]
72
74
  properties['useSSL'] ||= true # supported by MariaDB as well
@@ -89,11 +91,12 @@ ArJdbc::ConnectionMethods.module_eval do
89
91
  properties['localSocket'] ||= socket if mariadb_driver
90
92
  end
91
93
 
94
+ # properties['useJDBCCompliantTimezoneShift'] ||= true
92
95
  # for the Connector/J 5.1 line this is true by default - but it requires some really nasty
93
96
  # quirks to get casted Time values extracted properly according for AR's default_timezone
94
97
  # - thus we're turning it off (should be off in newer driver versions >= 6 anyway)
95
98
  # + also MariaDB driver is compilant and we would need to branch out based on driver
96
- properties['useLegacyDatetimeCode'] = false
99
+ properties['useLegacyDatetimeCode'] = false # disables the effect of 'useTimezone'
97
100
 
98
101
  jdbc_connection(config)
99
102
  end
@@ -101,6 +104,8 @@ ArJdbc::ConnectionMethods.module_eval do
101
104
  alias_method :mysql2_connection, :mysql_connection
102
105
 
103
106
  def mariadb_connection(config)
107
+ config = config.deep_dup
108
+
104
109
  config[:adapter_spec] ||= ::ArJdbc::MySQL
105
110
  config[:adapter_class] = ActiveRecord::ConnectionAdapters::Mysql2Adapter unless config.key?(:adapter_class)
106
111
 
@@ -48,46 +48,6 @@ module ArJdbc
48
48
  ADAPTER_NAME
49
49
  end
50
50
 
51
- def get_database_version # :nodoc:
52
- begin
53
- version = @connection.database_product
54
- if match = version.match(/([\d\.]*\d).*?/)
55
- version = match[1].split('.').map(&:to_i)
56
- # PostgreSQL version representation does not have more than 4 digits
57
- # From version 10 onwards, PG has changed its versioning policy to
58
- # limit it to only 2 digits. i.e. in 10.x, 10 being the major
59
- # version and x representing the patch release
60
- # Refer to:
61
- # https://www.postgresql.org/support/versioning/
62
- # https://www.postgresql.org/docs/10/static/libpq-status.html -> PQserverVersion()
63
- # for more info
64
-
65
- if version.size >= 3
66
- (version[0] * 100 + version[1]) * 100 + version[2]
67
- elsif version.size == 2
68
- if version[0] >= 10
69
- version[0] * 100 * 100 + version[1]
70
- else
71
- (version[0] * 100 + version[1]) * 100
72
- end
73
- elsif version.size == 1
74
- version[0] * 100 * 100
75
- else
76
- 0
77
- end
78
- else
79
- 0
80
- end
81
- end
82
- end
83
-
84
- def check_version # :nodoc:
85
- if database_version < 90300
86
- raise "Your version of PostgreSQL (#{database_version}) is too old. Active Record supports PostgreSQL >= 9.3."
87
- end
88
- end
89
-
90
-
91
51
  def redshift?
92
52
  # SELECT version() :
93
53
  # PostgreSQL 8.0.2 on i686-pc-linux-gnu, compiled by GCC gcc (GCC) 3.4.2 20041017 (Red Hat 3.4.2-6.fc3), Redshift 1.0.647
@@ -127,6 +87,9 @@ module ArJdbc
127
87
  execute("SET time zone '#{tz}'", 'SCHEMA')
128
88
  end unless redshift?
129
89
 
90
+ # Set interval output format to ISO 8601 for ease of parsing by ActiveSupport::Duration.parse
91
+ execute("SET intervalstyle = iso_8601", "SCHEMA")
92
+
130
93
  # SET statements from :variables config hash
131
94
  # http://www.postgresql.org/docs/8.3/static/sql-set.html
132
95
  (config[:variables] || {}).map do |k, v|
@@ -209,6 +172,10 @@ module ArJdbc
209
172
  true
210
173
  end
211
174
 
175
+ def supports_partitioned_indexes?
176
+ database_version >= 110_000
177
+ end
178
+
212
179
  def supports_partial_index?
213
180
  true
214
181
  end
@@ -225,6 +192,10 @@ module ArJdbc
225
192
  true
226
193
  end
227
194
 
195
+ def supports_check_constraints?
196
+ true
197
+ end
198
+
228
199
  def supports_validate_constraints?
229
200
  true
230
201
  end
@@ -288,7 +259,7 @@ module ArJdbc
288
259
  database_version >= 90300
289
260
  end
290
261
 
291
- def supports_foreign_tables? # we don't really support this yet, its a reminder :)
262
+ def supports_foreign_tables?
292
263
  database_version >= 90300
293
264
  end
294
265
 
@@ -303,13 +274,12 @@ module ArJdbc
303
274
  @has_pg_hint_plan
304
275
  end
305
276
 
306
- def supports_lazy_transactions?
277
+ def supports_common_table_expressions?
307
278
  true
308
279
  end
309
280
 
310
- # From AR 5.1 postgres_adapter.rb
311
- def default_index_type?(index) # :nodoc:
312
- index.using == :btree || super
281
+ def supports_lazy_transactions?
282
+ true
313
283
  end
314
284
 
315
285
  def get_advisory_lock(lock_id) # :nodoc:
@@ -365,6 +335,65 @@ module ArJdbc
365
335
  @use_insert_returning
366
336
  end
367
337
 
338
+ def get_database_version # :nodoc:
339
+ begin
340
+ version = @connection.database_product
341
+ if match = version.match(/([\d\.]*\d).*?/)
342
+ version = match[1].split('.').map(&:to_i)
343
+ # PostgreSQL version representation does not have more than 4 digits
344
+ # From version 10 onwards, PG has changed its versioning policy to
345
+ # limit it to only 2 digits. i.e. in 10.x, 10 being the major
346
+ # version and x representing the patch release
347
+ # Refer to:
348
+ # https://www.postgresql.org/support/versioning/
349
+ # https://www.postgresql.org/docs/10/static/libpq-status.html -> PQserverVersion()
350
+ # for more info
351
+
352
+ if version.size >= 3
353
+ (version[0] * 100 + version[1]) * 100 + version[2]
354
+ elsif version.size == 2
355
+ if version[0] >= 10
356
+ version[0] * 100 * 100 + version[1]
357
+ else
358
+ (version[0] * 100 + version[1]) * 100
359
+ end
360
+ elsif version.size == 1
361
+ version[0] * 100 * 100
362
+ else
363
+ 0
364
+ end
365
+ else
366
+ 0
367
+ end
368
+ end
369
+ end
370
+
371
+ def default_index_type?(index) # :nodoc:
372
+ index.using == :btree || super
373
+ end
374
+
375
+ def build_insert_sql(insert) # :nodoc:
376
+ sql = +"INSERT #{insert.into} #{insert.values_list}"
377
+
378
+ if insert.skip_duplicates?
379
+ sql << " ON CONFLICT #{insert.conflict_target} DO NOTHING"
380
+ elsif insert.update_duplicates?
381
+ sql << " ON CONFLICT #{insert.conflict_target} DO UPDATE SET "
382
+ sql << insert.touch_model_timestamps_unless { |column| "#{insert.model.quoted_table_name}.#{column} IS NOT DISTINCT FROM excluded.#{column}" }
383
+ sql << insert.updatable_columns.map { |column| "#{column}=excluded.#{column}" }.join(",")
384
+ end
385
+
386
+ sql << " RETURNING #{insert.returning}" if insert.returning
387
+ sql
388
+ end
389
+
390
+ def check_version # :nodoc:
391
+ if database_version < 90300
392
+ raise "Your version of PostgreSQL (#{database_version}) is too old. Active Record supports PostgreSQL >= 9.3."
393
+ end
394
+ end
395
+
396
+
368
397
  def exec_insert(sql, name = nil, binds = [], pk = nil, sequence_name = nil)
369
398
  val = super
370
399
  if !use_insert_returning? && pk
@@ -379,13 +408,19 @@ module ArJdbc
379
408
  end
380
409
  end
381
410
 
411
+ def execute_batch(statements, name = nil)
412
+ execute(combine_multi_statements(statements), name)
413
+ end
414
+
382
415
  def explain(arel, binds = [])
383
416
  sql, binds = to_sql_and_binds(arel, binds)
384
417
  ActiveRecord::ConnectionAdapters::PostgreSQL::ExplainPrettyPrinter.new.pp(exec_query("EXPLAIN #{sql}", 'EXPLAIN', binds))
385
418
  end
386
419
 
387
420
  # from ActiveRecord::ConnectionAdapters::PostgreSQL::DatabaseStatements
388
- READ_QUERY = ActiveRecord::ConnectionAdapters::AbstractAdapter.build_read_query_regexp(:begin, :commit, :explain, :select, :set, :show, :release, :savepoint, :rollback) # :nodoc:
421
+ READ_QUERY = ActiveRecord::ConnectionAdapters::AbstractAdapter.build_read_query_regexp(
422
+ :close, :declare, :fetch, :move, :set, :show
423
+ ) # :nodoc:
389
424
  private_constant :READ_QUERY
390
425
 
391
426
  def write_query?(sql) # :nodoc:
@@ -420,22 +455,8 @@ module ArJdbc
420
455
  exec_query("SELECT currval('#{sequence_name}')", 'SQL')
421
456
  end
422
457
 
423
- def build_insert_sql(insert) # :nodoc:
424
- sql = +"INSERT #{insert.into} #{insert.values_list}"
425
-
426
- if insert.skip_duplicates?
427
- sql << " ON CONFLICT #{insert.conflict_target} DO NOTHING"
428
- elsif insert.update_duplicates?
429
- sql << " ON CONFLICT #{insert.conflict_target} DO UPDATE SET "
430
- sql << insert.updatable_columns.map { |column| "#{column}=excluded.#{column}" }.join(",")
431
- end
432
-
433
- sql << " RETURNING #{insert.returning}" if insert.returning
434
- sql
435
- end
436
-
437
- def build_truncate_statements(*table_names)
438
- "TRUNCATE TABLE #{table_names.map(&method(:quote_table_name)).join(", ")}"
458
+ def build_truncate_statements(table_names)
459
+ ["TRUNCATE TABLE #{table_names.map(&method(:quote_table_name)).join(", ")}"]
439
460
  end
440
461
 
441
462
  def all_schemas
@@ -493,7 +514,7 @@ module ArJdbc
493
514
  alias_method :quote_schema_name, :quote_column_name
494
515
 
495
516
  # Need to clear the cache even though the AR adapter doesn't for some reason
496
- def remove_column(table_name, column_name, type = nil, options = {})
517
+ def remove_column(table_name, column_name, type = nil, **options)
497
518
  super
498
519
  clear_cache!
499
520
  end
@@ -522,6 +543,16 @@ module ArJdbc
522
543
 
523
544
  # Returns the list of a table's column names, data types, and default values.
524
545
  #
546
+ # The underlying query is roughly:
547
+ # SELECT column.name, column.type, default.value, column.comment
548
+ # FROM column LEFT JOIN default
549
+ # ON column.table_id = default.table_id
550
+ # AND column.num = default.column_num
551
+ # WHERE column.table_id = get_table_id('table_name')
552
+ # AND column.num > 0
553
+ # AND NOT column.is_dropped
554
+ # ORDER BY column.num
555
+ #
525
556
  # If the table name is not prefixed with a schema, the database will
526
557
  # take the first match from the schema search path.
527
558
  #