activerecord-oracle_enhanced-adapter 1.7.11 → 1.8.2

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.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +206 -4
  3. data/README.md +37 -1
  4. data/VERSION +1 -1
  5. data/lib/active_record/connection_adapters/emulation/oracle_adapter.rb +1 -1
  6. data/lib/active_record/connection_adapters/oracle_enhanced/column.rb +7 -59
  7. data/lib/active_record/connection_adapters/oracle_enhanced/column_dumper.rb +6 -50
  8. data/lib/active_record/connection_adapters/oracle_enhanced/connection.rb +11 -11
  9. data/lib/active_record/connection_adapters/oracle_enhanced/context_index.rb +117 -117
  10. data/lib/active_record/connection_adapters/oracle_enhanced/database_statements.rb +37 -27
  11. data/lib/active_record/connection_adapters/oracle_enhanced/database_tasks.rb +10 -10
  12. data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_connection.rb +56 -71
  13. data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_quoting.rb +0 -7
  14. data/lib/active_record/connection_adapters/oracle_enhanced/oci_connection.rb +51 -69
  15. data/lib/active_record/connection_adapters/oracle_enhanced/oci_quoting.rb +4 -4
  16. data/lib/active_record/connection_adapters/oracle_enhanced/procedures.rb +76 -76
  17. data/lib/active_record/connection_adapters/oracle_enhanced/quoting.rb +14 -43
  18. data/lib/active_record/connection_adapters/oracle_enhanced/schema_creation.rb +60 -64
  19. data/lib/active_record/connection_adapters/oracle_enhanced/schema_definitions.rb +33 -47
  20. data/lib/active_record/connection_adapters/oracle_enhanced/schema_dumper.rb +150 -160
  21. data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb +95 -133
  22. data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements_ext.rb +3 -3
  23. data/lib/active_record/connection_adapters/oracle_enhanced/structure_dump.rb +66 -101
  24. data/lib/active_record/connection_adapters/oracle_enhanced/version.rb +1 -1
  25. data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +290 -533
  26. data/lib/active_record/oracle_enhanced/type/boolean.rb +7 -10
  27. data/lib/active_record/oracle_enhanced/type/integer.rb +3 -4
  28. data/lib/active_record/oracle_enhanced/type/json.rb +8 -0
  29. data/lib/active_record/oracle_enhanced/type/national_character_string.rb +1 -1
  30. data/lib/active_record/oracle_enhanced/type/raw.rb +2 -3
  31. data/lib/active_record/oracle_enhanced/type/string.rb +2 -2
  32. data/lib/active_record/oracle_enhanced/type/text.rb +2 -2
  33. data/lib/active_record/oracle_enhanced/type/timestamptz.rb +23 -0
  34. data/lib/activerecord-oracle_enhanced-adapter.rb +2 -2
  35. data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +55 -162
  36. data/spec/active_record/connection_adapters/oracle_enhanced_connection_spec.rb +32 -34
  37. data/spec/active_record/connection_adapters/oracle_enhanced_context_index_spec.rb +44 -42
  38. data/spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb +250 -357
  39. data/spec/active_record/connection_adapters/oracle_enhanced_database_tasks_spec.rb +14 -6
  40. data/spec/active_record/connection_adapters/oracle_enhanced_dbms_output_spec.rb +3 -5
  41. data/spec/active_record/connection_adapters/oracle_enhanced_dirty_spec.rb +115 -124
  42. data/spec/active_record/connection_adapters/oracle_enhanced_emulate_oracle_adapter_spec.rb +2 -3
  43. data/spec/active_record/connection_adapters/oracle_enhanced_procedures_spec.rb +68 -72
  44. data/spec/active_record/connection_adapters/oracle_enhanced_schema_dump_spec.rb +64 -80
  45. data/spec/active_record/connection_adapters/oracle_enhanced_schema_statements_spec.rb +223 -329
  46. data/spec/active_record/connection_adapters/oracle_enhanced_structure_dump_spec.rb +18 -20
  47. data/spec/spec_config.yaml.template +11 -0
  48. data/spec/spec_helper.rb +59 -59
  49. data/spec/support/alter_system_user_password.sql +2 -0
  50. data/spec/support/create_oracle_enhanced_users.sql +31 -0
  51. metadata +25 -25
  52. data/.rspec +0 -2
  53. data/Gemfile +0 -22
  54. data/RUNNING_TESTS.md +0 -83
  55. data/Rakefile +0 -45
  56. data/activerecord-oracle_enhanced-adapter.gemspec +0 -94
  57. data/lib/active_record/connection_adapters/oracle_enhanced/cpk.rb +0 -19
  58. data/spec/active_record/connection_adapters/oracle_enhanced_cpk_spec.rb +0 -113
@@ -28,17 +28,18 @@
28
28
  # contribution.
29
29
  # portions Copyright 2005 Graham Jenkins
30
30
 
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'
31
+ require "active_record/connection_adapters/abstract_adapter"
32
+ require "active_record/connection_adapters/statement_pool"
33
+ require "active_record/connection_adapters/oracle_enhanced/connection"
34
+ require "active_record/connection_adapters/oracle_enhanced/database_statements"
35
+ require "active_record/connection_adapters/oracle_enhanced/schema_statements"
36
+ require "active_record/connection_adapters/oracle_enhanced/schema_statements_ext"
37
+ require "active_record/connection_adapters/oracle_enhanced/column_dumper"
38
+ require "active_record/connection_adapters/oracle_enhanced/context_index"
39
+ require "active_record/connection_adapters/oracle_enhanced/column"
40
+ require "active_record/connection_adapters/oracle_enhanced/quoting"
41
+
42
+ require "digest/sha1"
42
43
 
43
44
  ActiveRecord::Base.class_eval do
44
45
  class_attribute :custom_create_method, :custom_update_method, :custom_delete_method
@@ -46,89 +47,12 @@ end
46
47
 
47
48
  module ActiveRecord
48
49
  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
50
  def self.lob_columns
116
51
  columns.select do |column|
117
52
  column.respond_to?(:lob?) && column.lob?
118
53
  end
119
54
  end
