activerecord-oracle_enhanced-adapter 5.2.8 → 6.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/History.md +79 -13
- data/README.md +1 -7
- data/VERSION +1 -1
- data/lib/active_record/connection_adapters/oracle_enhanced/connection.rb +10 -13
- data/lib/active_record/connection_adapters/oracle_enhanced/context_index.rb +7 -7
- data/lib/active_record/connection_adapters/oracle_enhanced/database_limits.rb +4 -0
- data/lib/active_record/connection_adapters/oracle_enhanced/database_statements.rb +7 -18
- data/lib/active_record/connection_adapters/oracle_enhanced/database_tasks.rb +1 -1
- data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_connection.rb +17 -4
- data/lib/active_record/connection_adapters/oracle_enhanced/oci_connection.rb +32 -32
- data/lib/active_record/connection_adapters/oracle_enhanced/quoting.rb +17 -27
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_creation.rb +4 -4
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_definitions.rb +13 -3
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_dumper.rb +1 -13
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb +55 -71
- data/lib/active_record/connection_adapters/oracle_enhanced/structure_dump.rb +27 -17
- data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +87 -61
- data/lib/active_record/type/oracle_enhanced/character_string.rb +36 -0
- data/spec/active_record/connection_adapters/emulation/oracle_adapter_spec.rb +0 -2
- data/spec/active_record/connection_adapters/oracle_enhanced/connection_spec.rb +25 -50
- data/spec/active_record/connection_adapters/oracle_enhanced/context_index_spec.rb +5 -13
- data/spec/active_record/connection_adapters/oracle_enhanced/procedures_spec.rb +0 -2
- data/spec/active_record/connection_adapters/oracle_enhanced/quoting_spec.rb +0 -15
- data/spec/active_record/connection_adapters/oracle_enhanced/schema_dumper_spec.rb +1 -31
- data/spec/active_record/connection_adapters/oracle_enhanced/schema_statements_spec.rb +71 -253
- data/spec/active_record/connection_adapters/oracle_enhanced/structure_dump_spec.rb +2 -3
- data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +81 -81
- data/spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb +0 -1
- data/spec/active_record/oracle_enhanced/type/boolean_spec.rb +0 -2
- data/spec/active_record/oracle_enhanced/type/character_string_spec.rb +43 -0
- data/spec/active_record/oracle_enhanced/type/decimal_spec.rb +56 -0
- data/spec/active_record/oracle_enhanced/type/dirty_spec.rb +1 -1
- data/spec/active_record/oracle_enhanced/type/json_spec.rb +0 -1
- data/spec/active_record/oracle_enhanced/type/national_character_string_spec.rb +1 -2
- data/spec/active_record/oracle_enhanced/type/timestamp_spec.rb +0 -2
- data/spec/spec_helper.rb +2 -0
- metadata +27 -23
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements_ext.rb +0 -28
@@ -11,7 +11,7 @@ module ActiveRecord #:nodoc:
|
|
11
11
|
sequences = select(<<-SQL.strip.gsub(/\s+/, " "), "sequences to dump at structure dump")
|
12
12
|
SELECT sequence_name, min_value, max_value, increment_by, order_flag, cycle_flag
|
13
13
|
FROM all_sequences
|
14
|
-
where sequence_owner = SYS_CONTEXT('userenv', '
|
14
|
+
where sequence_owner = SYS_CONTEXT('userenv', 'current_schema') ORDER BY 1
|
15
15
|
SQL
|
16
16
|
|
17
17
|
structure = sequences.map do |result|
|
@@ -28,13 +28,13 @@ module ActiveRecord #:nodoc:
|
|
28
28
|
SQL
|
29
29
|
tables.each do |table_name|
|
30
30
|
virtual_columns = virtual_columns_for(table_name) if supports_virtual_columns?
|
31
|
-
ddl = "CREATE#{ ' GLOBAL TEMPORARY' if temporary_table?(table_name)} TABLE \"#{table_name}\" (\n"
|
31
|
+
ddl = +"CREATE#{ ' GLOBAL TEMPORARY' if temporary_table?(table_name)} TABLE \"#{table_name}\" (\n"
|
32
32
|
columns = select_all(<<-SQL.strip.gsub(/\s+/, " "), "columns at structure dump")
|
33
33
|
SELECT column_name, data_type, data_length, char_used, char_length,
|
34
34
|
data_precision, data_scale, data_default, nullable
|
35
35
|
FROM all_tab_columns
|
36
36
|
WHERE table_name = '#{table_name}'
|
37
|
-
AND owner = SYS_CONTEXT('userenv', '
|
37
|
+
AND owner = SYS_CONTEXT('userenv', 'current_schema')
|
38
38
|
ORDER BY column_id
|
39
39
|
SQL
|
40
40
|
cols = columns.map do |row|
|
@@ -55,10 +55,11 @@ module ActiveRecord #:nodoc:
|
|
55
55
|
end
|
56
56
|
|
57
57
|
join_with_statement_token(structure) << structure_dump_fk_constraints
|
58
|
+
join_with_statement_token(structure) << structure_dump_views
|
58
59
|
end
|
59
60
|
|
60
61
|
def structure_dump_column(column) #:nodoc:
|
61
|
-
col = "\"#{column['column_name']}\" #{column['data_type']}"
|
62
|
+
col = +"\"#{column['column_name']}\" #{column['data_type']}"
|
62
63
|
if (column["data_type"] == "NUMBER") && !column["data_precision"].nil?
|
63
64
|
col << "(#{column['data_precision'].to_i}"
|
64
65
|
col << ",#{column['data_scale'].to_i}" if !column["data_scale"].nil?
|
@@ -74,7 +75,7 @@ module ActiveRecord #:nodoc:
|
|
74
75
|
|
75
76
|
def structure_dump_virtual_column(column, data_default) #:nodoc:
|
76
77
|
data_default = data_default.gsub(/"/, "")
|
77
|
-
col = "\"#{column['column_name']}\" #{column['data_type']}"
|
78
|
+
col = +"\"#{column['column_name']}\" #{column['data_type']}"
|
78
79
|
if (column["data_type"] == "NUMBER") && !column["data_precision"].nil?
|
79
80
|
col << "(#{column['data_precision'].to_i}"
|
80
81
|
col << ",#{column['data_scale'].to_i}" if !column["data_scale"].nil?
|
@@ -150,7 +151,7 @@ module ActiveRecord #:nodoc:
|
|
150
151
|
fks = foreign_keys.map do |table|
|
151
152
|
if respond_to?(:foreign_keys) && (foreign_keys = foreign_keys(table["table_name"])).any?
|
152
153
|
foreign_keys.map do |fk|
|
153
|
-
sql = "ALTER TABLE #{quote_table_name(fk.from_table)} ADD CONSTRAINT #{quote_column_name(fk.options[:name])} "
|
154
|
+
sql = +"ALTER TABLE #{quote_table_name(fk.from_table)} ADD CONSTRAINT #{quote_column_name(fk.options[:name])} "
|
154
155
|
sql << "#{foreign_key_definition(fk.to_table, fk.options)}"
|
155
156
|
end
|
156
157
|
end
|
@@ -202,7 +203,7 @@ module ActiveRecord #:nodoc:
|
|
202
203
|
sql
|
203
204
|
end
|
204
205
|
|
205
|
-
# Extract all stored procedures, packages, synonyms
|
206
|
+
# Extract all stored procedures, packages, synonyms.
|
206
207
|
def structure_dump_db_stored_code #:nodoc:
|
207
208
|
structure = []
|
208
209
|
all_source = select_all(<<-SQL.strip.gsub(/\s+/, " "), "stored program at structure dump")
|
@@ -213,7 +214,7 @@ module ActiveRecord #:nodoc:
|
|
213
214
|
AND owner = SYS_CONTEXT('userenv', 'current_schema') ORDER BY type
|
214
215
|
SQL
|
215
216
|
all_source.each do |source|
|
216
|
-
ddl = "CREATE OR REPLACE \n"
|
217
|
+
ddl = +"CREATE OR REPLACE \n"
|
217
218
|
texts = select_all(<<-SQL.strip.gsub(/\s+/, " "), "all source at structure dump")
|
218
219
|
SELECT text
|
219
220
|
FROM all_source
|
@@ -229,16 +230,26 @@ module ActiveRecord #:nodoc:
|
|
229
230
|
structure << ddl
|
230
231
|
end
|
231
232
|
|
232
|
-
# export
|
233
|
+
# export synonyms
|
234
|
+
structure << structure_dump_synonyms
|
235
|
+
|
236
|
+
join_with_statement_token(structure)
|
237
|
+
end
|
238
|
+
|
239
|
+
def structure_dump_views #:nodoc:
|
240
|
+
structure = []
|
233
241
|
views = select_all(<<-SQL.strip.gsub(/\s+/, " "), "views at structure dump")
|
234
242
|
SELECT view_name, text FROM all_views
|
235
|
-
WHERE owner = SYS_CONTEXT('userenv', '
|
243
|
+
WHERE owner = SYS_CONTEXT('userenv', 'current_schema') ORDER BY view_name ASC
|
236
244
|
SQL
|
237
245
|
views.each do |view|
|
238
246
|
structure << "CREATE OR REPLACE FORCE VIEW #{view['view_name']} AS\n #{view['text']}"
|
239
247
|
end
|
248
|
+
join_with_statement_token(structure)
|
249
|
+
end
|
240
250
|
|
241
|
-
|
251
|
+
def structure_dump_synonyms #:nodoc:
|
252
|
+
structure = []
|
242
253
|
synonyms = select_all(<<-SQL.strip.gsub(/\s+/, " "), "synonyms at structure dump")
|
243
254
|
SELECT owner, synonym_name, table_name, table_owner
|
244
255
|
FROM all_synonyms
|
@@ -246,15 +257,14 @@ module ActiveRecord #:nodoc:
|
|
246
257
|
SQL
|
247
258
|
synonyms.each do |synonym|
|
248
259
|
structure << "CREATE OR REPLACE #{synonym['owner'] == 'PUBLIC' ? 'PUBLIC' : '' } SYNONYM #{synonym['synonym_name']}
|
249
|
-
|
260
|
+
FOR #{synonym['table_owner']}.#{synonym['table_name']}"
|
250
261
|
end
|
251
|
-
|
252
262
|
join_with_statement_token(structure)
|
253
263
|
end
|
254
264
|
|
255
265
|
def structure_drop #:nodoc:
|
256
266
|
sequences = select_values(<<-SQL.strip.gsub(/\s+/, " "), "sequences to drop at structure dump")
|
257
|
-
SELECT sequence_name FROM all_sequences where sequence_owner = SYS_CONTEXT('userenv', '
|
267
|
+
SELECT sequence_name FROM all_sequences where sequence_owner = SYS_CONTEXT('userenv', 'current_schema') ORDER BY 1
|
258
268
|
SQL
|
259
269
|
statements = sequences.map do |seq|
|
260
270
|
"DROP SEQUENCE \"#{seq}\""
|
@@ -314,7 +324,7 @@ module ActiveRecord #:nodoc:
|
|
314
324
|
SELECT column_name, data_default
|
315
325
|
FROM all_tab_cols
|
316
326
|
WHERE virtual_column = 'YES'
|
317
|
-
AND owner = SYS_CONTEXT('userenv', '
|
327
|
+
AND owner = SYS_CONTEXT('userenv', 'current_schema')
|
318
328
|
AND table_name = '#{table.upcase}'
|
319
329
|
SQL
|
320
330
|
end
|
@@ -323,7 +333,7 @@ module ActiveRecord #:nodoc:
|
|
323
333
|
short_type = type == "materialized view" ? "mview" : type
|
324
334
|
features = select_values(<<-SQL.strip.gsub(/\s+/, " "), "features to drop")
|
325
335
|
SELECT #{short_type}_name FROM all_#{short_type.tableize}
|
326
|
-
where owner = SYS_CONTEXT('userenv', '
|
336
|
+
where owner = SYS_CONTEXT('userenv', 'current_schema')
|
327
337
|
SQL
|
328
338
|
statements = features.map do |name|
|
329
339
|
"DROP #{type.upcase} \"#{name}\""
|
@@ -334,7 +344,7 @@ module ActiveRecord #:nodoc:
|
|
334
344
|
def drop_sql_for_object(type)
|
335
345
|
objects = select_values(<<-SQL.strip.gsub(/\s+/, " "), "objects to drop")
|
336
346
|
SELECT object_name FROM all_objects
|
337
|
-
WHERE object_type = '#{type.upcase}' and owner = SYS_CONTEXT('userenv', '
|
347
|
+
WHERE object_type = '#{type.upcase}' and owner = SYS_CONTEXT('userenv', 'current_schema')
|
338
348
|
SQL
|
339
349
|
statements = objects.map do |name|
|
340
350
|
"DROP #{type.upcase} \"#{name}\""
|
@@ -38,7 +38,6 @@ require "active_record/connection_adapters/oracle_enhanced/schema_creation"
|
|
38
38
|
require "active_record/connection_adapters/oracle_enhanced/schema_definitions"
|
39
39
|
require "active_record/connection_adapters/oracle_enhanced/schema_dumper"
|
40
40
|
require "active_record/connection_adapters/oracle_enhanced/schema_statements"
|
41
|
-
require "active_record/connection_adapters/oracle_enhanced/schema_statements_ext"
|
42
41
|
require "active_record/connection_adapters/oracle_enhanced/context_index"
|
43
42
|
require "active_record/connection_adapters/oracle_enhanced/column"
|
44
43
|
require "active_record/connection_adapters/oracle_enhanced/quoting"
|
@@ -58,6 +57,7 @@ require "active_record/type/oracle_enhanced/boolean"
|
|
58
57
|
require "active_record/type/oracle_enhanced/json"
|
59
58
|
require "active_record/type/oracle_enhanced/timestamptz"
|
60
59
|
require "active_record/type/oracle_enhanced/timestampltz"
|
60
|
+
require "active_record/type/oracle_enhanced/character_string"
|
61
61
|
|
62
62
|
module ActiveRecord
|
63
63
|
module ConnectionHandling #:nodoc:
|
@@ -115,16 +115,12 @@ module ActiveRecord
|
|
115
115
|
# * <tt>:time_zone</tt> - database session time zone
|
116
116
|
# (it is recommended to set it using ENV['TZ'] which will be then also used for database session time zone)
|
117
117
|
# * <tt>:schema</tt> - database schema which holds schema objects.
|
118
|
-
# * <tt>:tcp_keepalive</tt> - TCP keepalive is enabled for OCI client, defaults to true
|
119
|
-
# * <tt>:tcp_keepalive_time</tt> - TCP keepalive time for OCI client, defaults to 600
|
120
118
|
#
|
121
119
|
# Optionals NLS parameters:
|
122
120
|
#
|
123
121
|
# * <tt>:nls_calendar</tt>
|
124
122
|
# * <tt>:nls_comp</tt>
|
125
123
|
# * <tt>:nls_currency</tt>
|
126
|
-
# * <tt>:nls_date_format</tt> - format for :date columns, defaults to <tt>YYYY-MM-DD HH24:MI:SS</tt>
|
127
|
-
# (changing `nls_date_format` parameter value is not supported. Use the default value.)
|
128
124
|
# * <tt>:nls_date_language</tt>
|
129
125
|
# * <tt>:nls_dual_currency</tt>
|
130
126
|
# * <tt>:nls_iso_currency</tt>
|
@@ -135,16 +131,18 @@ module ActiveRecord
|
|
135
131
|
# * <tt>:nls_numeric_characters</tt>
|
136
132
|
# * <tt>:nls_sort</tt>
|
137
133
|
# * <tt>:nls_territory</tt>
|
138
|
-
# * <tt>:nls_timestamp_format</tt> - format for :timestamp columns, defaults to <tt>YYYY-MM-DD HH24:MI:SS:FF6</tt>
|
139
|
-
# (changing `nls_timestamp_format` parameter value is not supported. Use the default value.)
|
140
134
|
# * <tt>:nls_timestamp_tz_format</tt>
|
141
135
|
# * <tt>:nls_time_format</tt>
|
142
136
|
# * <tt>:nls_time_tz_format</tt>
|
143
137
|
#
|
138
|
+
# Fixed NLS values (not overridable):
|
139
|
+
#
|
140
|
+
# * <tt>:nls_date_format</tt> - format for :date columns is <tt>YYYY-MM-DD HH24:MI:SS</tt>
|
141
|
+
# * <tt>:nls_timestamp_format</tt> - format for :timestamp columns is <tt>YYYY-MM-DD HH24:MI:SS:FF6</tt>
|
142
|
+
#
|
144
143
|
class OracleEnhancedAdapter < AbstractAdapter
|
145
144
|
include OracleEnhanced::DatabaseStatements
|
146
145
|
include OracleEnhanced::SchemaStatements
|
147
|
-
include OracleEnhanced::SchemaStatementsExt
|
148
146
|
include OracleEnhanced::ContextIndex
|
149
147
|
include OracleEnhanced::Quoting
|
150
148
|
include OracleEnhanced::DatabaseLimits
|
@@ -196,11 +194,26 @@ module ActiveRecord
|
|
196
194
|
|
197
195
|
##
|
198
196
|
# :singleton-method:
|
199
|
-
# Specify default sequence start with value (by default
|
197
|
+
# Specify default sequence start with value (by default 1 if not explicitly set), e.g.:
|
200
198
|
#
|
201
|
-
# ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_sequence_start_value =
|
199
|
+
# ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_sequence_start_value = 10000
|
202
200
|
cattr_accessor :default_sequence_start_value
|
203
|
-
self.default_sequence_start_value =
|
201
|
+
self.default_sequence_start_value = 1
|
202
|
+
|
203
|
+
##
|
204
|
+
# :singleton-method:
|
205
|
+
# By default, OracleEnhanced adapter will use longer 128 bytes identifier
|
206
|
+
# if database version is Oracle 12.2 or higher.
|
207
|
+
# If you wish to use shorter 30 byte identifier with Oracle Database supporting longer identifier
|
208
|
+
# you can add the following line to your initializer file:
|
209
|
+
#
|
210
|
+
# ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.use_shorter_identifier = true
|
211
|
+
cattr_accessor :use_shorter_identifier
|
212
|
+
self.use_shorter_identifier = false
|
213
|
+
|
214
|
+
##
|
215
|
+
# :singleton-method:
|
216
|
+
# Specify default sequence start with value (by default 1 if not explicitly set), e.g.:
|
204
217
|
|
205
218
|
class StatementPool < ConnectionAdapters::StatementPool
|
206
219
|
private
|
@@ -212,13 +225,12 @@ module ActiveRecord
|
|
212
225
|
|
213
226
|
def initialize(connection, logger = nil, config = {}) # :nodoc:
|
214
227
|
super(connection, logger, config)
|
215
|
-
@statements = StatementPool.new(self.class.type_cast_config_to_integer(config[:statement_limit]))
|
216
228
|
@enable_dbms_output = false
|
217
229
|
@do_not_prefetch_primary_key = {}
|
218
230
|
@columns_cache = {}
|
219
231
|
end
|
220
232
|
|
221
|
-
ADAPTER_NAME = "OracleEnhanced"
|
233
|
+
ADAPTER_NAME = "OracleEnhanced"
|
222
234
|
|
223
235
|
def adapter_name #:nodoc:
|
224
236
|
ADAPTER_NAME
|
@@ -232,6 +244,10 @@ module ActiveRecord
|
|
232
244
|
end
|
233
245
|
end
|
234
246
|
|
247
|
+
def build_statement_pool
|
248
|
+
StatementPool.new(self.class.type_cast_config_to_integer(@config[:statement_limit]))
|
249
|
+
end
|
250
|
+
|
235
251
|
def supports_savepoints? #:nodoc:
|
236
252
|
true
|
237
253
|
end
|
@@ -244,8 +260,8 @@ module ActiveRecord
|
|
244
260
|
true
|
245
261
|
end
|
246
262
|
|
247
|
-
def
|
248
|
-
|
263
|
+
def supports_optimizer_hints?
|
264
|
+
true
|
249
265
|
end
|
250
266
|
|
251
267
|
def supports_views?
|
@@ -307,12 +323,19 @@ module ActiveRecord
|
|
307
323
|
false
|
308
324
|
end
|
309
325
|
|
326
|
+
def supports_longer_identifier?
|
327
|
+
if !use_shorter_identifier && @connection.database_version.to_s >= [12, 2].to_s
|
328
|
+
true
|
329
|
+
else
|
330
|
+
false
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
310
334
|
#:stopdoc:
|
311
335
|
DEFAULT_NLS_PARAMETERS = {
|
312
336
|
nls_calendar: nil,
|
313
337
|
nls_comp: nil,
|
314
338
|
nls_currency: nil,
|
315
|
-
nls_date_format: "YYYY-MM-DD HH24:MI:SS",
|
316
339
|
nls_date_language: nil,
|
317
340
|
nls_dual_currency: nil,
|
318
341
|
nls_iso_currency: nil,
|
@@ -322,12 +345,17 @@ module ActiveRecord
|
|
322
345
|
nls_numeric_characters: nil,
|
323
346
|
nls_sort: nil,
|
324
347
|
nls_territory: nil,
|
325
|
-
nls_timestamp_format: "YYYY-MM-DD HH24:MI:SS:FF6",
|
326
348
|
nls_timestamp_tz_format: nil,
|
327
349
|
nls_time_format: nil,
|
328
350
|
nls_time_tz_format: nil
|
329
351
|
}
|
330
352
|
|
353
|
+
#:stopdoc:
|
354
|
+
FIXED_NLS_PARAMETERS = {
|
355
|
+
nls_date_format: "YYYY-MM-DD HH24:MI:SS",
|
356
|
+
nls_timestamp_format: "YYYY-MM-DD HH24:MI:SS:FF6"
|
357
|
+
}
|
358
|
+
|
331
359
|
#:stopdoc:
|
332
360
|
NATIVE_DATABASE_TYPES = {
|
333
361
|
primary_key: "NUMBER(38) NOT NULL PRIMARY KEY",
|
@@ -336,7 +364,7 @@ module ActiveRecord
|
|
336
364
|
ntext: { name: "NCLOB" },
|
337
365
|
integer: { name: "NUMBER", limit: 38 },
|
338
366
|
float: { name: "BINARY_FLOAT" },
|
339
|
-
decimal: { name: "
|
367
|
+
decimal: { name: "NUMBER" },
|
340
368
|
datetime: { name: "TIMESTAMP" },
|
341
369
|
timestamp: { name: "TIMESTAMP" },
|
342
370
|
timestamptz: { name: "TIMESTAMP WITH TIME ZONE" },
|
@@ -412,14 +440,14 @@ module ActiveRecord
|
|
412
440
|
end
|
413
441
|
|
414
442
|
# use in set_sequence_name to avoid fetching primary key value from sequence
|
415
|
-
AUTOGENERATED_SEQUENCE_NAME = "autogenerated"
|
443
|
+
AUTOGENERATED_SEQUENCE_NAME = "autogenerated"
|
416
444
|
|
417
445
|
# Returns the next sequence value from a sequence generator. Not generally
|
418
446
|
# called directly; used by ActiveRecord to get the next primary key value
|
419
447
|
# when inserting a new database record (see #prefetch_primary_key?).
|
420
448
|
def next_sequence_value(sequence_name)
|
421
449
|
# if sequence_name is set to :autogenerated then it means that primary key will be populated by trigger
|
422
|
-
|
450
|
+
raise ArgumentError "Trigger based primary key is not supported" if sequence_name == AUTOGENERATED_SEQUENCE_NAME
|
423
451
|
# call directly connection method to avoid prepared statement which causes fetching of next sequence value twice
|
424
452
|
select_value(<<-SQL.strip.gsub(/\s+/, " "), "next sequence value")
|
425
453
|
SELECT #{quote_table_name(sequence_name)}.NEXTVAL FROM dual
|
@@ -433,8 +461,8 @@ module ActiveRecord
|
|
433
461
|
table_name = table_name.to_s
|
434
462
|
do_not_prefetch = @do_not_prefetch_primary_key[table_name]
|
435
463
|
if do_not_prefetch.nil?
|
436
|
-
owner, desc_table_name
|
437
|
-
@do_not_prefetch_primary_key [table_name] = do_not_prefetch = !has_primary_key?(table_name, owner, desc_table_name
|
464
|
+
owner, desc_table_name = @connection.describe(table_name)
|
465
|
+
@do_not_prefetch_primary_key [table_name] = do_not_prefetch = !has_primary_key?(table_name, owner, desc_table_name)
|
438
466
|
end
|
439
467
|
!do_not_prefetch
|
440
468
|
end
|
@@ -501,25 +529,8 @@ module ActiveRecord
|
|
501
529
|
SQL
|
502
530
|
end
|
503
531
|
|
504
|
-
# check if table has primary key trigger with _pkt suffix
|
505
|
-
def has_primary_key_trigger?(table_name, owner = nil, desc_table_name = nil, db_link = nil)
|
506
|
-
(owner, desc_table_name, db_link) = @connection.describe(table_name) unless owner
|
507
|
-
|
508
|
-
trigger_name = default_trigger_name(table_name).upcase
|
509
|
-
|
510
|
-
!!select_value(<<-SQL.strip.gsub(/\s+/, " "), "Primary Key Trigger", [bind_string("owner", owner), bind_string("trigger_name", trigger_name), bind_string("owner", owner), bind_string("table_name", desc_table_name)])
|
511
|
-
SELECT trigger_name
|
512
|
-
FROM all_triggers#{db_link}
|
513
|
-
WHERE owner = :owner
|
514
|
-
AND trigger_name = :trigger_name
|
515
|
-
AND table_owner = :owner
|
516
|
-
AND table_name = :table_name
|
517
|
-
AND status = 'ENABLED'
|
518
|
-
SQL
|
519
|
-
end
|
520
|
-
|
521
532
|
def column_definitions(table_name)
|
522
|
-
(owner, desc_table_name
|
533
|
+
(owner, desc_table_name) = @connection.describe(table_name)
|
523
534
|
|
524
535
|
select_all(<<-SQL.strip.gsub(/\s+/, " "), "Column definitions")
|
525
536
|
SELECT cols.column_name AS name, cols.data_type AS sql_type,
|
@@ -533,7 +544,7 @@ module ActiveRecord
|
|
533
544
|
NULL) AS limit,
|
534
545
|
DECODE(data_type, 'NUMBER', data_scale, NULL) AS scale,
|
535
546
|
comments.comments as column_comment
|
536
|
-
FROM all_tab_cols
|
547
|
+
FROM all_tab_cols cols, all_col_comments comments
|
537
548
|
WHERE cols.owner = '#{owner}'
|
538
549
|
AND cols.table_name = #{quote(desc_table_name)}
|
539
550
|
AND cols.hidden_column = 'NO'
|
@@ -550,12 +561,12 @@ module ActiveRecord
|
|
550
561
|
|
551
562
|
# Find a table's primary key and sequence.
|
552
563
|
# *Note*: Only primary key is implemented - sequence will be nil.
|
553
|
-
def pk_and_sequence_for(table_name, owner = nil, desc_table_name = nil
|
554
|
-
(owner, desc_table_name
|
564
|
+
def pk_and_sequence_for(table_name, owner = nil, desc_table_name = nil) #:nodoc:
|
565
|
+
(owner, desc_table_name) = @connection.describe(table_name)
|
555
566
|
|
556
567
|
seqs = select_values(<<-SQL.strip.gsub(/\s+/, " "), "Sequence")
|
557
568
|
select us.sequence_name
|
558
|
-
from all_sequences
|
569
|
+
from all_sequences us
|
559
570
|
where us.sequence_owner = '#{owner}'
|
560
571
|
and us.sequence_name = upper(#{quote(default_sequence_name(desc_table_name))})
|
561
572
|
SQL
|
@@ -563,7 +574,7 @@ module ActiveRecord
|
|
563
574
|
# changed back from user_constraints to all_constraints for consistency
|
564
575
|
pks = select_values(<<-SQL.strip.gsub(/\s+/, " "), "Primary Key")
|
565
576
|
SELECT cc.column_name
|
566
|
-
FROM all_constraints
|
577
|
+
FROM all_constraints c, all_cons_columns cc
|
567
578
|
WHERE c.owner = '#{owner}'
|
568
579
|
AND c.table_name = #{quote(desc_table_name)}
|
569
580
|
AND c.constraint_type = 'P'
|
@@ -571,7 +582,7 @@ module ActiveRecord
|
|
571
582
|
AND cc.constraint_name = c.constraint_name
|
572
583
|
SQL
|
573
584
|
|
574
|
-
warn
|
585
|
+
warn <<~WARNING if pks.count > 1
|
575
586
|
WARNING: Active Record does not support composite primary key.
|
576
587
|
|
577
588
|
#{table_name} has composite primary key. Composite primary key is ignored.
|
@@ -588,17 +599,17 @@ module ActiveRecord
|
|
588
599
|
pk_and_sequence && pk_and_sequence.first
|
589
600
|
end
|
590
601
|
|
591
|
-
def has_primary_key?(table_name, owner = nil, desc_table_name = nil
|
592
|
-
!pk_and_sequence_for(table_name, owner, desc_table_name
|
602
|
+
def has_primary_key?(table_name, owner = nil, desc_table_name = nil) #:nodoc:
|
603
|
+
!pk_and_sequence_for(table_name, owner, desc_table_name).nil?
|
593
604
|
end
|
594
605
|
|
595
606
|
def primary_keys(table_name) # :nodoc:
|
596
|
-
(
|
607
|
+
(_owner, desc_table_name) = @connection.describe(table_name)
|
597
608
|
|
598
|
-
pks = select_values(<<-SQL.strip.gsub(/\s+/, " "), "Primary Keys", [bind_string("
|
609
|
+
pks = select_values(<<-SQL.strip.gsub(/\s+/, " "), "Primary Keys", [bind_string("table_name", desc_table_name)])
|
599
610
|
SELECT cc.column_name
|
600
|
-
FROM all_constraints
|
601
|
-
WHERE c.owner =
|
611
|
+
FROM all_constraints c, all_cons_columns cc
|
612
|
+
WHERE c.owner = SYS_CONTEXT('userenv', 'current_schema')
|
602
613
|
AND c.table_name = :table_name
|
603
614
|
AND c.constraint_type = 'P'
|
604
615
|
AND cc.owner = c.owner
|
@@ -626,11 +637,24 @@ module ActiveRecord
|
|
626
637
|
|
627
638
|
def temporary_table?(table_name) #:nodoc:
|
628
639
|
select_value(<<-SQL.strip.gsub(/\s+/, " "), "temporary table", [bind_string("table_name", table_name.upcase)]) == "Y"
|
629
|
-
SELECT temporary FROM all_tables WHERE table_name = :table_name and owner = SYS_CONTEXT('userenv', '
|
640
|
+
SELECT temporary FROM all_tables WHERE table_name = :table_name and owner = SYS_CONTEXT('userenv', 'current_schema')
|
630
641
|
SQL
|
631
642
|
end
|
632
643
|
|
644
|
+
def max_identifier_length
|
645
|
+
supports_longer_identifier? ? 128 : 30
|
646
|
+
end
|
647
|
+
alias table_alias_length max_identifier_length
|
648
|
+
alias index_name_length max_identifier_length
|
649
|
+
|
633
650
|
private
|
651
|
+
def check_version
|
652
|
+
database_version = @connection.database_version.join(".").to_f
|
653
|
+
|
654
|
+
if database_version < 10
|
655
|
+
raise "Your version of Oracle (#{database_version}) is too old. Active Record Oracle enhanced adapter supports Oracle >= 10g."
|
656
|
+
end
|
657
|
+
end
|
634
658
|
|
635
659
|
def initialize_type_map(m = type_map)
|
636
660
|
super
|
@@ -638,7 +662,9 @@ module ActiveRecord
|
|
638
662
|
register_class_with_precision m, %r(WITH TIME ZONE)i, Type::OracleEnhanced::TimestampTz
|
639
663
|
register_class_with_precision m, %r(WITH LOCAL TIME ZONE)i, Type::OracleEnhanced::TimestampLtz
|
640
664
|
register_class_with_limit m, %r(raw)i, Type::OracleEnhanced::Raw
|
641
|
-
register_class_with_limit m, %r(char)i,
|
665
|
+
register_class_with_limit m, %r{^(char)}i, Type::OracleEnhanced::CharacterString
|
666
|
+
register_class_with_limit m, %r{^(nchar)}i, Type::OracleEnhanced::String
|
667
|
+
register_class_with_limit m, %r(varchar)i, Type::OracleEnhanced::String
|
642
668
|
register_class_with_limit m, %r(clob)i, Type::OracleEnhanced::Text
|
643
669
|
register_class_with_limit m, %r(nclob)i, Type::OracleEnhanced::NationalCharacterText
|
644
670
|
|
@@ -679,20 +705,20 @@ module ActiveRecord
|
|
679
705
|
end
|
680
706
|
end
|
681
707
|
|
682
|
-
def translate_exception(exception, message) #:nodoc:
|
708
|
+
def translate_exception(exception, message:, sql:, binds:) #:nodoc:
|
683
709
|
case @connection.error_code(exception)
|
684
710
|
when 1
|
685
|
-
RecordNotUnique.new(message)
|
711
|
+
RecordNotUnique.new(message, sql: sql, binds: binds)
|
686
712
|
when 60
|
687
713
|
Deadlocked.new(message)
|
688
714
|
when 900, 904, 942, 955, 1418, 2289, 2449, 17008
|
689
|
-
ActiveRecord::StatementInvalid.new(message)
|
715
|
+
ActiveRecord::StatementInvalid.new(message, sql: sql, binds: binds)
|
690
716
|
when 1400
|
691
|
-
ActiveRecord::NotNullViolation.new(message)
|
692
|
-
when 2291
|
693
|
-
InvalidForeignKey.new(message)
|
717
|
+
ActiveRecord::NotNullViolation.new(message, sql: sql, binds: binds)
|
718
|
+
when 2291, 2292
|
719
|
+
InvalidForeignKey.new(message, sql: sql, binds: binds)
|
694
720
|
when 12899
|
695
|
-
ValueTooLong.new(message)
|
721
|
+
ValueTooLong.new(message, sql: sql, binds: binds)
|
696
722
|
else
|
697
723
|
super
|
698
724
|
end
|