activerecord-jdbc-adapter 60.0-java → 61.0-java
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.
- checksums.yaml +4 -4
- data/.gitignore +2 -1
- data/.travis.yml +14 -11
- data/Gemfile +1 -1
- data/README.md +8 -7
- data/activerecord-jdbc-adapter.gemspec +1 -1
- data/lib/arel/visitors/postgresql_jdbc.rb +1 -1
- data/lib/arjdbc/abstract/core.rb +1 -0
- data/lib/arjdbc/abstract/database_statements.rb +6 -2
- data/lib/arjdbc/abstract/transaction_support.rb +20 -7
- data/lib/arjdbc/mysql/adapter.rb +14 -5
- data/lib/arjdbc/mysql/connection_methods.rb +6 -1
- data/lib/arjdbc/postgresql/adapter.rb +94 -63
- data/lib/arjdbc/postgresql/column.rb +1 -1
- data/lib/arjdbc/postgresql/connection_methods.rb +1 -0
- data/lib/arjdbc/postgresql/oid_types.rb +5 -4
- data/lib/arjdbc/sqlite3/adapter.rb +106 -56
- data/lib/arjdbc/sqlite3/connection_methods.rb +12 -1
- data/lib/arjdbc/tasks/databases.rake +15 -10
- data/lib/arjdbc/version.rb +1 -1
- data/rakelib/01-tomcat.rake +2 -2
- data/rakelib/rails.rake +1 -1
- data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +124 -41
- data/src/java/arjdbc/mssql/MSSQLRubyJdbcConnection.java +51 -0
- data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +101 -36
- data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +3 -4
- data/src/java/arjdbc/util/DateTimeUtils.java +12 -4
- metadata +6 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c0f6e1df31960b2169ea7d6c7d664a5d44a3302e0382957842124a0ed1090488
|
4
|
+
data.tar.gz: 63a7540994c1ef969cb67702fdf0860ab17f47632b985b9d52f690a5e247ea51
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e367ae078f402928bb460a0677e506282deb20c802ccb6d4fafe27fea61717ea64048b6ef4b77b1143da97b56efbe71373b80e2ea870f007a6bcbf394a7be637
|
7
|
+
data.tar.gz: fb746f2b1260275e7cb4a7fe6f20c7720f5f23525e5a9ea5ecc852dac7f2141f01d177419ef701b43960ea36c42cb476536f229e575551200d2a5c8cc532c6ab
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -15,7 +15,7 @@ install:
|
|
15
15
|
|
16
16
|
language: ruby
|
17
17
|
rvm:
|
18
|
-
- jruby-9.2.
|
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
|
41
|
-
mysql -e "CREATE DATABASE activerecord_unittest2 DEFAULT CHARACTER SET
|
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="
|
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-
|
112
|
-
- env: DB=mysql2 TEST_PREFIX="rails:" AR_VERSION="6-
|
113
|
-
- env: DB=mysql2 TEST_PREFIX="rails:" AR_VERSION="6-
|
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-
|
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-
|
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-
|
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-
|
128
|
+
- env: DB=sqlite3 TEST_PREFIX="rails:" AR_VERSION="6-1-stable"
|
data/Gemfile
CHANGED
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 |
|
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', '~>
|
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 "~>
|
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.
|
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'
|
data/lib/arjdbc/abstract/core.rb
CHANGED
@@ -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.
|
23
|
+
log(sql, name) { @connection.execute_insert_pk(sql, pk) }
|
23
24
|
else
|
24
25
|
log(sql, name, binds) do
|
25
|
-
@connection.
|
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'
|
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
|
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'
|
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'
|
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}", '
|
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}", '
|
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}", '
|
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
|
data/lib/arjdbc/mysql/adapter.rb
CHANGED
@@ -33,10 +33,10 @@ module ActiveRecord
|
|
33
33
|
|
34
34
|
include ArJdbc::MySQL
|
35
35
|
|
36
|
-
def initialize(connection, logger,
|
37
|
-
|
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
|
-
:
|
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
|
-
|
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?
|
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
|
277
|
+
def supports_common_table_expressions?
|
307
278
|
true
|
308
279
|
end
|
309
280
|
|
310
|
-
|
311
|
-
|
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(
|
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
|
424
|
-
|
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
|
#
|