activerecord-oracle_enhanced-adapter 6.1.4 → 7.0.1

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 (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