120
55
 
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
56
  # After setting large objects to empty, select the OCI8::LOB
133
57
  # and write back the data.
134
58
  before_update :record_changed_lobs
@@ -136,21 +60,21 @@ module ActiveRecord
136
60
 
137
61
  private
138
62
 
139
- def enhanced_write_lobs
140
- if self.class.connection.is_a?(ConnectionAdapters::OracleEnhancedAdapter) &&
141
- !(
142
- (self.class.custom_create_method || self.class.custom_create_method) ||
143
- (self.class.custom_update_method || self.class.custom_update_method)
144
- )
145
- self.class.connection.write_lobs(self.class.table_name, self.class, attributes, @changed_lob_columns)
63
+ def enhanced_write_lobs
64
+ if self.class.connection.is_a?(ConnectionAdapters::OracleEnhancedAdapter) &&
65
+ !(
66
+ (self.class.custom_create_method || self.class.custom_create_method) ||
67
+ (self.class.custom_update_method || self.class.custom_update_method)
68
+ )
69
+ self.class.connection.write_lobs(self.class.table_name, self.class, attributes, @changed_lob_columns)
70
+ end
146
71
  end
147
- end
148
72
 
149
- def record_changed_lobs
150
- @changed_lob_columns = self.class.lob_columns.select do |col|
151
- self.attribute_changed?(col.name) && !self.class.readonly_attributes.to_a.include?(col.name)
73
+ def record_changed_lobs
74
+ @changed_lob_columns = self.class.lob_columns.select do |col|
75
+ self.attribute_changed?(col.name) && !self.class.readonly_attributes.to_a.include?(col.name)
76
+ end
152
77
  end
153
- end
154
78
  end
155
79
  end
156
80
 
@@ -161,7 +85,7 @@ module ActiveRecord
161
85
  if config[:emulate_oracle_adapter] == true
162
86
  # allows the enhanced adapter to look like the OracleAdapter. Useful to pick up
163
87
  # conditionals in the rails activerecord test suite
164
- require 'active_record/connection_adapters/emulation/oracle_adapter'
88
+ require "active_record/connection_adapters/emulation/oracle_adapter"
165
89
  ConnectionAdapters::OracleAdapter.new(
166
90
  ConnectionAdapters::OracleEnhancedConnection.create(config), logger, config)
167
91
  else
@@ -258,92 +182,16 @@ module ActiveRecord
258
182
 
259
183
  ##
260
184
  # :singleton-method:
261
- # By default, the OracleEnhancedAdapter will typecast all columns of type <tt>DATE</tt>
262
- # to Time or DateTime (if value is out of Time value range) value.
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:
185
+ # OracleEnhancedAdapter will use the default tablespace, but if you want specific types of
186
+ # objects to go into specific tablespaces, specify them like this in an initializer:
265
187
  #
266
- # ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.emulate_dates = true
188
+ # ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.default_tablespaces =
189
+ # {:clob => 'TS_LOB', :blob => 'TS_LOB', :index => 'TS_INDEX', :table => 'TS_DATA'}
267
190
  #
268
- # As this option can have side effects when unnecessary typecasting is done it is recommended
269
- # that Date columns are explicily defined with +set_date_columns+ method.
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.
191
+ # Using the :tablespace option where available (e.g create_table) will take precedence
192
+ # over these settings.
283
193
  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
194
+ self.default_tablespaces = {}
347
195
 
348
196
  ##
349
197
  # :singleton-method:
@@ -354,40 +202,6 @@ module ActiveRecord
354
202
  cattr_accessor :emulate_booleans_from_strings
355
203
  self.emulate_booleans_from_strings = false
356
204
 
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
205
  ##
392
206
  # :singleton-method:
393
207
  # By default, OracleEnhanced adapter will use Oracle12 visitor
@@ -399,44 +213,21 @@ module ActiveRecord
399
213
  cattr_accessor :use_old_oracle_visitor
400
214
  self.use_old_oracle_visitor = false
401
215
 
402
- class StatementPool
403
- include Enumerable
216
+ class StatementPool < ConnectionAdapters::StatementPool
217
+ private
404
218
 
405
- def initialize(connection, max = 300)
406
- @connection = connection
407
- @max = max
408
- @cache = {}
409
- end
410
-
411
- def each(&block); @cache.each(&block); end
412
- def key?(key); @cache.key?(key); end
413
- def [](key); @cache[key]; end
414
- def length; @cache.length; end
415
- def delete(key); @cache.delete(key); end
416
-
417
- def []=(sql, key)
418
- while @max <= @cache.size
419
- @cache.shift.last.close
420
- end
421
- @cache[sql] = key
422
- end
423
-
424
- def clear
425
- @cache.values.each do |cursor|
426
- cursor.close
219
+ def dealloc(stmt)
220
+ stmt.close
427
221
  end
428
- @cache.clear
429
- end
430
222
  end
431
223
 
432
224
  def initialize(connection, logger = nil, config = {}) # :nodoc:
433
225
  super(connection, logger, config)
434
- @quoted_column_names, @quoted_table_names = {}, {}
435
- @statements = StatementPool.new(connection, config.fetch(:statement_limit) { 250 })
226
+ @statements = StatementPool.new(self.class.type_cast_config_to_integer(config[:statement_limit]))
436
227
  @enable_dbms_output = false
437
228
  end
438
229
 
439
- ADAPTER_NAME = 'OracleEnhanced'.freeze
230
+ ADAPTER_NAME = "OracleEnhanced".freeze
440
231
 
441
232
  def adapter_name #:nodoc:
442
233
  ADAPTER_NAME
@@ -450,14 +241,6 @@ module ActiveRecord
450
241
  end
451
242
  end
452
243
 
453
- def supports_migrations? #:nodoc:
454
- true
455
- end
456
-
457
- def supports_primary_key? #:nodoc:
458
- true
459
- end
460
-
461
244
  def supports_savepoints? #:nodoc:
462
245
  true
463
246
  end
@@ -470,12 +253,16 @@ module ActiveRecord
470
253
  true
471
254
  end
472
255
 
