activerecord-jdbc-alt-adapter 71.0.0.alpha1-java → 71.0.0.alpha2-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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3a773766cbb0e3ea279a04ab67b60c578382c604214c0a3dd5e54b7f419f4b96
4
- data.tar.gz: d0f347ef628b4b791d81ad46a34d20f8ea3acb75cee3a473b2dbd8784769e897
3
+ metadata.gz: 6590c4d705c35e5a4849e4ef0bb076efba93509b8bcd8b4c2db49a4bc84b0f31
4
+ data.tar.gz: cb87d9f9f2763b178f990359efecb6b1199cbe15866460bb837232fcdd8b75e1
5
5
  SHA512:
6
- metadata.gz: 7c08cd49b3245c655a4c51d5c0d327cf7f058a7c2c98cedf7a59f00f60d14e7d79b1d9c2eef614712cee71b684f717fd6edd7c122fd0349d775a7e4fb2a48150
7
- data.tar.gz: b1a059930367508754dc54ff2b8b76434991ac2897ea4ff4917a7ef540d25c28272c4c5cbe13f5b5215eded00940c9beece3f2415860a69b4621a7c62664fa02
6
+ metadata.gz: 511e55410d149724a0765b5494a15ca4fe493bbd36b969a587d7bab23458cb32a45d34c01f79ca8b170b7f1e86fdf58e81bc4ba3ea15d464fe954a8266c41743
7
+ data.tar.gz: 9fdfe69ab63373f8e31cd2d60f5ae88fd3f4499250010aab4ffbeabb9c9345f017bb012932598a84297bd63d8b28f5bc38d18213f95b19b3307a93f38ecfc775
@@ -31,9 +31,12 @@ jobs:
31
31
  db: ['mssql']
32
32
  test_targets: ['test_mssql']
33
33
 
34
+ # NOTE: using a specific tag, it fails with 2019-latest.
35
+ # it seems the issue is related to some changes in mssql tools
36
+ # https://learn.microsoft.com/en-au/answers/questions/1853144/error-failed-to-initialize-container-mcr-microsoft
34
37
  services:
35
38
  mssql:
36
- image: mcr.microsoft.com/mssql/server:2019-latest
39
+ image: mcr.microsoft.com/mssql/server:2019-CU27-ubuntu-20.04
37
40
  env:
38
41
  ACCEPT_EULA: Y
39
42
  MSSQL_SA_PASSWORD: Password12!
@@ -112,7 +115,7 @@ jobs:
112
115
 
113
116
  services:
114
117
  postgres:
115
- image: postgres:10
118
+ image: postgres:11
116
119
  env:
117
120
  POSTGRES_PASSWORD: postgres
118
121
  POSTGRES_HOST_AUTH_METHOD: trust
@@ -157,7 +160,7 @@ jobs:
157
160
 
158
161
  services:
159
162
  mssql:
160
- image: mcr.microsoft.com/mssql/server:2019-latest
163
+ image: mcr.microsoft.com/mssql/server:2019-CU27-ubuntu-20.04
161
164
  env:
162
165
  ACCEPT_EULA: Y
163
166
  MSSQL_SA_PASSWORD: Password12!
@@ -243,7 +246,7 @@ jobs:
243
246
 
244
247
  services:
245
248
  postgres:
246
- image: postgres:10
249
+ image: postgres:11
247
250
  env:
248
251
  POSTGRES_PASSWORD: postgres
249
252
  POSTGRES_HOST_AUTH_METHOD: trust
@@ -84,7 +84,7 @@ jobs:
84
84
 
85
85
  services:
86
86
  postgres:
87
- image: postgres:10
87
+ image: postgres:11
88
88
  env:
89
89
  POSTGRES_PASSWORD: postgres
90
90
  POSTGRES_HOST_AUTH_METHOD: trust
@@ -211,7 +211,7 @@ jobs:
211
211
 
212
212
  services:
213
213
  postgres:
214
- image: postgres:10
214
+ image: postgres:11
215
215
  env:
216
216
  POSTGRES_PASSWORD: postgres
217
217
  POSTGRES_HOST_AUTH_METHOD: trust
data/.gitignore CHANGED
@@ -19,6 +19,8 @@ nbproject
19
19
  .project
20
20
  *.sqlite
21
21
  *.sqlite3
22
+ *.sqlite3-shm
23
+ *.sqlite3-wal
22
24
  *.derby
23
25
  derby.log
24
26
  test.hsqldb*
@@ -33,8 +35,9 @@ Gemfile.lock
33
35
  .settings
34
36
  activerecord-jdbc.iml
35
37
  lib/arjdbc/jdbc/adapter_java.jar
36
- .jrubyrc
37
38
  tags
38
- pik.sh
39
- .ruby-version
39
+ .jrubyrc
40
40
  .rubocop.yml
