activerecord-oracle_enhanced-adapter 5.2.8 → 6.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
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