activerecord-jdbc-adapter 60.4-java → 61.2-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/ruby.yml +266 -0
- data/.travis.yml +13 -12
- 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 +4 -0
- data/lib/arjdbc/abstract/transaction_support.rb +20 -7
- data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
- data/lib/arjdbc/jdbc/adapter_require.rb +3 -1
- data/lib/arjdbc/mysql/adapter.rb +14 -5
- data/lib/arjdbc/mysql/connection_methods.rb +5 -1
- data/lib/arjdbc/postgresql/adapter.rb +85 -73
- data/lib/arjdbc/postgresql/column.rb +1 -1
- data/lib/arjdbc/postgresql/oid_types.rb +4 -3
- data/lib/arjdbc/sqlite3/adapter.rb +95 -58
- data/lib/arjdbc/sqlite3/connection_methods.rb +11 -1
- data/lib/arjdbc/tasks/databases.rake +15 -10
- data/lib/arjdbc/version.rb +1 -1
- data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +106 -68
- data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +81 -22
- data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +3 -4
- metadata +6 -5
@@ -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
|
|
@@ -311,11 +282,6 @@ module ArJdbc
|
|
311
282
|
true
|
312
283
|
end
|
313
284
|
|
314
|
-
# From AR 5.1 postgres_adapter.rb
|
315
|
-
def default_index_type?(index) # :nodoc:
|
316
|
-
index.using == :btree || super
|
317
|
-
end
|
318
|
-
|
319
285
|
def get_advisory_lock(lock_id) # :nodoc:
|
320
286
|
unless lock_id.is_a?(Integer) && lock_id.bit_length <= 63
|
321
287
|
raise(ArgumentError, "PostgreSQL requires advisory lock ids to be a signed 64 bit integer")
|
@@ -369,6 +335,65 @@ module ArJdbc
|
|
369
335
|
@use_insert_returning
|
370
336
|
end
|
371
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
|
+
|
372
397
|
def exec_insert(sql, name = nil, binds = [], pk = nil, sequence_name = nil)
|
373
398
|
val = super
|
374
399
|
if !use_insert_returning? && pk
|
@@ -384,11 +409,7 @@ module ArJdbc
|
|
384
409
|
end
|
385
410
|
|
386
411
|
def execute_batch(statements, name = nil)
|
387
|
-
|
388
|
-
execute(combine_multi_statements(statements), name)
|
389
|
-
else
|
390
|
-
execute(statements, name)
|
391
|
-
end
|
412
|
+
execute(combine_multi_statements(statements), name)
|
392
413
|
end
|
393
414
|
|
394
415
|
def explain(arel, binds = [])
|
@@ -398,7 +419,7 @@ module ArJdbc
|
|
398
419
|
|
399
420
|
# from ActiveRecord::ConnectionAdapters::PostgreSQL::DatabaseStatements
|
400
421
|
READ_QUERY = ActiveRecord::ConnectionAdapters::AbstractAdapter.build_read_query_regexp(
|
401
|
-
:
|
422
|
+
:close, :declare, :fetch, :move, :set, :show
|
402
423
|
) # :nodoc:
|
403
424
|
private_constant :READ_QUERY
|
404
425
|
|
@@ -434,27 +455,8 @@ module ArJdbc
|
|
434
455
|
exec_query("SELECT currval('#{sequence_name}')", 'SQL')
|
435
456
|
end
|
436
457
|
|
437
|
-
def
|
438
|
-
|
439
|
-
|
440
|
-
if insert.skip_duplicates?
|
441
|
-
sql << " ON CONFLICT #{insert.conflict_target} DO NOTHING"
|
442
|
-
elsif insert.update_duplicates?
|
443
|
-
sql << " ON CONFLICT #{insert.conflict_target} DO UPDATE SET "
|
444
|
-
sql << insert.updatable_columns.map { |column| "#{column}=excluded.#{column}" }.join(",")
|
445
|
-
end
|
446
|
-
|
447
|
-
sql << " RETURNING #{insert.returning}" if insert.returning
|
448
|
-
sql
|
449
|
-
end
|
450
|
-
|
451
|
-
def build_truncate_statements(*table_names)
|
452
|
-
["TRUNCATE TABLE #{table_names.flatten.map(&method(:quote_table_name)).join(", ")}"]
|
453
|
-
end
|
454
|
-
|
455
|
-
def truncate(table_name, name = nil)
|
456
|
-
ActiveRecord::Base.clear_query_caches_for_current_thread if @query_cache_enabled
|
457
|
-
execute("TRUNCATE TABLE #{quote_table_name(table_name)}", name)
|
458
|
+
def build_truncate_statements(table_names)
|
459
|
+
["TRUNCATE TABLE #{table_names.map(&method(:quote_table_name)).join(", ")}"]
|
458
460
|
end
|
459
461
|
|
460
462
|
def all_schemas
|
@@ -541,6 +543,16 @@ module ArJdbc
|
|
541
543
|
|
542
544
|
# Returns the list of a table's column names, data types, and default values.
|
543
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
|
+
#
|
544
556
|
# If the table name is not prefixed with a schema, the database will
|
545
557
|
# take the first match from the schema search path.
|
546
558
|
#
|
@@ -48,7 +48,7 @@ module ArJdbc
|
|
48
48
|
end
|
49
49
|
|
50
50
|
def has_default_function?(default_value, default)
|
51
|
-
!default_value && %r{\w+\(.*\)|\(.*\)::\w+|CURRENT_DATE|CURRENT_TIMESTAMP}.match?(default)
|
51
|
+
!default_value && default && %r{\w+\(.*\)|\(.*\)::\w+|CURRENT_DATE|CURRENT_TIMESTAMP}.match?(default)
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
@@ -145,7 +145,7 @@ module ArJdbc
|
|
145
145
|
m.register_type 'uuid', OID::Uuid.new
|
146
146
|
m.register_type 'xml', OID::Xml.new
|
147
147
|
m.register_type 'tsvector', OID::SpecializedString.new(:tsvector)
|
148
|
-
m.register_type 'macaddr', OID::
|
148
|
+
m.register_type 'macaddr', OID::Macaddr.new
|
149
149
|
m.register_type 'citext', OID::SpecializedString.new(:citext)
|
150
150
|
m.register_type 'ltree', OID::SpecializedString.new(:ltree)
|
151
151
|
m.register_type 'line', OID::SpecializedString.new(:line)
|
@@ -155,9 +155,9 @@ module ArJdbc
|
|
155
155
|
m.register_type 'polygon', OID::SpecializedString.new(:polygon)
|
156
156
|
m.register_type 'circle', OID::SpecializedString.new(:circle)
|
157
157
|
|
158
|
-
m.register_type 'interval' do
|
158
|
+
m.register_type 'interval' do |*args, sql_type|
|
159
159
|
precision = extract_precision(sql_type)
|
160
|
-
OID::
|
160
|
+
OID::Interval.new(precision: precision)
|
161
161
|
end
|
162
162
|
|
163
163
|
register_class_with_precision m, 'time', Type::Time
|
@@ -244,6 +244,7 @@ module ArJdbc
|
|
244
244
|
ActiveRecord::Type.register(:enum, OID::Enum, adapter: :postgresql)
|
245
245
|
ActiveRecord::Type.register(:hstore, OID::Hstore, adapter: :postgresql)
|
246
246
|
ActiveRecord::Type.register(:inet, OID::Inet, adapter: :postgresql)
|
247
|
+
ActiveRecord::Type.register(:interval, OID::Interval, adapter: :postgresql)
|
247
248
|
ActiveRecord::Type.register(:json, Type::Json, adapter: :postgresql)
|
248
249
|
ActiveRecord::Type.register(:jsonb, OID::Jsonb, adapter: :postgresql)
|
249
250
|
ActiveRecord::Type.register(:money, OID::Money, adapter: :postgresql)
|
@@ -16,6 +16,33 @@ require "active_record/connection_adapters/sqlite3/schema_dumper"
|
|
16
16
|
require "active_record/connection_adapters/sqlite3/schema_statements"
|
17
17
|
require "active_support/core_ext/class/attribute"
|
18
18
|
|
19
|
+
module SQLite3
|
20
|
+
module Constants
|
21
|
+
module Open
|
22
|
+
READONLY = 0x00000001
|
23
|
+
READWRITE = 0x00000002
|
24
|
+
CREATE = 0x00000004
|
25
|
+
DELETEONCLOSE = 0x00000008
|
26
|
+
EXCLUSIVE = 0x00000010
|
27
|
+
AUTOPROXY = 0x00000020
|
28
|
+
URI = 0x00000040
|
29
|
+
MEMORY = 0x00000080
|
30
|
+
MAIN_DB = 0x00000100
|
31
|
+
TEMP_DB = 0x00000200
|
32
|
+
TRANSIENT_DB = 0x00000400
|
33
|
+
MAIN_JOURNAL = 0x00000800
|
34
|
+
TEMP_JOURNAL = 0x00001000
|
35
|
+
SUBJOURNAL = 0x00002000
|
36
|
+
MASTER_JOURNAL = 0x00004000
|
37
|
+
NOMUTEX = 0x00008000
|
38
|
+
FULLMUTEX = 0x00010000
|
39
|
+
SHAREDCACHE = 0x00020000
|
40
|
+
PRIVATECACHE = 0x00040000
|
41
|
+
WAL = 0x00080000
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
19
46
|
module ArJdbc
|
20
47
|
# All the code in this module is a copy of ConnectionAdapters::SQLite3Adapter from active_record 5.
|
21
48
|
# The constants at the front of this file are to allow the rest of the file to remain with no modifications
|
@@ -69,6 +96,10 @@ module ArJdbc
|
|
69
96
|
true
|
70
97
|
end
|
71
98
|
|
99
|
+
def supports_transaction_isolation?
|
100
|
+
true
|
101
|
+
end
|
102
|
+
|
72
103
|
def supports_partial_index?
|
73
104
|
database_version >= "3.9.0"
|
74
105
|
end
|
@@ -85,6 +116,10 @@ module ArJdbc
|
|
85
116
|
true
|
86
117
|
end
|
87
118
|
|
119
|
+
def supports_check_constraints?
|
120
|
+
true
|
121
|
+
end
|
122
|
+
|
88
123
|
def supports_views?
|
89
124
|
true
|
90
125
|
end
|
@@ -114,13 +149,6 @@ module ArJdbc
|
|
114
149
|
true
|
115
150
|
end
|
116
151
|
|
117
|
-
# Returns 62. SQLite supports index names up to 64
|
118
|
-
# characters. The rest is used by Rails internally to perform
|
119
|
-
# temporary rename operations
|
120
|
-
def allowed_index_name_length
|
121
|
-
index_name_length - 2
|
122
|
-
end
|
123
|
-
|
124
152
|
def native_database_types #:nodoc:
|
125
153
|
NATIVE_DATABASE_TYPES
|
126
154
|
end
|
@@ -159,7 +187,7 @@ module ArJdbc
|
|
159
187
|
#++
|
160
188
|
|
161
189
|
READ_QUERY = ActiveRecord::ConnectionAdapters::AbstractAdapter.build_read_query_regexp(
|
162
|
-
:
|
190
|
+
:pragma
|
163
191
|
) # :nodoc:
|
164
192
|
private_constant :READ_QUERY
|
165
193
|
|
@@ -187,15 +215,15 @@ module ArJdbc
|
|
187
215
|
#def execute(sql, name = nil) #:nodoc:
|
188
216
|
|
189
217
|
def begin_db_transaction #:nodoc:
|
190
|
-
log("begin transaction",
|
218
|
+
log("begin transaction", 'TRANSACTION') { @connection.transaction }
|
191
219
|
end
|
192
220
|
|
193
221
|
def commit_db_transaction #:nodoc:
|
194
|
-
log("commit transaction",
|
222
|
+
log("commit transaction", 'TRANSACTION') { @connection.commit }
|
195
223
|
end
|
196
224
|
|
197
225
|
def exec_rollback_db_transaction #:nodoc:
|
198
|
-
log("rollback transaction",
|
226
|
+
log("rollback transaction", 'TRANSACTION') { @connection.rollback }
|
199
227
|
end
|
200
228
|
|
201
229
|
# SCHEMA STATEMENTS ========================================
|
@@ -205,8 +233,11 @@ module ArJdbc
|
|
205
233
|
pks.sort_by { |f| f["pk"] }.map { |f| f["name"] }
|
206
234
|
end
|
207
235
|
|
208
|
-
|
209
|
-
|
236
|
+
def remove_index(table_name, column_name = nil, **options) # :nodoc:
|
237
|
+
return if options[:if_exists] && !index_exists?(table_name, column_name, **options)
|
238
|
+
|
239
|
+
index_name = index_name_for_remove(table_name, column_name, options)
|
240
|
+
|
210
241
|
exec_query "DROP INDEX #{quote_column_name(index_name)}"
|
211
242
|
end
|
212
243
|
|
@@ -215,14 +246,16 @@ module ArJdbc
|
|
215
246
|
# Example:
|
216
247
|
# rename_table('octopuses', 'octopi')
|
217
248
|
def rename_table(table_name, new_name)
|
249
|
+
schema_cache.clear_data_source_cache!(table_name.to_s)
|
250
|
+
schema_cache.clear_data_source_cache!(new_name.to_s)
|
218
251
|
exec_query "ALTER TABLE #{quote_table_name(table_name)} RENAME TO #{quote_table_name(new_name)}"
|
219
252
|
rename_table_indexes(table_name, new_name)
|
220
253
|
end
|
221
254
|
|
222
|
-
def add_column(table_name, column_name, type, options
|
255
|
+
def add_column(table_name, column_name, type, **options) #:nodoc:
|
223
256
|
if invalid_alter_table_type?(type, options)
|
224
257
|
alter_table(table_name) do |definition|
|
225
|
-
definition.column(column_name, type, options)
|
258
|
+
definition.column(column_name, type, **options)
|
226
259
|
end
|
227
260
|
else
|
228
261
|
super
|
@@ -255,16 +288,11 @@ module ArJdbc
|
|
255
288
|
end
|
256
289
|
end
|
257
290
|
|
258
|
-
def change_column(table_name, column_name, type, options
|
291
|
+
def change_column(table_name, column_name, type, **options) #:nodoc:
|
259
292
|
alter_table(table_name) do |definition|
|
260
293
|
definition[column_name].instance_eval do
|
261
294
|
self.type = type
|
262
|
-
|
263
|
-
self.default = options[:default] if options.include?(:default)
|
264
|
-
self.null = options[:null] if options.include?(:null)
|
265
|
-
self.precision = options[:precision] if options.include?(:precision)
|
266
|
-
self.scale = options[:scale] if options.include?(:scale)
|
267
|
-
self.collation = options[:collation] if options.include?(:collation)
|
295
|
+
self.options.merge!(options)
|
268
296
|
end
|
269
297
|
end
|
270
298
|
end
|
@@ -313,12 +341,17 @@ module ArJdbc
|
|
313
341
|
sql << " ON CONFLICT #{insert.conflict_target} DO NOTHING"
|
314
342
|
elsif insert.update_duplicates?
|
315
343
|
sql << " ON CONFLICT #{insert.conflict_target} DO UPDATE SET "
|
344
|
+
sql << insert.touch_model_timestamps_unless { |column| "#{column} IS excluded.#{column}" }
|
316
345
|
sql << insert.updatable_columns.map { |column| "#{column}=excluded.#{column}" }.join(",")
|
317
346
|
end
|
318
347
|
|
319
348
|
sql
|
320
349
|
end
|
321
350
|
|
351
|
+
def shared_cache?
|
352
|
+
config[:properties] && config[:properties][:shared_cache] == true
|
353
|
+
end
|
354
|
+
|
322
355
|
def get_database_version # :nodoc:
|
323
356
|
SQLite3Adapter::Version.new(query_value("SELECT sqlite_version(*)"))
|
324
357
|
end
|
@@ -327,15 +360,6 @@ module ArJdbc
|
|
327
360
|
"DELETE FROM #{quote_table_name(table_name)}"
|
328
361
|
end
|
329
362
|
|
330
|
-
def build_truncate_statements(*table_names)
|
331
|
-
table_names.flatten.map { |table_name| build_truncate_statement table_name }
|
332
|
-
end
|
333
|
-
|
334
|
-
def truncate(table_name, name = nil)
|
335
|
-
ActiveRecord::Base.clear_query_caches_for_current_thread if @query_cache_enabled
|
336
|
-
execute(build_truncate_statement(table_name), name)
|
337
|
-
end
|
338
|
-
|
339
363
|
def check_version
|
340
364
|
if database_version < "3.8.0"
|
341
365
|
raise "Your version of SQLite (#{database_version}) is too old. Active Record supports SQLite >= 3.8."
|
@@ -349,11 +373,6 @@ module ArJdbc
|
|
349
373
|
999
|
350
374
|
end
|
351
375
|
|
352
|
-
def initialize_type_map(m = type_map)
|
353
|
-
super
|
354
|
-
register_class_with_limit m, %r(int)i, SQLite3Integer
|
355
|
-
end
|
356
|
-
|
357
376
|
def table_structure(table_name)
|
358
377
|
structure = exec_query("PRAGMA table_info(#{quote_table_name(table_name)})", "SCHEMA")
|
359
378
|
raise(ActiveRecord::StatementInvalid, "Could not find table '#{table_name}'") if structure.empty?
|
@@ -368,7 +387,12 @@ module ArJdbc
|
|
368
387
|
options[:null] == false && options[:default].nil?
|
369
388
|
end
|
370
389
|
|
371
|
-
def alter_table(
|
390
|
+
def alter_table(
|
391
|
+
table_name,
|
392
|
+
foreign_keys = foreign_keys(table_name),
|
393
|
+
check_constraints = check_constraints(table_name),
|
394
|
+
**options
|
395
|
+
)
|
372
396
|
altered_table_name = "a#{table_name}"
|
373
397
|
|
374
398
|
caller = lambda do |definition|
|
@@ -378,7 +402,11 @@ module ArJdbc
|
|
378
402
|
fk.options[:column] = column
|
379
403
|
end
|
380
404
|
to_table = strip_table_name_prefix_and_suffix(fk.to_table)
|
381
|
-
definition.foreign_key(to_table, fk.options)
|
405
|
+
definition.foreign_key(to_table, **fk.options)
|
406
|
+
end
|
407
|
+
|
408
|
+
check_constraints.each do |chk|
|
409
|
+
definition.check_constraint(chk.expression, **chk.options)
|
382
410
|
end
|
383
411
|
|
384
412
|
yield definition if block_given?
|
@@ -400,11 +428,12 @@ module ArJdbc
|
|
400
428
|
def copy_table(from, to, options = {})
|
401
429
|
from_primary_key = primary_key(from)
|
402
430
|
options[:id] = false
|
403
|
-
create_table(to, options) do |definition|
|
431
|
+
create_table(to, **options) do |definition|
|
404
432
|
@definition = definition
|
405
433
|
if from_primary_key.is_a?(Array)
|
406
434
|
@definition.primary_keys from_primary_key
|
407
435
|
end
|
436
|
+
|
408
437
|
columns(from).each do |column|
|
409
438
|
column_name = options[:rename] ?
|
410
439
|
(options[:rename][column.name] ||
|
@@ -432,7 +461,7 @@ module ArJdbc
|
|
432
461
|
name = index.name
|
433
462
|
# indexes sqlite creates for internal use start with `sqlite_` and
|
434
463
|
# don't need to be copied
|
435
|
-
next if name.
|
464
|
+
next if name.start_with?("sqlite_")
|
436
465
|
if to == "a#{from}"
|
437
466
|
name = "t#{name}"
|
438
467
|
elsif from == "a#{to}"
|
@@ -449,10 +478,10 @@ module ArJdbc
|
|
449
478
|
|
450
479
|
unless columns.empty?
|
451
480
|
# index name can't be the same
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
add_index(to, columns,
|
481
|
+
options = { name: name.gsub(/(^|_)(#{from})_/, "\\1#{to}_"), internal: true }
|
482
|
+
options[:unique] = true if index.unique
|
483
|
+
options[:where] = index.where if index.where
|
484
|
+
add_index(to, columns, **options)
|
456
485
|
end
|
457
486
|
end
|
458
487
|
end
|
@@ -517,7 +546,7 @@ module ArJdbc
|
|
517
546
|
collation_hash[$1] = $2 if COLLATE_REGEX =~ column_string
|
518
547
|
end
|
519
548
|
|
520
|
-
basic_structure.map
|
549
|
+
basic_structure.map do |column|
|
521
550
|
column_name = column["name"]
|
522
551
|
|
523
552
|
if collation_hash.has_key? column_name
|
@@ -539,18 +568,6 @@ module ArJdbc
|
|
539
568
|
execute("PRAGMA foreign_keys = ON", "SCHEMA")
|
540
569
|
end
|
541
570
|
|
542
|
-
# DIFFERENCE: FQN
|
543
|
-
class SQLite3Integer < ::ActiveRecord::Type::Integer # :nodoc:
|
544
|
-
private
|
545
|
-
def _limit
|
546
|
-
# INTEGER storage class can be stored 8 bytes value.
|
547
|
-
# See https://www.sqlite.org/datatype3.html#storage_classes_and_datatypes
|
548
|
-
limit || 8
|
549
|
-
end
|
550
|
-
end
|
551
|
-
|
552
|
-
# DIFFERENCE: FQN
|
553
|
-
::ActiveRecord::Type.register(:integer, SQLite3Integer, adapter: :sqlite3)
|
554
571
|
end
|
555
572
|
# DIFFERENCE: A registration here is moved down to concrete class so we are not registering part of an adapter.
|
556
573
|
end
|
@@ -671,7 +688,9 @@ module ActiveRecord::ConnectionAdapters
|
|
671
688
|
end
|
672
689
|
|
673
690
|
def begin_isolated_db_transaction(isolation)
|
674
|
-
raise ActiveRecord::TransactionIsolationError,
|
691
|
+
raise ActiveRecord::TransactionIsolationError, "SQLite3 only supports the `read_uncommitted` transaction isolation level" if isolation != :read_uncommitted
|
692
|
+
raise StandardError, "You need to enable the shared-cache mode in SQLite mode before attempting to change the transaction isolation level" unless shared_cache?
|
693
|
+
super
|
675
694
|
end
|
676
695
|
|
677
696
|
# SQLite driver doesn't support all types of insert statements with executeUpdate so
|
@@ -707,5 +726,23 @@ module ActiveRecord::ConnectionAdapters
|
|
707
726
|
total_sql
|
708
727
|
end
|
709
728
|
end
|
729
|
+
|
730
|
+
def initialize_type_map(m = type_map)
|
731
|
+
super
|
732
|
+
register_class_with_limit m, %r(int)i, SQLite3Integer
|
733
|
+
end
|
734
|
+
|
735
|
+
# DIFFERENCE: FQN
|
736
|
+
class SQLite3Integer < ::ActiveRecord::Type::Integer # :nodoc:
|
737
|
+
private
|
738
|
+
def _limit
|
739
|
+
# INTEGER storage class can be stored 8 bytes value.
|
740
|
+
# See https://www.sqlite.org/datatype3.html#storage_classes_and_datatypes
|
741
|
+
limit || 8
|
742
|
+
end
|
743
|
+
end
|
744
|
+
|
745
|
+
# DIFFERENCE: FQN
|
746
|
+
::ActiveRecord::Type.register(:integer, SQLite3Integer, adapter: :sqlite3)
|
710
747
|
end
|
711
748
|
end
|
@@ -35,7 +35,17 @@ ArJdbc::ConnectionMethods.module_eval do
|
|
35
35
|
# * http://sqlite.org/c3ref/open.html
|
36
36
|
# * http://sqlite.org/c3ref/c_open_autoproxy.html
|
37
37
|
# => 0x01 = readonly, 0x40 = uri (default in JDBC)
|
38
|
-
config[:properties][:open_mode] =
|
38
|
+
config[:properties][:open_mode] = ::SQLite3::Constants::Open::READONLY | ::SQLite3::Constants::Open::URI
|
39
|
+
end
|
40
|
+
|
41
|
+
if config[:flags]
|
42
|
+
config[:properties][:open_mode] ||= 0
|
43
|
+
config[:properties][:open_mode] |= config[:flags]
|
44
|
+
|
45
|
+
# JDBC driver has an extra flag for it
|
46
|
+
if config[:flags] & ::SQLite3::Constants::Open::SHAREDCACHE != 0
|
47
|
+
config[:properties][:shared_cache] = true
|
48
|
+
end
|
39
49
|
end
|
40
50
|
|
41
51
|
timeout = config[:timeout]
|
@@ -5,15 +5,17 @@ module ActiveRecord::Tasks
|
|
5
5
|
DatabaseTasks.module_eval do
|
6
6
|
|
7
7
|
# @override patched to adapt jdbc configuration
|
8
|
-
def each_current_configuration(environment,
|
8
|
+
def each_current_configuration(environment, name = nil)
|
9
9
|
environments = [environment]
|
10
10
|
environments << 'test' if environment == 'development'
|
11
11
|
|
12
12
|
environments.each do |env|
|
13
13
|
ActiveRecord::Base.configurations.configs_for(env_name: env).each do |db_config|
|
14
|
-
next if
|
14
|
+
next if name && name != db_config.name
|
15
15
|
|
16
|
-
|
16
|
+
if db_config.database
|
17
|
+
yield adapt_jdbc_config(db_config), db_config.name, env
|
18
|
+
end
|
17
19
|
end
|
18
20
|
end
|
19
21
|
end
|
@@ -21,21 +23,24 @@ module ActiveRecord::Tasks
|
|
21
23
|
# @override patched to adapt jdbc configuration
|
22
24
|
def each_local_configuration
|
23
25
|
ActiveRecord::Base.configurations.configs_for.each do |db_config|
|
24
|
-
next unless db_config.
|
26
|
+
next unless db_config.database
|
25
27
|
|
26
|
-
if local_database?(db_config
|
27
|
-
yield adapt_jdbc_config(db_config
|
28
|
+
if local_database?(db_config)
|
29
|
+
yield adapt_jdbc_config(db_config)
|
28
30
|
else
|
29
|
-
$stderr.puts "This task only modifies local databases. #{db_config.
|
31
|
+
$stderr.puts "This task only modifies local databases. #{db_config.database} is on a remote host."
|
30
32
|
end
|
31
33
|
end
|
32
34
|
end
|
33
35
|
|
34
36
|
private
|
35
37
|
|
36
|
-
def adapt_jdbc_config(
|
37
|
-
|
38
|
-
|
38
|
+
def adapt_jdbc_config(db_config)
|
39
|
+
if db_config.adapter.start_with? 'jdbc'
|
40
|
+
config = db_config.configuration_hash.merge(adapter: db_config.adapter.sub(/^jdbc/, ''))
|
41
|
+
db_config = ActiveRecord::DatabaseConfigurations::HashConfig.new(db_config.env_name, db_config.name, config)
|
42
|
+
end
|
43
|
+
db_config
|
39
44
|
end
|
40
45
|
|
41
46
|
end
|
data/lib/arjdbc/version.rb
CHANGED