activerecord-jdbc-adapter 5.0.pre1 → 51.0
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 +5 -5
- data/.gitignore +1 -2
- data/.travis.yml +15 -416
- data/Gemfile +35 -37
- data/README.md +23 -118
- data/RUNNING_TESTS.md +31 -26
- data/Rakefile +2 -3
- data/activerecord-jdbc-adapter.gemspec +1 -2
- data/lib/arjdbc/abstract/connection_management.rb +21 -0
- data/lib/arjdbc/abstract/core.rb +62 -0
- data/lib/arjdbc/abstract/database_statements.rb +46 -0
- data/lib/arjdbc/abstract/statement_cache.rb +58 -0
- data/lib/arjdbc/abstract/transaction_support.rb +86 -0
- data/lib/arjdbc/derby/adapter.rb +6 -1
- data/lib/arjdbc/discover.rb +0 -7
- data/lib/arjdbc/firebird/adapter.rb +2 -2
- data/lib/arjdbc/jdbc/adapter.rb +10 -252
- data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
- data/lib/arjdbc/jdbc/connection.rb +6 -0
- data/lib/arjdbc/jdbc.rb +2 -2
- data/lib/arjdbc/mysql/adapter.rb +87 -944
- data/lib/arjdbc/mysql/connection_methods.rb +4 -2
- data/lib/arjdbc/postgresql/adapter.rb +288 -1023
- data/lib/arjdbc/postgresql/base/array_decoder.rb +26 -0
- data/lib/arjdbc/postgresql/base/array_encoder.rb +25 -0
- data/lib/arjdbc/postgresql/base/pgconn.rb +8 -5
- data/lib/arjdbc/postgresql/column.rb +10 -599
- data/lib/arjdbc/postgresql/connection_methods.rb +9 -0
- data/lib/arjdbc/postgresql/name.rb +24 -0
- data/lib/arjdbc/postgresql/oid_types.rb +25 -110
- data/lib/arjdbc/sqlite3/adapter.rb +171 -170
- data/lib/arjdbc/tasks/database_tasks.rb +1 -3
- data/lib/arjdbc/tasks/db2_database_tasks.rb +2 -2
- data/lib/arjdbc/version.rb +1 -1
- data/pom.xml +3 -3
- data/rakelib/02-test.rake +0 -12
- data/rakelib/compile.rake +1 -1
- data/rakelib/db.rake +7 -5
- data/rakelib/rails.rake +63 -64
- data/src/java/arjdbc/firebird/FirebirdRubyJdbcConnection.java +1 -17
- data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +518 -1260
- data/src/java/arjdbc/mysql/MySQLModule.java +3 -3
- data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +53 -134
- data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +214 -240
- data/src/java/arjdbc/sqlite3/SQLite3Module.java +0 -20
- data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +85 -10
- metadata +20 -34
- data/Appraisals +0 -41
- data/lib/active_record/connection_adapters/oracle_adapter.rb +0 -1
- data/lib/arjdbc/common_jdbc_methods.rb +0 -89
- data/lib/arjdbc/mysql/bulk_change_table.rb +0 -150
- data/lib/arjdbc/mysql/column.rb +0 -162
- data/lib/arjdbc/mysql/explain_support.rb +0 -82
- data/lib/arjdbc/mysql/schema_creation.rb +0 -58
- data/lib/arjdbc/oracle/adapter.rb +0 -952
- data/lib/arjdbc/oracle/column.rb +0 -126
- data/lib/arjdbc/oracle/connection_methods.rb +0 -21
- data/lib/arjdbc/oracle.rb +0 -4
- data/lib/arjdbc/postgresql/_bc_time_cast_patch.rb +0 -21
- data/lib/arjdbc/postgresql/base/oid.rb +0 -412
- data/lib/arjdbc/postgresql/base/schema_definitions.rb +0 -131
- data/lib/arjdbc/postgresql/explain_support.rb +0 -53
- data/lib/arjdbc/postgresql/oid/bytea.rb +0 -2
- data/lib/arjdbc/postgresql/schema_creation.rb +0 -60
- data/lib/arjdbc/tasks/oracle/enhanced_structure_dump.rb +0 -297
- data/lib/arjdbc/tasks/oracle_database_tasks.rb +0 -65
- data/src/java/arjdbc/oracle/OracleModule.java +0 -75
- data/src/java/arjdbc/oracle/OracleRubyJdbcConnection.java +0 -465
@@ -1,16 +1,25 @@
|
|
1
1
|
ArJdbc.load_java_part :SQLite3
|
2
2
|
|
3
|
-
require "arjdbc/
|
3
|
+
require "arjdbc/abstract/core"
|
4
|
+
require "arjdbc/abstract/database_statements"
|
5
|
+
require 'arjdbc/abstract/statement_cache'
|
6
|
+
require "arjdbc/abstract/transaction_support"
|
7
|
+
require "active_record/connection_adapters/abstract_adapter"
|
4
8
|
require "active_record/connection_adapters/statement_pool"
|
5
|
-
require "active_record/connection_adapters/abstract/database_statements"
|
6
9
|
require "active_record/connection_adapters/sqlite3/explain_pretty_printer"
|
7
10
|
require "active_record/connection_adapters/sqlite3/quoting"
|
8
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"
|
9
15
|
|
10
16
|
module ArJdbc
|
11
17
|
# All the code in this module is a copy of ConnectionAdapters::SQLite3Adapter from active_record 5.
|
12
18
|
# The constants at the front of this file are to allow the rest of the file to remain with no modifications
|
13
|
-
# from its original source.
|
19
|
+
# from its original source. If you hack on this file try not to modify this module and instead try and
|
20
|
+
# put those overrides in SQL3Adapter below. We try and keep a copy of the Rails this adapter supports
|
21
|
+
# with the current goal of being able to diff changes easily over time and to also eventually remove
|
22
|
+
# this module from ARJDBC altogether.
|
14
23
|
module SQLite3
|
15
24
|
# DIFFERENCE: Some common constant names to reduce differences in rest of this module from AR5 version
|
16
25
|
ConnectionAdapters = ::ActiveRecord::ConnectionAdapters
|
@@ -22,7 +31,10 @@ module ArJdbc
|
|
22
31
|
|
23
32
|
ADAPTER_NAME = 'SQLite'.freeze
|
24
33
|
|
25
|
-
|
34
|
+
# DIFFERENCE: FQN
|
35
|
+
include ::ActiveRecord::ConnectionAdapters::SQLite3::Quoting
|
36
|
+
include ::ActiveRecord::ConnectionAdapters::SQLite3::ColumnDumper
|
37
|
+
include ::ActiveRecord::ConnectionAdapters::SQLite3::SchemaStatements
|
26
38
|
|
27
39
|
NATIVE_DATABASE_TYPES = {
|
28
40
|
primary_key: "INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL",
|
@@ -46,15 +58,22 @@ module ArJdbc
|
|
46
58
|
end
|
47
59
|
end
|
48
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
|
+
|
49
66
|
def schema_creation # :nodoc:
|
50
|
-
|
67
|
+
# DIFFERENCE: FQN
|
68
|
+
::ActiveRecord::ConnectionAdapters::SQLite3::SchemaCreation.new self
|
51
69
|
end
|
52
70
|
|
53
71
|
def arel_visitor # :nodoc:
|
54
72
|
Arel::Visitors::SQLite.new(self)
|
55
73
|
end
|
56
74
|
|
57
|
-
|
75
|
+
# Difference we remove connection_options because we are not using it.
|
76
|
+
def initialize(connection, logger, config)
|
58
77
|
super(connection, logger, config)
|
59
78
|
|
60
79
|
@active = nil
|
@@ -79,17 +98,12 @@ module ArJdbc
|
|
79
98
|
true
|
80
99
|
end
|
81
100
|
|
82
|
-
|
83
|
-
def supports_migrations? #:nodoc:
|
84
|
-
true
|
85
|
-
end
|
86
|
-
|
87
|
-
def supports_primary_key? #:nodoc:
|
101
|
+
def requires_reloading?
|
88
102
|
true
|
89
103
|
end
|
90
104
|
|
91
|
-
def
|
92
|
-
|
105
|
+
def supports_foreign_keys_in_create?
|
106
|
+
sqlite_version >= "3.6.19"
|
93
107
|
end
|
94
108
|
|
95
109
|
def supports_views?
|
@@ -125,10 +139,6 @@ module ArJdbc
|
|
125
139
|
true
|
126
140
|
end
|
127
141
|
|
128
|
-
def valid_type?(type)
|
129
|
-
true
|
130
|
-
end
|
131
|
-
|
132
142
|
# Returns 62. SQLite supports index names up to 64
|
133
143
|
# characters. The rest is used by Rails internally to perform
|
134
144
|
# temporary rename operations
|
@@ -149,45 +159,61 @@ module ArJdbc
|
|
149
159
|
true
|
150
160
|
end
|
151
161
|
|
162
|
+
# REFERENTIAL INTEGRITY ====================================
|
163
|
+
|
164
|
+
def disable_referential_integrity # :nodoc:
|
165
|
+
old = query_value("PRAGMA foreign_keys")
|
166
|
+
|
167
|
+
begin
|
168
|
+
execute("PRAGMA foreign_keys = OFF")
|
169
|
+
yield
|
170
|
+
ensure
|
171
|
+
execute("PRAGMA foreign_keys = #{old}")
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
152
175
|
#--
|
153
176
|
# DATABASE STATEMENTS ======================================
|
154
177
|
#++
|
155
178
|
|
156
179
|
def explain(arel, binds = [])
|
157
180
|
sql = "EXPLAIN QUERY PLAN #{to_sql(arel, binds)}"
|
181
|
+
# DIFFERENCE: FQN
|
158
182
|
::ActiveRecord::ConnectionAdapters::SQLite3::ExplainPrettyPrinter.new.pp(exec_query(sql, "EXPLAIN", []))
|
159
183
|
end
|
160
184
|
|
161
185
|
def exec_query(sql, name = nil, binds = [], prepare: false)
|
162
|
-
type_casted_binds = binds
|
163
|
-
|
164
|
-
log(sql, name, binds) do
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
186
|
+
type_casted_binds = type_casted_binds(binds)
|
187
|
+
|
188
|
+
log(sql, name, binds, type_casted_binds) do
|
189
|
+
ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
|
190
|
+
# Don't cache statements if they are not prepared
|
191
|
+
unless prepare
|
192
|
+
stmt = @connection.prepare(sql)
|
193
|
+
begin
|
194
|
+
cols = stmt.columns
|
195
|
+
unless without_prepared_statement?(binds)
|
196
|
+
stmt.bind_params(type_casted_binds)
|
197
|
+
end
|
198
|
+
records = stmt.to_a
|
199
|
+
ensure
|
200
|
+
stmt.close
|
172
201
|
end
|
202
|
+
else
|
203
|
+
cache = @statements[sql] ||= {
|
204
|
+
stmt: @connection.prepare(sql)
|
205
|
+
}
|
206
|
+
stmt = cache[:stmt]
|
207
|
+
cols = cache[:cols] ||= stmt.columns
|
208
|
+
stmt.reset!
|
209
|
+
stmt.bind_params(type_casted_binds)
|
173
210
|
records = stmt.to_a
|
174
|
-
ensure
|
175
|
-
stmt.close
|
176
211
|
end
|
177
|
-
stmt = records
|
178
|
-
else
|
179
|
-
cache = @statements[sql] ||= {
|
180
|
-
:stmt => @connection.prepare(sql)
|
181
|
-
}
|
182
|
-
stmt = cache[:stmt]
|
183
|
-
cols = cache[:cols] ||= stmt.columns
|
184
|
-
stmt.reset!
|
185
|
-
stmt.bind_params(type_casted_binds)
|
186
|
-
end
|
187
212
|
|
188
|
-
|
213
|
+
ActiveRecord::Result.new(cols, records)
|
214
|
+
end
|
189
215
|
end
|
190
|
-
end
|
216
|
+
end
|
191
217
|
|
192
218
|
def exec_delete(sql, name = 'SQL', binds = [])
|
193
219
|
exec_query(sql, name, binds)
|
@@ -200,7 +226,11 @@ module ArJdbc
|
|
200
226
|
end
|
201
227
|
|
202
228
|
def execute(sql, name = nil) #:nodoc:
|
203
|
-
log(sql, name)
|
229
|
+
log(sql, name) do
|
230
|
+
ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
|
231
|
+
@connection.execute(sql)
|
232
|
+
end
|
233
|
+
end
|
204
234
|
end
|
205
235
|
|
206
236
|
def begin_db_transaction #:nodoc:
|
@@ -217,80 +247,30 @@ module ArJdbc
|
|
217
247
|
|
218
248
|
# SCHEMA STATEMENTS ========================================
|
219
249
|
|
220
|
-
def
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
229
|
-
Passing arguments to #tables is deprecated without replacement.
|
230
|
-
MSG
|
250
|
+
def new_column_from_field(table_name, field) # :nondoc:
|
251
|
+
case field["dflt_value"]
|
252
|
+
when /^null$/i
|
253
|
+
field["dflt_value"] = nil
|
254
|
+
when /^'(.*)'$/m
|
255
|
+
field["dflt_value"] = $1.gsub("''", "'")
|
256
|
+
when /^"(.*)"$/m
|
257
|
+
field["dflt_value"] = $1.gsub('""', '"')
|
231
258
|
end
|
232
259
|
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
select_values("SELECT name FROM sqlite_master WHERE type IN ('table','view') AND name <> 'sqlite_sequence'", "SCHEMA")
|
238
|
-
end
|
239
|
-
|
240
|
-
def table_exists?(table_name)
|
241
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
242
|
-
#table_exists? currently checks both tables and views.
|
243
|
-
This behavior is deprecated and will be changed with Rails 5.1 to only check tables.
|
244
|
-
Use #data_source_exists? instead.
|
245
|
-
MSG
|
246
|
-
|
247
|
-
data_source_exists?(table_name)
|
248
|
-
end
|
249
|
-
|
250
|
-
def data_source_exists?(table_name)
|
251
|
-
return false unless table_name.present?
|
252
|
-
|
253
|
-
sql = "SELECT name FROM sqlite_master WHERE type IN ('table','view') AND name <> 'sqlite_sequence'"
|
254
|
-
sql << " AND name = #{quote(table_name)}"
|
255
|
-
|
256
|
-
select_values(sql, "SCHEMA").any?
|
257
|
-
end
|
258
|
-
|
259
|
-
def views # :nodoc:
|
260
|
-
select_values("SELECT name FROM sqlite_master WHERE type = 'view' AND name <> 'sqlite_sequence'", "SCHEMA")
|
261
|
-
end
|
262
|
-
|
263
|
-
def view_exists?(view_name) # :nodoc:
|
264
|
-
return false unless view_name.present?
|
265
|
-
|
266
|
-
sql = "SELECT name FROM sqlite_master WHERE type = 'view' AND name <> 'sqlite_sequence'"
|
267
|
-
sql << " AND name = #{quote(view_name)}"
|
268
|
-
|
269
|
-
select_values(sql, "SCHEMA").any?
|
270
|
-
end
|
271
|
-
|
272
|
-
# Returns an array of +Column+ objects for the table specified by +table_name+.
|
273
|
-
def columns(table_name) # :nodoc:
|
274
|
-
table_name = table_name.to_s
|
275
|
-
table_structure(table_name).map do |field|
|
276
|
-
case field["dflt_value"]
|
277
|
-
when /^null$/i
|
278
|
-
field["dflt_value"] = nil
|
279
|
-
when /^'(.*)'$/m
|
280
|
-
field["dflt_value"] = $1.gsub("''", "'")
|
281
|
-
when /^"(.*)"$/m
|
282
|
-
field["dflt_value"] = $1.gsub('""', '"')
|
283
|
-
end
|
284
|
-
|
285
|
-
collation = field["collation"]
|
286
|
-
sql_type = field["type"]
|
287
|
-
type_metadata = fetch_type_metadata(sql_type)
|
288
|
-
new_column(field["name"], field["dflt_value"], type_metadata, field["notnull"].to_i == 0, table_name, nil, collation)
|
289
|
-
end
|
260
|
+
collation = field["collation"]
|
261
|
+
sql_type = field["type"]
|
262
|
+
type_metadata = fetch_type_metadata(sql_type)
|
263
|
+
new_column(field["name"], field["dflt_value"], type_metadata, field["notnull"].to_i == 0, table_name, nil, collation)
|
290
264
|
end
|
291
265
|
|
292
266
|
# Returns an array of indexes for the given table.
|
293
267
|
def indexes(table_name, name = nil) #:nodoc:
|
268
|
+
if name
|
269
|
+
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
270
|
+
Passing name to #indexes is deprecated without replacement.
|
271
|
+
MSG
|
272
|
+
end
|
273
|
+
|
294
274
|
exec_query("PRAGMA index_list(#{quote_table_name(table_name)})", "SCHEMA").map do |row|
|
295
275
|
sql = <<-SQL
|
296
276
|
SELECT sql
|
@@ -300,17 +280,17 @@ module ArJdbc
|
|
300
280
|
SELECT sql
|
301
281
|
FROM sqlite_temp_master
|
302
282
|
WHERE name=#{quote(row['name'])} AND type='index'
|
303
|
-
|
283
|
+
SQL
|
304
284
|
index_sql = exec_query(sql).first["sql"]
|
305
285
|
match = /\sWHERE\s+(.+)$/i.match(index_sql)
|
306
286
|
where = match[1] if match
|
307
287
|
IndexDefinition.new(
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
288
|
+
table_name,
|
289
|
+
row["name"],
|
290
|
+
row["unique"] != 0,
|
291
|
+
exec_query("PRAGMA index_info('#{row['name']}')", "SCHEMA").map { |col|
|
292
|
+
col["name"]
|
293
|
+
}, nil, nil, where)
|
314
294
|
end
|
315
295
|
end
|
316
296
|
|
@@ -393,14 +373,34 @@ module ArJdbc
|
|
393
373
|
rename_column_indexes(table_name, column.name, new_column_name)
|
394
374
|
end
|
395
375
|
|
396
|
-
|
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
|
397
396
|
|
398
397
|
def table_structure(table_name)
|
399
398
|
structure = exec_query("PRAGMA table_info(#{quote_table_name(table_name)})", "SCHEMA")
|
400
399
|
raise(ActiveRecord::StatementInvalid, "Could not find table '#{table_name}'") if structure.empty?
|
401
400
|
table_structure_with_collation(table_name, structure)
|
402
401
|
end
|
403
|
-
|
402
|
+
alias column_definitions table_structure
|
403
|
+
|
404
404
|
def alter_table(table_name, options = {}) #:nodoc:
|
405
405
|
altered_table_name = "a#{table_name}"
|
406
406
|
caller = lambda { |definition| yield definition if block_given? }
|
@@ -490,43 +490,51 @@ module ArJdbc
|
|
490
490
|
# Older versions of SQLite return:
|
491
491
|
# column *column_name* is not unique
|
492
492
|
when /column(s)? .* (is|are) not unique/, /UNIQUE constraint failed: .*/
|
493
|
-
|
493
|
+
# DIFFERENCE: FQN
|
494
|
+
::ActiveRecord::RecordNotUnique.new(message)
|
495
|
+
when /.* may not be NULL/, /NOT NULL constraint failed: .*/
|
496
|
+
# DIFFERENCE: FQN
|
497
|
+
::ActiveRecord::NotNullViolation.new(message)
|
498
|
+
when /FOREIGN KEY constraint failed/i
|
499
|
+
# DIFFERENCE: FQN
|
500
|
+
::ActiveRecord::InvalidForeignKey.new(message)
|
494
501
|
else
|
495
502
|
super
|
496
503
|
end
|
497
504
|
end
|
498
505
|
|
499
|
-
private
|
500
506
|
COLLATE_REGEX = /.*\"(\w+)\".*collate\s+\"(\w+)\".*/i.freeze
|
501
507
|
|
502
508
|
def table_structure_with_collation(table_name, basic_structure)
|
503
509
|
collation_hash = {}
|
504
|
-
sql
|
505
|
-
|
506
|
-
|
507
|
-
|
510
|
+
sql = <<-SQL
|
511
|
+
SELECT sql FROM
|
512
|
+
(SELECT * FROM sqlite_master UNION ALL
|
513
|
+
SELECT * FROM sqlite_temp_master)
|
514
|
+
WHERE type = 'table' AND name = #{quote(table_name)}
|
515
|
+
SQL
|
508
516
|
|
509
517
|
# Result will have following sample string
|
510
518
|
# CREATE TABLE "users" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
511
519
|
# "password_digest" varchar COLLATE "NOCASE");
|
512
|
-
result = exec_query(sql,
|
520
|
+
result = exec_query(sql, "SCHEMA").first
|
513
521
|
|
514
522
|
if result
|
515
523
|
# Splitting with left parentheses and picking up last will return all
|
516
524
|
# columns separated with comma(,).
|
517
|
-
columns_string = result["sql"].split(
|
525
|
+
columns_string = result["sql"].split("(").last
|
518
526
|
|
519
|
-
columns_string.split(
|
527
|
+
columns_string.split(",").each do |column_string|
|
520
528
|
# This regex will match the column name and collation type and will save
|
521
529
|
# the value in $1 and $2 respectively.
|
522
|
-
collation_hash[$1] = $2 if
|
530
|
+
collation_hash[$1] = $2 if COLLATE_REGEX =~ column_string
|
523
531
|
end
|
524
532
|
|
525
533
|
basic_structure.map! do |column|
|
526
|
-
column_name = column[
|
534
|
+
column_name = column["name"]
|
527
535
|
|
528
536
|
if collation_hash.has_key? column_name
|
529
|
-
column[
|
537
|
+
column["collation"] = collation_hash[column_name]
|
530
538
|
end
|
531
539
|
|
532
540
|
column
|
@@ -535,6 +543,23 @@ module ArJdbc
|
|
535
543
|
basic_structure.to_hash
|
536
544
|
end
|
537
545
|
end
|
546
|
+
|
547
|
+
def create_table_definition(*args)
|
548
|
+
# DIFFERENCE: FQN
|
549
|
+
::ActiveRecord::ConnectionAdapters::SQLite3::TableDefinition.new(*args)
|
550
|
+
end
|
551
|
+
|
552
|
+
def extract_foreign_key_action(specifier)
|
553
|
+
case specifier
|
554
|
+
when "CASCADE"; :cascade
|
555
|
+
when "SET NULL"; :nullify
|
556
|
+
when "RESTRICT"; :restrict
|
557
|
+
end
|
558
|
+
end
|
559
|
+
|
560
|
+
def configure_connection
|
561
|
+
execute("PRAGMA foreign_keys = ON", "SCHEMA")
|
562
|
+
end
|
538
563
|
end
|
539
564
|
end
|
540
565
|
|
@@ -639,50 +664,26 @@ module ActiveRecord::ConnectionAdapters
|
|
639
664
|
# ActiveRecord::ConnectionAdapters::SQLite3Adapter. Once we can do that we can remove the
|
640
665
|
# module SQLite3 above and remove a majority of this file.
|
641
666
|
class SQLite3Adapter < AbstractAdapter
|
642
|
-
include ArJdbc::
|
667
|
+
include ArJdbc::Abstract::Core
|
643
668
|
include ArJdbc::SQLite3
|
669
|
+
include ArJdbc::Abstract::DatabaseStatements
|
670
|
+
include ArJdbc::Abstract::StatementCache
|
671
|
+
include ArJdbc::Abstract::TransactionSupport
|
644
672
|
|
645
|
-
|
646
|
-
|
647
|
-
select_value 'PRAGMA encoding'
|
648
|
-
end
|
649
|
-
|
650
|
-
def exec_query(sql, name = nil, binds = [], prepare: false)
|
651
|
-
use_prepared = prepare || !without_prepared_statement?(binds)
|
652
|
-
|
653
|
-
if use_prepared
|
654
|
-
type_casted_binds = prepare_binds_for_jdbc(binds)
|
655
|
-
log(sql, name, binds) { @connection.execute_prepared(sql, type_casted_binds) }
|
656
|
-
else
|
657
|
-
log(sql, name) { @connection.execute(sql) }
|
658
|
-
end
|
659
|
-
end
|
660
|
-
|
661
|
-
def exec_update(sql, name = nil, binds = [])
|
662
|
-
use_prepared = !without_prepared_statement?(binds)
|
663
|
-
|
664
|
-
if use_prepared
|
665
|
-
type_casted_binds = prepare_binds_for_jdbc(binds)
|
666
|
-
log(sql, name, binds) { @connection.execute_prepared_update(sql, type_casted_binds) }
|
667
|
-
else
|
668
|
-
log(sql, name) { @connection.execute_update(sql, nil) }
|
669
|
-
end
|
673
|
+
def begin_isolated_db_transaction(isolation)
|
674
|
+
raise ActiveRecord::TransactionIsolationError, 'adapter does not support setting transaction isolation'
|
670
675
|
end
|
671
|
-
alias :exec_delete :exec_update
|
672
676
|
|
673
|
-
#
|
674
|
-
# So
|
675
|
-
#
|
676
|
-
|
677
|
-
|
678
|
-
binds.map do |attribute|
|
679
|
-
[attribute.type.type, type_cast(attribute.value_for_database)]
|
680
|
-
end
|
677
|
+
# FIXME: 5.1 crashes without this. I think this is Arel hitting a fallback path in to_sql.rb.
|
678
|
+
# So maybe an untested code path in their source. Still means we are doing something wrong to
|
679
|
+
# even hit it.
|
680
|
+
def quote(value, comment=nil)
|
681
|
+
super(value)
|
681
682
|
end
|
682
683
|
|
683
|
-
#
|
684
|
-
def
|
685
|
-
|
684
|
+
# FIXME: Add @connection.encoding then remove this method
|
685
|
+
def encoding
|
686
|
+
select_value 'PRAGMA encoding'
|
686
687
|
end
|
687
688
|
|
688
689
|
def indexes(table_name, name = nil) #:nodoc:
|
@@ -32,11 +32,9 @@ module ArJdbc
|
|
32
32
|
require 'arjdbc/tasks/h2_database_tasks'
|
33
33
|
require 'arjdbc/tasks/hsqldb_database_tasks'
|
34
34
|
require 'arjdbc/tasks/mssql_database_tasks'
|
35
|
-
require 'arjdbc/tasks/oracle_database_tasks'
|
36
35
|
|
37
36
|
# re-invent built-in (but deprecated on 4.0) tasks :
|
38
37
|
register_tasks(/sqlserver/, MSSQLDatabaseTasks)
|
39
|
-
register_tasks(/(oci|oracle)/, OracleDatabaseTasks)
|
40
38
|
register_tasks(/mssql/, MSSQLDatabaseTasks) # (built-in) alias
|
41
39
|
# tasks for custom (JDBC) adapters :
|
42
40
|
register_tasks(/db2/, DB2DatabaseTasks)
|
@@ -51,4 +49,4 @@ module ArJdbc
|
|
51
49
|
# - while on 2.3/3.x we keep the AR built-in task behavior
|
52
50
|
|
53
51
|
end
|
54
|
-
end
|
52
|
+
end
|
@@ -82,9 +82,9 @@ module ArJdbc
|
|
82
82
|
ensure
|
83
83
|
pk_rs.close
|
84
84
|
end
|
85
|
-
primary_keys.each do |
|
85
|
+
primary_keys.each do |constraint_name, cols|
|
86
86
|
dump << "ALTER TABLE #{connection.quote_table_name(table_name)}\n"
|
87
|
-
dump << " ADD CONSTRAINT #{
|
87
|
+
dump << " ADD CONSTRAINT #{constraint_name}\n"
|
88
88
|
dump << " PRIMARY KEY (#{cols.join(', ')});\n\n"
|
89
89
|
end
|
90
90
|
end
|
data/lib/arjdbc/version.rb
CHANGED
data/pom.xml
CHANGED
@@ -12,7 +12,7 @@
|
|
12
12
|
<url>http://github.com/jruby/activerecord-jdbc-adapter/wiki</url>
|
13
13
|
|
14
14
|
<properties>
|
15
|
-
<jruby.version>1.6.
|
15
|
+
<jruby.version>9.1.6.0</jruby.version>
|
16
16
|
</properties>
|
17
17
|
|
18
18
|
<issueManagement>
|
@@ -103,8 +103,8 @@
|
|
103
103
|
<artifactId>maven-compiler-plugin</artifactId>
|
104
104
|
<version>2.5.1</version>
|
105
105
|
<configuration>
|
106
|
-
<source>1.
|
107
|
-
<target>1.
|
106
|
+
<source>1.7</source>
|
107
|
+
<target>1.7</target>
|
108
108
|
</configuration>
|
109
109
|
</plugin>
|
110
110
|
</plugins>
|
data/rakelib/02-test.rake
CHANGED
@@ -17,15 +17,6 @@ task 'test_postgresql_with_hint' do
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
task 'test_appraisal_hint' do
|
21
|
-
next if File.exists?('.disable-appraisal-hint')
|
22
|
-
unless (ENV['BUNDLE_GEMFILE'] || '') =~ /gemfiles\/.*?\.gemfile/
|
23
|
-
appraisals = []; Appraisal::File.each { |file| appraisals << file.name }
|
24
|
-
puts "HINT: specify AR version with `rake appraisal:{version} test_{adapter}'" +
|
25
|
-
" where version=(#{appraisals.join('|')}) (`touch .disable-appraisal-hint' to disable)"
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
20
|
Rake::TestTask.class_eval { attr_reader :test_files }
|
30
21
|
|
31
22
|
def test_task_for(adapter, options = {})
|
@@ -34,9 +25,6 @@ def test_task_for(adapter, options = {})
|
|
34
25
|
adapter = adapter.to_s.downcase
|
35
26
|
driver = adapter if ( driver = options[:driver] ).nil?
|
36
27
|
prereqs = options[:prereqs] || []
|
37
|
-
unless prereqs.frozen?
|
38
|
-
prereqs = [ prereqs ].flatten; prereqs << 'test_appraisal_hint'
|
39
|
-
end
|
40
28
|
name = options[:name] || "test_#{adapter}"
|
41
29
|
test_task = Rake::TestTask.new(name => prereqs) do |test_task|
|
42
30
|
files = options[:files] || begin
|
data/rakelib/compile.rake
CHANGED
@@ -11,7 +11,7 @@ begin
|
|
11
11
|
file jar_file => FileList['src/java/**/*.java', 'pkg/classes'] do
|
12
12
|
rm_rf FileList["#{classes}/**/*"]
|
13
13
|
ant.javac :srcdir => "src/java", :destdir => "pkg/classes",
|
14
|
-
:source => "
|
14
|
+
:source => "7", :target => "7", :debug => true, :deprecation => true,
|
15
15
|
:classpath => "${java.class.path}:${sun.boot.class.path}:#{driver_jars.join(':')}",
|
16
16
|
:includeantRuntime => false
|
17
17
|
|
data/rakelib/db.rake
CHANGED
@@ -6,6 +6,7 @@ namespace :db do
|
|
6
6
|
task :mysql do
|
7
7
|
fail "could not create test database: mysql executable not found" unless mysql = which('mysql')
|
8
8
|
load 'test/db/mysql_config.rb' # rescue nil
|
9
|
+
puts MYSQL_CONFIG.inspect if $VERBOSE
|
9
10
|
script = sql_script <<-SQL, 'mysql'
|
10
11
|
DROP DATABASE IF EXISTS `#{MYSQL_CONFIG[:database]}`;
|
11
12
|
CREATE USER #{MYSQL_CONFIG[:username]}@localhost;
|
@@ -15,13 +16,13 @@ GRANT ALL PRIVILEGES ON `test\_%`.* TO #{MYSQL_CONFIG[:username]}@localhost;
|
|
15
16
|
SET PASSWORD FOR #{MYSQL_CONFIG[:username]}@localhost = PASSWORD('#{MYSQL_CONFIG[:password]}');
|
16
17
|
SQL
|
17
18
|
params = { '-u' => 'root' }
|
18
|
-
if ENV['DATABASE_YML']
|
19
|
-
|
20
|
-
password = YAML.load(File.new(ENV['DATABASE_YML']))["production"]["password"]
|
21
|
-
params['--password'] = password
|
19
|
+
if ENV['DATABASE_YML']; require 'yaml'
|
20
|
+
params['-p'] = YAML.load(File.new(ENV['DATABASE_YML']))["production"]["password"]
|
22
21
|
end
|
22
|
+
params['-u'] = ENV['MY_USER'] if ENV['MY_USER']
|
23
|
+
params['-p'] = ENV['MY_PASSWORD'] if ENV['MY_PASSWORD']
|
23
24
|
puts "Creating MySQL (test) database: #{MYSQL_CONFIG[:database]}"
|
24
|
-
sh "cat #{script.path} | #{mysql} -f #{params.
|
25
|
+
sh "cat #{script.path} | #{mysql} -f #{params.map {|k, v| "#{k}#{v}"}.join(' ')}", :verbose => $VERBOSE # so password is not echoed
|
25
26
|
end
|
26
27
|
|
27
28
|
desc "Creates the test database for PostgreSQL"
|
@@ -29,6 +30,7 @@ SQL
|
|
29
30
|
fail 'could not create test database: psql executable not found' unless psql = which('psql')
|
30
31
|
fail 'could not create test database: missing "postgres" role' unless PostgresHelper.postgres_role?
|
31
32
|
load 'test/db/postgres_config.rb' # rescue nil
|
33
|
+
puts POSTGRES_CONFIG.inspect if $VERBOSE
|
32
34
|
script = sql_script <<-SQL, 'psql'
|
33
35
|
DROP DATABASE IF EXISTS #{POSTGRES_CONFIG[:database]};
|
34
36
|
DROP USER IF EXISTS #{POSTGRES_CONFIG[:username]};
|