activerecord-oracle_enhanced-adapter 5.2.8 → 6.0.0.beta1

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