256
+ def supports_foreign_keys_in_create?
257
+ supports_foreign_keys?
258
+ end
259
+
473
260
  def supports_views?
474
261
  true
475
262
  end
476
263
 
477
264
  def supports_fetch_first_n_rows_and_offset?
478
- if !use_old_oracle_visitor && @connection.database_version == [12,1]
265
+ if !use_old_oracle_visitor && @connection.database_version.first >= 12
479
266
  true
480
267
  else
481
268
  false
@@ -483,9 +270,7 @@ module ActiveRecord
483
270
  end
484
271
 
485
272
  def supports_datetime_with_precision?
486
- #TODO: Needs to consider to return false to keep old behaviour
487
- #to map :datetime as DATE
488
- @connection.database_version.first >= 9
273
+ true
489
274
  end
490
275
 
491
276
  def supports_comments?
@@ -496,47 +281,77 @@ module ActiveRecord
496
281
  @connection.database_version.to_s >= [11, 2].to_s
497
282
  end
498
283
 
284
+ def supports_virtual_columns?
285
+ @connection.database_version.first >= 11
286
+ end
287
+
288
+ def supports_json?
289
+ # No migration supported for :json type due to there is no `JSON` data type
290
+ # in Oracle Database itself.
291
+ #
292
+ # 1.Define :string or :text in migration
293
+ #
294
+ # create_table :test_posts, force: true do |t|
295
+ # t.string :title
296
+ # t.text :article
297
+ # end
298
+ #
299
+ # 2. Set :json attributes
300
+ #
301
+ # class TestPost < ActiveRecord::Base
302
+ # attribute :title, :json
303
+ # attribute :article, :json
304
+ # end
305
+ #
306
+ # 3. Add `is json` database constraints by running sql statements
307
+ #
308
+ # alter table test_posts add constraint test_posts_title_is_json check (title is json)
309
+ # alter table test_posts add constraint test_posts_article_is_json check (article is json)
310
+ #
311
+ @connection.database_version.first >= 12
312
+ end
313
+
499
314
  #:stopdoc:
500
315
  DEFAULT_NLS_PARAMETERS = {
501
- :nls_calendar => nil,
502
- :nls_comp => nil,
503
- :nls_currency => nil,
504
- :nls_date_format => 'YYYY-MM-DD HH24:MI:SS',
505
- :nls_date_language => nil,
506
- :nls_dual_currency => nil,
507
- :nls_iso_currency => nil,
508
- :nls_language => nil,
509
- :nls_length_semantics => 'CHAR',
510
- :nls_nchar_conv_excp => nil,
511
- :nls_numeric_characters => nil,
512
- :nls_sort => nil,
513
- :nls_territory => nil,
514
- :nls_timestamp_format => 'YYYY-MM-DD HH24:MI:SS:FF6',
515
- :nls_timestamp_tz_format => nil,
516
- :nls_time_format => nil,
517
- :nls_time_tz_format => nil
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
- :primary_key => "NUMBER(38) NOT NULL PRIMARY KEY",
523
- :string => { :name => "VARCHAR2", :limit => 255 },
524
- :text => { :name => "CLOB" },
525
- :integer => { :name => "NUMBER", :limit => 38 },
526
- :float => { :name => "BINARY_FLOAT" },
527
- :decimal => { :name => "DECIMAL" },
528
- :datetime => { :name => "TIMESTAMP" },
529
- :timestamp => { :name => "TIMESTAMP" },
530
- :time => { :name => "TIMESTAMP" },
531
- :date => { :name => "DATE" },
532
- :binary => { :name => "BLOB" },
533
- :boolean => { :name => "NUMBER", :limit => 1 },
534
- :raw => { :name => "RAW", :limit => 2000 },
535
- :bigint => { :name => "NUMBER", :limit => 19 }
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
- :boolean => { :name => "VARCHAR2", :limit => 1 }
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 = 'autogenerated'.freeze
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 and sequence_name
678
- # *Note*: Only primary key is implemented - sequence will be nil.
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
@@ -703,13 +517,7 @@ module ActiveRecord
703
517
 
704
518
  # Writes LOB values from attributes for specified columns
705
519
  def write_lobs(table_name, klass, attributes, columns) #:nodoc:
706
- # is class with composite primary key>
707
- is_with_cpk = klass.respond_to?(:composite?) && klass.composite?
708
- if is_with_cpk
709
- id = klass.primary_key.map {|pk| attributes[pk.to_s] }
710
- else
711
- id = quote(attributes[klass.primary_key])
712
- end
520
+ id = quote(attributes[klass.primary_key])
713
521
  columns.each do |col|
714
522
  value = attributes[col.name]
715
523
  # changed sequence of next two lines - should check if value is nil before converting to yaml
@@ -718,9 +526,8 @@ module ActiveRecord
718
526
  value = klass.attribute_types[col.name].serialize(value)
719
527
  end
720
528
  uncached do
721
- 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
- "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, 'Writable Large Object')
529
+ sql = "SELECT #{quote_column_name(col.name)} FROM #{quote_table_name(table_name)} WHERE #{quote_column_name(klass.primary_key)} = #{id} FOR UPDATE"
530
+ unless lob_record = select_one(sql, "Writable Large Object")
724
531
  raise ActiveRecord::RecordNotFound, "statement #{sql} returned no rows"
725
532
  end
726
533
  lob = lob_record[col.name]
@@ -731,6 +538,8 @@ module ActiveRecord
731
538
 
732
539
  # Current database name
733
540
  def current_database
541
+ select_value("SELECT SYS_CONTEXT('userenv', 'con_name') FROM dual")
542
+ rescue ActiveRecord::StatementInvalid
734
543
  select_value("SELECT SYS_CONTEXT('userenv', 'db_name') FROM dual")
735
544
  end
736
545
 
@@ -749,39 +558,40 @@ module ActiveRecord
749
558
  select_value("SELECT LOWER(default_tablespace) FROM user_users WHERE username = SYS_CONTEXT('userenv', 'current_schema')")
750
559
  end
751
560
 
752
- def tables(name = nil) #:nodoc:
753
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
754
- #tables currently returns both tables and views.
755
- This behavior is deprecated and will be changed with Rails 5.1 to only return tables.
756
- Use #data_sources instead.
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
561
+ def tables #:nodoc:
562
+ select_values(<<-SQL, "SCHEMA")
563
+ SELECT DECODE(table_name, UPPER(table_name), LOWER(table_name), table_name)
564
+ FROM all_tables WHERE owner = SYS_CONTEXT('userenv', 'current_schema') AND secondary = 'N'
565
+ SQL
766
566
  end
767
567
 
768
568
  def data_sources
769
- select_values(
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')
569
+ super
772
570
  end
773
571
 
774
572
  def table_exists?(table_name)
775
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
776
- #table_exists? currently checks both tables and views.
777
- This behavior is deprecated and will be changed with Rails 5.1 to only check tables.
778
- Use #data_source_exists? instead.
779
- MSG
780
-
781
- data_source_exists?(table_name)
573
+ table_name = table_name.to_s
574
+ if table_name.include?("@")
575
+ # db link is not table
576
+ false
577
+ else
578
+ default_owner = current_schema
579
+ end
580
+ real_name = ActiveRecord::ConnectionAdapters::OracleEnhanced::Quoting.valid_table_name?(table_name) ?
581
+ table_name.upcase : table_name
582
+ if real_name.include?(".")
583
+ table_owner, table_name = real_name.split(".")
584
+ else
585
+ table_owner, table_name = default_owner, real_name
586
+ end
587
+ select_values(<<-SQL, "SCHEMA").any?
588
+ SELECT owner, table_name
589
+ FROM all_tables
590
+ WHERE owner = '#{table_owner}'
591
+ AND table_name = q'[#{table_name}]'
592
+ SQL
782
593
  end
783
594
 
784
- # Will return true if database object exists (to be able to use also views and synonyms for ActiveRecord models)
785
595
  # Needs to consider how to support synonyms in Rails 5.1
786
596
  def data_source_exists?(table_name)
787
597
  (_owner, table_name, _db_link) = @connection.describe(table_name)
@@ -791,7 +601,7 @@ module ActiveRecord
791
601
  end
792
602
 
793
603
  def views # :nodoc:
794
- select_values("SELECT LOWER(view_name) FROM all_views WHERE owner = SYS_CONTEXT('userenv', 'session_user')")
604
+ select_values("SELECT LOWER(view_name) FROM all_views WHERE owner = SYS_CONTEXT('userenv', 'current_schema')")
795
605
  end
796
606
 
797
607
  def materialized_views #:nodoc:
@@ -806,7 +616,7 @@ module ActiveRecord
806
616
  (owner, table_name, db_link) = @connection.describe(table_name)
807
617
  unless all_schema_indexes
808
618
  default_tablespace_name = default_tablespace
809
- result = select_all(<<-SQL.strip.gsub(/\s+/, ' '))
619
+ result = select_all(<<-SQL.strip.gsub(/\s+/, " "))
810
620
  SELECT LOWER(i.table_name) AS table_name, LOWER(i.index_name) AS index_name, i.uniqueness,
811
621
  i.index_type, i.ityp_owner, i.ityp_name, i.parameters,
812
622
  LOWER(i.tablespace_name) AS tablespace_name,
@@ -831,10 +641,10 @@ module ActiveRecord
831
641
  result.each do |row|
832
642
  # have to keep track of indexes because above query returns dups
833
643
  # there is probably a better query we could figure out
834
- if current_index != row['index_name']
644
+ if current_index != row["index_name"]
835
645
  statement_parameters = nil
836
- if row['index_type'] == 'DOMAIN' && row['ityp_owner'] == 'CTXSYS' && row['ityp_name'] == 'CONTEXT'
837
- procedure_name = default_datastore_procedure(row['index_name'])
646
+ if row["index_type"] == "DOMAIN" && row["ityp_owner"] == "CTXSYS" && row["ityp_name"] == "CONTEXT"
647
+ procedure_name = default_datastore_procedure(row["index_name"])
838
648
  source = select_values(<<-SQL).join
839
649
  SELECT text
840
650
  FROM all_source#{db_link}
@@ -847,82 +657,36 @@ module ActiveRecord
847
657
  end
848
658
  end
849
659
  all_schema_indexes << OracleEnhanced::IndexDefinition.new(
850
- row['table_name'],
851
- row['index_name'],
852
- row['uniqueness'] == "UNIQUE",
660
+ row["table_name"],
661
+ row["index_name"],
662
+ row["uniqueness"] == "UNIQUE",
853
663
  [],
854
664
  nil,
855
665
  nil,
856
666
  nil,
857
- row['index_type'] == 'DOMAIN' ? "#{row['ityp_owner']}.#{row['ityp_name']}" : nil,
667
+ row["index_type"] == "DOMAIN" ? "#{row['ityp_owner']}.#{row['ityp_name']}" : nil,
858
668
  nil,
859
- row['parameters'],
669
+ row["parameters"],
860
670
  statement_parameters,
861
- row['tablespace_name'] == default_tablespace_name ? nil : row['tablespace_name'])
862
- current_index = row['index_name']
671
+ row["tablespace_name"] == default_tablespace_name ? nil : row["tablespace_name"])
672
+ current_index = row["index_name"]
863
673
  end
864
674
 
865
675
  # Functional index columns and virtual columns both get stored as column expressions,
866
676
  # but re-creating a virtual column index as an expression (instead of using the virtual column's name)
867
677
  # results in a ORA-54018 error. Thus, we only want the column expression value returned
868
678
  # when the column is not virtual.
869
- if row['column_expression'] && row['virtual_column'] != 'YES'
870
- all_schema_indexes.last.columns << row['column_expression']
679
+ if row["column_expression"] && row["virtual_column"] != "YES"
680
+ all_schema_indexes.last.columns << row["column_expression"]
871
681
  else
872
- all_schema_indexes.last.columns << row['column_name'].downcase
682
+ all_schema_indexes.last.columns << row["column_name"].downcase
873
683
  end
874
684
  end
875
685
  end
876
686
 
877
687
  # Return the indexes just for the requested table, since AR is structured that way
878
688
  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
689
+ all_schema_indexes.select { |i| i.table == table_name }
926
690
  end
927
691
 
928
692
  # check if table has primary key trigger with _pkt suffix
@@ -934,12 +698,12 @@ module ActiveRecord
934
698
  SELECT trigger_name
935
699
  FROM all_triggers#{db_link}
936
700
  WHERE owner = '#{owner}'
937
- AND trigger_name = '#{trigger_name}'
701
+ AND trigger_name = q'[#{trigger_name}]'
938
702
  AND table_owner = '#{owner}'
939
- AND table_name = '#{desc_table_name}'
703
+ AND table_name = q'[#{desc_table_name}]'
940
704
  AND status = 'ENABLED'
941
705
  SQL
942
- select_value(pkt_sql, 'Primary Key Trigger') ? true : false
706
+ select_value(pkt_sql, "Primary Key Trigger") ? true : false
943
707
  end
944
708
 
945
709
  ##
@@ -963,15 +727,13 @@ module ActiveRecord
963
727
 
964
728
  def columns_without_cache(table_name, name = nil) #:nodoc:
965
729
  table_name = table_name.to_s
966
- # get ignored_columns by original table name
967
- ignored_columns = ignored_table_columns(table_name)
968
730
 
969
731
  (owner, desc_table_name, db_link) = @connection.describe(table_name)
970
732
 
971
733
  # reset do_not_prefetch_primary_key cache for this table
972
734
  @@do_not_prefetch_primary_key[table_name] = nil
973
735
 
974
- table_cols = <<-SQL.strip.gsub(/\s+/, ' ')
736
+ table_cols = <<-SQL.strip.gsub(/\s+/, " ")
975
737
  SELECT cols.column_name AS name, cols.data_type AS sql_type,
976
738
  cols.data_default, cols.nullable, cols.virtual_column, cols.hidden_column,
977
739
  cols.data_type_owner AS sql_type_owner,
@@ -985,7 +747,7 @@ module ActiveRecord
985
747
  comments.comments as column_comment
986
748
  FROM all_tab_cols#{db_link} cols, all_col_comments#{db_link} comments
987
749
  WHERE cols.owner = '#{owner}'
988
- AND cols.table_name = '#{desc_table_name}'
750
+ AND cols.table_name = #{quote(desc_table_name)}
989
751
  AND cols.hidden_column = 'NO'
990
752
  AND cols.owner = comments.owner
991
753
  AND cols.table_name = comments.table_name
@@ -994,46 +756,44 @@ module ActiveRecord
994
756
  SQL
995
757
 
996
758
  # added deletion of ignored columns
997
- select_all(table_cols, name).to_a.delete_if do |row|
998
- ignored_columns && ignored_columns.include?(row['name'].downcase)
999
- end.map do |row|
1000
- limit, scale = row['limit'], row['scale']
759
+ select_all(table_cols, name).to_a.map do |row|
760
+ limit, scale = row["limit"], row["scale"]
1001
761
  if limit || scale
1002
- row['sql_type'] += "(#{(limit || 38).to_i}" + ((scale = scale.to_i) > 0 ? ",#{scale})" : ")")
762
+ row["sql_type"] += "(#{(limit || 38).to_i}" + ((scale = scale.to_i) > 0 ? ",#{scale})" : ")")
1003
763
  end
1004
764
 
1005
- if row['sql_type_owner']
1006
- row['sql_type'] = row['sql_type_owner'] + '.' + row['sql_type']
765
+ if row["sql_type_owner"]
766
+ row["sql_type"] = row["sql_type_owner"] + "." + row["sql_type"]
1007
767
  end
1008
768
 
1009
- is_virtual = row['virtual_column']=='YES'
769
+ is_virtual = row["virtual_column"] == "YES"
1010
770
 
1011
771
  # clean up odd default spacing from Oracle
1012
- if row['data_default'] && !is_virtual
1013
- row['data_default'].sub!(/^(.*?)\s*$/, '\1')
772
+ if row["data_default"] && !is_virtual
773
+ row["data_default"].sub!(/^(.*?)\s*$/, '\1')
1014
774
 
1015
775
  # If a default contains a newline these cleanup regexes need to
1016
776
  # match newlines.
1017
- row['data_default'].sub!(/^'(.*)'$/m, '\1')
1018
- row['data_default'] = nil if row['data_default'] =~ /^(null|empty_[bc]lob\(\))$/i
777
+ row["data_default"].sub!(/^'(.*)'$/m, '\1')
778
+ row["data_default"] = nil if row["data_default"] =~ /^(null|empty_[bc]lob\(\))$/i
1019
779
  # TODO: Needs better fix to fallback "N" to false
1020
- row['data_default'] = false if (row['data_default'] == "N" && OracleEnhancedAdapter.emulate_booleans_from_strings)
780
+ row["data_default"] = false if (row["data_default"] == "N" && OracleEnhancedAdapter.emulate_booleans_from_strings)
1021
781
  end
1022
782
 
1023
- type_metadata = fetch_type_metadata(row['sql_type'])
1024
- new_column(oracle_downcase(row['name']),
1025
- row['data_default'],
783
+ type_metadata = fetch_type_metadata(row["sql_type"])
784
+ new_column(oracle_downcase(row["name"]),
785
+ row["data_default"],
1026
786
  type_metadata,
1027
- row['nullable'] == 'Y',
787
+ row["nullable"] == "Y",
1028
788
  table_name,
1029
789
  is_virtual,
1030
790
  false,
1031
- row['column_comment']
791
+ row["column_comment"]
1032
792
  )
1033
793
  end
1034
794
  end
1035
795
 
1036
- def new_column(name, default, sql_type_metadata = nil, null = true, table_name = nil, virtual = false, returning_id = false,comment = nil) # :nodoc:
796
+ def new_column(name, default, sql_type_metadata = nil, null = true, table_name = nil, virtual = false, returning_id = false, comment = nil) # :nodoc:
1037
797
  OracleEnhancedColumn.new(name, default, sql_type_metadata, null, table_name, virtual, returning_id, comment)
1038
798
  end
1039
799
 
@@ -1061,7 +821,7 @@ module ActiveRecord
1061
821
 
1062
822
  # Find a table's primary key and sequence.
1063
823
  # *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:
824
+ def pk_and_sequence_for(table_name, owner = nil, desc_table_name = nil, db_link = nil) #:nodoc:
1065
825
  if @@cache_columns
1066
826
  @@pk_and_sequence_for_cache ||= {}
1067
827
  if @@pk_and_sequence_for_cache.key?(table_name)
@@ -1074,22 +834,22 @@ module ActiveRecord
1074
834
  end
1075
835
  end
1076
836
 
1077
- def pk_and_sequence_for_without_cache(table_name, owner=nil, desc_table_name=nil, db_link=nil) #:nodoc:
837
+ def pk_and_sequence_for_without_cache(table_name, owner = nil, desc_table_name = nil, db_link = nil) #:nodoc:
1078
838
  (owner, desc_table_name, db_link) = @connection.describe(table_name) unless owner
1079
839
 
1080
- seqs = select_values(<<-SQL.strip.gsub(/\s+/, ' '), 'Sequence')
840
+ seqs = select_values(<<-SQL.strip.gsub(/\s+/, " "), "Sequence")
1081
841
  select us.sequence_name
1082
842
  from all_sequences#{db_link} us
1083
843
  where us.sequence_owner = '#{owner}'
1084
- and us.sequence_name = '#{desc_table_name}_SEQ'
844
+ and us.sequence_name = upper(#{quote(default_sequence_name(desc_table_name))})
1085
845
  SQL
1086
846
 
1087
847
  # changed back from user_constraints to all_constraints for consistency
1088
- pks = select_values(<<-SQL.strip.gsub(/\s+/, ' '), 'Primary Key')
848
+ pks = select_values(<<-SQL.strip.gsub(/\s+/, " "), "Primary Key")
1089
849
  SELECT cc.column_name
1090
850
  FROM all_constraints#{db_link} c, all_cons_columns#{db_link} cc
1091
851
  WHERE c.owner = '#{owner}'
1092
- AND c.table_name = '#{desc_table_name}'
852
+ AND c.table_name = #{quote(desc_table_name)}
1093
853
  AND c.constraint_type = 'P'
1094
854
  AND cc.owner = c.owner
1095
855
  AND cc.constraint_name = c.constraint_name
@@ -1112,14 +872,14 @@ module ActiveRecord
1112
872
  pk_and_sequence && pk_and_sequence.first
1113
873
  end
1114
874
 
1115
- def has_primary_key?(table_name, owner=nil, desc_table_name=nil, db_link=nil) #:nodoc:
875
+ def has_primary_key?(table_name, owner = nil, desc_table_name = nil, db_link = nil) #:nodoc:
1116
876
  !pk_and_sequence_for(table_name, owner, desc_table_name, db_link).nil?
1117
877
  end
1118
878
 
1119
879
  def primary_keys(table_name) # :nodoc:
1120
880
  (owner, desc_table_name, db_link) = @connection.describe(table_name) unless owner
1121
881
 
1122
- pks = select_values(<<-SQL.strip_heredoc, 'Primary Keys')
882
+ pks = select_values(<<-SQL.strip_heredoc, "Primary Keys")
1123
883
  SELECT cc.column_name
1124
884
  FROM all_constraints#{db_link} c, all_cons_columns#{db_link} cc
1125
885
  WHERE c.owner = '#{owner}'
@@ -1129,7 +889,7 @@ module ActiveRecord
1129
889
  AND cc.constraint_name = c.constraint_name
1130
890
  order by cc.position
1131
891
  SQL
1132
- pks.map {|pk| oracle_downcase(pk)}
892
+ pks.map { |pk| oracle_downcase(pk) }
1133
893
  end
1134
894
 
1135
895
  def columns_for_distinct(columns, orders) #:nodoc:
@@ -1138,30 +898,18 @@ module ActiveRecord
1138
898
  # the inclusion of these columns doesn't invalidate the DISTINCT
1139
899
  #
1140
900
  # It does not construct DISTINCT clause. Just return column names for distinct.
1141
- order_columns = orders.reject(&:blank?).map{ |s|
1142
- s = s.to_sql unless s.is_a?(String)
1143
- # remove any ASC/DESC modifiers
1144
- s.gsub(/\s+(ASC|DESC)\s*?/i, '')
1145
- }.reject(&:blank?).map.with_index { |column,i|
901
+ order_columns = orders.reject(&:blank?).map { |s|
902
+ s = s.to_sql unless s.is_a?(String)
903
+ # remove any ASC/DESC modifiers
904
+ s.gsub(/\s+(ASC|DESC)\s*?/i, "")
905
+ }.reject(&:blank?).map.with_index { |column, i|
1146
906
  "FIRST_VALUE(#{column}) OVER (PARTITION BY #{columns} ORDER BY #{column}) AS alias_#{i}__"
1147
907
  }
1148
- [super, *order_columns].join(', ')
908
+ [super, *order_columns].join(", ")
1149
909
  end
1150
910
 
1151
911
  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')") == 'Y'
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
1161
- end
1162
-
1163
- def valid_type?(type)
1164
- !native_database_types[type].nil?
912
+ select_value("SELECT temporary FROM all_tables WHERE table_name = '#{table_name.upcase}' and owner = SYS_CONTEXT('userenv', 'session_user')") == "Y"
1165
913
  end
1166
914
 
1167
915
  def combine_bind_parameters(
@@ -1173,7 +921,7 @@ module ActiveRecord
1173
921
  offset: nil
1174
922
  ) # :nodoc:
1175
923
  result = from_clause + join_clause + where_clause + having_clause
1176
- if RUBY_ENGINE == 'jruby' && !supports_fetch_first_n_rows_and_offset? && offset && limit
924
+ if RUBY_ENGINE == "jruby" && !supports_fetch_first_n_rows_and_offset? && offset && limit
1177
925
  result << offset
1178
926
  result << limit
1179
927
  result << offset
@@ -1190,67 +938,72 @@ module ActiveRecord
1190
938
 
1191
939
  protected
1192
940
 
1193
- def initialize_type_map(m)
1194
- super
1195
- # oracle
1196
- register_class_with_limit m, %r(raw)i, ActiveRecord::OracleEnhanced::Type::Raw
1197
- register_class_with_limit m, %r(char)i, ActiveRecord::OracleEnhanced::Type::String
1198
- register_class_with_limit m, %r(clob)i, ActiveRecord::OracleEnhanced::Type::Text
1199
-
1200
- m.register_type 'NCHAR', ActiveRecord::OracleEnhanced::Type::NationalCharacterString.new
1201
- m.alias_type %r(NVARCHAR2)i, 'NCHAR'
1202
-
1203
- m.register_type(%r(NUMBER)i) do |sql_type|
1204
- scale = extract_scale(sql_type)
1205
- precision = extract_precision(sql_type)
1206
- limit = extract_limit(sql_type)
1207
- if scale == 0
1208
- ActiveRecord::OracleEnhanced::Type::Integer.new(precision: precision, limit: limit)
1209
- else
1210
- Type::Decimal.new(precision: precision, scale: scale)
941
+ def initialize_type_map(m)
942
+ super
943
+ # oracle
944
+ register_class_with_precision m, %r(ZONE)i, ActiveRecord::OracleEnhanced::Type::TimestampTz
945
+ register_class_with_limit m, %r(raw)i, ActiveRecord::OracleEnhanced::Type::Raw
946
+ register_class_with_limit m, %r(char)i, ActiveRecord::OracleEnhanced::Type::String
947
+ register_class_with_limit m, %r(clob)i, ActiveRecord::OracleEnhanced::Type::Text
948
+
949
+ m.register_type "NCHAR", ActiveRecord::OracleEnhanced::Type::NationalCharacterString.new
950
+ m.alias_type %r(NVARCHAR2)i, "NCHAR"
951
+
952
+ m.register_type(%r(NUMBER)i) do |sql_type|
953
+ scale = extract_scale(sql_type)
954
+ precision = extract_precision(sql_type)
955
+ limit = extract_limit(sql_type)
956
+ if scale == 0
957
+ ActiveRecord::OracleEnhanced::Type::Integer.new(precision: precision, limit: limit)
958
+ else
959
+ Type::Decimal.new(precision: precision, scale: scale)
960
+ end
1211
961
  end
1212
- end
1213
962
 
1214
- if OracleEnhancedAdapter.emulate_booleans
1215
- if OracleEnhancedAdapter.emulate_booleans_from_strings
1216
- m.register_type %r(^VARCHAR2\(1\))i, ActiveRecord::OracleEnhanced::Type::Boolean.new
1217
- else
1218
- m.register_type %r(^NUMBER\(1\))i, Type::Boolean.new
963
+ if OracleEnhancedAdapter.emulate_booleans
964
+ if OracleEnhancedAdapter.emulate_booleans_from_strings
965
+ m.register_type %r(^VARCHAR2\(1\))i, ActiveRecord::OracleEnhanced::Type::Boolean.new
966
+ else
967
+ m.register_type %r(^NUMBER\(1\))i, Type::Boolean.new
968
+ end
1219
969
  end
1220
970
  end
1221
- end
1222
971
 
1223
- def extract_limit(sql_type) #:nodoc:
1224
- case sql_type
1225
- when /^bigint/i
1226
- 19
1227
- when /\((.*)\)/
1228
- $1.to_i
972
+ def extract_limit(sql_type) #:nodoc:
973
+ case sql_type
974
+ when /^bigint/i
975
+ 19
976
+ when /\((.*)\)/
977
+ $1.to_i
978
+ end
1229
979
  end
1230
- end
1231
980
 
1232
- def translate_exception(exception, message) #:nodoc:
1233
- case @connection.error_code(exception)
1234
- when 1
1235
- RecordNotUnique.new(message)
1236
- when 2291
1237
- InvalidForeignKey.new(message)
1238
- when 12899
1239
- ValueTooLong.new(message)
1240
- else
1241
- super
981
+ def translate_exception(exception, message) #:nodoc:
982
+ case @connection.error_code(exception)
983
+ when 1
984
+ RecordNotUnique.new(message)
985
+ when 942, 955, 1418
986
+ ActiveRecord::StatementInvalid.new(message)
987
+ when 1400
988
+ ActiveRecord::NotNullViolation.new(message)
989
+ when 2291
990
+ InvalidForeignKey.new(message)
991
+ when 12899
992
+ ValueTooLong.new(message)
993
+ else
994
+ super
995
+ end
1242
996
  end
1243
- end
1244
997
 
1245
998
  private
1246
999
 
1247
- def oracle_downcase(column_name)
1248
- @connection.oracle_downcase(column_name)
1249
- end
1000
+ def oracle_downcase(column_name)
1001
+ @connection.oracle_downcase(column_name)
1002
+ end
1250
1003
 
1251
- def compress_lines(string, join_with = "\n")
1252
- string.split($/).map { |line| line.strip }.join(join_with)
1253
- end
1004
+ def compress_lines(string, join_with = "\n")
1005
+ string.split($/).map { |line| line.strip }.join(join_with)
1006
+ end
1254
1007
 
1255
1008
  public
1256
1009
  # DBMS_OUTPUT =============================================
@@ -1280,84 +1033,88 @@ module ActiveRecord
1280
1033
  end
1281
1034
 
1282
1035
  protected
1283
- def log(sql, name = "SQL", binds = [], statement_name = nil) #:nodoc:
1284
- super
1285
- ensure
1286
- log_dbms_output if dbms_output_enabled?
1287
- end
1036
+ def log(sql, name = "SQL", binds = [], type_casted_binds = [], statement_name = nil)
1037
+ super
1038
+ ensure
1039
+ log_dbms_output if dbms_output_enabled?
1040
+ end
1288
1041
 
1289
1042
  private
1290
1043
 
1291
- def set_dbms_output_plsql_connection
1292
- raise OracleEnhancedConnectionException, "ruby-plsql gem is required for logging DBMS output" unless self.respond_to?(:plsql)
1293
- # do not reset plsql connection if it is the same (as resetting will clear PL/SQL metadata cache)
1294
- unless plsql(:dbms_output).connection && plsql(:dbms_output).connection.raw_connection == raw_connection
1295
- plsql(:dbms_output).connection = raw_connection
1044
+ def set_dbms_output_plsql_connection
1045
+ raise OracleEnhancedConnectionException, "ruby-plsql gem is required for logging DBMS output" unless self.respond_to?(:plsql)
1046
+ # do not reset plsql connection if it is the same (as resetting will clear PL/SQL metadata cache)
1047
+ unless plsql(:dbms_output).connection && plsql(:dbms_output).connection.raw_connection == raw_connection
1048
+ plsql(:dbms_output).connection = raw_connection
1049
+ end
1296
1050
  end
1297
- end
1298
1051
 
1299
- def log_dbms_output
1300
- while true do
1301
- result = plsql(:dbms_output).sys.dbms_output.get_line(:line => '', :status => 0)
1302
- break unless result[:status] == 0
1303
- @logger.debug "DBMS_OUTPUT: #{result[:line]}" if @logger
1052
+ def log_dbms_output
1053
+ while true do
1054
+ result = plsql(:dbms_output).sys.dbms_output.get_line(line: "", status: 0)
1055
+ break unless result[:status] == 0
1056
+ @logger.debug "DBMS_OUTPUT: #{result[:line]}" if @logger
1057
+ end
1304
1058
  end
1305
- end
1306
1059
  end
1307
1060
  end
1308
1061
  end
1309
1062
 
1310
1063
  # Implementation of standard schema definition statements and extensions for schema definition
1311
- require 'active_record/connection_adapters/oracle_enhanced/schema_statements'
1312
- require 'active_record/connection_adapters/oracle_enhanced/schema_statements_ext'
1064
+ require "active_record/connection_adapters/oracle_enhanced/schema_statements"
1065
+ require "active_record/connection_adapters/oracle_enhanced/schema_statements_ext"
1313
1066
 
1314
1067
  # Extensions for schema definition
1315
- require 'active_record/connection_adapters/oracle_enhanced/schema_definitions'
1068
+ require "active_record/connection_adapters/oracle_enhanced/schema_definitions"
1316
1069
 
1317
1070
  # Extensions for context index definition
1318
- require 'active_record/connection_adapters/oracle_enhanced/context_index'
1319
-
1320
- # Load additional methods for composite_primary_keys support
1321
- require 'active_record/connection_adapters/oracle_enhanced/cpk'
1071
+ require "active_record/connection_adapters/oracle_enhanced/context_index"
1322
1072
 
1323
1073
  # Patches and enhancements for schema dumper
1324
- require 'active_record/connection_adapters/oracle_enhanced/schema_dumper'
1074
+ require "active_record/connection_adapters/oracle_enhanced/schema_dumper"
1325
1075
 
1326
1076
  # Implementation of structure dump
1327
- require 'active_record/connection_adapters/oracle_enhanced/structure_dump'
1077
+ require "active_record/connection_adapters/oracle_enhanced/structure_dump"
1328
1078
 
1329
- require 'active_record/connection_adapters/oracle_enhanced/version'
1079
+ require "active_record/connection_adapters/oracle_enhanced/version"
1330
1080
 
1331
1081
  module ActiveRecord
1332
- autoload :OracleEnhancedProcedures, 'active_record/connection_adapters/oracle_enhanced/procedures'
1082
+ autoload :OracleEnhancedProcedures, "active_record/connection_adapters/oracle_enhanced/procedures"
1333
1083
  end
1334
1084
 
1335
1085
  # Patches and enhancements for column dumper
1336
- require 'active_record/connection_adapters/oracle_enhanced/column_dumper'
1086
+ require "active_record/connection_adapters/oracle_enhanced/column_dumper"
1337
1087
 
1338
1088
  # Moved SchemaCreation class
1339
- require 'active_record/connection_adapters/oracle_enhanced/schema_creation'
1089
+ require "active_record/connection_adapters/oracle_enhanced/schema_creation"
1340
1090
 
1341
1091
  # Moved DatabaseStetements
1342
- require 'active_record/connection_adapters/oracle_enhanced/database_statements'
1092
+ require "active_record/connection_adapters/oracle_enhanced/database_statements"
1343
1093
 
1344
1094
  # Add Type:Raw
1345
- require 'active_record/oracle_enhanced/type/raw'
1095
+ require "active_record/oracle_enhanced/type/raw"
1346
1096
 
1347
1097
  # Add OracleEnhanced::Type::Integer
1348
- require 'active_record/oracle_enhanced/type/integer'
1098
+ require "active_record/oracle_enhanced/type/integer"
1349
1099
 
1350
1100
  # Add OracleEnhanced::Type::String
1351
- require 'active_record/oracle_enhanced/type/string'
1101
+ require "active_record/oracle_enhanced/type/string"
1352
1102
 
1353
1103
  # Add OracleEnhanced::Type::NationalCharacterString
1354
- require 'active_record/oracle_enhanced/type/national_character_string'
1104
+ require "active_record/oracle_enhanced/type/national_character_string"
1355
1105
 
1356
1106
  # Add OracleEnhanced::Type::Text
1357
- require 'active_record/oracle_enhanced/type/text'
1107
+ require "active_record/oracle_enhanced/type/text"
1358
1108
 
1359
1109
  # Add OracleEnhanced::Type::Boolean
1360
- require 'active_record/oracle_enhanced/type/boolean'
1110
+ require "active_record/oracle_enhanced/type/boolean"
1361
1111
 
1362
1112
  # To use :boolean type for Attribute API, each type needs registered explicitly.
1363
1113
  ActiveRecord::Type.register(:boolean, ActiveRecord::OracleEnhanced::Type::Boolean, adapter: :oracleenhanced)
1114
+
1115
+ # Add JSON attribute support
1116
+ require "active_record/oracle_enhanced/type/json"
1117
+ ActiveRecord::Type.register(:json, ActiveRecord::OracleEnhanced::Type::Json, adapter: :oracleenhanced)
1118
+
1119
+ # Add Type:TimestampTz
1120
+ require "active_record/oracle_enhanced/type/timestamptz"