41
+ .solargraph.yml
42
+ pik.sh
43
+ .tool-versions
@@ -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', '~> 7.1.0'
44
+ gem.add_dependency 'activerecord', '~> 7.1.3'
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'
@@ -36,10 +36,13 @@ module ArJdbc
36
36
  # end
37
37
  # end
38
38
 
39
+ private
40
+
39
41
  # DIFFERENCE: we delve into jdbc shared code and this does self.class.new_client.
40
42
  def connect
41
- @raw_connection = jdbc_connection_class(@config[:adapter_spec]).new(@config, self)
42
- @raw_connection.configure_connection
43
+ @raw_connection = self.class.new_client(@connection_parameters, self)
44
+ rescue ActiveRecord::ConnectionNotEstablished => ex
45
+ raise ex.set_pool(@pool)
43
46
  end
44
47
 
45
48
  def reconnect
@@ -2,23 +2,17 @@
2
2
 
3
3
  module ArJdbc
4
4
  module Abstract
5
-
6
5
  # This is minimum amount of code needed from base JDBC Adapter class to make common adapters
7
6
  # work. This replaces using jdbc/adapter as a base class for all adapters.
8
7
  module Core
9
-
10
- attr_reader :config
11
-
12
- def initialize(config)
13
- @config = config
8
+ def initialize(...)
9
+ super
14
10
 
15
11
  if self.class.equal? ActiveRecord::ConnectionAdapters::JdbcAdapter
16
12
  spec = @config.key?(:adapter_spec) ? @config[:adapter_spec] :
17
13
  ( @config[:adapter_spec] = adapter_spec(@config) ) # due resolving visitor
18
14
  extend spec if spec
19
15
  end
20
-
21
- super(config) # AbstractAdapter
22
16
  end
23
17
 
24
18
  # Retrieve the raw `java.sql.Connection` object.
@@ -33,7 +33,7 @@ module ArJdbc
33
33
 
34
34
  # It appears that at this point (AR 5.0) "prepare" should only ever be true
35
35
  # if prepared statements are enabled
36
- def internal_exec_query(sql, name = nil, binds = NO_BINDS, prepare: false, async: false)
36
+ def internal_exec_query(sql, name = nil, binds = NO_BINDS, prepare: false, async: false, allow_retry: false, materialize_transactions: true)
37
37
  sql = transform_query(sql)
38
38
 
39
39
  if preventing_writes? && write_query?(sql)
@@ -104,7 +104,7 @@ module ArJdbc
104
104
  end
105
105
  end
106
106
 
107
- def raw_execute(sql, name, async: false, allow_retry: false, materialize_transactions: false)
107
+ def raw_execute(sql, name, async: false, allow_retry: false, materialize_transactions: true)
108
108
  log(sql, name, async: async) do
109
109
  with_raw_connection(allow_retry: allow_retry, materialize_transactions: materialize_transactions) do |conn|
110
110
  conn.execute(sql)
@@ -24,7 +24,7 @@ module ArJdbc
24
24
 
25
25
  # Only say we support the statement cache if we are using prepared statements
26
26
  # and have a max number of statements defined
27
- statement_limit = self.class.type_cast_config_to_integer(config[:statement_limit])
27
+ statement_limit = self.class.type_cast_config_to_integer(@config[:statement_limit])
28
28
  @jdbc_statement_cache_enabled = prepared_statements && (statement_limit.nil? || statement_limit > 0)
29
29
 
30
30
  @statements = StatementPool.new(statement_limit) # AR (5.0) expects this to be stored as @statements
@@ -107,16 +107,3 @@ module ArJdbc
107
107
  end
108
108
  end
109
109
  end
110
-
111
- # patch to avoid the usage of WeakMap
112
- require 'active_record/connection_adapters/abstract/transaction'
113
- module ActiveRecord
114
- module ConnectionAdapters
115
- class Transaction
116
- def add_record(record, ensure_finalize = true)
117
- @records ||= []
118
- @records << record
119
- end
120
- end
121
- end
122
- end
Binary file
@@ -88,15 +88,20 @@ module ActiveRecord
88
88
 
89
89
  # @override
90
90
  def active?
91
- return false unless @raw_connection
91
+ @lock.synchronize do
92
+ return false unless @raw_connection
92
93
 
93
- @raw_connection.active?
94
+ @raw_connection.active?
95
+ end
94
96
  end
95
97
 
96
98
  # @override
97
99
  def disconnect!
98
- super # clear_cache! && reset_transaction
99
- @raw_connection&.disconnect!
100
+ @lock.synchronize do
101
+ super # clear_cache! && reset_transaction
102
+ @raw_connection&.disconnect!
103
+ @raw_connection = nil
104
+ end
100
105
  end
101
106
 
102
107
  # Returns the (JDBC) `ActiveRecord` column class for this adapter.
@@ -490,6 +495,10 @@ module ActiveRecord
490
495
  RangeError.new(message, sql: sql, binds: binds)
