activerecord-oracle_enhanced-adapter 5.2.8 → 6.0.0.beta1
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/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
|