activerecord-oracle_enhanced-adapter 1.7.11 → 1.8.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/.rspec +2 -0
- data/Gemfile +20 -11
- data/History.md +123 -4
- data/RUNNING_TESTS.md +79 -55
- data/Rakefile +13 -19
- data/VERSION +1 -1
- data/activerecord-oracle_enhanced-adapter.gemspec +16 -17
- data/lib/active_record/connection_adapters/emulation/oracle_adapter.rb +1 -1
- data/lib/active_record/connection_adapters/oracle_enhanced/column.rb +7 -59
- data/lib/active_record/connection_adapters/oracle_enhanced/column_dumper.rb +6 -50
- data/lib/active_record/connection_adapters/oracle_enhanced/connection.rb +11 -11
- data/lib/active_record/connection_adapters/oracle_enhanced/context_index.rb +117 -117
- data/lib/active_record/connection_adapters/oracle_enhanced/database_statements.rb +30 -23
- data/lib/active_record/connection_adapters/oracle_enhanced/database_tasks.rb +10 -10
- data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_connection.rb +48 -70
- data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_quoting.rb +1 -4
- data/lib/active_record/connection_adapters/oracle_enhanced/oci_connection.rb +51 -69
- data/lib/active_record/connection_adapters/oracle_enhanced/oci_quoting.rb +4 -4
- data/lib/active_record/connection_adapters/oracle_enhanced/procedures.rb +76 -76
- data/lib/active_record/connection_adapters/oracle_enhanced/quoting.rb +13 -42
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_creation.rb +60 -64
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_definitions.rb +33 -47
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_dumper.rb +146 -159
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb +94 -132
- data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements_ext.rb +3 -3
- data/lib/active_record/connection_adapters/oracle_enhanced/structure_dump.rb +65 -100
- data/lib/active_record/connection_adapters/oracle_enhanced/version.rb +1 -1
- data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +250 -487
- data/lib/active_record/oracle_enhanced/type/boolean.rb +7 -10
- data/lib/active_record/oracle_enhanced/type/integer.rb +3 -4
- data/lib/active_record/oracle_enhanced/type/national_character_string.rb +1 -1
- data/lib/active_record/oracle_enhanced/type/raw.rb +2 -3
- data/lib/active_record/oracle_enhanced/type/string.rb +2 -2
- data/lib/active_record/oracle_enhanced/type/text.rb +2 -2
- data/lib/activerecord-oracle_enhanced-adapter.rb +2 -2
- data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +57 -131
- data/spec/active_record/connection_adapters/oracle_enhanced_connection_spec.rb +32 -34
- data/spec/active_record/connection_adapters/oracle_enhanced_context_index_spec.rb +40 -42
- data/spec/active_record/connection_adapters/oracle_enhanced_cpk_spec.rb +83 -85
- data/spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb +205 -286
- data/spec/active_record/connection_adapters/oracle_enhanced_database_tasks_spec.rb +14 -6
- data/spec/active_record/connection_adapters/oracle_enhanced_dbms_output_spec.rb +3 -5
- data/spec/active_record/connection_adapters/oracle_enhanced_dirty_spec.rb +42 -49
- data/spec/active_record/connection_adapters/oracle_enhanced_emulate_oracle_adapter_spec.rb +1 -3
- data/spec/active_record/connection_adapters/oracle_enhanced_procedures_spec.rb +68 -71
- data/spec/active_record/connection_adapters/oracle_enhanced_schema_dump_spec.rb +51 -92
- data/spec/active_record/connection_adapters/oracle_enhanced_schema_statements_spec.rb +221 -327
- data/spec/active_record/connection_adapters/oracle_enhanced_structure_dump_spec.rb +16 -18
- data/spec/spec_helper.rb +59 -57
- metadata +10 -10
@@ -1 +1 @@
|
|
1
|
-
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter::VERSION = File.read(File.expand_path(
|
1
|
+
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter::VERSION = File.read(File.expand_path("../../../../../VERSION", __FILE__)).chomp
|
@@ -28,17 +28,17 @@
|
|
28
28
|
# contribution.
|
29
29
|
# portions Copyright 2005 Graham Jenkins
|
30
30
|
|
31
|
-
require
|
32
|
-
require
|
33
|
-
require
|
34
|
-
require
|
35
|
-
require
|
36
|
-
require
|
37
|
-
require
|
38
|
-
require
|
39
|
-
require
|
40
|
-
|
41
|
-
require
|
31
|
+
require "active_record/connection_adapters/abstract_adapter"
|
32
|
+
require "active_record/connection_adapters/oracle_enhanced/connection"
|
33
|
+
require "active_record/connection_adapters/oracle_enhanced/database_statements"
|
34
|
+
require "active_record/connection_adapters/oracle_enhanced/schema_statements"
|
35
|
+
require "active_record/connection_adapters/oracle_enhanced/schema_statements_ext"
|
36
|
+
require "active_record/connection_adapters/oracle_enhanced/column_dumper"
|
37
|
+
require "active_record/connection_adapters/oracle_enhanced/context_index"
|
38
|
+
require "active_record/connection_adapters/oracle_enhanced/column"
|
39
|
+
require "active_record/connection_adapters/oracle_enhanced/quoting"
|
40
|
+
|
41
|
+
require "digest/sha1"
|
42
42
|
|
43
43
|
ActiveRecord::Base.class_eval do
|
44
44
|
class_attribute :custom_create_method, :custom_update_method, :custom_delete_method
|
@@ -46,89 +46,12 @@ end
|
|
46
46
|
|
47
47
|
module ActiveRecord
|
48
48
|
class Base
|
49
|
-
# Specify table columns which should be ignored by ActiveRecord, e.g.:
|
50
|
-
#
|
51
|
-
# ignore_table_columns :attribute1, :attribute2
|
52
|
-
def self.ignore_table_columns(*args)
|
53
|
-
connection.ignore_table_columns(table_name,*args)
|
54
|
-
end
|
55
|
-
|
56
|
-
# Specify which table columns should be typecasted to Date (without time), e.g.:
|
57
|
-
#
|
58
|
-
# set_date_columns :created_on, :updated_on
|
59
|
-
def self.set_date_columns(*args)
|
60
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
61
|
-
'set_date_columns` has been deprecated. Please use Rails attribute API.
|
62
|
-
MSG
|
63
|
-
# connection.set_type_for_columns(table_name,:date,*args)
|
64
|
-
end
|
65
|
-
|
66
|
-
# Specify which table columns should be typecasted to Time (or DateTime), e.g.:
|
67
|
-
#
|
68
|
-
# set_datetime_columns :created_date, :updated_date
|
69
|
-
def self.set_datetime_columns(*args)
|
70
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
71
|
-
'set_datetime_columns` has been deprecated. Please use Rails attribute API.
|
72
|
-
MSG
|
73
|
-
# connection.set_type_for_columns(table_name,:datetime,*args)
|
74
|
-
end
|
75
|
-
|
76
|
-
# Specify which table columns should be typecasted to boolean values +true+ or +false+, e.g.:
|
77
|
-
#
|
78
|
-
# set_boolean_columns :is_valid, :is_completed
|
79
|
-
def self.set_boolean_columns(*args)
|
80
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
81
|
-
'set_boolean_columns` has been deprecated. Please use Rails attribute API.
|
82
|
-
MSG
|
83
|
-
# connection.set_type_for_columns(table_name,:boolean,*args)
|
84
|
-
end
|
85
|
-
|
86
|
-
# Specify which table columns should be typecasted to integer values.
|
87
|
-
# Might be useful to force NUMBER(1) column to be integer and not boolean, or force NUMBER column without
|
88
|
-
# scale to be retrieved as integer and not decimal. Example:
|
89
|
-
#
|
90
|
-
# set_integer_columns :version_number, :object_identifier
|
91
|
-
def self.set_integer_columns(*args)
|
92
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
93
|
-
'set_integer_columns` has been deprecated. Please use Rails attribute API.
|
94
|
-
MSG
|
95
|
-
# connection.set_type_for_columns(table_name,:integer,*args)
|
96
|
-
end
|
97
|
-
|
98
|
-
# Specify which table columns should be typecasted to string values.
|
99
|
-
# Might be useful to specify that columns should be string even if its name matches boolean column criteria.
|
100
|
-
#
|
101
|
-
# set_string_columns :active_flag
|
102
|
-
def self.set_string_columns(*args)
|
103
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
104
|
-
'set_string_columns` has been deprecated. Please use Rails attribute API.
|
105
|
-
MSG
|
106
|
-
# connection.set_type_for_columns(table_name,:string,*args)
|
107
|
-
end
|
108
|
-
|
109
|
-
# Get table comment from schema definition.
|
110
|
-
def self.table_comment
|
111
|
-
#TODO: may be deprecated
|
112
|
-
connection.table_comment(self.table_name)
|
113
|
-
end
|
114
|
-
|
115
49
|
def self.lob_columns
|
116
50
|
columns.select do |column|
|
117
51
|
column.respond_to?(:lob?) && column.lob?
|
118
52
|
end
|
119
53
|
end
|
120
54
|
|
121
|
-
def self.virtual_columns
|
122
|
-
columns.select do |column|
|
123
|
-
column.respond_to?(:virtual?) && column.virtual?
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
def arel_attributes_with_values(attribute_names)
|
128
|
-
virtual_column_names = self.class.virtual_columns.map(&:name)
|
129
|
-
super(attribute_names - virtual_column_names)
|
130
|
-
end
|
131
|
-
|
132
55
|
# After setting large objects to empty, select the OCI8::LOB
|
133
56
|
# and write back the data.
|
134
57
|
before_update :record_changed_lobs
|
@@ -136,21 +59,21 @@ module ActiveRecord
|
|
136
59
|
|
137
60
|
private
|
138
61
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
62
|
+
def enhanced_write_lobs
|
63
|
+
if self.class.connection.is_a?(ConnectionAdapters::OracleEnhancedAdapter) &&
|
64
|
+
!(
|
65
|
+
(self.class.custom_create_method || self.class.custom_create_method) ||
|
66
|
+
(self.class.custom_update_method || self.class.custom_update_method)
|
67
|
+
)
|
68
|
+
self.class.connection.write_lobs(self.class.table_name, self.class, attributes, @changed_lob_columns)
|
69
|
+
end
|
146
70
|
end
|
147
|
-
end
|
148
71
|
|
149
|
-
|
150
|
-
|
151
|
-
|
72
|
+
def record_changed_lobs
|
73
|
+
@changed_lob_columns = self.class.lob_columns.select do |col|
|
74
|
+
self.attribute_changed?(col.name) && !self.class.readonly_attributes.to_a.include?(col.name)
|
75
|
+
end
|
152
76
|
end
|
153
|
-
end
|
154
77
|
end
|
155
78
|
end
|
156
79
|
|
@@ -161,7 +84,7 @@ module ActiveRecord
|
|
161
84
|
if config[:emulate_oracle_adapter] == true
|
162
85
|
# allows the enhanced adapter to look like the OracleAdapter. Useful to pick up
|
163
86
|
# conditionals in the rails activerecord test suite
|
164
|
-
require
|
87
|
+
require "active_record/connection_adapters/emulation/oracle_adapter"
|
165
88
|
ConnectionAdapters::OracleAdapter.new(
|
166
89
|
ConnectionAdapters::OracleEnhancedConnection.create(config), logger, config)
|
167
90
|
else
|
@@ -258,92 +181,16 @@ module ActiveRecord
|
|
258
181
|
|
259
182
|
##
|
260
183
|
# :singleton-method:
|
261
|
-
#
|
262
|
-
# to
|
263
|
-
# If you wish that DATE values with hour, minutes and seconds equal to 0 are typecasted
|
264
|
-
# to Date then you can add the following line to your initializer file:
|
184
|
+
# OracleEnhancedAdapter will use the default tablespace, but if you want specific types of
|
185
|
+
# objects to go into specific tablespaces, specify them like this in an initializer:
|
265
186
|
#
|
266
|
-
# ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.
|
187
|
+
# ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces =
|
188
|
+
# {:clob => 'TS_LOB', :blob => 'TS_LOB', :index => 'TS_INDEX', :table => 'TS_DATA'}
|
267
189
|
#
|
268
|
-
#
|
269
|
-
#
|
270
|
-
cattr_accessor :emulate_dates
|
271
|
-
self.emulate_dates = false
|
272
|
-
|
273
|
-
##
|
274
|
-
# :singleton-method:
|
275
|
-
# OracleEnhancedAdapter will use the default tablespace, but if you want specific types of
|
276
|
-
# objects to go into specific tablespaces, specify them like this in an initializer:
|
277
|
-
#
|
278
|
-
# ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces =
|
279
|
-
# {:clob => 'TS_LOB', :blob => 'TS_LOB', :index => 'TS_INDEX', :table => 'TS_DATA'}
|
280
|
-
#
|
281
|
-
# Using the :tablespace option where available (e.g create_table) will take precedence
|
282
|
-
# over these settings.
|
190
|
+
# Using the :tablespace option where available (e.g create_table) will take precedence
|
191
|
+
# over these settings.
|
283
192
|
cattr_accessor :default_tablespaces
|
284
|
-
self.default_tablespaces={}
|
285
|
-
|
286
|
-
##
|
287
|
-
# :singleton-method:
|
288
|
-
# By default, the OracleEnhancedAdapter will typecast all columns of type <tt>DATE</tt>
|
289
|
-
# to Time or DateTime (if value is out of Time value range) value.
|
290
|
-
# If you wish that DATE columns with "date" in their name (e.g. "creation_date") are typecasted
|
291
|
-
# to Date then you can add the following line to your initializer file:
|
292
|
-
#
|
293
|
-
# ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates_by_column_name = true
|
294
|
-
#
|
295
|
-
# As this option can have side effects when unnecessary typecasting is done it is recommended
|
296
|
-
# that Date columns are explicily defined with +set_date_columns+ method.
|
297
|
-
cattr_accessor :emulate_dates_by_column_name
|
298
|
-
self.emulate_dates_by_column_name = false
|
299
|
-
|
300
|
-
# Check column name to identify if it is Date (and not Time) column.
|
301
|
-
# Is used if +emulate_dates_by_column_name+ option is set to +true+.
|
302
|
-
# Override this method definition in initializer file if different Date column recognition is needed.
|
303
|
-
def self.is_date_column?(name, table_name = nil)
|
304
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
305
|
-
`self.is_date_column?` has been deprecated. Please use Rails attribute API.
|
306
|
-
MSG
|
307
|
-
return false
|
308
|
-
# name =~ /(^|_)date(_|$)/i
|
309
|
-
end
|
310
|
-
|
311
|
-
# instance method uses at first check if column type defined at class level
|
312
|
-
def is_date_column?(name, table_name = nil) #:nodoc:
|
313
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
314
|
-
`is_date_column?` has been deprecated. Please use Rails attribute API.
|
315
|
-
MSG
|
316
|
-
return false
|
317
|
-
#case get_type_for_column(table_name, name)
|
318
|
-
#when nil
|
319
|
-
# self.class.is_date_column?(name, table_name)
|
320
|
-
#when :date
|
321
|
-
# true
|
322
|
-
#else
|
323
|
-
# false
|
324
|
-
#end
|
325
|
-
end
|
326
|
-
|
327
|
-
##
|
328
|
-
# :singleton-method:
|
329
|
-
# By default, the OracleEnhancedAdapter will typecast all columns of type <tt>NUMBER</tt>
|
330
|
-
# (without precision or scale) to Float or BigDecimal value.
|
331
|
-
# If you wish that NUMBER columns with name "id" or that end with "_id" are typecasted
|
332
|
-
# to Integer then you can add the following line to your initializer file:
|
333
|
-
#
|
334
|
-
# ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_integers_by_column_name = true
|
335
|
-
cattr_accessor :emulate_integers_by_column_name
|
336
|
-
self.emulate_integers_by_column_name = false
|
337
|
-
|
338
|
-
# Check column name to identify if it is Integer (and not Float or BigDecimal) column.
|
339
|
-
# Is used if +emulate_integers_by_column_name+ option is set to +true+.
|
340
|
-
# Override this method definition in initializer file if different Integer column recognition is needed.
|
341
|
-
def self.is_integer_column?(name, table_name = nil)
|
342
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
343
|
-
`is_integer_column?` has been deprecated. Please use Rails attribute API.
|
344
|
-
MSG
|
345
|
-
return false
|
346
|
-
end
|
193
|
+
self.default_tablespaces = {}
|
347
194
|
|
348
195
|
##
|
349
196
|
# :singleton-method:
|
@@ -354,40 +201,6 @@ module ActiveRecord
|
|
354
201
|
cattr_accessor :emulate_booleans_from_strings
|
355
202
|
self.emulate_booleans_from_strings = false
|
356
203
|
|
357
|
-
# Check column name to identify if it is boolean (and not String) column.
|
358
|
-
# Is used if +emulate_booleans_from_strings+ option is set to +true+.
|
359
|
-
# Override this method definition in initializer file if different boolean column recognition is needed.
|
360
|
-
def self.is_boolean_column?(name, sql_type, table_name = nil)
|
361
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
362
|
-
`is_boolean_column?` has been deprecated. Please use Rails attribute API.
|
363
|
-
MSG
|
364
|
-
return false
|
365
|
-
# return true if ["CHAR(1)","VARCHAR2(1)"].include?(sql_type)
|
366
|
-
# sql_type =~ /^VARCHAR2/ && (name =~ /_flag$/i || name =~ /_yn$/i)
|
367
|
-
end
|
368
|
-
|
369
|
-
# How boolean value should be quoted to String.
|
370
|
-
# Used if +emulate_booleans_from_strings+ option is set to +true+.
|
371
|
-
def self.boolean_to_string(bool)
|
372
|
-
bool ? "Y" : "N"
|
373
|
-
end
|
374
|
-
|
375
|
-
##
|
376
|
-
# :singleton-method:
|
377
|
-
# Specify non-default date format that should be used when assigning string values to :date columns, e.g.:
|
378
|
-
#
|
379
|
-
# ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.string_to_date_format = “%d.%m.%Y”
|
380
|
-
cattr_accessor :string_to_date_format
|
381
|
-
self.string_to_date_format = nil
|
382
|
-
|
383
|
-
##
|
384
|
-
# :singleton-method:
|
385
|
-
# Specify non-default time format that should be used when assigning string values to :datetime columns, e.g.:
|
386
|
-
#
|
387
|
-
# ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.string_to_time_format = “%d.%m.%Y %H:%M:%S”
|
388
|
-
cattr_accessor :string_to_time_format
|
389
|
-
self.string_to_time_format = nil
|
390
|
-
|
391
204
|
##
|
392
205
|
# :singleton-method:
|
393
206
|
# By default, OracleEnhanced adapter will use Oracle12 visitor
|
@@ -436,7 +249,7 @@ module ActiveRecord
|
|
436
249
|
@enable_dbms_output = false
|
437
250
|
end
|
438
251
|
|
439
|
-
ADAPTER_NAME =
|
252
|
+
ADAPTER_NAME = "OracleEnhanced".freeze
|
440
253
|
|
441
254
|
def adapter_name #:nodoc:
|
442
255
|
ADAPTER_NAME
|
@@ -454,10 +267,6 @@ module ActiveRecord
|
|
454
267
|
true
|
455
268
|
end
|
456
269
|
|
457
|
-
def supports_primary_key? #:nodoc:
|
458
|
-
true
|
459
|
-
end
|
460
|
-
|
461
270
|
def supports_savepoints? #:nodoc:
|
462
271
|
true
|
463
272
|
end
|
@@ -470,12 +279,16 @@ module ActiveRecord
|
|
470
279
|
true
|
471
280
|
end
|
472
281
|
|
282
|
+
def supports_foreign_keys_in_create?
|
283
|
+
supports_foreign_keys?
|
284
|
+
end
|
285
|
+
|
473
286
|
def supports_views?
|
474
287
|
true
|
475
288
|
end
|
476
289
|
|
477
290
|
def supports_fetch_first_n_rows_and_offset?
|
478
|
-
if !use_old_oracle_visitor && @connection.database_version == [12,1]
|
291
|
+
if !use_old_oracle_visitor && @connection.database_version == [12, 1]
|
479
292
|
true
|
480
293
|
else
|
481
294
|
false
|
@@ -483,9 +296,7 @@ module ActiveRecord
|
|
483
296
|
end
|
484
297
|
|
485
298
|
def supports_datetime_with_precision?
|
486
|
-
|
487
|
-
#to map :datetime as DATE
|
488
|
-
@connection.database_version.first >= 9
|
299
|
+
true
|
489
300
|
end
|
490
301
|
|
491
302
|
def supports_comments?
|
@@ -496,47 +307,51 @@ module ActiveRecord
|
|
496
307
|
@connection.database_version.to_s >= [11, 2].to_s
|
497
308
|
end
|
498
309
|
|
310
|
+
def supports_virtual_columns?
|
311
|
+
@connection.database_version.first >= 11
|
312
|
+
end
|
313
|
+
|
499
314
|
#:stopdoc:
|
500
315
|
DEFAULT_NLS_PARAMETERS = {
|
501
|
-
:
|
502
|
-
:
|
503
|
-
:
|
504
|
-
:
|
505
|
-
:
|
506
|
-
:
|
507
|
-
:
|
508
|
-
:
|
509
|
-
:
|
510
|
-
:
|
511
|
-
:
|
512
|
-
:
|
513
|
-
:
|
514
|
-
:
|
515
|
-
:
|
516
|
-
:
|
517
|
-
:
|
316
|
+
nls_calendar: nil,
|
317
|
+
nls_comp: nil,
|
318
|
+
nls_currency: nil,
|
319
|
+
nls_date_format: "YYYY-MM-DD HH24:MI:SS",
|
320
|
+
nls_date_language: nil,
|
321
|
+
nls_dual_currency: nil,
|
322
|
+
nls_iso_currency: nil,
|
323
|
+
nls_language: nil,
|
324
|
+
nls_length_semantics: "CHAR",
|
325
|
+
nls_nchar_conv_excp: nil,
|
326
|
+
nls_numeric_characters: nil,
|
327
|
+
nls_sort: nil,
|
328
|
+
nls_territory: nil,
|
329
|
+
nls_timestamp_format: "YYYY-MM-DD HH24:MI:SS:FF6",
|
330
|
+
nls_timestamp_tz_format: nil,
|
331
|
+
nls_time_format: nil,
|
332
|
+
nls_time_tz_format: nil
|
518
333
|
}
|
519
334
|
|
520
335
|
#:stopdoc:
|
521
336
|
NATIVE_DATABASE_TYPES = {
|
522
|
-
:
|
523
|
-
:
|
524
|
-
:
|
525
|
-
:
|
526
|
-
:
|
527
|
-
:
|
528
|
-
:
|
529
|
-
:
|
530
|
-
:
|
531
|
-
:
|
532
|
-
:
|
533
|
-
:
|
534
|
-
:
|
535
|
-
:
|
337
|
+
primary_key: "NUMBER(38) NOT NULL PRIMARY KEY",
|
338
|
+
string: { name: "VARCHAR2", limit: 255 },
|
339
|
+
text: { name: "CLOB" },
|
340
|
+
integer: { name: "NUMBER", limit: 38 },
|
341
|
+
float: { name: "BINARY_FLOAT" },
|
342
|
+
decimal: { name: "DECIMAL" },
|
343
|
+
datetime: { name: "TIMESTAMP" },
|
344
|
+
timestamp: { name: "TIMESTAMP" },
|
345
|
+
time: { name: "TIMESTAMP" },
|
346
|
+
date: { name: "DATE" },
|
347
|
+
binary: { name: "BLOB" },
|
348
|
+
boolean: { name: "NUMBER", limit: 1 },
|
349
|
+
raw: { name: "RAW", limit: 2000 },
|
350
|
+
bigint: { name: "NUMBER", limit: 19 }
|
536
351
|
}
|
537
352
|
# if emulate_booleans_from_strings then store booleans in VARCHAR2
|
538
353
|
NATIVE_DATABASE_TYPES_BOOLEAN_STRINGS = NATIVE_DATABASE_TYPES.dup.merge(
|
539
|
-
:
|
354
|
+
boolean: { name: "VARCHAR2", limit: 1 }
|
540
355
|
)
|
541
356
|
#:startdoc:
|
542
357
|
|
@@ -586,7 +401,6 @@ module ActiveRecord
|
|
586
401
|
def in_clause_length
|
587
402
|
1000
|
588
403
|
end
|
589
|
-
alias ids_in_list_limit in_clause_length
|
590
404
|
|
591
405
|
# CONNECTION MANAGEMENT ====================================
|
592
406
|
#
|
@@ -638,7 +452,7 @@ module ActiveRecord
|
|
638
452
|
end
|
639
453
|
|
640
454
|
# use in set_sequence_name to avoid fetching primary key value from sequence
|
641
|
-
AUTOGENERATED_SEQUENCE_NAME =
|
455
|
+
AUTOGENERATED_SEQUENCE_NAME = "autogenerated".freeze
|
642
456
|
|
643
457
|
# Returns the next sequence value from a sequence generator. Not generally
|
644
458
|
# called directly; used by ActiveRecord to get the next primary key value
|
@@ -674,8 +488,8 @@ module ActiveRecord
|
|
674
488
|
|
675
489
|
def reset_pk_sequence!(table_name, primary_key = nil, sequence_name = nil) #:nodoc:
|
676
490
|
return nil unless data_source_exists?(table_name)
|
677
|
-
unless primary_key
|
678
|
-
|
491
|
+
unless primary_key && sequence_name
|
492
|
+
# *Note*: Only primary key is implemented - sequence will be nil.
|
679
493
|
primary_key, sequence_name = pk_and_sequence_for(table_name)
|
680
494
|
# TODO This sequence_name implemantation is just enough
|
681
495
|
# to satisty fixures. To get correct sequence_name always
|
@@ -706,7 +520,7 @@ module ActiveRecord
|
|
706
520
|
# is class with composite primary key>
|
707
521
|
is_with_cpk = klass.respond_to?(:composite?) && klass.composite?
|
708
522
|
if is_with_cpk
|
709
|
-
id = klass.primary_key.map {|pk| attributes[pk.to_s] }
|
523
|
+
id = klass.primary_key.map { |pk| attributes[pk.to_s] }
|
710
524
|
else
|
711
525
|
id = quote(attributes[klass.primary_key])
|
712
526
|
end
|
@@ -720,7 +534,7 @@ module ActiveRecord
|
|
720
534
|
uncached do
|
721
535
|
sql = is_with_cpk ? "SELECT #{quote_column_name(col.name)} FROM #{quote_table_name(table_name)} WHERE #{klass.composite_where_clause(id)} FOR UPDATE" :
|
722
536
|
"SELECT #{quote_column_name(col.name)} FROM #{quote_table_name(table_name)} WHERE #{quote_column_name(klass.primary_key)} = #{id} FOR UPDATE"
|
723
|
-
unless lob_record = select_one(sql,
|
537
|
+
unless lob_record = select_one(sql, "Writable Large Object")
|
724
538
|
raise ActiveRecord::RecordNotFound, "statement #{sql} returned no rows"
|
725
539
|
end
|
726
540
|
lob = lob_record[col.name]
|
@@ -731,6 +545,8 @@ module ActiveRecord
|
|
731
545
|
|
732
546
|
# Current database name
|
733
547
|
def current_database
|
548
|
+
select_value("SELECT SYS_CONTEXT('userenv', 'con_name') FROM dual")
|
549
|
+
rescue ActiveRecord::StatementInvalid
|
734
550
|
select_value("SELECT SYS_CONTEXT('userenv', 'db_name') FROM dual")
|
735
551
|
end
|
736
552
|
|
@@ -749,39 +565,40 @@ module ActiveRecord
|
|
749
565
|
select_value("SELECT LOWER(default_tablespace) FROM user_users WHERE username = SYS_CONTEXT('userenv', 'current_schema')")
|
750
566
|
end
|
751
567
|
|
752
|
-
def tables
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
MSG
|
758
|
-
|
759
|
-
if name
|
760
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
761
|
-
Passing arguments to #tables is deprecated without replacement.
|
762
|
-
MSG
|
763
|
-
end
|
764
|
-
|
765
|
-
data_sources
|
568
|
+
def tables #:nodoc:
|
569
|
+
select_values(<<-SQL, "SCHEMA")
|
570
|
+
SELECT DECODE(table_name, UPPER(table_name), LOWER(table_name), table_name)
|
571
|
+
FROM all_tables WHERE owner = SYS_CONTEXT('userenv', 'current_schema') AND secondary = 'N'
|
572
|
+
SQL
|
766
573
|
end
|
767
574
|
|
768
575
|
def data_sources
|
769
|
-
|
770
|
-
"SELECT DECODE(table_name, UPPER(table_name), LOWER(table_name), table_name) FROM all_tables WHERE owner = SYS_CONTEXT('userenv', 'current_schema') AND secondary = 'N'",
|
771
|
-
'SCHEMA')
|
576
|
+
super
|
772
577
|
end
|
773
578
|
|
774
579
|
def table_exists?(table_name)
|
775
|
-
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
580
|
+
table_name = table_name.to_s
|
581
|
+
if table_name.include?("@")
|
582
|
+
# db link is not table
|
583
|
+
false
|
584
|
+
else
|
585
|
+
default_owner = current_schema
|
586
|
+
end
|
587
|
+
real_name = ActiveRecord::ConnectionAdapters::OracleEnhanced::Quoting.valid_table_name?(table_name) ?
|
588
|
+
table_name.upcase : table_name
|
589
|
+
if real_name.include?(".")
|
590
|
+
table_owner, table_name = real_name.split(".")
|
591
|
+
else
|
592
|
+
table_owner, table_name = default_owner, real_name
|
593
|
+
end
|
594
|
+
select_values(<<-SQL, "SCHEMA").any?
|
595
|
+
SELECT owner, table_name
|
596
|
+
FROM all_tables
|
597
|
+
WHERE owner = '#{table_owner}'
|
598
|
+
AND table_name = q'[#{table_name}]'
|
599
|
+
SQL
|
782
600
|
end
|
783
601
|
|
784
|
-
# Will return true if database object exists (to be able to use also views and synonyms for ActiveRecord models)
|
785
602
|
# Needs to consider how to support synonyms in Rails 5.1
|
786
603
|
def data_source_exists?(table_name)
|
787
604
|
(_owner, table_name, _db_link) = @connection.describe(table_name)
|
@@ -791,7 +608,7 @@ module ActiveRecord
|
|
791
608
|
end
|
792
609
|
|
793
610
|
def views # :nodoc:
|
794
|
-
select_values("SELECT LOWER(view_name) FROM all_views WHERE owner = SYS_CONTEXT('userenv', '
|
611
|
+
select_values("SELECT LOWER(view_name) FROM all_views WHERE owner = SYS_CONTEXT('userenv', 'current_schema')")
|
795
612
|
end
|
796
613
|
|
797
614
|
def materialized_views #:nodoc:
|
@@ -806,7 +623,7 @@ module ActiveRecord
|
|
806
623
|
(owner, table_name, db_link) = @connection.describe(table_name)
|
807
624
|
unless all_schema_indexes
|
808
625
|
default_tablespace_name = default_tablespace
|
809
|
-
result = select_all(<<-SQL.strip.gsub(/\s+/,
|
626
|
+
result = select_all(<<-SQL.strip.gsub(/\s+/, " "))
|
810
627
|
SELECT LOWER(i.table_name) AS table_name, LOWER(i.index_name) AS index_name, i.uniqueness,
|
811
628
|
i.index_type, i.ityp_owner, i.ityp_name, i.parameters,
|
812
629
|
LOWER(i.tablespace_name) AS tablespace_name,
|
@@ -831,10 +648,10 @@ module ActiveRecord
|
|
831
648
|
result.each do |row|
|
832
649
|
# have to keep track of indexes because above query returns dups
|
833
650
|
# there is probably a better query we could figure out
|
834
|
-
if current_index != row[
|
651
|
+
if current_index != row["index_name"]
|
835
652
|
statement_parameters = nil
|
836
|
-
if row[
|
837
|
-
procedure_name = default_datastore_procedure(row[
|
653
|
+
if row["index_type"] == "DOMAIN" && row["ityp_owner"] == "CTXSYS" && row["ityp_name"] == "CONTEXT"
|
654
|
+
procedure_name = default_datastore_procedure(row["index_name"])
|
838
655
|
source = select_values(<<-SQL).join
|
839
656
|
SELECT text
|
840
657
|
FROM all_source#{db_link}
|
@@ -847,82 +664,36 @@ module ActiveRecord
|
|
847
664
|
end
|
848
665
|
end
|
849
666
|
all_schema_indexes << OracleEnhanced::IndexDefinition.new(
|
850
|
-
row[
|
851
|
-
row[
|
852
|
-
row[
|
667
|
+
row["table_name"],
|
668
|
+
row["index_name"],
|
669
|
+
row["uniqueness"] == "UNIQUE",
|
853
670
|
[],
|
854
671
|
nil,
|
855
672
|
nil,
|
856
673
|
nil,
|
857
|
-
row[
|
674
|
+
row["index_type"] == "DOMAIN" ? "#{row['ityp_owner']}.#{row['ityp_name']}" : nil,
|
858
675
|
nil,
|
859
|
-
row[
|
676
|
+
row["parameters"],
|
860
677
|
statement_parameters,
|
861
|
-
row[
|
862
|
-
current_index = row[
|
678
|
+
row["tablespace_name"] == default_tablespace_name ? nil : row["tablespace_name"])
|
679
|
+
current_index = row["index_name"]
|
863
680
|
end
|
864
681
|
|
865
682
|
# Functional index columns and virtual columns both get stored as column expressions,
|
866
683
|
# but re-creating a virtual column index as an expression (instead of using the virtual column's name)
|
867
684
|
# results in a ORA-54018 error. Thus, we only want the column expression value returned
|
868
685
|
# when the column is not virtual.
|
869
|
-
if row[
|
870
|
-
all_schema_indexes.last.columns << row[
|
686
|
+
if row["column_expression"] && row["virtual_column"] != "YES"
|
687
|
+
all_schema_indexes.last.columns << row["column_expression"]
|
871
688
|
else
|
872
|
-
all_schema_indexes.last.columns << row[
|
689
|
+
all_schema_indexes.last.columns << row["column_name"].downcase
|
873
690
|
end
|
874
691
|
end
|
875
692
|
end
|
876
693
|
|
877
694
|
# Return the indexes just for the requested table, since AR is structured that way
|
878
695
|
table_name = table_name.downcase
|
879
|
-
all_schema_indexes.select{|i| i.table == table_name}
|
880
|
-
end
|
881
|
-
|
882
|
-
@@ignore_table_columns = nil #:nodoc:
|
883
|
-
|
884
|
-
# set ignored columns for table
|
885
|
-
def ignore_table_columns(table_name, *args) #:nodoc:
|
886
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
887
|
-
`ignore_table_columns` will be deprecated in next version of Oracle enhanced adapter
|
888
|
-
since Rails 5 introduces `ignored_columns`. Use `ignored_columns` instead of `ignore_table_columns`.
|
889
|
-
MSG
|
890
|
-
@@ignore_table_columns ||= {}
|
891
|
-
@@ignore_table_columns[table_name] ||= []
|
892
|
-
@@ignore_table_columns[table_name] += args.map{|a| a.to_s.downcase}
|
893
|
-
@@ignore_table_columns[table_name].uniq!
|
894
|
-
end
|
895
|
-
|
896
|
-
def ignored_table_columns(table_name) #:nodoc:
|
897
|
-
@@ignore_table_columns ||= {}
|
898
|
-
@@ignore_table_columns[table_name]
|
899
|
-
end
|
900
|
-
|
901
|
-
# used just in tests to clear ignored table columns
|
902
|
-
def clear_ignored_table_columns #:nodoc:
|
903
|
-
@@ignore_table_columns = nil
|
904
|
-
end
|
905
|
-
|
906
|
-
@@table_column_type = nil #:nodoc:
|
907
|
-
|
908
|
-
# set explicit type for specified table columns
|
909
|
-
def set_type_for_columns(table_name, column_type, *args) #:nodoc:
|
910
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
911
|
-
`set_type_for_columns` has been deprecated. Please use Rails attribute API.
|
912
|
-
MSG
|
913
|
-
end
|
914
|
-
|
915
|
-
def get_type_for_column(table_name, column_name) #:nodoc:
|
916
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
917
|
-
`get_type_for_columns` has been deprecated. Please use Rails attribute API.
|
918
|
-
MSG
|
919
|
-
end
|
920
|
-
|
921
|
-
# used just in tests to clear column data type definitions
|
922
|
-
def clear_types_for_columns #:nodoc:
|
923
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
924
|
-
`clear_types_for_columns` has been deprecated. Please use Rails attribute API.
|
925
|
-
MSG
|
696
|
+
all_schema_indexes.select { |i| i.table == table_name }
|
926
697
|
end
|
927
698
|
|
928
699
|
# check if table has primary key trigger with _pkt suffix
|
@@ -934,12 +705,12 @@ module ActiveRecord
|
|
934
705
|
SELECT trigger_name
|
935
706
|
FROM all_triggers#{db_link}
|
936
707
|
WHERE owner = '#{owner}'
|
937
|
-
AND trigger_name = '#{trigger_name}'
|
708
|
+
AND trigger_name = q'[#{trigger_name}]'
|
938
709
|
AND table_owner = '#{owner}'
|
939
|
-
AND table_name = '#{desc_table_name}'
|
710
|
+
AND table_name = q'[#{desc_table_name}]'
|
940
711
|
AND status = 'ENABLED'
|
941
712
|
SQL
|
942
|
-
select_value(pkt_sql,
|
713
|
+
select_value(pkt_sql, "Primary Key Trigger") ? true : false
|
943
714
|
end
|
944
715
|
|
945
716
|
##
|
@@ -963,15 +734,13 @@ module ActiveRecord
|
|
963
734
|
|
964
735
|
def columns_without_cache(table_name, name = nil) #:nodoc:
|
965
736
|
table_name = table_name.to_s
|
966
|
-
# get ignored_columns by original table name
|
967
|
-
ignored_columns = ignored_table_columns(table_name)
|
968
737
|
|
969
738
|
(owner, desc_table_name, db_link) = @connection.describe(table_name)
|
970
739
|
|
971
740
|
# reset do_not_prefetch_primary_key cache for this table
|
972
741
|
@@do_not_prefetch_primary_key[table_name] = nil
|
973
742
|
|
974
|
-
table_cols = <<-SQL.strip.gsub(/\s+/,
|
743
|
+
table_cols = <<-SQL.strip.gsub(/\s+/, " ")
|
975
744
|
SELECT cols.column_name AS name, cols.data_type AS sql_type,
|
976
745
|
cols.data_default, cols.nullable, cols.virtual_column, cols.hidden_column,
|
977
746
|
cols.data_type_owner AS sql_type_owner,
|
@@ -985,7 +754,7 @@ module ActiveRecord
|
|
985
754
|
comments.comments as column_comment
|
986
755
|
FROM all_tab_cols#{db_link} cols, all_col_comments#{db_link} comments
|
987
756
|
WHERE cols.owner = '#{owner}'
|
988
|
-
AND cols.table_name =
|
757
|
+
AND cols.table_name = #{quote(desc_table_name)}
|
989
758
|
AND cols.hidden_column = 'NO'
|
990
759
|
AND cols.owner = comments.owner
|
991
760
|
AND cols.table_name = comments.table_name
|
@@ -994,46 +763,44 @@ module ActiveRecord
|
|
994
763
|
SQL
|
995
764
|
|
996
765
|
# added deletion of ignored columns
|
997
|
-
select_all(table_cols, name).to_a.
|
998
|
-
|
999
|
-
end.map do |row|
|
1000
|
-
limit, scale = row['limit'], row['scale']
|
766
|
+
select_all(table_cols, name).to_a.map do |row|
|
767
|
+
limit, scale = row["limit"], row["scale"]
|
1001
768
|
if limit || scale
|
1002
|
-
row[
|
769
|
+
row["sql_type"] += "(#{(limit || 38).to_i}" + ((scale = scale.to_i) > 0 ? ",#{scale})" : ")")
|
1003
770
|
end
|
1004
771
|
|
1005
|
-
if row[
|
1006
|
-
row[
|
772
|
+
if row["sql_type_owner"]
|
773
|
+
row["sql_type"] = row["sql_type_owner"] + "." + row["sql_type"]
|
1007
774
|
end
|
1008
775
|
|
1009
|
-
is_virtual = row[
|
776
|
+
is_virtual = row["virtual_column"] == "YES"
|
1010
777
|
|
1011
778
|
# clean up odd default spacing from Oracle
|
1012
|
-
if row[
|
1013
|
-
row[
|
779
|
+
if row["data_default"] && !is_virtual
|
780
|
+
row["data_default"].sub!(/^(.*?)\s*$/, '\1')
|
1014
781
|
|
1015
782
|
# If a default contains a newline these cleanup regexes need to
|
1016
783
|
# match newlines.
|
1017
|
-
row[
|
1018
|
-
row[
|
784
|
+
row["data_default"].sub!(/^'(.*)'$/m, '\1')
|
785
|
+
row["data_default"] = nil if row["data_default"] =~ /^(null|empty_[bc]lob\(\))$/i
|
1019
786
|
# TODO: Needs better fix to fallback "N" to false
|
1020
|
-
row[
|
787
|
+
row["data_default"] = false if (row["data_default"] == "N" && OracleEnhancedAdapter.emulate_booleans_from_strings)
|
1021
788
|
end
|
1022
789
|
|
1023
|
-
type_metadata = fetch_type_metadata(row[
|
1024
|
-
new_column(oracle_downcase(row[
|
1025
|
-
row[
|
790
|
+
type_metadata = fetch_type_metadata(row["sql_type"])
|
791
|
+
new_column(oracle_downcase(row["name"]),
|
792
|
+
row["data_default"],
|
1026
793
|
type_metadata,
|
1027
|
-
row[
|
794
|
+
row["nullable"] == "Y",
|
1028
795
|
table_name,
|
1029
796
|
is_virtual,
|
1030
797
|
false,
|
1031
|
-
row[
|
798
|
+
row["column_comment"]
|
1032
799
|
)
|
1033
800
|
end
|
1034
801
|
end
|
1035
802
|
|
1036
|
-
def new_column(name, default, sql_type_metadata = nil, null = true, table_name = nil, virtual = false, returning_id = false,comment = nil) # :nodoc:
|
803
|
+
def new_column(name, default, sql_type_metadata = nil, null = true, table_name = nil, virtual = false, returning_id = false, comment = nil) # :nodoc:
|
1037
804
|
OracleEnhancedColumn.new(name, default, sql_type_metadata, null, table_name, virtual, returning_id, comment)
|
1038
805
|
end
|
1039
806
|
|
@@ -1061,7 +828,7 @@ module ActiveRecord
|
|
1061
828
|
|
1062
829
|
# Find a table's primary key and sequence.
|
1063
830
|
# *Note*: Only primary key is implemented - sequence will be nil.
|
1064
|
-
def pk_and_sequence_for(table_name, owner=nil, desc_table_name=nil, db_link=nil) #:nodoc:
|
831
|
+
def pk_and_sequence_for(table_name, owner = nil, desc_table_name = nil, db_link = nil) #:nodoc:
|
1065
832
|
if @@cache_columns
|
1066
833
|
@@pk_and_sequence_for_cache ||= {}
|
1067
834
|
if @@pk_and_sequence_for_cache.key?(table_name)
|
@@ -1074,22 +841,22 @@ module ActiveRecord
|
|
1074
841
|
end
|
1075
842
|
end
|
1076
843
|
|
1077
|
-
def pk_and_sequence_for_without_cache(table_name, owner=nil, desc_table_name=nil, db_link=nil) #:nodoc:
|
844
|
+
def pk_and_sequence_for_without_cache(table_name, owner = nil, desc_table_name = nil, db_link = nil) #:nodoc:
|
1078
845
|
(owner, desc_table_name, db_link) = @connection.describe(table_name) unless owner
|
1079
846
|
|
1080
|
-
seqs = select_values(<<-SQL.strip.gsub(/\s+/,
|
847
|
+
seqs = select_values(<<-SQL.strip.gsub(/\s+/, " "), "Sequence")
|
1081
848
|
select us.sequence_name
|
1082
849
|
from all_sequences#{db_link} us
|
1083
850
|
where us.sequence_owner = '#{owner}'
|
1084
|
-
and us.sequence_name =
|
851
|
+
and us.sequence_name = upper(#{quote(default_sequence_name(desc_table_name))})
|
1085
852
|
SQL
|
1086
853
|
|
1087
854
|
# changed back from user_constraints to all_constraints for consistency
|
1088
|
-
pks = select_values(<<-SQL.strip.gsub(/\s+/,
|
855
|
+
pks = select_values(<<-SQL.strip.gsub(/\s+/, " "), "Primary Key")
|
1089
856
|
SELECT cc.column_name
|
1090
857
|
FROM all_constraints#{db_link} c, all_cons_columns#{db_link} cc
|
1091
858
|
WHERE c.owner = '#{owner}'
|
1092
|
-
AND c.table_name =
|
859
|
+
AND c.table_name = #{quote(desc_table_name)}
|
1093
860
|
AND c.constraint_type = 'P'
|
1094
861
|
AND cc.owner = c.owner
|
1095
862
|
AND cc.constraint_name = c.constraint_name
|
@@ -1112,14 +879,14 @@ module ActiveRecord
|
|
1112
879
|
pk_and_sequence && pk_and_sequence.first
|
1113
880
|
end
|
1114
881
|
|
1115
|
-
def has_primary_key?(table_name, owner=nil, desc_table_name=nil, db_link=nil) #:nodoc:
|
882
|
+
def has_primary_key?(table_name, owner = nil, desc_table_name = nil, db_link = nil) #:nodoc:
|
1116
883
|
!pk_and_sequence_for(table_name, owner, desc_table_name, db_link).nil?
|
1117
884
|
end
|
1118
885
|
|
1119
886
|
def primary_keys(table_name) # :nodoc:
|
1120
887
|
(owner, desc_table_name, db_link) = @connection.describe(table_name) unless owner
|
1121
888
|
|
1122
|
-
pks = select_values(<<-SQL.strip_heredoc,
|
889
|
+
pks = select_values(<<-SQL.strip_heredoc, "Primary Keys")
|
1123
890
|
SELECT cc.column_name
|
1124
891
|
FROM all_constraints#{db_link} c, all_cons_columns#{db_link} cc
|
1125
892
|
WHERE c.owner = '#{owner}'
|
@@ -1129,7 +896,7 @@ module ActiveRecord
|
|
1129
896
|
AND cc.constraint_name = c.constraint_name
|
1130
897
|
order by cc.position
|
1131
898
|
SQL
|
1132
|
-
pks.map {|pk| oracle_downcase(pk)}
|
899
|
+
pks.map { |pk| oracle_downcase(pk) }
|
1133
900
|
end
|
1134
901
|
|
1135
902
|
def columns_for_distinct(columns, orders) #:nodoc:
|
@@ -1138,26 +905,18 @@ module ActiveRecord
|
|
1138
905
|
# the inclusion of these columns doesn't invalidate the DISTINCT
|
1139
906
|
#
|
1140
907
|
# It does not construct DISTINCT clause. Just return column names for distinct.
|
1141
|
-
order_columns = orders.reject(&:blank?).map{ |s|
|
1142
|
-
|
1143
|
-
|
1144
|
-
|
1145
|
-
}.reject(&:blank?).map.with_index { |column,i|
|
908
|
+
order_columns = orders.reject(&:blank?).map { |s|
|
909
|
+
s = s.to_sql unless s.is_a?(String)
|
910
|
+
# remove any ASC/DESC modifiers
|
911
|
+
s.gsub(/\s+(ASC|DESC)\s*?/i, "")
|
912
|
+
}.reject(&:blank?).map.with_index { |column, i|
|
1146
913
|
"FIRST_VALUE(#{column}) OVER (PARTITION BY #{columns} ORDER BY #{column}) AS alias_#{i}__"
|
1147
914
|
}
|
1148
|
-
|
915
|
+
[super, *order_columns].join(", ")
|
1149
916
|
end
|
1150
917
|
|
1151
918
|
def temporary_table?(table_name) #:nodoc:
|
1152
|
-
select_value("SELECT temporary FROM all_tables WHERE table_name = '#{table_name.upcase}' and owner = SYS_CONTEXT('userenv', 'session_user')") ==
|
1153
|
-
end
|
1154
|
-
|
1155
|
-
# construct additional wrapper subquery if select.offset is used to avoid generation of invalid subquery
|
1156
|
-
# ... IN ( SELECT * FROM ( SELECT raw_sql_.*, rownum raw_rnum_ FROM ( ... ) raw_sql_ ) WHERE raw_rnum_ > ... )
|
1157
|
-
def join_to_update(update, select, key) #:nodoc:
|
1158
|
-
#TODO: Need to validate if we can remove join_to_update from Oracle enhanced adapter after testing
|
1159
|
-
# older version of Oracle 11gR2
|
1160
|
-
super
|
919
|
+
select_value("SELECT temporary FROM all_tables WHERE table_name = '#{table_name.upcase}' and owner = SYS_CONTEXT('userenv', 'session_user')") == "Y"
|
1161
920
|
end
|
1162
921
|
|
1163
922
|
def valid_type?(type)
|
@@ -1173,7 +932,7 @@ module ActiveRecord
|
|
1173
932
|
offset: nil
|
1174
933
|
) # :nodoc:
|
1175
934
|
result = from_clause + join_clause + where_clause + having_clause
|
1176
|
-
if RUBY_ENGINE ==
|
935
|
+
if RUBY_ENGINE == "jruby" && !supports_fetch_first_n_rows_and_offset? && offset && limit
|
1177
936
|
result << offset
|
1178
937
|
result << limit
|
1179
938
|
result << offset
|
@@ -1190,67 +949,71 @@ module ActiveRecord
|
|
1190
949
|
|
1191
950
|
protected
|
1192
951
|
|
1193
|
-
|
1194
|
-
|
1195
|
-
|
1196
|
-
|
1197
|
-
|
1198
|
-
|
1199
|
-
|
1200
|
-
|
1201
|
-
|
1202
|
-
|
1203
|
-
|
1204
|
-
|
1205
|
-
|
1206
|
-
|
1207
|
-
|
1208
|
-
|
1209
|
-
|
1210
|
-
|
952
|
+
def initialize_type_map(m)
|
953
|
+
super
|
954
|
+
# oracle
|
955
|
+
register_class_with_limit m, %r(raw)i, ActiveRecord::OracleEnhanced::Type::Raw
|
956
|
+
register_class_with_limit m, %r(char)i, ActiveRecord::OracleEnhanced::Type::String
|
957
|
+
register_class_with_limit m, %r(clob)i, ActiveRecord::OracleEnhanced::Type::Text
|
958
|
+
|
959
|
+
m.register_type "NCHAR", ActiveRecord::OracleEnhanced::Type::NationalCharacterString.new
|
960
|
+
m.alias_type %r(NVARCHAR2)i, "NCHAR"
|
961
|
+
|
962
|
+
m.register_type(%r(NUMBER)i) do |sql_type|
|
963
|
+
scale = extract_scale(sql_type)
|
964
|
+
precision = extract_precision(sql_type)
|
965
|
+
limit = extract_limit(sql_type)
|
966
|
+
if scale == 0
|
967
|
+
ActiveRecord::OracleEnhanced::Type::Integer.new(precision: precision, limit: limit)
|
968
|
+
else
|
969
|
+
Type::Decimal.new(precision: precision, scale: scale)
|
970
|
+
end
|
1211
971
|
end
|
1212
|
-
end
|
1213
972
|
|
1214
|
-
|
1215
|
-
|
1216
|
-
|
1217
|
-
|
1218
|
-
|
973
|
+
if OracleEnhancedAdapter.emulate_booleans
|
974
|
+
if OracleEnhancedAdapter.emulate_booleans_from_strings
|
975
|
+
m.register_type %r(^VARCHAR2\(1\))i, ActiveRecord::OracleEnhanced::Type::Boolean.new
|
976
|
+
else
|
977
|
+
m.register_type %r(^NUMBER\(1\))i, Type::Boolean.new
|
978
|
+
end
|
1219
979
|
end
|
1220
980
|
end
|
1221
|
-
end
|
1222
981
|
|
1223
|
-
|
1224
|
-
|
1225
|
-
|
1226
|
-
|
1227
|
-
|
1228
|
-
|
982
|
+
def extract_limit(sql_type) #:nodoc:
|
983
|
+
case sql_type
|
984
|
+
when /^bigint/i
|
985
|
+
19
|
986
|
+
when /\((.*)\)/
|
987
|
+
$1.to_i
|
988
|
+
end
|
1229
989
|
end
|
1230
|
-
end
|
1231
990
|
|
1232
|
-
|
1233
|
-
|
1234
|
-
|
1235
|
-
|
1236
|
-
|
1237
|
-
|
1238
|
-
|
1239
|
-
|
1240
|
-
|
1241
|
-
|
991
|
+
def translate_exception(exception, message) #:nodoc:
|
992
|
+
case @connection.error_code(exception)
|
993
|
+
when 1
|
994
|
+
RecordNotUnique.new(message)
|
995
|
+
when 942, 955, 1418
|
996
|
+
ActiveRecord::StatementInvalid.new(message)
|
997
|
+
when 1400
|
998
|
+
ActiveRecord::NotNullViolation.new(message)
|
999
|
+
when 2291
|
1000
|
+
InvalidForeignKey.new(message)
|
1001
|
+
when 12899
|
1002
|
+
ValueTooLong.new(message)
|
1003
|
+
else
|
1004
|
+
super
|
1005
|
+
end
|
1242
1006
|
end
|
1243
|
-
end
|
1244
1007
|
|
1245
1008
|
private
|
1246
1009
|
|
1247
|
-
|
1248
|
-
|
1249
|
-
|
1010
|
+
def oracle_downcase(column_name)
|
1011
|
+
@connection.oracle_downcase(column_name)
|
1012
|
+
end
|
1250
1013
|
|
1251
|
-
|
1252
|
-
|
1253
|
-
|
1014
|
+
def compress_lines(string, join_with = "\n")
|
1015
|
+
string.split($/).map { |line| line.strip }.join(join_with)
|
1016
|
+
end
|
1254
1017
|
|
1255
1018
|
public
|
1256
1019
|
# DBMS_OUTPUT =============================================
|
@@ -1280,84 +1043,84 @@ module ActiveRecord
|
|
1280
1043
|
end
|
1281
1044
|
|
1282
1045
|
protected
|
1283
|
-
|
1284
|
-
|
1285
|
-
|
1286
|
-
|
1287
|
-
|
1046
|
+
def log(sql, name = "SQL", binds = [], type_casted_binds = [], statement_name = nil)
|
1047
|
+
super
|
1048
|
+
ensure
|
1049
|
+
log_dbms_output if dbms_output_enabled?
|
1050
|
+
end
|
1288
1051
|
|
1289
1052
|
private
|
1290
1053
|
|
1291
|
-
|
1292
|
-
|
1293
|
-
|
1294
|
-
|
1295
|
-
|
1054
|
+
def set_dbms_output_plsql_connection
|
1055
|
+
raise OracleEnhancedConnectionException, "ruby-plsql gem is required for logging DBMS output" unless self.respond_to?(:plsql)
|
1056
|
+
# do not reset plsql connection if it is the same (as resetting will clear PL/SQL metadata cache)
|
1057
|
+
unless plsql(:dbms_output).connection && plsql(:dbms_output).connection.raw_connection == raw_connection
|
1058
|
+
plsql(:dbms_output).connection = raw_connection
|
1059
|
+
end
|
1296
1060
|
end
|
1297
|
-
end
|
1298
1061
|
|
1299
|
-
|
1300
|
-
|
1301
|
-
|
1302
|
-
|
1303
|
-
|
1062
|
+
def log_dbms_output
|
1063
|
+
while true do
|
1064
|
+
result = plsql(:dbms_output).sys.dbms_output.get_line(line: "", status: 0)
|
1065
|
+
break unless result[:status] == 0
|
1066
|
+
@logger.debug "DBMS_OUTPUT: #{result[:line]}" if @logger
|
1067
|
+
end
|
1304
1068
|
end
|
1305
|
-
end
|
1306
1069
|
end
|
1307
1070
|
end
|
1308
1071
|
end
|
1309
1072
|
|
1310
1073
|
# Implementation of standard schema definition statements and extensions for schema definition
|
1311
|
-
require
|
1312
|
-
require
|
1074
|
+
require "active_record/connection_adapters/oracle_enhanced/schema_statements"
|
1075
|
+
require "active_record/connection_adapters/oracle_enhanced/schema_statements_ext"
|
1313
1076
|
|
1314
1077
|
# Extensions for schema definition
|
1315
|
-
require
|
1078
|
+
require "active_record/connection_adapters/oracle_enhanced/schema_definitions"
|
1316
1079
|
|
1317
1080
|
# Extensions for context index definition
|
1318
|
-
require
|
1081
|
+
require "active_record/connection_adapters/oracle_enhanced/context_index"
|
1319
1082
|
|
1320
1083
|
# Load additional methods for composite_primary_keys support
|
1321
|
-
require
|
1084
|
+
require "active_record/connection_adapters/oracle_enhanced/cpk"
|
1322
1085
|
|
1323
1086
|
# Patches and enhancements for schema dumper
|
1324
|
-
require
|
1087
|
+
require "active_record/connection_adapters/oracle_enhanced/schema_dumper"
|
1325
1088
|
|
1326
1089
|
# Implementation of structure dump
|
1327
|
-
require
|
1090
|
+
require "active_record/connection_adapters/oracle_enhanced/structure_dump"
|
1328
1091
|
|
1329
|
-
require
|
1092
|
+
require "active_record/connection_adapters/oracle_enhanced/version"
|
1330
1093
|
|
1331
1094
|
module ActiveRecord
|
1332
|
-
autoload :OracleEnhancedProcedures,
|
1095
|
+
autoload :OracleEnhancedProcedures, "active_record/connection_adapters/oracle_enhanced/procedures"
|
1333
1096
|
end
|
1334
1097
|
|
1335
1098
|
# Patches and enhancements for column dumper
|
1336
|
-
require
|
1099
|
+
require "active_record/connection_adapters/oracle_enhanced/column_dumper"
|
1337
1100
|
|
1338
1101
|
# Moved SchemaCreation class
|
1339
|
-
require
|
1102
|
+
require "active_record/connection_adapters/oracle_enhanced/schema_creation"
|
1340
1103
|
|
1341
1104
|
# Moved DatabaseStetements
|
1342
|
-
require
|
1105
|
+
require "active_record/connection_adapters/oracle_enhanced/database_statements"
|
1343
1106
|
|
1344
1107
|
# Add Type:Raw
|
1345
|
-
require
|
1108
|
+
require "active_record/oracle_enhanced/type/raw"
|
1346
1109
|
|
1347
1110
|
# Add OracleEnhanced::Type::Integer
|
1348
|
-
require
|
1111
|
+
require "active_record/oracle_enhanced/type/integer"
|
1349
1112
|
|
1350
1113
|
# Add OracleEnhanced::Type::String
|
1351
|
-
require
|
1114
|
+
require "active_record/oracle_enhanced/type/string"
|
1352
1115
|
|
1353
1116
|
# Add OracleEnhanced::Type::NationalCharacterString
|
1354
|
-
require
|
1117
|
+
require "active_record/oracle_enhanced/type/national_character_string"
|
1355
1118
|
|
1356
1119
|
# Add OracleEnhanced::Type::Text
|
1357
|
-
require
|
1120
|
+
require "active_record/oracle_enhanced/type/text"
|
1358
1121
|
|
1359
1122
|
# Add OracleEnhanced::Type::Boolean
|
1360
|
-
require
|
1123
|
+
require "active_record/oracle_enhanced/type/boolean"
|
1361
1124
|
|
1362
1125
|
# To use :boolean type for Attribute API, each type needs registered explicitly.
|
1363
1126
|
ActiveRecord::Type.register(:boolean, ActiveRecord::OracleEnhanced::Type::Boolean, adapter: :oracleenhanced)
|