491
496
  when /Snapshot isolation transaction aborted due to update conflict. You cannot use snapshot isolation/
492
497
  StatementInvalid.new(message, sql: sql, binds: binds)
498
+ when /Incorrect syntax near the keyword .*/
499
+ StatementInvalid.new(message, sql: sql, binds: binds)
500
+ when /Could not find stored procedure .*/
501
+ StatementInvalid.new(message, sql: sql, binds: binds)
493
502
  else
494
503
  super
495
504
  end
@@ -174,9 +174,12 @@ module ActiveRecord
174
174
  end
175
175
  end
176
176
 
177
- def rename_table(table_name, new_table_name)
178
- execute "EXEC sp_rename '#{table_name}', '#{new_table_name}'"
179
- rename_table_indexes(table_name, new_table_name)
177
+ def rename_table(table_name, new_name, **options)
178
+ validate_table_length!(new_name) unless options[:_uses_legacy_table_name]
179
+ schema_cache.clear_data_source_cache!(table_name.to_s)
180
+ schema_cache.clear_data_source_cache!(new_name.to_s)
181
+ execute "EXEC sp_rename '#{table_name}', '#{new_name}'"
182
+ rename_table_indexes(table_name, new_name)
180
183
  end
181
184
 
182
185
  # This is the same as the abstract method
@@ -23,7 +23,7 @@ module ActiveRecord
23
23
  class Mysql2Adapter < AbstractMysqlAdapter
24
24
  ADAPTER_NAME = 'Mysql2'
25
25
 
26
- include Jdbc::ConnectionPoolCallbacks
26
+ # include Jdbc::ConnectionPoolCallbacks
27
27
 
28
28
  include ArJdbc::Abstract::ConnectionManagement
29
29
  include ArJdbc::Abstract::DatabaseStatements
@@ -33,6 +33,34 @@ module ActiveRecord
33
33
 
34
34
  include ArJdbc::MySQL
35
35
 
36
+ class << self
37
+ def jdbc_connection_class
38
+ ::ActiveRecord::ConnectionAdapters::MySQLJdbcConnection
39
+ end
40
+
41
+ def new_client(conn_params, adapter_instance)
42
+ jdbc_connection_class.new(conn_params, adapter_instance)
43
+ end
44
+
45
+ private
46
+ def initialize_type_map(m)
47
+ super
48
+
49
+ m.register_type(%r(char)i) do |sql_type|
50
+ limit = extract_limit(sql_type)
51
+ Type.lookup(:string, adapter: :mysql2, limit: limit)
52
+ end
53
+
54
+ m.register_type %r(^enum)i, Type.lookup(:string, adapter: :mysql2)
55
+ m.register_type %r(^set)i, Type.lookup(:string, adapter: :mysql2)
56
+ end
57
+ end
58
+
59
+ # NOTE: redefines constant defined in abstract class however this time
60
+ # will use methods defined in the mysql abstract class and map properly
61
+ # mysql types.
62
+ TYPE_MAP = Type::TypeMap.new.tap { |m| initialize_type_map(m) }
63
+
36
64
  def initialize(...)
37
65
  super
38
66
 
@@ -171,7 +199,7 @@ module ActiveRecord
171
199
  #++
172
200
 
173
201
  def active?
174
- !(@raw_connection.nil? || @raw_connection.closed?) && @lock.synchronize { @raw_connection&.execute_query("/* ping */ SELECT 1") } || false
202
+ !(@raw_connection.nil? || @raw_connection.closed?) && @lock.synchronize { @raw_connection&.ping } || false
175
203
  end
176
204
 
177
205
  alias :reset! :reconnect!
@@ -221,14 +249,21 @@ module ActiveRecord
221
249
  @full_version ||= any_raw_connection.full_version
222
250
  end
223
251
 
224
- def jdbc_connection_class(spec)
225
- ::ActiveRecord::ConnectionAdapters::MySQLJdbcConnection
226
- end
227
-
228
252
  def jdbc_column_class
229
253
  ::ActiveRecord::ConnectionAdapters::MySQL::Column
230
254
  end
231
255
 
256
+ def translate_exception(exception, message:, sql:, binds:)
257
+ case message
258
+ when /Table .* doesn't exist/i
259
+ StatementInvalid.new(message, sql: sql, binds: binds, connection_pool: @pool)
260
+ when /BLOB, TEXT, GEOMETRY or JSON column .* can't have a default value/i
261
+ StatementInvalid.new(message, sql: sql, binds: binds, connection_pool: @pool)
262
+ else
263
+ super
264
+ end
265
+ end
266
+
232
267
  # defined in MySQL::DatabaseStatements which is not included
233
268
  def default_insert_value(column)
234
269
  super unless column.auto_increment?
@@ -13,6 +13,7 @@ require 'active_record/connection_adapters/postgresql/schema_dumper'
13
13
  require 'active_record/connection_adapters/postgresql/schema_statements'
