activerecord-jdbc-alt-adapter 70.0.0.rc1-java → 70.0.0.rc2-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/.github/workflows/main.yml +118 -0
- data/Gemfile +1 -1
- data/README.md +4 -1
- data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
- data/lib/arjdbc/mssql/adapter.rb +4 -3
- data/lib/arjdbc/mssql/connection_methods.rb +3 -0
- data/lib/arjdbc/postgresql/adapter.rb +88 -3
- data/lib/arjdbc/postgresql/oid_types.rb +122 -107
- data/lib/arjdbc/version.rb +1 -1
- data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +5 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 61ee665d7dfe0dc2b0a84c5c2014ba1c4427dfb63a52a0992eee1ba8449360c0
|
4
|
+
data.tar.gz: fdd181f5107c6af495b97f3d67bc5031fd9b9c0a9e454ea6e0fc06e280a544dd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 16c1ca8af769eec8eaab04650e6293f0b0e8cfdc20ae77bb5c2d37c276f5104ed3e42da35a1397215f4d8925bd192e87a18c163cdbdb03578573baa181d7550b
|
7
|
+
data.tar.gz: e200993abec93188a25038d74a3641d83e16cd11d87b10fba1051d51e2e61622dca977edad111c965215e731f51d013bec95bdf42ef73f6c98067a118acf9117
|
@@ -0,0 +1,118 @@
|
|
1
|
+
# This workflow uses actions that are not certified by GitHub.
|
2
|
+
# They are provided by a third-party and are governed by
|
3
|
+
# separate terms of service, privacy policy, and support
|
4
|
+
# documentation.
|
5
|
+
# This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
|
6
|
+
# For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
|
7
|
+
|
8
|
+
name: Tests
|
9
|
+
|
10
|
+
on:
|
11
|
+
push:
|
12
|
+
branches: [ stable-dev ]
|
13
|
+
pull_request:
|
14
|
+
branches: [ stable-dev ]
|
15
|
+
|
16
|
+
# Allows you to run this workflow manually from the Actions tab
|
17
|
+
workflow_dispatch:
|
18
|
+
|
19
|
+
permissions:
|
20
|
+
contents: read
|
21
|
+
|
22
|
+
jobs:
|
23
|
+
test-rails-pgsql:
|
24
|
+
|
25
|
+
name: Rails Tests (Postgres)
|
26
|
+
runs-on: ubuntu-latest
|
27
|
+
strategy:
|
28
|
+
fail-fast: false
|
29
|
+
matrix:
|
30
|
+
ruby-version: [ 'jruby-head' ]
|
31
|
+
db: [ 'postgresql' ]
|
32
|
+
test_targets: [ "rails:test_postgresql" ]
|
33
|
+
ar_version: ["7-0-stable"]
|
34
|
+
prepared_statements: [ 'false', 'true' ]
|
35
|
+
|
36
|
+
services:
|
37
|
+
postgres:
|
38
|
+
image: postgres:10
|
39
|
+
env:
|
40
|
+
POSTGRES_PASSWORD: postgres
|
41
|
+
POSTGRES_HOST_AUTH_METHOD: trust
|
42
|
+
ports:
|
43
|
+
- 5432:5432
|
44
|
+
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
|
45
|
+
|
46
|
+
env:
|
47
|
+
DB: ${{ matrix.db }}
|
48
|
+
AR_VERSION: ${{ matrix.ar_version }}
|
49
|
+
JRUBY_OPTS: "-J-Xms64M -J-Xmx1024M"
|
50
|
+
PREPARED_STATEMENTS: ${{ matrix.prepared_statements }}
|
51
|
+
JDBC_SQLITE_VERSION: "3.32.3.3"
|
52
|
+
PGHOST: localhost
|
53
|
+
PGPORT: 5432
|
54
|
+
PGUSER: postgres
|
55
|
+
|
56
|
+
steps:
|
57
|
+
- uses: actions/checkout@v3
|
58
|
+
- name: Set up Ruby
|
59
|
+
uses: ruby/setup-ruby@v1
|
60
|
+
with:
|
61
|
+
ruby-version: ${{ matrix.ruby-version }}
|
62
|
+
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
63
|
+
- name: Setup database
|
64
|
+
run: |
|
65
|
+
psql -c "create database activerecord_unittest;" -U postgres
|
66
|
+
psql -c "create database activerecord_unittest2;" -U postgres
|
67
|
+
- name: Build
|
68
|
+
run: |
|
69
|
+
rake jar # compiles ext generates: lib/arjdbc/jdbc/adapter_java.jar
|
70
|
+
- name: Run tests
|
71
|
+
run: |
|
72
|
+
bundle exec rake ${{ matrix.test_targets }}
|
73
|
+
|
74
|
+
test-arjdbc-pgsql:
|
75
|
+
|
76
|
+
name: ARJDBC Tests (Postgres)
|
77
|
+
runs-on: ubuntu-latest
|
78
|
+
strategy:
|
79
|
+
fail-fast: false
|
80
|
+
matrix:
|
81
|
+
ruby-version: ['jruby-head']
|
82
|
+
db: ['postgresql']
|
83
|
+
test_targets: ["db:postgresql test_postgresql"]
|
84
|
+
prepared_statements: ['false', 'true']
|
85
|
+
insert_returning: ['false', 'true']
|
86
|
+
|
87
|
+
services:
|
88
|
+
postgres:
|
89
|
+
image: postgres:10
|
90
|
+
env:
|
91
|
+
POSTGRES_PASSWORD: postgres
|
92
|
+
POSTGRES_HOST_AUTH_METHOD: trust
|
93
|
+
ports:
|
94
|
+
- 5432:5432
|
95
|
+
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
|
96
|
+
|
97
|
+
env:
|
98
|
+
DB: ${{ matrix.db }}
|
99
|
+
JRUBY_OPTS: "-J-Xms64M -J-Xmx1024M"
|
100
|
+
PREPARED_STATEMENTS: ${{ matrix.prepared_statements }}
|
101
|
+
INSERT_RETURNING: ${{ matrix.insert_returning }}
|
102
|
+
PGHOST: localhost
|
103
|
+
PGPORT: 5432
|
104
|
+
PGUSER: postgres
|
105
|
+
|
106
|
+
steps:
|
107
|
+
- uses: actions/checkout@v3
|
108
|
+
- name: Set up Ruby
|
109
|
+
uses: ruby/setup-ruby@v1
|
110
|
+
with:
|
111
|
+
ruby-version: ${{ matrix.ruby-version }}
|
112
|
+
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
113
|
+
- name: Build
|
114
|
+
run: |
|
115
|
+
rake jar
|
116
|
+
- name: Run tests
|
117
|
+
run: |
|
118
|
+
bundle exec rake ${{ matrix.test_targets }}
|
data/Gemfile
CHANGED
@@ -55,7 +55,7 @@ group :test do
|
|
55
55
|
gem 'mocha', '~> 1.2', require: false # Rails has '~> 0.14'
|
56
56
|
|
57
57
|
gem 'bcrypt', '~> 3.1.11', require: false
|
58
|
-
gem 'jdbc-mssql', '~>
|
58
|
+
gem 'jdbc-mssql', '~> 12.2', require: nil
|
59
59
|
# gem 'pry-debugger-jruby', platform: :jruby
|
60
60
|
end
|
61
61
|
|
data/README.md
CHANGED
@@ -30,13 +30,16 @@ Add the following to your `Gemfile`:
|
|
30
30
|
```ruby
|
31
31
|
platforms :jruby do
|
32
32
|
# Use jdbc as the database for Active Record
|
33
|
-
gem 'activerecord-jdbc-alt-adapter', '~>
|
33
|
+
gem 'activerecord-jdbc-alt-adapter', '~> 70.0.0.rc1'
|
34
34
|
gem 'jdbc-mssql', '~> 0.9.0'
|
35
35
|
end
|
36
36
|
```
|
37
37
|
|
38
38
|
Or look at the sample rails and see how is set up:
|
39
39
|
|
40
|
+
|
41
|
+
- Rails 7.0 sample app [wombat70](https://github.com/JesseChavez/wombat70)
|
42
|
+
|
40
43
|
- Rails 6.1 sample app [wombat61](https://github.com/JesseChavez/wombat61)
|
41
44
|
|
42
45
|
- Rails 6.0 sample app [wombat60](https://github.com/JesseChavez/wombat60)
|
Binary file
|
data/lib/arjdbc/mssql/adapter.rb
CHANGED
@@ -35,14 +35,15 @@ module ActiveRecord
|
|
35
35
|
ADAPTER_NAME = 'MSSQL'.freeze
|
36
36
|
|
37
37
|
MSSQL_VERSION_YEAR = {
|
38
|
-
8
|
39
|
-
9
|
38
|
+
8 => '2000',
|
39
|
+
9 => '2005',
|
40
40
|
10 => '2008',
|
41
41
|
11 => '2012',
|
42
42
|
12 => '2014',
|
43
43
|
13 => '2016',
|
44
44
|
14 => '2017',
|
45
|
-
15 => '2019'
|
45
|
+
15 => '2019',
|
46
|
+
16 => '2022'
|
46
47
|
}.freeze
|
47
48
|
|
48
49
|
include Jdbc::ConnectionPoolCallbacks
|
@@ -78,12 +78,15 @@ ArJdbc::ConnectionMethods.module_eval do
|
|
78
78
|
url << "sendTimeAsDatetime=#{config[:send_time_as_datetime] || false};"
|
79
79
|
url << "loginTimeout=#{config[:login_timeout].to_i};" if config[:login_timeout]
|
80
80
|
url << "lockTimeout=#{config[:lock_timeout].to_i};"
|
81
|
+
url << "encrypt=#{config[:encrypt]};" if config.key?(:encrypt)
|
82
|
+
url << "trustServerCertificate=#{config[:trust_server_certificate]};" if config.key?(:trust_server_certificate)
|
81
83
|
app = config[:appname] || config[:application]
|
82
84
|
url << "applicationName=#{app};" if app
|
83
85
|
isc = config[:integrated_security] # Win only - needs sqljdbc_auth.dll
|
84
86
|
url << "integratedSecurity=#{isc};" unless isc.nil?
|
85
87
|
url
|
86
88
|
end
|
89
|
+
|
87
90
|
jdbc_connection(config)
|
88
91
|
end
|
89
92
|
alias_method :jdbcsqlserver_connection, :sqlserver_connection
|
@@ -798,11 +798,96 @@ module ActiveRecord::ConnectionAdapters
|
|
798
798
|
|
799
799
|
private
|
800
800
|
|
801
|
-
|
802
|
-
|
801
|
+
FEATURE_NOT_SUPPORTED = "0A000" # :nodoc:
|
802
|
+
|
803
|
+
def execute_and_clear(sql, name, binds, prepare: false, async: false)
|
804
|
+
sql = transform_query(sql)
|
805
|
+
check_if_write_query(sql)
|
806
|
+
|
807
|
+
if !prepare || without_prepared_statement?(binds)
|
808
|
+
result = exec_no_cache(sql, name, binds, async: async)
|
809
|
+
else
|
810
|
+
result = exec_cache(sql, name, binds, async: async)
|
811
|
+
end
|
812
|
+
begin
|
813
|
+
ret = yield result
|
814
|
+
ensure
|
815
|
+
# Is this really result in AR PG?
|
816
|
+
# result.clear
|
817
|
+
end
|
818
|
+
ret
|
819
|
+
end
|
820
|
+
|
821
|
+
def exec_no_cache(sql, name, binds, async: false)
|
822
|
+
materialize_transactions
|
823
|
+
mark_transaction_written_if_write(sql)
|
824
|
+
|
825
|
+
# make sure we carry over any changes to ActiveRecord.default_timezone that have been
|
826
|
+
# made since we established the connection
|
827
|
+
update_typemap_for_default_timezone
|
828
|
+
|
829
|
+
type_casted_binds = type_casted_binds(binds)
|
830
|
+
log(sql, name, binds, type_casted_binds, async: async) do
|
831
|
+
ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
|
832
|
+
@connection.exec_params(sql, type_casted_binds)
|
833
|
+
end
|
834
|
+
end
|
835
|
+
end
|
836
|
+
|
837
|
+
def exec_cache(sql, name, binds, async: false)
|
838
|
+
materialize_transactions
|
839
|
+
mark_transaction_written_if_write(sql)
|
840
|
+
update_typemap_for_default_timezone
|
841
|
+
|
842
|
+
stmt_key = prepare_statement(sql, binds)
|
843
|
+
type_casted_binds = type_casted_binds(binds)
|
844
|
+
|
845
|
+
log(sql, name, binds, type_casted_binds, stmt_key, async: async) do
|
846
|
+
ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
|
847
|
+
@connection.exec_prepared(stmt_key, type_casted_binds)
|
848
|
+
end
|
849
|
+
end
|
850
|
+
rescue ActiveRecord::StatementInvalid => e
|
851
|
+
raise unless is_cached_plan_failure?(e)
|
852
|
+
|
853
|
+
# Nothing we can do if we are in a transaction because all commands
|
854
|
+
# will raise InFailedSQLTransaction
|
855
|
+
if in_transaction?
|
856
|
+
raise ActiveRecord::PreparedStatementCacheExpired.new(e.cause.message)
|
857
|
+
else
|
858
|
+
@lock.synchronize do
|
859
|
+
# outside of transactions we can simply flush this query and retry
|
860
|
+
@statements.delete sql_key(sql)
|
861
|
+
end
|
862
|
+
retry
|
863
|
+
end
|
864
|
+
end
|
865
|
+
|
866
|
+
# Annoyingly, the code for prepared statements whose return value may
|
867
|
+
# have changed is FEATURE_NOT_SUPPORTED.
|
868
|
+
#
|
869
|
+
# This covers various different error types so we need to do additional
|
870
|
+
# work to classify the exception definitively as a
|
871
|
+
# ActiveRecord::PreparedStatementCacheExpired
|
872
|
+
#
|
873
|
+
# Check here for more details:
|
874
|
+
# https://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/backend/utils/cache/plancache.c#l573
|
875
|
+
def is_cached_plan_failure?(e)
|
876
|
+
pgerror = e.cause
|
877
|
+
pgerror.result.result_error_field(PG::PG_DIAG_SQLSTATE) == FEATURE_NOT_SUPPORTED &&
|
878
|
+
pgerror.result.result_error_field(PG::PG_DIAG_SOURCE_FUNCTION) == "RevalidateCachedQuery"
|
879
|
+
rescue
|
880
|
+
false
|
881
|
+
end
|
882
|
+
|
883
|
+
def in_transaction?
|
884
|
+
open_transactions > 0
|
885
|
+
end
|
886
|
+
|
887
|
+
# Returns the statement identifier for the client side cache
|
888
|
+
# of statements
|
803
889
|
def sql_key(sql)
|
804
890
|
"#{schema_search_path}-#{sql}"
|
805
891
|
end
|
806
|
-
|
807
892
|
end
|
808
893
|
end
|
@@ -92,7 +92,7 @@ module ArJdbc
|
|
92
92
|
|
93
93
|
def get_oid_type(oid, fmod, column_name, sql_type = '') # :nodoc:
|
94
94
|
if !type_map.key?(oid)
|
95
|
-
load_additional_types(
|
95
|
+
load_additional_types([oid])
|
96
96
|
end
|
97
97
|
|
98
98
|
type_map.fetch(oid, fmod, sql_type) {
|
@@ -103,15 +103,94 @@ module ArJdbc
|
|
103
103
|
}
|
104
104
|
end
|
105
105
|
|
106
|
+
def reload_type_map
|
107
|
+
type_map.clear
|
108
|
+
initialize_type_map
|
109
|
+
end
|
110
|
+
|
111
|
+
def initialize_type_map_inner(m)
|
112
|
+
m.register_type "int2", Type::Integer.new(limit: 2)
|
113
|
+
m.register_type "int4", Type::Integer.new(limit: 4)
|
114
|
+
m.register_type "int8", Type::Integer.new(limit: 8)
|
115
|
+
m.register_type "oid", OID::Oid.new
|
116
|
+
m.register_type "float4", Type::Float.new
|
117
|
+
m.alias_type "float8", "float4"
|
118
|
+
m.register_type "text", Type::Text.new
|
119
|
+
register_class_with_limit m, "varchar", Type::String
|
120
|
+
m.alias_type "char", "varchar"
|
121
|
+
m.alias_type "name", "varchar"
|
122
|
+
m.alias_type "bpchar", "varchar"
|
123
|
+
m.register_type "bool", Type::Boolean.new
|
124
|
+
register_class_with_limit m, "bit", OID::Bit
|
125
|
+
register_class_with_limit m, "varbit", OID::BitVarying
|
126
|
+
m.register_type "date", OID::Date.new
|
127
|
+
|
128
|
+
m.register_type "money", OID::Money.new
|
129
|
+
m.register_type "bytea", OID::Bytea.new
|
130
|
+
m.register_type "point", OID::Point.new
|
131
|
+
m.register_type "hstore", OID::Hstore.new
|
132
|
+
m.register_type "json", Type::Json.new
|
133
|
+
m.register_type "jsonb", OID::Jsonb.new
|
134
|
+
m.register_type "cidr", OID::Cidr.new
|
135
|
+
m.register_type "inet", OID::Inet.new
|
136
|
+
m.register_type "uuid", OID::Uuid.new
|
137
|
+
m.register_type "xml", OID::Xml.new
|
138
|
+
m.register_type "tsvector", OID::SpecializedString.new(:tsvector)
|
139
|
+
m.register_type "macaddr", OID::Macaddr.new
|
140
|
+
m.register_type "citext", OID::SpecializedString.new(:citext)
|
141
|
+
m.register_type "ltree", OID::SpecializedString.new(:ltree)
|
142
|
+
m.register_type "line", OID::SpecializedString.new(:line)
|
143
|
+
m.register_type "lseg", OID::SpecializedString.new(:lseg)
|
144
|
+
m.register_type "box", OID::SpecializedString.new(:box)
|
145
|
+
m.register_type "path", OID::SpecializedString.new(:path)
|
146
|
+
m.register_type "polygon", OID::SpecializedString.new(:polygon)
|
147
|
+
m.register_type "circle", OID::SpecializedString.new(:circle)
|
148
|
+
m.register_type "regproc", OID::Enum.new
|
149
|
+
# FIXME: adding this vector type leads to quoting not handlign Array data in quoting.
|
150
|
+
#m.register_type "_int4", OID::Vector.new(",", m.lookup("int4"))
|
151
|
+
register_class_with_precision m, "time", Type::Time
|
152
|
+
register_class_with_precision m, "timestamp", OID::Timestamp
|
153
|
+
register_class_with_precision m, "timestamptz", OID::TimestampWithTimeZone
|
154
|
+
|
155
|
+
m.register_type "numeric" do |_, fmod, sql_type|
|
156
|
+
precision = extract_precision(sql_type)
|
157
|
+
scale = extract_scale(sql_type)
|
158
|
+
|
159
|
+
# The type for the numeric depends on the width of the field,
|
160
|
+
# so we'll do something special here.
|
161
|
+
#
|
162
|
+
# When dealing with decimal columns:
|
163
|
+
#
|
164
|
+
# places after decimal = fmod - 4 & 0xffff
|
165
|
+
# places before decimal = (fmod - 4) >> 16 & 0xffff
|
166
|
+
if fmod && (fmod - 4 & 0xffff).zero?
|
167
|
+
# FIXME: Remove this class, and the second argument to
|
168
|
+
# lookups on PG
|
169
|
+
Type::DecimalWithoutScale.new(precision: precision)
|
170
|
+
else
|
171
|
+
OID::Decimal.new(precision: precision, scale: scale)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
m.register_type "interval" do |*args, sql_type|
|
176
|
+
precision = extract_precision(sql_type)
|
177
|
+
OID::Interval.new(precision: precision)
|
178
|
+
end
|
179
|
+
|
180
|
+
# pgjdbc returns these if the column is auto-incrmenting
|
181
|
+
m.alias_type 'serial', 'int4'
|
182
|
+
m.alias_type 'bigserial', 'int8'
|
183
|
+
end
|
184
|
+
|
185
|
+
|
186
|
+
# We differ from AR here because we will initialize type_map when adapter initializes
|
106
187
|
def type_map
|
107
188
|
@type_map
|
108
189
|
end
|
109
190
|
|
110
|
-
def
|
111
|
-
|
112
|
-
|
113
|
-
initialize_type_map(@type_map)
|
114
|
-
end
|
191
|
+
def initialize_type_map(m = type_map)
|
192
|
+
initialize_type_map_inner(m)
|
193
|
+
load_additional_types
|
115
194
|
end
|
116
195
|
|
117
196
|
private
|
@@ -124,117 +203,53 @@ module ArJdbc
|
|
124
203
|
::ActiveRecord::ConnectionAdapters::AbstractAdapter.send(:register_class_with_precision, ...)
|
125
204
|
end
|
126
205
|
|
127
|
-
def
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
m.alias_type "float8", "float4"
|
134
|
-
m.register_type "text", Type::Text.new
|
135
|
-
register_class_with_limit m, "varchar", Type::String
|
136
|
-
m.alias_type "char", "varchar"
|
137
|
-
m.alias_type "name", "varchar"
|
138
|
-
m.alias_type "bpchar", "varchar"
|
139
|
-
m.register_type "bool", Type::Boolean.new
|
140
|
-
register_class_with_limit m, "bit", OID::Bit
|
141
|
-
register_class_with_limit m, "varbit", OID::BitVarying
|
142
|
-
m.register_type "date", OID::Date.new
|
143
|
-
|
144
|
-
m.register_type "money", OID::Money.new
|
145
|
-
m.register_type "bytea", OID::Bytea.new
|
146
|
-
m.register_type "point", OID::Point.new
|
147
|
-
m.register_type "hstore", OID::Hstore.new
|
148
|
-
m.register_type "json", Type::Json.new
|
149
|
-
m.register_type "jsonb", OID::Jsonb.new
|
150
|
-
m.register_type "cidr", OID::Cidr.new
|
151
|
-
m.register_type "inet", OID::Inet.new
|
152
|
-
m.register_type "uuid", OID::Uuid.new
|
153
|
-
m.register_type "xml", OID::Xml.new
|
154
|
-
m.register_type "tsvector", OID::SpecializedString.new(:tsvector)
|
155
|
-
m.register_type "macaddr", OID::Macaddr.new
|
156
|
-
m.register_type "citext", OID::SpecializedString.new(:citext)
|
157
|
-
m.register_type "ltree", OID::SpecializedString.new(:ltree)
|
158
|
-
m.register_type "line", OID::SpecializedString.new(:line)
|
159
|
-
m.register_type "lseg", OID::SpecializedString.new(:lseg)
|
160
|
-
m.register_type "box", OID::SpecializedString.new(:box)
|
161
|
-
m.register_type "path", OID::SpecializedString.new(:path)
|
162
|
-
m.register_type "polygon", OID::SpecializedString.new(:polygon)
|
163
|
-
m.register_type "circle", OID::SpecializedString.new(:circle)
|
164
|
-
|
165
|
-
register_class_with_precision m, "time", Type::Time
|
166
|
-
register_class_with_precision m, "timestamp", OID::Timestamp
|
167
|
-
register_class_with_precision m, "timestamptz", OID::TimestampWithTimeZone
|
168
|
-
|
169
|
-
m.register_type "numeric" do |_, fmod, sql_type|
|
170
|
-
precision = extract_precision(sql_type)
|
171
|
-
scale = extract_scale(sql_type)
|
172
|
-
|
173
|
-
# The type for the numeric depends on the width of the field,
|
174
|
-
# so we'll do something special here.
|
175
|
-
#
|
176
|
-
# When dealing with decimal columns:
|
177
|
-
#
|
178
|
-
# places after decimal = fmod - 4 & 0xffff
|
179
|
-
# places before decimal = (fmod - 4) >> 16 & 0xffff
|
180
|
-
if fmod && (fmod - 4 & 0xffff).zero?
|
181
|
-
# FIXME: Remove this class, and the second argument to
|
182
|
-
# lookups on PG
|
183
|
-
Type::DecimalWithoutScale.new(precision: precision)
|
184
|
-
else
|
185
|
-
OID::Decimal.new(precision: precision, scale: scale)
|
206
|
+
def load_additional_types(oids = nil) # :nodoc:
|
207
|
+
initializer = ArjdbcTypeMapInitializer.new(type_map)
|
208
|
+
load_types_queries(initializer, oids) do |query|
|
209
|
+
execute_and_clear(query, "SCHEMA", []) do |records|
|
210
|
+
#puts "RECORDS: #{records.to_a}"
|
211
|
+
initializer.run(records)
|
186
212
|
end
|
187
213
|
end
|
188
|
-
|
189
|
-
m.register_type "interval" do |*args, sql_type|
|
190
|
-
precision = extract_precision(sql_type)
|
191
|
-
OID::Interval.new(precision: precision)
|
192
|
-
end
|
193
|
-
|
194
|
-
# pgjdbc returns these if the column is auto-incrmenting
|
195
|
-
m.alias_type 'serial', 'int4'
|
196
|
-
m.alias_type 'bigserial', 'int8'
|
197
214
|
end
|
198
215
|
|
199
|
-
def
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
216
|
+
def load_types_queries(initializer, oids)
|
217
|
+
query = <<~SQL
|
218
|
+
SELECT t.oid, t.typname, t.typelem, t.typdelim, t.typinput, r.rngsubtype, t.typtype, t.typbasetype
|
219
|
+
FROM pg_type as t
|
220
|
+
LEFT JOIN pg_range as r ON oid = rngtypid
|
221
|
+
SQL
|
222
|
+
if oids
|
223
|
+
if oids.all? { |e| e.kind_of? Numeric }
|
224
|
+
yield query + "WHERE t.oid IN (%s)" % oids.join(", ")
|
225
|
+
else
|
226
|
+
in_list = oids.map { |e| %Q{'#{e}'} }.join(", ")
|
227
|
+
#puts caller[0..40]
|
228
|
+
puts "IN_LIST = #{in_list}"
|
229
|
+
yield query + "WHERE t.typname IN (%s)" % in_list
|
230
|
+
end
|
210
231
|
else
|
211
|
-
query
|
212
|
-
|
213
|
-
|
214
|
-
FROM pg_type as t
|
215
|
-
JOIN pg_namespace AS ns ON t.typnamespace = ns.oid
|
216
|
-
SQL
|
232
|
+
yield query + initializer.query_conditions_for_known_type_names
|
233
|
+
yield query + initializer.query_conditions_for_known_type_types
|
234
|
+
yield query + initializer.query_conditions_for_array_types
|
217
235
|
end
|
236
|
+
end
|
218
237
|
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
238
|
+
def update_typemap_for_default_timezone
|
239
|
+
if @default_timezone != ActiveRecord.default_timezone && @timestamp_decoder
|
240
|
+
decoder_class = ActiveRecord.default_timezone == :utc ?
|
241
|
+
PG::TextDecoder::TimestampUtc :
|
242
|
+
PG::TextDecoder::TimestampWithoutTimeZone
|
223
243
|
|
224
|
-
|
225
|
-
|
226
|
-
query += "WHERE ns.nspname = '%s' AND t.typname = '%s'" % [m[1], m[2]]
|
244
|
+
@timestamp_decoder = decoder_class.new(@timestamp_decoder.to_h)
|
245
|
+
@connection.type_map_for_results.add_coder(@timestamp_decoder)
|
227
246
|
|
228
|
-
|
229
|
-
# only type name
|
230
|
-
query += "WHERE t.typname = '%s' AND ns.nspname = ANY(current_schemas(true))" % oid
|
231
|
-
end
|
232
|
-
else
|
233
|
-
query += initializer.query_conditions_for_initial_load
|
234
|
-
end
|
247
|
+
@default_timezone = ActiveRecord.default_timezone
|
235
248
|
|
236
|
-
|
237
|
-
|
249
|
+
# if default timezone has changed, we need to reconfigure the connection
|
250
|
+
# (specifically, the session time zone)
|
251
|
+
configure_connection
|
252
|
+
end
|
238
253
|
end
|
239
254
|
|
240
255
|
def extract_scale(sql_type)
|
data/lib/arjdbc/version.rb
CHANGED
@@ -214,6 +214,11 @@ public class PostgreSQLRubyJdbcConnection extends arjdbc.jdbc.RubyJdbcConnection
|
|
214
214
|
});
|
215
215
|
}
|
216
216
|
|
217
|
+
@JRubyMethod
|
218
|
+
public IRubyObject exec_params(ThreadContext context, IRubyObject sql, IRubyObject binds) {
|
219
|
+
return execute_prepared_query(context, sql, binds, null);
|
220
|
+
}
|
221
|
+
|
217
222
|
private transient RubyClass oidArray; // PostgreSQL::OID::Array
|
218
223
|
|
219
224
|
private RubyClass oidArray(final ThreadContext context) {
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord-jdbc-alt-adapter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 70.0.0.
|
4
|
+
version: 70.0.0.rc2
|
5
5
|
platform: java
|
6
6
|
authors:
|
7
7
|
- Nick Sieger, Ola Bini, Karol Bucek, Jesse Chavez, and JRuby contributors
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-02
|
11
|
+
date: 2023-03-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
@@ -38,6 +38,7 @@ executables: []
|
|
38
38
|
extensions: []
|
39
39
|
extra_rdoc_files: []
|
40
40
|
files:
|
41
|
+
- ".github/workflows/main.yml"
|
41
42
|
- ".github/workflows/ruby.yml"
|
42
43
|
- ".gitignore"
|
43
44
|
- ".nvimlog"
|