activerecord-jdbc-alt-adapter 50.7.0-java → 51.3.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 +0 -3
- data/.travis.yml +24 -28
- data/Gemfile +5 -2
- data/README.md +26 -20
- data/Rakefile +4 -30
- data/activerecord-jdbc-adapter.gemspec +2 -2
- data/activerecord-jdbc-alt-adapter.gemspec +4 -3
- data/lib/arel/visitors/sqlserver.rb +17 -3
- data/lib/arjdbc/abstract/core.rb +4 -2
- data/lib/arjdbc/abstract/database_statements.rb +2 -8
- data/lib/arjdbc/abstract/transaction_support.rb +2 -9
- data/lib/arjdbc/db2/adapter.rb +2 -52
- data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
- data/lib/arjdbc/jdbc/column.rb +11 -5
- data/lib/arjdbc/jdbc/error.rb +1 -1
- data/lib/arjdbc/jdbc.rb +4 -0
- data/lib/arjdbc/mssql/adapter.rb +33 -39
- data/lib/arjdbc/mssql/connection_methods.rb +0 -5
- data/lib/arjdbc/mssql/database_statements.rb +1 -1
- data/lib/arjdbc/mssql/explain_support.rb +1 -1
- data/lib/arjdbc/mssql/{extensions.rb → extensions/attribute_methods.rb} +0 -0
- data/lib/arjdbc/mssql/extensions/calculations.rb +29 -0
- data/lib/arjdbc/mssql/schema_creation.rb +12 -0
- data/lib/arjdbc/mssql/schema_definitions.rb +17 -0
- data/lib/arjdbc/mssql/schema_dumper.rb +37 -0
- data/lib/arjdbc/mssql/schema_statements.rb +73 -44
- data/lib/arjdbc/mssql/types/date_and_time_types.rb +9 -9
- data/lib/arjdbc/mssql/utils.rb +1 -0
- data/lib/arjdbc/mssql.rb +1 -1
- data/lib/arjdbc/mysql/adapter.rb +12 -1
- data/lib/arjdbc/mysql/connection_methods.rb +7 -13
- data/lib/arjdbc/postgresql/adapter.rb +29 -12
- data/lib/arjdbc/postgresql/column.rb +3 -6
- data/lib/arjdbc/postgresql/connection_methods.rb +1 -3
- data/lib/arjdbc/postgresql/oid_types.rb +7 -12
- data/lib/arjdbc/sqlite3/adapter.rb +169 -139
- data/lib/arjdbc/sqlite3/connection_methods.rb +1 -2
- data/lib/arjdbc/version.rb +1 -1
- data/rakelib/01-tomcat.rake +2 -2
- data/rakelib/02-test.rake +2 -0
- data/rakelib/rails.rake +1 -1
- data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +17 -68
- data/src/java/arjdbc/mssql/MSSQLRubyJdbcConnection.java +38 -282
- data/src/java/arjdbc/postgresql/ByteaUtils.java +1 -0
- data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +3 -3
- data/src/java/arjdbc/util/DateTimeUtils.java +5 -22
- metadata +20 -12
- data/lib/activerecord-jdbc-alt-adapter.rb +0 -1
@@ -4,11 +4,14 @@ require "arjdbc/abstract/core"
|
|
4
4
|
require "arjdbc/abstract/database_statements"
|
5
5
|
require 'arjdbc/abstract/statement_cache'
|
6
6
|
require "arjdbc/abstract/transaction_support"
|
7
|
+
require "active_record/connection_adapters/abstract_adapter"
|
7
8
|
require "active_record/connection_adapters/statement_pool"
|
8
|
-
require "active_record/connection_adapters/abstract/database_statements"
|
9
9
|
require "active_record/connection_adapters/sqlite3/explain_pretty_printer"
|
10
10
|
require "active_record/connection_adapters/sqlite3/quoting"
|
11
11
|
require "active_record/connection_adapters/sqlite3/schema_creation"
|
12
|
+
require "active_record/connection_adapters/sqlite3/schema_definitions"
|
13
|
+
require "active_record/connection_adapters/sqlite3/schema_dumper"
|
14
|
+
require "active_record/connection_adapters/sqlite3/schema_statements"
|
12
15
|
|
13
16
|
module ArJdbc
|
14
17
|
# All the code in this module is a copy of ConnectionAdapters::SQLite3Adapter from active_record 5.
|
@@ -28,7 +31,10 @@ module ArJdbc
|
|
28
31
|
|
29
32
|
ADAPTER_NAME = 'SQLite'.freeze
|
30
33
|
|
31
|
-
|
34
|
+
# DIFFERENCE: FQN
|
35
|
+
include ::ActiveRecord::ConnectionAdapters::SQLite3::Quoting
|
36
|
+
include ::ActiveRecord::ConnectionAdapters::SQLite3::ColumnDumper
|
37
|
+
include ::ActiveRecord::ConnectionAdapters::SQLite3::SchemaStatements
|
32
38
|
|
33
39
|
NATIVE_DATABASE_TYPES = {
|
34
40
|
primary_key: "INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL",
|
@@ -52,8 +58,14 @@ module ArJdbc
|
|
52
58
|
end
|
53
59
|
end
|
54
60
|
|
61
|
+
def update_table_definition(table_name, base) # :nodoc:
|
62
|
+
# DIFFERENCE: FQN
|
63
|
+
::ActiveRecord::ConnectionAdapters::SQLite3::Table.new(table_name, base)
|
64
|
+
end
|
65
|
+
|
55
66
|
def schema_creation # :nodoc:
|
56
|
-
|
67
|
+
# DIFFERENCE: FQN
|
68
|
+
::ActiveRecord::ConnectionAdapters::SQLite3::SchemaCreation.new self
|
57
69
|
end
|
58
70
|
|
59
71
|
def arel_visitor # :nodoc:
|
@@ -65,6 +77,8 @@ module ArJdbc
|
|
65
77
|
|
66
78
|
@active = nil
|
67
79
|
@statements = StatementPool.new(self.class.type_cast_config_to_integer(config[:statement_limit]))
|
80
|
+
|
81
|
+
configure_connection
|
68
82
|
end
|
69
83
|
|
70
84
|
def supports_ddl_transactions?
|
@@ -85,17 +99,12 @@ module ArJdbc
|
|
85
99
|
true
|
86
100
|
end
|
87
101
|
|
88
|
-
|
89
|
-
def supports_migrations? #:nodoc:
|
90
|
-
true
|
91
|
-
end
|
92
|
-
|
93
|
-
def supports_primary_key? #:nodoc:
|
102
|
+
def requires_reloading?
|
94
103
|
true
|
95
104
|
end
|
96
105
|
|
97
|
-
def
|
98
|
-
|
106
|
+
def supports_foreign_keys_in_create?
|
107
|
+
sqlite_version >= "3.6.19"
|
99
108
|
end
|
100
109
|
|
101
110
|
def supports_views?
|
@@ -131,10 +140,6 @@ module ArJdbc
|
|
131
140
|
true
|
132
141
|
end
|
133
142
|
|
134
|
-
def valid_type?(type)
|
135
|
-
true
|
136
|
-
end
|
137
|
-
|
138
143
|
# Returns 62. SQLite supports index names up to 64
|
139
144
|
# characters. The rest is used by Rails internally to perform
|
140
145
|
# temporary rename operations
|
@@ -155,43 +160,59 @@ module ArJdbc
|
|
155
160
|
true
|
156
161
|
end
|
157
162
|
|
163
|
+
# REFERENTIAL INTEGRITY ====================================
|
164
|
+
|
165
|
+
def disable_referential_integrity # :nodoc:
|
166
|
+
old = query_value("PRAGMA foreign_keys")
|
167
|
+
|
168
|
+
begin
|
169
|
+
execute("PRAGMA foreign_keys = OFF")
|
170
|
+
yield
|
171
|
+
ensure
|
172
|
+
execute("PRAGMA foreign_keys = #{old}")
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
158
176
|
#--
|
159
177
|
# DATABASE STATEMENTS ======================================
|
160
178
|
#++
|
161
179
|
|
162
180
|
def explain(arel, binds = [])
|
163
181
|
sql = "EXPLAIN QUERY PLAN #{to_sql(arel, binds)}"
|
182
|
+
# DIFFERENCE: FQN
|
164
183
|
::ActiveRecord::ConnectionAdapters::SQLite3::ExplainPrettyPrinter.new.pp(exec_query(sql, "EXPLAIN", []))
|
165
184
|
end
|
166
185
|
|
167
186
|
def exec_query(sql, name = nil, binds = [], prepare: false)
|
168
|
-
type_casted_binds = binds
|
169
|
-
|
170
|
-
log(sql, name, binds) do
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
187
|
+
type_casted_binds = type_casted_binds(binds)
|
188
|
+
|
189
|
+
log(sql, name, binds, type_casted_binds) do
|
190
|
+
ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
|
191
|
+
# Don't cache statements if they are not prepared
|
192
|
+
unless prepare
|
193
|
+
stmt = @connection.prepare(sql)
|
194
|
+
begin
|
195
|
+
cols = stmt.columns
|
196
|
+
unless without_prepared_statement?(binds)
|
197
|
+
stmt.bind_params(type_casted_binds)
|
198
|
+
end
|
199
|
+
records = stmt.to_a
|
200
|
+
ensure
|
201
|
+
stmt.close
|
178
202
|
end
|
203
|
+
else
|
204
|
+
cache = @statements[sql] ||= {
|
205
|
+
stmt: @connection.prepare(sql)
|
206
|
+
}
|
207
|
+
stmt = cache[:stmt]
|
208
|
+
cols = cache[:cols] ||= stmt.columns
|
209
|
+
stmt.reset!
|
210
|
+
stmt.bind_params(type_casted_binds)
|
179
211
|
records = stmt.to_a
|
180
|
-
ensure
|
181
|
-
stmt.close
|
182
212
|
end
|
183
|
-
stmt = records
|
184
|
-
else
|
185
|
-
cache = @statements[sql] ||= {
|
186
|
-
:stmt => @connection.prepare(sql)
|
187
|
-
}
|
188
|
-
stmt = cache[:stmt]
|
189
|
-
cols = cache[:cols] ||= stmt.columns
|
190
|
-
stmt.reset!
|
191
|
-
stmt.bind_params(type_casted_binds)
|
192
|
-
end
|
193
213
|
|
194
|
-
|
214
|
+
ActiveRecord::Result.new(cols, records)
|
215
|
+
end
|
195
216
|
end
|
196
217
|
end
|
197
218
|
|
@@ -206,7 +227,11 @@ module ArJdbc
|
|
206
227
|
end
|
207
228
|
|
208
229
|
def execute(sql, name = nil) #:nodoc:
|
209
|
-
log(sql, name)
|
230
|
+
log(sql, name) do
|
231
|
+
ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
|
232
|
+
@connection.execute(sql)
|
233
|
+
end
|
234
|
+
end
|
210
235
|
end
|
211
236
|
|
212
237
|
def begin_db_transaction #:nodoc:
|
@@ -223,80 +248,30 @@ module ArJdbc
|
|
223
248
|
|
224
249
|
# SCHEMA STATEMENTS ========================================
|
225
250
|
|
226
|
-
def
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
235
|
-
Passing arguments to #tables is deprecated without replacement.
|
236
|
-
MSG
|
251
|
+
def new_column_from_field(table_name, field) # :nondoc:
|
252
|
+
case field["dflt_value"]
|
253
|
+
when /^null$/i
|
254
|
+
field["dflt_value"] = nil
|
255
|
+
when /^'(.*)'$/m
|
256
|
+
field["dflt_value"] = $1.gsub("''", "'")
|
257
|
+
when /^"(.*)"$/m
|
258
|
+
field["dflt_value"] = $1.gsub('""', '"')
|
237
259
|
end
|
238
260
|
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
select_values("SELECT name FROM sqlite_master WHERE type IN ('table','view') AND name <> 'sqlite_sequence'", "SCHEMA")
|
244
|
-
end
|
245
|
-
|
246
|
-
def table_exists?(table_name)
|
247
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
248
|
-
#table_exists? currently checks both tables and views.
|
249
|
-
This behavior is deprecated and will be changed with Rails 5.1 to only check tables.
|
250
|
-
Use #data_source_exists? instead.
|
251
|
-
MSG
|
252
|
-
|
253
|
-
data_source_exists?(table_name)
|
254
|
-
end
|
255
|
-
|
256
|
-
def data_source_exists?(table_name)
|
257
|
-
return false unless table_name.present?
|
258
|
-
|
259
|
-
sql = "SELECT name FROM sqlite_master WHERE type IN ('table','view') AND name <> 'sqlite_sequence'"
|
260
|
-
sql << " AND name = #{quote(table_name)}"
|
261
|
-
|
262
|
-
select_values(sql, "SCHEMA").any?
|
263
|
-
end
|
264
|
-
|
265
|
-
def views # :nodoc:
|
266
|
-
select_values("SELECT name FROM sqlite_master WHERE type = 'view' AND name <> 'sqlite_sequence'", "SCHEMA")
|
267
|
-
end
|
268
|
-
|
269
|
-
def view_exists?(view_name) # :nodoc:
|
270
|
-
return false unless view_name.present?
|
271
|
-
|
272
|
-
sql = "SELECT name FROM sqlite_master WHERE type = 'view' AND name <> 'sqlite_sequence'"
|
273
|
-
sql << " AND name = #{quote(view_name)}"
|
274
|
-
|
275
|
-
select_values(sql, "SCHEMA").any?
|
276
|
-
end
|
277
|
-
|
278
|
-
# Returns an array of +Column+ objects for the table specified by +table_name+.
|
279
|
-
def columns(table_name) # :nodoc:
|
280
|
-
table_name = table_name.to_s
|
281
|
-
table_structure(table_name).map do |field|
|
282
|
-
case field["dflt_value"]
|
283
|
-
when /^null$/i
|
284
|
-
field["dflt_value"] = nil
|
285
|
-
when /^'(.*)'$/m
|
286
|
-
field["dflt_value"] = $1.gsub("''", "'")
|
287
|
-
when /^"(.*)"$/m
|
288
|
-
field["dflt_value"] = $1.gsub('""', '"')
|
289
|
-
end
|
290
|
-
|
291
|
-
collation = field["collation"]
|
292
|
-
sql_type = field["type"]
|
293
|
-
type_metadata = fetch_type_metadata(sql_type)
|
294
|
-
new_column(field["name"], field["dflt_value"], type_metadata, field["notnull"].to_i == 0, table_name, nil, collation)
|
295
|
-
end
|
261
|
+
collation = field["collation"]
|
262
|
+
sql_type = field["type"]
|
263
|
+
type_metadata = fetch_type_metadata(sql_type)
|
264
|
+
new_column(field["name"], field["dflt_value"], type_metadata, field["notnull"].to_i == 0, table_name, nil, collation)
|
296
265
|
end
|
297
266
|
|
298
267
|
# Returns an array of indexes for the given table.
|
299
268
|
def indexes(table_name, name = nil) #:nodoc:
|
269
|
+
if name
|
270
|
+
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
271
|
+
Passing name to #indexes is deprecated without replacement.
|
272
|
+
MSG
|
273
|
+
end
|
274
|
+
|
300
275
|
exec_query("PRAGMA index_list(#{quote_table_name(table_name)})", "SCHEMA").map do |row|
|
301
276
|
sql = <<-SQL
|
302
277
|
SELECT sql
|
@@ -306,17 +281,17 @@ module ArJdbc
|
|
306
281
|
SELECT sql
|
307
282
|
FROM sqlite_temp_master
|
308
283
|
WHERE name=#{quote(row['name'])} AND type='index'
|
309
|
-
|
284
|
+
SQL
|
310
285
|
index_sql = exec_query(sql).first["sql"]
|
311
286
|
match = /\sWHERE\s+(.+)$/i.match(index_sql)
|
312
287
|
where = match[1] if match
|
313
288
|
IndexDefinition.new(
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
289
|
+
table_name,
|
290
|
+
row["name"],
|
291
|
+
row["unique"] != 0,
|
292
|
+
exec_query("PRAGMA index_info('#{row['name']}')", "SCHEMA").map { |col|
|
293
|
+
col["name"]
|
294
|
+
}, nil, nil, where)
|
320
295
|
end
|
321
296
|
end
|
322
297
|
|
@@ -346,7 +321,7 @@ module ArJdbc
|
|
346
321
|
end
|
347
322
|
|
348
323
|
def add_column(table_name, column_name, type, options = {}) #:nodoc:
|
349
|
-
if valid_alter_table_type?(type)
|
324
|
+
if valid_alter_table_type?(type) && !options[:primary_key]
|
350
325
|
super(table_name, column_name, type, options)
|
351
326
|
else
|
352
327
|
alter_table(table_name) do |definition|
|
@@ -380,11 +355,10 @@ module ArJdbc
|
|
380
355
|
|
381
356
|
def change_column(table_name, column_name, type, options = {}) #:nodoc:
|
382
357
|
alter_table(table_name) do |definition|
|
383
|
-
include_default = options_include_default?(options)
|
384
358
|
definition[column_name].instance_eval do
|
385
359
|
self.type = type
|
386
360
|
self.limit = options[:limit] if options.include?(:limit)
|
387
|
-
self.default = options[:default] if
|
361
|
+
self.default = options[:default] if options.include?(:default)
|
388
362
|
self.null = options[:null] if options.include?(:null)
|
389
363
|
self.precision = options[:precision] if options.include?(:precision)
|
390
364
|
self.scale = options[:scale] if options.include?(:scale)
|
@@ -399,14 +373,34 @@ module ArJdbc
|
|
399
373
|
rename_column_indexes(table_name, column.name, new_column_name)
|
400
374
|
end
|
401
375
|
|
402
|
-
|
376
|
+
def add_reference(table_name, ref_name, **options) # :nodoc:
|
377
|
+
super(table_name, ref_name, type: :integer, **options)
|
378
|
+
end
|
379
|
+
alias :add_belongs_to :add_reference
|
380
|
+
|
381
|
+
def foreign_keys(table_name)
|
382
|
+
fk_info = exec_query("PRAGMA foreign_key_list(#{quote(table_name)})", "SCHEMA")
|
383
|
+
fk_info.map do |row|
|
384
|
+
options = {
|
385
|
+
column: row["from"],
|
386
|
+
primary_key: row["to"],
|
387
|
+
on_delete: extract_foreign_key_action(row["on_delete"]),
|
388
|
+
on_update: extract_foreign_key_action(row["on_update"])
|
389
|
+
}
|
390
|
+
# DIFFERENCE: FQN
|
391
|
+
::ActiveRecord::ConnectionAdapters::ForeignKeyDefinition.new(table_name, row["table"], options)
|
392
|
+
end
|
393
|
+
end
|
394
|
+
|
395
|
+
private
|
403
396
|
|
404
397
|
def table_structure(table_name)
|
405
398
|
structure = exec_query("PRAGMA table_info(#{quote_table_name(table_name)})", "SCHEMA")
|
406
399
|
raise(ActiveRecord::StatementInvalid, "Could not find table '#{table_name}'") if structure.empty?
|
407
400
|
table_structure_with_collation(table_name, structure)
|
408
401
|
end
|
409
|
-
|
402
|
+
alias column_definitions table_structure
|
403
|
+
|
410
404
|
def alter_table(table_name, options = {}) #:nodoc:
|
411
405
|
altered_table_name = "a#{table_name}"
|
412
406
|
caller = lambda { |definition| yield definition if block_given? }
|
@@ -418,28 +412,31 @@ module ArJdbc
|
|
418
412
|
end
|
419
413
|
end
|
420
414
|
|
421
|
-
def move_table(from, to, options = {}, &block)
|
415
|
+
def move_table(from, to, options = {}, &block)
|
422
416
|
copy_table(from, to, options, &block)
|
423
417
|
drop_table(from)
|
424
418
|
end
|
425
419
|
|
426
|
-
def copy_table(from, to, options = {})
|
420
|
+
def copy_table(from, to, options = {})
|
427
421
|
from_primary_key = primary_key(from)
|
428
422
|
options[:id] = false
|
429
423
|
create_table(to, options) do |definition|
|
430
424
|
@definition = definition
|
431
|
-
|
425
|
+
if from_primary_key.is_a?(Array)
|
426
|
+
@definition.primary_keys from_primary_key
|
427
|
+
end
|
432
428
|
columns(from).each do |column|
|
433
429
|
column_name = options[:rename] ?
|
434
430
|
(options[:rename][column.name] ||
|
435
431
|
options[:rename][column.name.to_sym] ||
|
436
432
|
column.name) : column.name
|
437
|
-
next if column_name == from_primary_key
|
438
433
|
|
439
434
|
@definition.column(column_name, column.type,
|
440
435
|
limit: column.limit, default: column.default,
|
441
436
|
precision: column.precision, scale: column.scale,
|
442
|
-
null: column.null, collation: column.collation
|
437
|
+
null: column.null, collation: column.collation,
|
438
|
+
primary_key: column_name == from_primary_key
|
439
|
+
)
|
443
440
|
end
|
444
441
|
yield @definition if block_given?
|
445
442
|
end
|
@@ -449,9 +446,12 @@ module ArJdbc
|
|
449
446
|
options[:rename] || {})
|
450
447
|
end
|
451
448
|
|
452
|
-
def copy_table_indexes(from, to, rename = {})
|
449
|
+
def copy_table_indexes(from, to, rename = {})
|
453
450
|
indexes(from).each do |index|
|
454
451
|
name = index.name
|
452
|
+
# indexes sqlite creates for internal use start with `sqlite_` and
|
453
|
+
# don't need to be copied
|
454
|
+
next if name.starts_with?("sqlite_")
|
455
455
|
if to == "a#{from}"
|
456
456
|
name = "t#{name}"
|
457
457
|
elsif from == "a#{to}"
|
@@ -467,12 +467,13 @@ module ArJdbc
|
|
467
467
|
# index name can't be the same
|
468
468
|
opts = { name: name.gsub(/(^|_)(#{from})_/, "\\1#{to}_"), internal: true }
|
469
469
|
opts[:unique] = true if index.unique
|
470
|
+
opts[:where] = index.where if index.where
|
470
471
|
add_index(to, columns, opts)
|
471
472
|
end
|
472
473
|
end
|
473
474
|
end
|
474
475
|
|
475
|
-
def copy_table_contents(from, to, columns, rename = {})
|
476
|
+
def copy_table_contents(from, to, columns, rename = {})
|
476
477
|
column_mappings = Hash[columns.map { |name| [name, name] }]
|
477
478
|
rename.each { |a| column_mappings[a.last] = a.first }
|
478
479
|
from_columns = columns(from).collect(&:name)
|
@@ -496,43 +497,51 @@ module ArJdbc
|
|
496
497
|
# Older versions of SQLite return:
|
497
498
|
# column *column_name* is not unique
|
498
499
|
when /column(s)? .* (is|are) not unique/, /UNIQUE constraint failed: .*/
|
499
|
-
|
500
|
+
# DIFFERENCE: FQN
|
501
|
+
::ActiveRecord::RecordNotUnique.new(message)
|
502
|
+
when /.* may not be NULL/, /NOT NULL constraint failed: .*/
|
503
|
+
# DIFFERENCE: FQN
|
504
|
+
::ActiveRecord::NotNullViolation.new(message)
|
505
|
+
when /FOREIGN KEY constraint failed/i
|
506
|
+
# DIFFERENCE: FQN
|
507
|
+
::ActiveRecord::InvalidForeignKey.new(message)
|
500
508
|
else
|
501
509
|
super
|
502
510
|
end
|
503
511
|
end
|
504
512
|
|
505
|
-
private
|
506
513
|
COLLATE_REGEX = /.*\"(\w+)\".*collate\s+\"(\w+)\".*/i.freeze
|
507
514
|
|
508
515
|
def table_structure_with_collation(table_name, basic_structure)
|
509
516
|
collation_hash = {}
|
510
|
-
sql
|
511
|
-
|
512
|
-
|
513
|
-
|
517
|
+
sql = <<-SQL
|
518
|
+
SELECT sql FROM
|
519
|
+
(SELECT * FROM sqlite_master UNION ALL
|
520
|
+
SELECT * FROM sqlite_temp_master)
|
521
|
+
WHERE type = 'table' AND name = #{quote(table_name)}
|
522
|
+
SQL
|
514
523
|
|
515
524
|
# Result will have following sample string
|
516
525
|
# CREATE TABLE "users" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
517
526
|
# "password_digest" varchar COLLATE "NOCASE");
|
518
|
-
result = exec_query(sql,
|
527
|
+
result = exec_query(sql, "SCHEMA").first
|
519
528
|
|
520
529
|
if result
|
521
530
|
# Splitting with left parentheses and picking up last will return all
|
522
531
|
# columns separated with comma(,).
|
523
|
-
columns_string = result["sql"].split(
|
532
|
+
columns_string = result["sql"].split("(").last
|
524
533
|
|
525
|
-
columns_string.split(
|
534
|
+
columns_string.split(",").each do |column_string|
|
526
535
|
# This regex will match the column name and collation type and will save
|
527
536
|
# the value in $1 and $2 respectively.
|
528
|
-
collation_hash[$1] = $2 if
|
537
|
+
collation_hash[$1] = $2 if COLLATE_REGEX =~ column_string
|
529
538
|
end
|
530
539
|
|
531
540
|
basic_structure.map! do |column|
|
532
|
-
column_name = column[
|
541
|
+
column_name = column["name"]
|
533
542
|
|
534
543
|
if collation_hash.has_key? column_name
|
535
|
-
column[
|
544
|
+
column["collation"] = collation_hash[column_name]
|
536
545
|
end
|
537
546
|
|
538
547
|
column
|
@@ -541,6 +550,23 @@ module ArJdbc
|
|
541
550
|
basic_structure.to_hash
|
542
551
|
end
|
543
552
|
end
|
553
|
+
|
554
|
+
def create_table_definition(*args)
|
555
|
+
# DIFFERENCE: FQN
|
556
|
+
::ActiveRecord::ConnectionAdapters::SQLite3::TableDefinition.new(*args)
|
557
|
+
end
|
558
|
+
|
559
|
+
def extract_foreign_key_action(specifier)
|
560
|
+
case specifier
|
561
|
+
when "CASCADE"; :cascade
|
562
|
+
when "SET NULL"; :nullify
|
563
|
+
when "RESTRICT"; :restrict
|
564
|
+
end
|
565
|
+
end
|
566
|
+
|
567
|
+
def configure_connection
|
568
|
+
execute("PRAGMA foreign_keys = ON", "SCHEMA")
|
569
|
+
end
|
544
570
|
end
|
545
571
|
end
|
546
572
|
|
@@ -651,10 +677,14 @@ module ActiveRecord::ConnectionAdapters
|
|
651
677
|
include ArJdbc::Abstract::StatementCache
|
652
678
|
include ArJdbc::Abstract::TransactionSupport
|
653
679
|
|
680
|
+
def supports_transaction_isolation?
|
681
|
+
false
|
682
|
+
end
|
683
|
+
|
654
684
|
def begin_isolated_db_transaction(isolation)
|
655
685
|
raise ActiveRecord::TransactionIsolationError, 'adapter does not support setting transaction isolation'
|
656
686
|
end
|
657
|
-
|
687
|
+
|
658
688
|
# SQLite driver doesn't support all types of insert statements with executeUpdate so
|
659
689
|
# make it act like a regular query and the ids will be returned from #last_inserted_id
|
660
690
|
# example: INSERT INTO "aircraft" DEFAULT VALUES
|
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
ArJdbc::ConnectionMethods.module_eval do
|
3
3
|
def sqlite3_connection(config)
|
4
|
-
config = config.deep_dup
|
5
4
|
config[:adapter_spec] ||= ::ArJdbc::SQLite3
|
6
5
|
config[:adapter_class] = ActiveRecord::ConnectionAdapters::SQLite3Adapter unless config.key?(:adapter_class)
|
7
6
|
|
@@ -23,7 +22,7 @@ ArJdbc::ConnectionMethods.module_eval do
|
|
23
22
|
raise
|
24
23
|
end
|
25
24
|
end
|
26
|
-
|
25
|
+
|
27
26
|
database = config[:database] # NOTE: "jdbc:sqlite::memory:" syntax is supported
|
28
27
|
config[:url] ||= "jdbc:sqlite:#{database == ':memory:' ? '' : database}"
|
29
28
|
config[:connection_alive_sql] ||= 'SELECT 1'
|
data/lib/arjdbc/version.rb
CHANGED
data/rakelib/01-tomcat.rake
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
namespace :'tomcat-jndi' do # contains a FS JNDI impl (for tests)
|
2
2
|
|
3
|
-
TOMCAT_MAVEN_REPO = '
|
3
|
+
TOMCAT_MAVEN_REPO = 'http://repo2.maven.org/maven2/org/apache/tomcat'
|
4
4
|
TOMCAT_VERSION = '7.0.54'
|
5
5
|
|
6
6
|
DOWNLOAD_DIR = File.expand_path('../test/jars', File.dirname(__FILE__))
|
@@ -48,4 +48,4 @@ namespace :'tomcat-jndi' do # contains a FS JNDI impl (for tests)
|
|
48
48
|
rm jar_path if File.exist?(jar_path)
|
49
49
|
end
|
50
50
|
|
51
|
-
end
|
51
|
+
end
|
data/rakelib/02-test.rake
CHANGED
@@ -76,6 +76,8 @@ end
|
|
76
76
|
test_task_for adapter, :desc => "Run tests against #{adapter} (ensure driver is on class-path)"
|
77
77
|
end
|
78
78
|
|
79
|
+
#test_task_for :MSSQL, :name => 'test_sqlserver', :driver => nil, :database_name => 'MS-SQL using SQLJDBC'
|
80
|
+
|
79
81
|
test_task_for :AS400, :desc => "Run tests against AS400 (DB2) (ensure driver is on class-path)",
|
80
82
|
:files => FileList["test/db2*_test.rb"] + FileList["test/db/db2/*_test.rb"]
|
81
83
|
|
data/rakelib/rails.rake
CHANGED
@@ -57,7 +57,7 @@ namespace :rails do
|
|
57
57
|
ruby_opts_string += " -C \"#{ar_path}\""
|
58
58
|
ruby_opts_string += " -rbundler/setup"
|
59
59
|
ruby_opts_string += " -rminitest -rminitest/excludes" unless ENV['NO_EXCLUDES'].eql?('true')
|
60
|
-
file_list = ENV["TEST"] ? FileList[ ENV["TEST"]
|
60
|
+
file_list = ENV["TEST"] ? FileList[ ENV["TEST"] ] : test_files_finder.call
|
61
61
|
file_list_string = file_list.map { |fn| "\"#{fn}\"" }.join(' ')
|
62
62
|
# test_loader_code = "-e \"ARGV.each{|f| require f}\"" # :direct
|
63
63
|
option_list = ( ENV["TESTOPTS"] || ENV["TESTOPT"] || ENV["TEST_OPTS"] || '' )
|