14
14
  require 'active_record/connection_adapters/postgresql/type_metadata'
15
15
  require 'active_record/connection_adapters/postgresql/utils'
16
+
16
17
  require 'arjdbc/abstract/core'
17
18
  require 'arjdbc/abstract/connection_management'
18
19
  require 'arjdbc/abstract/database_statements'
@@ -21,6 +22,8 @@ require 'arjdbc/abstract/transaction_support'
21
22
  require 'arjdbc/postgresql/base/array_decoder'
22
23
  require 'arjdbc/postgresql/base/array_encoder'
23
24
  require 'arjdbc/postgresql/name'
25
+ require 'arjdbc/postgresql/schema_statements'
26
+
24
27
  require 'active_model'
25
28
 
26
29
  module ArJdbc
@@ -35,11 +38,6 @@ module ArJdbc
35
38
  # @private
36
39
  Type = ::ActiveRecord::Type
37
40
 
38
- # @see ActiveRecord::ConnectionAdapters::JdbcAdapter#jdbc_connection_class
39
- def self.jdbc_connection_class
40
- ::ActiveRecord::ConnectionAdapters::PostgreSQLJdbcConnection
41
- end
42
-
43
41
  # @see ActiveRecord::ConnectionAdapters::JdbcAdapter#jdbc_column_class
44
42
  def jdbc_column_class; ::ActiveRecord::ConnectionAdapters::PostgreSQLColumn end
45
43
 
@@ -52,8 +50,8 @@ module ArJdbc
52
50
  def redshift?
53
51
  # SELECT version() :
54
52
  # 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
55
- if ( redshift = config[:redshift] ).nil?
56
- redshift = !! (@connection.database_product || '').index('Redshift')
53
+ if (redshift = @config[:redshift]).nil?
54
+ redshift = !! (valid_raw_connection.database_product || '').index('Redshift')
57
55
  end
58
56
  redshift
59
57
  end
@@ -73,8 +71,8 @@ module ArJdbc
73
71
  # see http://jdbc.postgresql.org/documentation/91/connect.html
74
72
  # self.set_client_encoding(encoding)
75
73
  #end
76
- self.client_min_messages = config[:min_messages] || 'warning'
77
- self.schema_search_path = config[:schema_search_path] || config[:schema_order]
74
+ self.client_min_messages = @config[:min_messages] || 'warning'
75
+ self.schema_search_path = @config[:schema_search_path] || @config[:schema_order]
78
76
 
79
77
  # Use standard-conforming strings if available so we don't have to do the E'...' dance.
80
78
  set_standard_conforming_strings
@@ -93,7 +91,7 @@ module ArJdbc
93
91
 
94
92
  # SET statements from :variables config hash
95
93
  # http://www.postgresql.org/docs/8.3/static/sql-set.html
96
- (config[:variables] || {}).map do |k, v|
94
+ (@config[:variables] || {}).map do |k, v|
97
95
  if v == ':default' || v == :default
98
96
  # Sets the value to the global or compile default
99
97
  execute("SET SESSION #{k} TO DEFAULT", 'SCHEMA')
@@ -101,6 +99,8 @@ module ArJdbc
101
99
  execute("SET SESSION #{k} TO #{quote(v)}", 'SCHEMA')
102
100
  end
103
101
  end
102
+
103
+ reload_type_map
104
104
  end
105
105
 
106
106
  # @private
@@ -127,7 +127,7 @@ module ArJdbc
127
127
  inet: { name: 'inet' },
128
128
  int4range: { name: 'int4range' },
129
129
  int8range: { name: 'int8range' },
130
- integer: { name: 'integer' },
130
+ integer: { name: 'integer', limit: 4 },
131
131
  interval: { name: 'interval' },
132
132
  json: { name: 'json' },
133
133
  jsonb: { name: 'jsonb' },
@@ -232,6 +232,10 @@ module ArJdbc
232
232
  alias supports_insert_on_duplicate_update? supports_insert_on_conflict?
233
233
  alias supports_insert_conflict_target? supports_insert_on_conflict?
234
234
 
235
+ def supports_identity_columns? # :nodoc:
236
+ database_version >= 10_00_00 # >= 10.0
237
+ end
238
+
235
239
  def index_algorithms
236
240
  { concurrently: 'CONCURRENTLY' }
237
241
  end
@@ -297,14 +301,21 @@ module ArJdbc
297
301
  query_value("SELECT pg_advisory_unlock(#{lock_id})")
298
302
  end
299
303
 
300
- def enable_extension(name)
301
- exec_query("CREATE EXTENSION IF NOT EXISTS \"#{name}\"").tap {
302
- reload_type_map
303
- }
304
+ def enable_extension(name, **)
305
+ schema, name = name.to_s.split(".").values_at(-2, -1)
306
+ sql = +"CREATE EXTENSION IF NOT EXISTS \"#{name}\""
307
+ sql << " SCHEMA #{schema}" if schema
308
+
309
+ internal_exec_query(sql).tap { reload_type_map }
304
310
  end
