activerecord-oracle_enhanced-adapter 6.1.4 → 7.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +78 -0
  3. data/README.md +12 -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 +2 -2
  7. data/lib/active_record/connection_adapters/oracle_enhanced/connection.rb +22 -13
  8. data/lib/active_record/connection_adapters/oracle_enhanced/context_index.rb +3 -3
  9. data/lib/active_record/connection_adapters/oracle_enhanced/database_limits.rb +1 -1
  10. data/lib/active_record/connection_adapters/oracle_enhanced/database_statements.rb +19 -22
  11. data/lib/active_record/connection_adapters/oracle_enhanced/dbms_output.rb +1 -1
  12. data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_connection.rb +14 -8
  13. data/lib/active_record/connection_adapters/oracle_enhanced/jdbc_quoting.rb +1 -1
  14. data/lib/active_record/connection_adapters/oracle_enhanced/lob.rb +4 -4
  15. data/lib/active_record/connection_adapters/oracle_enhanced/oci_connection.rb +18 -18
  16. data/lib/active_record/connection_adapters/oracle_enhanced/oci_quoting.rb +1 -1
  17. data/lib/active_record/connection_adapters/oracle_enhanced/procedures.rb +6 -6
  18. data/lib/active_record/connection_adapters/oracle_enhanced/quoting.rb +16 -16
  19. data/lib/active_record/connection_adapters/oracle_enhanced/schema_creation.rb +1 -1
  20. data/lib/active_record/connection_adapters/oracle_enhanced/schema_definitions.rb +1 -1
  21. data/lib/active_record/connection_adapters/oracle_enhanced/schema_dumper.rb +6 -6
  22. data/lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb +37 -27
  23. data/lib/active_record/connection_adapters/oracle_enhanced/structure_dump.rb +30 -29
  24. data/lib/active_record/connection_adapters/oracle_enhanced/type_metadata.rb +1 -1
  25. data/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb +123 -98
  26. data/lib/arel/visitors/oracle.rb +6 -2
  27. data/lib/arel/visitors/oracle12.rb +4 -0
  28. data/spec/active_record/connection_adapters/oracle_enhanced/connection_spec.rb +18 -1
  29. data/spec/active_record/connection_adapters/oracle_enhanced/context_index_spec.rb +2 -2
  30. data/spec/active_record/connection_adapters/oracle_enhanced/procedures_spec.rb +5 -5
  31. data/spec/active_record/connection_adapters/oracle_enhanced/schema_dumper_spec.rb +3 -3
  32. data/spec/active_record/connection_adapters/oracle_enhanced/schema_statements_spec.rb +5 -5
  33. data/spec/active_record/connection_adapters/oracle_enhanced/structure_dump_spec.rb +10 -10
  34. data/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb +34 -7
  35. data/spec/active_record/connection_adapters/oracle_enhanced_data_types_spec.rb +5 -5
  36. data/spec/active_record/oracle_enhanced/type/custom_spec.rb +88 -0
  37. data/spec/active_record/oracle_enhanced/type/timestamp_spec.rb +2 -2
  38. metadata +22 -6
@@ -8,25 +8,25 @@ module ActiveRecord
8
8
  #
9
9
  # see: abstract/quoting.rb
10
10
 
11
- def quote_column_name(name) #:nodoc:
11
+ def quote_column_name(name) # :nodoc:
12
12
  name = name.to_s
13
- self.class.quoted_column_names[name] ||= if /\A[a-z][a-z_0-9\$#]*\Z/.match?(name)
13
+ self.class.quoted_column_names[name] ||= if /\A[a-z][a-z_0-9$#]*\Z/.match?(name)
14
14
  "\"#{name.upcase}\""
15
15
  else
16
16
  # remove double quotes which cannot be used inside quoted identifier
17
- "\"#{name.gsub('"', '')}\""
17
+ "\"#{name.delete('"')}\""
18
18
  end
19
19
  end
20
20
 
21
21
  # This method is used in add_index to identify either column name (which is quoted)
22
22
  # or function based index (in which case function expression is not quoted)
23
- def quote_column_name_or_expression(name) #:nodoc:
23
+ def quote_column_name_or_expression(name) # :nodoc:
24
24
  name = name.to_s
25
25
  case name
26
26
  # if only valid lowercase column characters in name
27
- when /^[a-z][a-z_0-9\$#]*$/
27
+ when /^[a-z][a-z_0-9$#]*$/
28
28
  "\"#{name.upcase}\""
29
- when /^[a-z][a-z_0-9\$#\-]*$/i
29
+ when /^[a-z][a-z_0-9$#\-]*$/i
30
30
  "\"#{name}\""
31
31
  # if other characters present then assume that it is expression
32
32
  # which should not be quoted
@@ -55,7 +55,7 @@ module ActiveRecord
55
55
  # contain letters, digits, _, $ or #
56
56
  # can be prefixed with schema name
57
57
  # CamelCase table names should be quoted
58
- def self.valid_table_name?(name) #:nodoc:
58
+ def self.valid_table_name?(name) # :nodoc:
59
59
  object_name = name.to_s
60
60
  !!(object_name =~ VALID_TABLE_NAME && !mixed_case?(object_name))
61
61
  end
@@ -65,16 +65,16 @@ module ActiveRecord
65
65
  !!(object_name =~ /[A-Z]/ && object_name =~ /[a-z]/)
66
66
  end
67
67
 
68
- def quote_table_name(name) #:nodoc:
68
+ def quote_table_name(name) # :nodoc:
69
69
  name, _link = name.to_s.split("@")
70
70
  self.class.quoted_table_names[name] ||= [name.split(".").map { |n| quote_column_name(n) }].join(".")
71
71
  end
72
72
 
73
- def quote_string(s) #:nodoc:
73
+ def quote_string(s) # :nodoc:
74
74
  s.gsub(/'/, "''")
75
75
  end
76
76
 
77
- def _quote(value) #:nodoc:
77
+ def quote(value) # :nodoc:
78
78
  case value
79
79
  when Type::OracleEnhanced::CharacterString::Data then
80
80
  "'#{quote_string(value.to_s)}'"
@@ -91,31 +91,31 @@ module ActiveRecord
91
91
  end
92
92
  end
93
93
 
94
- def quoted_true #:nodoc:
94
+ def quoted_true # :nodoc:
95
95
  return "'Y'" if emulate_booleans_from_strings
96
96
  "1"
97
97
  end
98
98
 
99
- def unquoted_true #:nodoc:
99
+ def unquoted_true # :nodoc:
100
100
  return "Y" if emulate_booleans_from_strings
101
101
  "1"
102
102
  end
103
103
 
104
- def quoted_false #:nodoc:
104
+ def quoted_false # :nodoc:
105
105
  return "'N'" if emulate_booleans_from_strings
106
106
  "0"
107
107
  end
108
108
 
109
- def unquoted_false #:nodoc:
109
+ def unquoted_false # :nodoc:
110
110
  return "N" if emulate_booleans_from_strings
111
111
  "0"
112
112
  end
113
113
 
114
- def _type_cast(value)
114
+ def type_cast(value)
115
115
  case value
116
116
  when Type::OracleEnhanced::TimestampTz::Data, Type::OracleEnhanced::TimestampLtz::Data
117
117
  if value.acts_like?(:time)
118
- zone_conversion_method = ActiveRecord::Base.default_timezone == :utc ? :getutc : :getlocal
118
+ zone_conversion_method = ActiveRecord.default_timezone == :utc ? :getutc : :getlocal
119
119
  value.respond_to?(zone_conversion_method) ? value.send(zone_conversion_method) : value
120
120
  else
121
121
  value
@@ -21,7 +21,7 @@ module ActiveRecord
21
21
  statements << accept(o.primary_keys) if o.primary_keys
22
22
 
23
23
  if supports_foreign_keys?
24
- statements.concat(o.foreign_keys.map { |to_table, options| foreign_key_in_create(o.name, to_table, options) })
24
+ statements.concat(o.foreign_keys.map { |fk| accept fk })
25
25
  end
26
26
 
27
27
  create_sql << "(#{statements.join(', ')})" if statements.present?
@@ -35,7 +35,7 @@ module ActiveRecord
35
35
  end
36
36
  end
37
37
 
38
- class SynonymDefinition < Struct.new(:name, :table_owner, :table_name) #:nodoc:
38
+ class SynonymDefinition < Struct.new(:name, :table_owner, :table_name) # :nodoc:
39
39
  end
40
40
 
41
41
  class IndexDefinition < ActiveRecord::ConnectionAdapters::IndexDefinition
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module ActiveRecord #:nodoc:
4
- module ConnectionAdapters #:nodoc:
5
- module OracleEnhanced #:nodoc:
6
- class SchemaDumper < ConnectionAdapters::SchemaDumper #:nodoc:
3
+ module ActiveRecord # :nodoc:
4
+ module ConnectionAdapters # :nodoc:
5
+ module OracleEnhanced # :nodoc:
6
+ class SchemaDumper < ConnectionAdapters::SchemaDumper # :nodoc:
7
7
  DEFAULT_PRIMARY_KEY_COLUMN_SPEC = { precision: "38", null: "false" }.freeze
8
8
  private_constant :DEFAULT_PRIMARY_KEY_COLUMN_SPEC
9
9
 
@@ -47,7 +47,7 @@ module ActiveRecord #:nodoc:
47
47
 
48
48
  def _indexes(table, stream)
49
49
  if (indexes = @connection.indexes(table)).any?
50
- add_index_statements = indexes.map do |index|
50
+ add_index_statements = indexes.filter_map do |index|
51
51
  case index.type
52
52
  when nil
53
53
  # do nothing here. see indexes_in_create
@@ -67,7 +67,7 @@ module ActiveRecord #:nodoc:
67
67
  statement_parts = ["# unrecognized index #{index.name.inspect} with type #{index.type.inspect}"]
68
68
  end
69
69
  " " + statement_parts.join(", ") unless statement_parts.empty?
70
- end.compact
70
+ end
71
71
 
72
72
  return if add_index_statements.empty?
73
73
 
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "digest/sha1"
3
+ require "openssl"
4
4
 
5
5
  module ActiveRecord
6
6
  module ConnectionAdapters
@@ -10,7 +10,7 @@ module ActiveRecord
10
10
  #
11
11
  # see: abstract/schema_statements.rb
12
12
 
13
- def tables #:nodoc:
13
+ def tables # :nodoc:
14
14
  select_values(<<~SQL.squish, "SCHEMA")
15
15
  SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */
16
16
  DECODE(table_name, UPPER(table_name), LOWER(table_name), table_name)
@@ -66,7 +66,7 @@ module ActiveRecord
66
66
  SQL
67
67
  end
68
68
 
69
- def materialized_views #:nodoc:
69
+ def materialized_views # :nodoc:
70
70
  select_values(<<~SQL.squish, "SCHEMA")
71
71
  SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */
72
72
  LOWER(mview_name) FROM all_mviews WHERE owner = SYS_CONTEXT('userenv', 'current_schema')
@@ -86,7 +86,7 @@ module ActiveRecord
86
86
  end
87
87
  end
88
88
 
89
- def indexes(table_name) #:nodoc:
89
+ def indexes(table_name) # :nodoc:
90
90
  (_owner, table_name) = @connection.describe(table_name)
91
91
  default_tablespace_name = default_tablespace
92
92
 
@@ -252,7 +252,7 @@ module ActiveRecord
252
252
  rebuild_primary_key_index_to_default_tablespace(table_name, options)
253
253
  end
254
254
 
255
- def rename_table(table_name, new_name) #:nodoc:
255
+ def rename_table(table_name, new_name) # :nodoc:
256
256
  if new_name.to_s.length > DatabaseLimits::IDENTIFIER_MAX_LENGTH
257
257
  raise ArgumentError, "New table name '#{new_name}' is too long; the limit is #{DatabaseLimits::IDENTIFIER_MAX_LENGTH} characters"
258
258
  end
@@ -264,7 +264,7 @@ module ActiveRecord
264
264
  rename_table_indexes(table_name, new_name)
265
265
  end
266
266
 
267
- def drop_table(table_name, **options) #:nodoc:
267
+ def drop_table(table_name, **options) # :nodoc:
268
268
  schema_cache.clear_data_source_cache!(table_name.to_s)
269
269
  execute "DROP TABLE #{quote_table_name(table_name)}#{' CASCADE CONSTRAINTS' if options[:force] == :cascade}"
270
270
  seq_name = options[:sequence_name] || default_sequence_name(table_name)
@@ -295,7 +295,7 @@ module ActiveRecord
295
295
  end
296
296
  end
297
297
 
298
- def add_index(table_name, column_name, **options) #:nodoc:
298
+ def add_index(table_name, column_name, **options) # :nodoc:
299
299
  index_name, index_type, quoted_column_names, tablespace, index_options = add_index_options(table_name, column_name, **options)
300
300
  execute "CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} (#{quoted_column_names})#{tablespace} #{index_options}"
301
301
  if index_type == "UNIQUE"
@@ -305,7 +305,7 @@ module ActiveRecord
305
305
  end
306
306
  end
307
307
 
308
- def add_index_options(table_name, column_name, comment: nil, **options) #:nodoc:
308
+ def add_index_options(table_name, column_name, comment: nil, **options) # :nodoc:
309
309
  column_names = Array(column_name)
310
310
  index_name = index_name(table_name, column: column_names)
311
311
 
@@ -329,7 +329,9 @@ module ActiveRecord
329
329
 
330
330
  # Remove the given index from the table.
331
331
  # Gives warning if index does not exist
332
- def remove_index(table_name, column_name = nil, **options) #:nodoc:
332
+ def remove_index(table_name, column_name = nil, **options) # :nodoc:
333
+ return if options[:if_exists] && !index_exists?(table_name, column_name, **options)
334
+
333
335
  index_name = index_name_for_remove(table_name, column_name, options)
334
336
  # TODO: It should execute only when index_type == "UNIQUE"
335
337
  execute "ALTER TABLE #{quote_table_name(table_name)} DROP CONSTRAINT #{quote_column_name(index_name)}" rescue nil
@@ -337,7 +339,7 @@ module ActiveRecord
337
339
  end
338
340
 
339
341
  # returned shortened index name if default is too large
340
- def index_name(table_name, options) #:nodoc:
342
+ def index_name(table_name, options) # :nodoc:
341
343
  default_name = super(table_name, options).to_s
342
344
  # sometimes options can be String or Array with column names
343
345
  options = {} unless options.is_a?(Hash)
@@ -353,7 +355,7 @@ module ActiveRecord
353
355
  end
354
356
  # generate unique name using hash function
355
357
  if shortened_name.length > identifier_max_length
356
- shortened_name = "i" + Digest::SHA1.hexdigest(default_name)[0, identifier_max_length - 1]
358
+ shortened_name = "i" + OpenSSL::Digest::SHA1.hexdigest(default_name)[0, identifier_max_length - 1]
357
359
  end
358
360
  @logger.warn "#{adapter_name} shortened default index name #{default_name} to #{shortened_name}" if @logger
359
361
  shortened_name
@@ -367,17 +369,17 @@ module ActiveRecord
367
369
  # Will always query database and not index cache.
368
370
  def index_name_exists?(table_name, index_name)
369
371
  (_owner, table_name) = @connection.describe(table_name)
370
- result = select_value(<<~SQL.squish, "SCHEMA")
372
+ result = select_value(<<~SQL.squish, "SCHEMA", [bind_string("table_name", table_name), bind_string("index_name", index_name.to_s.upcase)])
371
373
  SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ 1 FROM all_indexes i
372
374
  WHERE i.owner = SYS_CONTEXT('userenv', 'current_schema')
373
375
  AND i.table_owner = SYS_CONTEXT('userenv', 'current_schema')
374
- AND i.table_name = '#{table_name}'
375
- AND i.index_name = '#{index_name.to_s.upcase}'
376
+ AND i.table_name = :table_name
377
+ AND i.index_name = :index_name
376
378
  SQL
377
379
  result == 1
378
380
  end
379
381
 
380
- def rename_index(table_name, old_name, new_name) #:nodoc:
382
+ def rename_index(table_name, old_name, new_name) # :nodoc:
381
383
  validate_index_length!(table_name, new_name)
382
384
  execute "ALTER INDEX #{quote_column_name(old_name)} rename to #{quote_column_name(new_name)}"
383
385
  end
@@ -412,7 +414,7 @@ module ActiveRecord
412
414
  OracleEnhanced::ReferenceDefinition.new(ref_name, **options).add_to(update_table_definition(table_name, self))
413
415
  end
414
416
 
415
- def add_column(table_name, column_name, type, **options) #:nodoc:
417
+ def add_column(table_name, column_name, type, **options) # :nodoc:
416
418
  type = aliased_types(type.to_s, type)
417
419
  at = create_alter_table table_name
418
420
  at.add_column(column_name, type, **options)
@@ -429,14 +431,14 @@ module ActiveRecord
429
431
  fallback
430
432
  end
431
433
 
432
- def change_column_default(table_name, column_name, default_or_changes) #:nodoc:
434
+ def change_column_default(table_name, column_name, default_or_changes) # :nodoc:
433
435
  default = extract_new_default_value(default_or_changes)
434
436
  execute "ALTER TABLE #{quote_table_name(table_name)} MODIFY #{quote_column_name(column_name)} DEFAULT #{quote(default)}"
435
437
  ensure
436
438
  clear_table_columns_cache(table_name)
437
439
  end
438
440
 
439
- def change_column_null(table_name, column_name, null, default = nil) #:nodoc:
441
+ def change_column_null(table_name, column_name, null, default = nil) # :nodoc:
440
442
  column = column_for(table_name, column_name)
441
443
 
442
444
  unless null || default.nil?
@@ -446,7 +448,7 @@ module ActiveRecord
446
448
  change_column table_name, column_name, column.sql_type, null: null
447
449
  end
448
450
 
449
- def change_column(table_name, column_name, type, **options) #:nodoc:
451
+ def change_column(table_name, column_name, type, **options) # :nodoc:
450
452
  column = column_for(table_name, column_name)
451
453
 
452
454
  # remove :null option if its value is the same as current column definition
@@ -470,19 +472,27 @@ module ActiveRecord
470
472
  clear_table_columns_cache(table_name)
471
473
  end
472
474
 
473
- def rename_column(table_name, column_name, new_column_name) #:nodoc:
475
+ def rename_column(table_name, column_name, new_column_name) # :nodoc:
474
476
  execute "ALTER TABLE #{quote_table_name(table_name)} RENAME COLUMN #{quote_column_name(column_name)} to #{quote_column_name(new_column_name)}"
475
477
  rename_column_indexes(table_name, column_name, new_column_name)
476
478
  ensure
477
479
  clear_table_columns_cache(table_name)
478
480
  end
479
481
 
480
- def remove_column(table_name, column_name, type = nil, options = {}) #:nodoc:
482
+ def remove_column(table_name, column_name, type = nil, options = {}) # :nodoc:
481
483
  execute "ALTER TABLE #{quote_table_name(table_name)} DROP COLUMN #{quote_column_name(column_name)} CASCADE CONSTRAINTS"
482
484
  ensure
483
485
  clear_table_columns_cache(table_name)
484
486
  end
485
487
 
488
+ def remove_columns(table_name, *column_names, type: nil, **options) # :nodoc:
489
+ quoted_column_names = column_names.map { |column_name| quote_column_name(column_name) }.join(", ")
490
+
491
+ execute "ALTER TABLE #{quote_table_name(table_name)} DROP (#{quoted_column_names}) CASCADE CONSTRAINTS"
492
+ ensure
493
+ clear_table_columns_cache(table_name)
494
+ end
495
+
486
496
  def change_table_comment(table_name, comment_or_changes)
487
497
  clear_cache!
488
498
  comment = extract_new_comment_value(comment_or_changes)
@@ -499,7 +509,7 @@ module ActiveRecord
499
509
  execute "COMMENT ON COLUMN #{quote_table_name(table_name)}.#{quote_column_name(column_name)} IS '#{comment}'"
500
510
  end
501
511
 
502
- def table_comment(table_name) #:nodoc:
512
+ def table_comment(table_name) # :nodoc:
503
513
  # TODO
504
514
  (_owner, table_name) = @connection.describe(table_name)
505
515
  select_value(<<~SQL.squish, "SCHEMA", [bind_string("table_name", table_name)])
@@ -515,7 +525,7 @@ module ActiveRecord
515
525
  end
516
526
  end
517
527
 
518
- def column_comment(table_name, column_name) #:nodoc:
528
+ def column_comment(table_name, column_name) # :nodoc:
519
529
  # TODO: it does not exist in Abstract adapter
520
530
  (_owner, table_name) = @connection.describe(table_name)
521
531
  select_value(<<~SQL.squish, "SCHEMA", [bind_string("table_name", table_name), bind_string("column_name", column_name.upcase)])
@@ -527,7 +537,7 @@ module ActiveRecord
527
537
  end
528
538
 
529
539
  # Maps logical Rails types to Oracle-specific data types.
530
- def type_to_sql(type, limit: nil, precision: nil, scale: nil, **) #:nodoc:
540
+ def type_to_sql(type, limit: nil, precision: nil, scale: nil, **) # :nodoc:
531
541
  # Ignore options for :text, :ntext and :binary columns
532
542
  return super(type) if ["text", "ntext", "binary"].include?(type.to_s)
533
543
 
@@ -544,7 +554,7 @@ module ActiveRecord
544
554
  end
545
555
 
546
556
  # get table foreign keys for schema dump
547
- def foreign_keys(table_name) #:nodoc:
557
+ def foreign_keys(table_name) # :nodoc:
548
558
  (_owner, desc_table_name) = @connection.describe(table_name)
549
559
 
550
560
  fk_info = select_all(<<~SQL.squish, "SCHEMA", [bind_string("desc_table_name", desc_table_name)])
@@ -588,7 +598,7 @@ module ActiveRecord
588
598
 
589
599
  # REFERENTIAL INTEGRITY ====================================
590
600
 
591
- def disable_referential_integrity(&block) #:nodoc:
601
+ def disable_referential_integrity(&block) # :nodoc:
592
602
  old_constraints = select_all(<<~SQL.squish, "SCHEMA")
593
603
  SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ constraint_name, owner, table_name
594
604
  FROM all_constraints
@@ -661,7 +671,7 @@ module ActiveRecord
661
671
  type_metadata,
662
672
  field["nullable"] == "Y",
663
673
  comment: field["column_comment"]
664
- )
674
+ )
665
675
  end
666
676
 
667
677
  def fetch_type_metadata(sql_type, virtual = nil)
@@ -1,13 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module ActiveRecord #:nodoc:
4
- module ConnectionAdapters #:nodoc:
5
- module OracleEnhanced #:nodoc:
6
- module StructureDump #:nodoc:
3
+ module ActiveRecord # :nodoc:
4
+ module ConnectionAdapters # :nodoc:
5
+ module OracleEnhanced # :nodoc:
6
+ module StructureDump # :nodoc:
7
7
  # Statements separator used in structure dump to allow loading of structure dump also with SQL*Plus
8
8
  STATEMENT_TOKEN = "\n\n/\n\n"
9
9
 
10
- def structure_dump #:nodoc:
10
+ def structure_dump # :nodoc:
11
11
  sequences = select(<<~SQL.squish, "SCHEMA")
12
12
  SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */
13
13
  sequence_name, min_value, max_value, increment_by, order_flag, cycle_flag
@@ -30,11 +30,11 @@ module ActiveRecord #:nodoc:
30
30
  tables.each do |table_name|
31
31
  virtual_columns = virtual_columns_for(table_name) if supports_virtual_columns?
32
32
  ddl = +"CREATE#{ ' GLOBAL TEMPORARY' if temporary_table?(table_name)} TABLE \"#{table_name}\" (\n"
33
- columns = select_all(<<~SQL.squish, "SCHEMA")
33
+ columns = select_all(<<~SQL.squish, "SCHEMA", [bind_string("table_name", table_name)])
34
34
  SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ column_name, data_type, data_length, char_used, char_length,
35
35
  data_precision, data_scale, data_default, nullable
36
36
  FROM all_tab_columns
37
- WHERE table_name = '#{table_name}'
37
+ WHERE table_name = :table_name
38
38
  AND owner = SYS_CONTEXT('userenv', 'current_schema')
39
39
  ORDER BY column_id
40
40
  SQL
@@ -60,7 +60,7 @@ module ActiveRecord #:nodoc:
60
60
  structure_dump_views
61
61
  end
62
62
 
63
- def structure_dump_column(column) #:nodoc:
63
+ def structure_dump_column(column) # :nodoc:
64
64
  col = +"\"#{column['column_name']}\" #{column['data_type']}"
65
65
  if (column["data_type"] == "NUMBER") && !column["data_precision"].nil?
66
66
  col << "(#{column['data_precision'].to_i}"
@@ -75,8 +75,8 @@ module ActiveRecord #:nodoc:
75
75
  col
76
76
  end
77
77
 
78
- def structure_dump_virtual_column(column, data_default) #:nodoc:
79
- data_default = data_default.gsub(/"/, "")
78
+ def structure_dump_virtual_column(column, data_default) # :nodoc:
79
+ data_default = data_default.delete('"')
80
80
  col = +"\"#{column['column_name']}\" #{column['data_type']}"
81
81
  if (column["data_type"] == "NUMBER") && !column["data_precision"].nil?
82
82
  col << "(#{column['data_precision'].to_i}"
@@ -89,7 +89,7 @@ module ActiveRecord #:nodoc:
89
89
  col << " GENERATED ALWAYS AS (#{data_default}) VIRTUAL"
90
90
  end
91
91
 
92
- def structure_dump_primary_key(table) #:nodoc:
92
+ def structure_dump_primary_key(table) # :nodoc:
93
93
  opts = { name: "", cols: [] }
94
94
  pks = select_all(<<~SQL.squish, "SCHEMA")
95
95
  SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ a.constraint_name, a.column_name, a.position
@@ -108,7 +108,7 @@ module ActiveRecord #:nodoc:
108
108
  opts[:cols].length > 0 ? ",\n CONSTRAINT #{opts[:name]} PRIMARY KEY (#{opts[:cols].join(',')})" : ""
109
109
  end
110
110
 
111
- def structure_dump_unique_keys(table) #:nodoc:
111
+ def structure_dump_unique_keys(table) # :nodoc:
112
112
  keys = {}
113
113
  uks = select_all(<<~SQL.squish, "SCHEMA")
114
114
  SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ a.constraint_name, a.column_name, a.position
@@ -129,7 +129,7 @@ module ActiveRecord #:nodoc:
129
129
  end
130
130
  end
131
131
 
132
- def structure_dump_indexes(table_name) #:nodoc:
132
+ def structure_dump_indexes(table_name) # :nodoc:
133
133
  indexes(table_name).map do |options|
134
134
  column_names = options.columns
135
135
  options = { name: options.name, unique: options.unique }
@@ -145,7 +145,7 @@ module ActiveRecord #:nodoc:
145
145
  end
146
146
  end
147
147
 
148
- def structure_dump_fk_constraints #:nodoc:
148
+ def structure_dump_fk_constraints # :nodoc:
149
149
  foreign_keys = select_all(<<~SQL.squish, "SCHEMA")
150
150
  SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ table_name FROM all_tables
151
151
  WHERE owner = SYS_CONTEXT('userenv', 'current_schema') ORDER BY 1
@@ -174,9 +174,10 @@ module ActiveRecord #:nodoc:
174
174
 
175
175
  def structure_dump_column_comments(table_name)
176
176
  comments = []
177
- columns = select_values(<<~SQL.squish, "SCHEMA")
178
- SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ column_name FROM user_tab_columns
179
- WHERE table_name = '#{table_name}' ORDER BY column_id
177
+ columns = select_values(<<~SQL.squish, "SCHEMA", [bind_string("table_name", table_name)])
178
+ SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ column_name FROM all_tab_columns
179
+ WHERE owner = SYS_CONTEXT('userenv', 'current_schema')
180
+ AND table_name = :table_name ORDER BY column_id
180
181
  SQL
181
182
 
182
183
  columns.each do |column|
@@ -189,7 +190,7 @@ module ActiveRecord #:nodoc:
189
190
  join_with_statement_token(comments)
190
191
  end
191
192
 
192
- def foreign_key_definition(to_table, options = {}) #:nodoc:
193
+ def foreign_key_definition(to_table, options = {}) # :nodoc:
193
194
  column_sql = quote_column_name(options[:column] || "#{to_table.to_s.singularize}_id")
194
195
  references = options[:references] ? options[:references].first : nil
195
196
  references_sql = quote_column_name(options[:primary_key] || references || "id")
@@ -206,7 +207,7 @@ module ActiveRecord #:nodoc:
206
207
  end
207
208
 
208
209
  # Extract all stored procedures, packages, synonyms.
209
- def structure_dump_db_stored_code #:nodoc:
210
+ def structure_dump_db_stored_code # :nodoc:
210
211
  structure = []
211
212
  all_source = select_all(<<~SQL.squish, "SCHEMA")
212
213
  SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ DISTINCT name, type
@@ -217,11 +218,11 @@ module ActiveRecord #:nodoc:
217
218
  SQL
218
219
  all_source.each do |source|
219
220
  ddl = +"CREATE OR REPLACE \n"
220
- texts = select_all(<<~SQL.squish, "all source at structure dump")
221
+ texts = select_all(<<~SQL.squish, "all source at structure dump", [bind_string("source_name", source["name"]), bind_string("source_type", source["type"])])
221
222
  SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ text
222
223
  FROM all_source
223
- WHERE name = '#{source['name']}'
224
- AND type = '#{source['type']}'
224
+ WHERE name = :source_name
225
+ AND type = :source_type
225
226
  AND owner = SYS_CONTEXT('userenv', 'current_schema')
226
227
  ORDER BY line
227
228
  SQL
@@ -238,7 +239,7 @@ module ActiveRecord #:nodoc:
238
239
  join_with_statement_token(structure)
239
240
  end
240
241
 
241
- def structure_dump_views #:nodoc:
242
+ def structure_dump_views # :nodoc:
242
243
  structure = []
243
244
  views = select_all(<<~SQL.squish, "SCHEMA")
244
245
  SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ view_name, text FROM all_views
@@ -250,7 +251,7 @@ module ActiveRecord #:nodoc:
250
251
  join_with_statement_token(structure)
251
252
  end
252
253
 
253
- def structure_dump_synonyms #:nodoc:
254
+ def structure_dump_synonyms # :nodoc:
254
255
  structure = []
255
256
  synonyms = select_all(<<~SQL.squish, "SCHEMA")
256
257
  SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ owner, synonym_name, table_name, table_owner
@@ -264,7 +265,7 @@ module ActiveRecord #:nodoc:
264
265
  join_with_statement_token(structure)
265
266
  end
266
267
 
267
- def structure_drop #:nodoc:
268
+ def structure_drop # :nodoc:
268
269
  sequences = select_values(<<~SQL.squish, "SCHEMA")
269
270
  SELECT/*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */
270
271
  sequence_name FROM all_sequences where sequence_owner = SYS_CONTEXT('userenv', 'current_schema') ORDER BY 1
@@ -287,7 +288,7 @@ module ActiveRecord #:nodoc:
287
288
  join_with_statement_token(statements)
288
289
  end
289
290
 
290
- def temp_table_drop #:nodoc:
291
+ def temp_table_drop # :nodoc:
291
292
  temporary_tables = select_values(<<~SQL.squish, "SCHEMA")
292
293
  SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ table_name FROM all_tables
293
294
  WHERE owner = SYS_CONTEXT('userenv', 'current_schema')
@@ -299,7 +300,7 @@ module ActiveRecord #:nodoc:
299
300
  join_with_statement_token(statements)
300
301
  end
301
302
 
302
- def full_drop(preserve_tables = false) #:nodoc:
303
+ def full_drop(preserve_tables = false) # :nodoc:
303
304
  s = preserve_tables ? [] : [structure_drop]
304
305
  s << temp_table_drop if preserve_tables
305
306
  s << drop_sql_for_feature("view")
@@ -322,12 +323,12 @@ module ActiveRecord #:nodoc:
322
323
  # Called only if `supports_virtual_columns?` returns true
323
324
  # return [{'column_name' => 'FOOS', 'data_default' => '...'}, ...]
324
325
  def virtual_columns_for(table)
325
- select_all(<<~SQL.squish, "SCHEMA")
326
+ select_all(<<~SQL.squish, "SCHEMA", [bind_string("table_name", table.upcase)])
326
327
  SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.2') */ column_name, data_default
327
328
  FROM all_tab_cols
328
329
  WHERE virtual_column = 'YES'
329
330
  AND owner = SYS_CONTEXT('userenv', 'current_schema')
330
- AND table_name = '#{table.upcase}'
331
+ AND table_name = :table_name
331
332
  SQL
332
333
  end
333
334
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveRecord
4
- module ConnectionAdapters #:nodoc:
4
+ module ConnectionAdapters # :nodoc:
5
5
  module OracleEnhanced
6
6
  class TypeMetadata < DelegateClass(ActiveRecord::ConnectionAdapters::SqlTypeMetadata) # :nodoc:
7
7
  include Deduplicable