305
311
 
306
- def disable_extension(name)
307
- exec_query("DROP EXTENSION IF EXISTS \"#{name}\" CASCADE").tap {
312
+ # Removes an extension from the database.
313
+ #
314
+ # [<tt>:force</tt>]
315
+ # Set to +:cascade+ to drop dependent objects as well.
316
+ # Defaults to false.
317
+ def disable_extension(name, force: false)
318
+ internal_exec_query("DROP EXTENSION IF EXISTS \"#{name}\"#{' CASCADE' if force == :cascade}").tap {
308
319
  reload_type_map
309
320
  }
310
321
  end
@@ -318,7 +329,7 @@ module ArJdbc
318
329
  end
319
330
 
320
331
  def extensions
321
- exec_query("SELECT extname FROM pg_extension", "SCHEMA").cast_values
332
+ internal_exec_query("SELECT extname FROM pg_extension", "SCHEMA", allow_retry: true, materialize_transactions: false).cast_values
322
333
  end
323
334
 
324
335
  # Returns a list of defined enum types, and their values.
@@ -370,7 +381,7 @@ module ArJdbc
370
381
 
371
382
  def get_database_version # :nodoc:
372
383
  begin
373
- version = @connection.database_product
384
+ version = valid_raw_connection.database_product
374
385
  if match = version.match(/([\d\.]*\d).*?/)
375
386
  version = match[1].split('.').map(&:to_i)
376
387
  # PostgreSQL version representation does not have more than 4 digits
@@ -426,8 +437,7 @@ module ArJdbc
426
437
  end
427
438
  end
428
439
 
429
-
430
- def exec_insert(sql, name = nil, binds = [], pk = nil, sequence_name = nil)
440
+ def exec_insert(sql, name = nil, binds = [], pk = nil, sequence_name = nil, returning: nil) # :nodoc:
431
441
  val = super
432
442
  if !use_insert_returning? && pk
433
443
  unless sequence_name
@@ -464,18 +474,23 @@ module ArJdbc
464
474
  # since apparently calling close on the statement object
465
475
  # doesn't always free the server resources and calling
466
476
  # 'DISCARD ALL' fails if we are inside a transaction
467
- def clear_cache!
468
- super
469
- # Make sure all query plans are *really* gone
470
- @connection.execute 'DEALLOCATE ALL' if active?
471
- end
477
+ # def clear_cache!
478
+ # super
479
+ # # Make sure all query plans are *really* gone
480
+ # @connection.execute 'DEALLOCATE ALL' if active?
481
+ # end
472
482
 
473
483
  def reset!
474
- clear_cache!
475
- reset_transaction
476
- @connection.rollback # Have to deal with rollbacks differently than the AR adapter
477
- @connection.execute 'DISCARD ALL'
478
- @connection.configure_connection
484
+ @lock.synchronize do
485
+ return connect! unless @raw_connection
486
+
487
+ # Have to deal with rollbacks differently than the AR adapter
488
+ @raw_connection.rollback
489
+
490
+ @raw_connection.execute("DISCARD ALL")
491
+
492
+ super
493
+ end
479
494
  end
480
495
 
481
496
  def default_sequence_name(table_name, pk = "id") #:nodoc:
@@ -660,6 +675,8 @@ module ArJdbc
660
675
  ::ActiveRecord::LockWaitTimeout.new(message, sql: sql, binds: binds)
661
676
  when /canceling statement/ # This needs to come after lock timeout because the lock timeout message also contains "canceling statement"
662
677
  ::ActiveRecord::QueryCanceled.new(message, sql: sql, binds: binds)
678
+ when /relation "animals" does not exist/i
679
+ ::ActiveRecord::StatementInvalid.new(message, sql: sql, binds: binds, connection_pool: @pool)
663
680
  else
664
681
  super
665
682
  end
@@ -742,7 +759,7 @@ module ActiveRecord::ConnectionAdapters
742
759
  include ActiveRecord::ConnectionAdapters::PostgreSQL::SchemaStatements
743
760
  include ActiveRecord::ConnectionAdapters::PostgreSQL::Quoting
744
761
 
745
- include Jdbc::ConnectionPoolCallbacks
762
+ # include Jdbc::ConnectionPoolCallbacks
746
763
 
747
764
  include ArJdbc::Abstract::Core
748
765
  include ArJdbc::Abstract::ConnectionManagement
@@ -753,6 +770,7 @@ module ActiveRecord::ConnectionAdapters
753
770
 
754
771
  require 'arjdbc/postgresql/oid_types'
755
772
  include ::ArJdbc::PostgreSQL::OIDTypes
773
+ include ::ArJdbc::PostgreSQL::SchemaStatements
756
774
 
757
775
  include ::ArJdbc::PostgreSQL::ColumnHelpers
758
776
 
@@ -761,16 +779,27 @@ module ActiveRecord::ConnectionAdapters
761
779
  # AR expects OID to be available on the adapter
762
780
  OID = ActiveRecord::ConnectionAdapters::PostgreSQL::OID
763
781
 
764
- def initialize(connection, logger = nil, connection_parameters = nil, config = {})
782
+ class << self
783
+ def jdbc_connection_class
784
+ ::ActiveRecord::ConnectionAdapters::PostgreSQLJdbcConnection
785
+ end
786
+
787
+ def new_client(conn_params, adapter_instance)
788
+ jdbc_connection_class.new(conn_params, adapter_instance)
789
+ end
790
+ end
791
+
792
+ def initialize(...)
793
+ super
794
+
795
+ conn_params = @config.compact
796
+
797
+ @connection_parameters = conn_params
798
+
765
799
  # @local_tz is initialized as nil to avoid warnings when connect tries to use it
766
800
  @local_tz = nil
767
801
  @max_identifier_length = nil
768
802
 
769
- super(connection, logger, config) # configure_connection happens in super
770
-
771
- @type_map = Type::HashLookupTypeMap.new
772
- initialize_type_map
773
-
774
803
  @use_insert_returning = @config.key?(:insert_returning) ?
775
804
  self.class.type_cast_config_to_boolean(@config[:insert_returning]) : true
776
805
  end
@@ -793,10 +822,6 @@ module ActiveRecord::ConnectionAdapters
793
822
  public :sql_for_insert
794
823
  alias :postgresql_version :database_version
795
824
 
796
- def jdbc_connection_class(spec)
797
- ::ArJdbc::PostgreSQL.jdbc_connection_class
798
- end
799
-
800
825
  private
801
826
 
802
827
  FEATURE_NOT_SUPPORTED = "0A000" # :nodoc:
@@ -829,8 +854,10 @@ module ActiveRecord::ConnectionAdapters
829
854
 
830
855
  type_casted_binds = type_casted_binds(binds)
831
856
  log(sql, name, binds, type_casted_binds, async: async) do
832
- ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
833
- @connection.exec_params(sql, type_casted_binds)
857
+ with_raw_connection do |conn|
858
+ result = conn.exec_params(sql, type_casted_binds)
859
+ verified!
860
+ result
834
861
  end
835
862
  end
836
863
  end
@@ -67,28 +67,6 @@ module ArJdbc
67
67
 
68
68
  # @private
69
69
  module OIDTypes
70
-
71
- # @override
72
- def enable_extension(name)
73
- result = super(name)
74
- @extensions = nil
75
- reload_type_map
76
- result
77
- end
78
-
79
- # @override
80
- def disable_extension(name)
81
- result = super(name)
82
- @extensions = nil
83
- reload_type_map
84
- result
85
- end
86
-
87
- # @override
88
- def extensions
89
- @extensions ||= super
90
- end
91
-
92
70
  def get_oid_type(oid, fmod, column_name, sql_type = '') # :nodoc:
93
71
  # Note: type_map is storing a bunch of oid type prefixed with a namespace even
94
72
  # if they are not namespaced (e.g. ""."oidvector"). builtin types which are
@@ -118,8 +96,15 @@ module ArJdbc
118
96
  end
119
97
 
120
98
  def reload_type_map
121
- type_map.clear
99
+ @lock.synchronize do
100
+ if @type_map
101
+ type_map.clear
102
+ else
103
+ @type_map = Type::HashLookupTypeMap.new
104
+ end
105
+
122
106
  initialize_type_map
107
+ end
123
108
  end
124
109
 
125
110
  def initialize_type_map_inner(m)
@@ -274,10 +259,6 @@ module ArJdbc
274
259
  $1.to_i if sql_type =~ /\((\d+)(,\d+)?\)/
275
260
  end
276
261
 
277
- def extract_limit(sql_type)
278
- $1.to_i if sql_type =~ /\((.*)\)/
279
- end
280
-
281
262
  # Support arrays/ranges for defining attributes that don't exist in the db
282
263
  ActiveRecord::Type.add_modifier({ array: true }, OID::Array, adapter: :postgresql)
283
264
  ActiveRecord::Type.add_modifier({ range: true }, OID::Range, adapter: :postgresql)
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ArJdbc
4
+ module PostgreSQL
5
+ module SchemaStatements
6
+ ForeignKeyDefinition = ActiveRecord::ConnectionAdapters::ForeignKeyDefinition
7
+ Utils = ActiveRecord::ConnectionAdapters::PostgreSQL::Utils
8
+
9
+ def foreign_keys(table_name)
10
+ scope = quoted_scope(table_name)
11
+ fk_info = internal_exec_query(<<~SQL, "SCHEMA", allow_retry: true, materialize_transactions: false)
12
+ SELECT t2.oid::regclass::text AS to_table, a1.attname AS column, a2.attname AS primary_key, c.conname AS name, c.confupdtype AS on_update, c.confdeltype AS on_delete, c.convalidated AS valid, c.condeferrable AS deferrable, c.condeferred AS deferred, c.conkey, c.confkey, c.conrelid, c.confrelid
13
+ FROM pg_constraint c
14
+ JOIN pg_class t1 ON c.conrelid = t1.oid
15
+ JOIN pg_class t2 ON c.confrelid = t2.oid
16
+ JOIN pg_attribute a1 ON a1.attnum = c.conkey[1] AND a1.attrelid = t1.oid
17
+ JOIN pg_attribute a2 ON a2.attnum = c.confkey[1] AND a2.attrelid = t2.oid
18
+ JOIN pg_namespace t3 ON c.connamespace = t3.oid
19
+ WHERE c.contype = 'f'
20
+ AND t1.relname = #{scope[:name]}
21
+ AND t3.nspname = #{scope[:schema]}
22
+ ORDER BY c.conname
23
+ SQL
24
+
25
+ fk_info.map do |row|
26
+ to_table = Utils.unquote_identifier(row["to_table"])
27
+ # conkey = row["conkey"].scan(/\d+/).map(&:to_i)
28
+ # confkey = row["confkey"].scan(/\d+/).map(&:to_i)
29
+ conkey = row["conkey"]
30
+ confkey = row["confkey"]
31
+
32
+ if conkey.size > 1
33
+ column = column_names_from_column_numbers(row["conrelid"], conkey)
34
+ primary_key = column_names_from_column_numbers(row["confrelid"], confkey)
35
+ else
36
+ column = Utils.unquote_identifier(row["column"])
37
+ primary_key = row["primary_key"]
38
+ end
39
+
40
+ options = {
41
+ column: column,
42
+ name: row["name"],
43
+ primary_key: primary_key
44
+ }
45
+
46
+ options[:on_delete] = extract_foreign_key_action(row["on_delete"])
47
+ options[:on_update] = extract_foreign_key_action(row["on_update"])
48
+ options[:deferrable] = extract_constraint_deferrable(row["deferrable"], row["deferred"])
49
+
50
+ options[:validate] = row["valid"]
51
+
52
+ ForeignKeyDefinition.new(table_name, to_table, options)
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -706,44 +706,6 @@ module ArJdbc
706
706
  # https://www.sqlite.org/pragma.html#pragma_cache_size
707
707
  raw_execute("PRAGMA cache_size = 2000", "SCHEMA")
708
708
  end
709
-
710
- def configure_connection
711
- if @config[:timeout] && @config[:retries]
712
- raise ArgumentError, "Cannot specify both timeout and retries arguments"
713
- elsif @config[:timeout]
714
- # FIXME:
715
- # @raw_connection.busy_timeout(self.class.type_cast_config_to_integer(@config[:timeout]))
716
- elsif @config[:retries]
717
- retries = self.class.type_cast_config_to_integer(@config[:retries])
718
- raw_connection.busy_handler do |count|
719
- count <= retries
720
- end
721
- end
722
-
723
- # Enforce foreign key constraints
724
- # https://www.sqlite.org/pragma.html#pragma_foreign_keys
725
- # https://www.sqlite.org/foreignkeys.html
726
- raw_execute("PRAGMA foreign_keys = ON", "SCHEMA")
727
- unless @memory_database
728
- # Journal mode WAL allows for greater concurrency (many readers + one writer)
729
- # https://www.sqlite.org/pragma.html#pragma_journal_mode
730
- raw_execute("PRAGMA journal_mode = WAL", "SCHEMA")
731
- # Set more relaxed level of database durability
732
- # 2 = "FULL" (sync on every write), 1 = "NORMAL" (sync every 1000 written pages) and 0 = "NONE"
733
- # https://www.sqlite.org/pragma.html#pragma_synchronous
734
- raw_execute("PRAGMA synchronous = NORMAL", "SCHEMA")
735
- # Set the global memory map so all processes can share some data
736
- # https://www.sqlite.org/pragma.html#pragma_mmap_size
737
- # https://www.sqlite.org/mmap.html
738
- raw_execute("PRAGMA mmap_size = #{128.megabytes}", "SCHEMA")
739
- end
740
- # Impose a limit on the WAL file to prevent unlimited growth
741
- # https://www.sqlite.org/pragma.html#pragma_journal_size_limit
742
- raw_execute("PRAGMA journal_size_limit = #{64.megabytes}", "SCHEMA")
743
- # Set the local connection cache to 2000 pages
744
- # https://www.sqlite.org/pragma.html#pragma_cache_size
745
- raw_execute("PRAGMA cache_size = 2000", "SCHEMA")
746
- end
747
709
  end
748
710
  # DIFFERENCE: A registration here is moved down to concrete class so we are not registering part of an adapter.
749
711
  end
@@ -774,6 +736,20 @@ module ActiveRecord::ConnectionAdapters
774
736
  # config.active_record.sqlite3_adapter_strict_strings_by_default = true
775
737
  class_attribute :strict_strings_by_default, default: false # Does not actually do anything right now
776
738
 
739
+ def initialize(...)
740
+ super
741
+
742
+ conn_params = @config.compact
743
+
744
+ # NOTE: strict strings is not supported by the jdbc driver yet,
745
+ # hope it will supported soon, I open a issue in their repository.
746
+ # https://github.com/xerial/sqlite-jdbc/issues/1153
747
+ #
748
+ # @config[:strict] = ConnectionAdapters::SQLite3Adapter.strict_strings_by_default unless @config.key?(:strict)
749
+
750
+ @connection_parameters = conn_params
751
+ end
752
+
777
753
  def self.represent_boolean_as_integer=(value) # :nodoc:
778
754
  if value == false
779
755
  raise "`.represent_boolean_as_integer=` is now always true, so make sure your application can work with it and remove this settings."
@@ -817,15 +793,6 @@ module ActiveRecord::ConnectionAdapters
817
793
  ::ActiveRecord::ConnectionAdapters::SQLite3Column
818
794
  end
819
795
 
820
- def jdbc_connection_class(spec)
821
- self.class.jdbc_connection_class
822
- end
823
-
824
- # @see ActiveRecord::ConnectionAdapters::JdbcAdapter#jdbc_connection_class
825
- def self.jdbc_connection_class
826
- ::ActiveRecord::ConnectionAdapters::SQLite3JdbcConnection
827
- end
828
-
829
796
  # Note: This is not an override of ours but a moved line from AR Sqlite3Adapter to register ours vs our copied module (which would be their class).
830
797
  # ActiveSupport.run_load_hooks(:active_record_sqlite3adapter, SQLite3Adapter)
831
798
 
@@ -843,6 +810,14 @@ module ActiveRecord::ConnectionAdapters
843
810
  ::ActiveRecord::Type.register(:integer, SQLite3Integer, adapter: :sqlite3)
844
811
 
845
812
  class << self
813
+ def jdbc_connection_class
814
+ ::ActiveRecord::ConnectionAdapters::SQLite3JdbcConnection
815
+ end
816
+
817
+ def new_client(conn_params, adapter_instance)
818
+ jdbc_connection_class.new(conn_params, adapter_instance)
819
+ end
820
+
846
821
  def dbconsole(config, options = {})
847
822
  args = []
848
823
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ArJdbc
4
- VERSION = '71.0.0.alpha1'
4
+ VERSION = '71.0.0.alpha2'
5
5
  end
@@ -793,8 +793,8 @@ public class RubyJdbcConnection extends RubyObject {
793
793
  // Unfortunately the result set gets closed when getMoreResults()
794
794
  // is called, so we have to process the result sets as we get them
795
795
  // this shouldn't be an issue in most cases since we're only getting 1 result set anyways
796
- //result = mapExecuteResult(context, connection, resultSet);
797
- result = mapToRawResult(context, connection, resultSet, false);
796
+ result = mapExecuteResult(context, connection, resultSet);
797
+ // result = mapToRawResult(context, connection, resultSet, false);
798
798
  resultSet.close();
799
799
  } else {
800
800
  result = context.runtime.newFixnum(updateCount);
@@ -119,6 +119,17 @@ public class MySQLRubyJdbcConnection extends RubyJdbcConnection {
119
119
  return driverWrapper;
120
120
  }
121
121
 
122
+ @JRubyMethod(name = "ping")
123
+ public RubyBoolean db_ping(final ThreadContext context) {
124
+ final Connection connection = getConnection(true);
125
+ if (connection == null) return context.fals;
126
+
127
+ // NOTE: It seems only `connection.isValid(aliveTimeout)` is needed
128
+ // for JDBC 4.0 and up. https://jira.mariadb.org/browse/CONJ-51
129
+
130
+ return context.runtime.newBoolean(isConnectionValid(context, connection));
131
+ }
132
+
122
133
  private static transient Class MYSQL_CONNECTION;
123
134
  private static transient Boolean MYSQL_CONNECTION_FOUND;
124
135
 
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: 71.0.0.alpha1
4
+ version: 71.0.0.alpha2
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: 2024-07-24 00:00:00.000000000 Z
11
+ date: 2024-08-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
@@ -145,6 +145,7 @@ files:
145
145
  - lib/arjdbc/postgresql/connection_methods.rb
146
146
  - lib/arjdbc/postgresql/name.rb
147
147
  - lib/arjdbc/postgresql/oid_types.rb
148
+ - lib/arjdbc/postgresql/schema_statements.rb
148
149
  - lib/arjdbc/railtie.rb
149
150
  - lib/arjdbc/sqlite3.rb
150
151
  - lib/arjdbc/sqlite3/adapter.rb