Module: ActiveRecord::ConnectionAdapters::OracleEnhanced::SchemaStatements

Included in:
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter
Defined in:
lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb

Instance Method Summary collapse

Instance Method Details

#add_column(table_name, column_name, type, **options) ⇒ Object

:nodoc:



417
418
419
420
421
422
423
424
425
426
427
428
# File 'lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb', line 417

def add_column(table_name, column_name, type, **options) # :nodoc:
  type = aliased_types(type.to_s, type)
  at = create_alter_table table_name
  at.add_column(column_name, type, **options)
  add_column_sql = schema_creation.accept at
  add_column_sql << tablespace_for((type_to_sql(type).downcase.to_sym), nil, table_name, column_name)
  execute add_column_sql
  create_sequence_and_trigger(table_name, options) if type && type.to_sym == :primary_key
  change_column_comment(table_name, column_name, options[:comment]) if options.key?(:comment)
ensure
  clear_table_columns_cache(table_name)
end

#add_index(table_name, column_name, **options) ⇒ Object

:nodoc:



298
299
300
301
302
303
304
305
306
# File 'lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb', line 298

def add_index(table_name, column_name, **options) # :nodoc:
  index_name, index_type, quoted_column_names, tablespace, index_options = add_index_options(table_name, column_name, **options)
  execute "CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} (#{quoted_column_names})#{tablespace} #{index_options}"
  if index_type == "UNIQUE"
    unless /\(.*\)/.match?(quoted_column_names)
      execute "ALTER TABLE #{quote_table_name(table_name)} ADD CONSTRAINT #{quote_column_name(index_name)} #{index_type} (#{quoted_column_names}) USING INDEX #{quote_column_name(index_name)}"
    end
  end
end

#add_index_options(table_name, column_name, comment: nil, **options) ⇒ Object

:nodoc:



308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
# File 'lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb', line 308

def add_index_options(table_name, column_name, comment: nil, **options) # :nodoc:
  column_names = Array(column_name)
  index_name   = index_name(table_name, column: column_names)

  options.assert_valid_keys(:unique, :order, :name, :where, :length, :internal, :tablespace, :options, :using)

  index_type = options[:unique] ? "UNIQUE" : ""
  index_name = options[:name].to_s if options.key?(:name)
  tablespace = tablespace_for(:index, options[:tablespace])
  # TODO: This option is used for NOLOGGING, needs better argument name
  index_options = options[:options]

  validate_index_length!(table_name, index_name, options.fetch(:internal, false))

  if table_exists?(table_name) && index_name_exists?(table_name, index_name)
    raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' already exists"
  end

  quoted_column_names = column_names.map { |e| quote_column_name_or_expression(e) }.join(", ")
  [index_name, index_type, quoted_column_names, tablespace, index_options]
end

#add_reference(table_name, ref_name, **options) ⇒ Object



413
414
415
# File 'lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb', line 413

def add_reference(table_name, ref_name, **options)
  OracleEnhanced::ReferenceDefinition.new(ref_name, **options).add_to(update_table_definition(table_name, self))
end

#add_synonym(name, table_name, options = {}) ⇒ Object

Add synonym to existing table or view or sequence. Can be used to create local synonym to remote table in other schema or in other database Examples:

add_synonym :posts, "blog.posts"
add_synonym :posts_seq, "blog.posts_seq"
add_synonym :employees, "hr.employees", :force => true


395
396
397
398
399
400
401
402
# File 'lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb', line 395

def add_synonym(name, table_name, options = {})
  sql = +"CREATE"
  if options[:force] == true
    sql << " OR REPLACE"
  end
  sql << " SYNONYM #{quote_table_name(name)} FOR #{quote_table_name(table_name)}"
  execute sql
end

#aliased_types(name, fallback) ⇒ Object



430
431
432
# File 'lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb', line 430

def aliased_types(name, fallback)
  fallback
end

#change_column(table_name, column_name, type, **options) ⇒ Object

:nodoc:



451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
# File 'lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb', line 451

def change_column(table_name, column_name, type, **options) # :nodoc:
  column = column_for(table_name, column_name)

  # remove :null option if its value is the same as current column definition
  # otherwise Oracle will raise error
  if options.has_key?(:null) && options[:null] == column.null
    options[:null] = nil
  end
  if type.to_sym == :virtual
    type = options[:type]
  end

  td = create_table_definition(table_name)
  cd = td.new_column_definition(column.name, type, **options)
  change_column_stmt = schema_creation.accept cd
  change_column_stmt << tablespace_for((type_to_sql(type).downcase.to_sym), nil, options[:table_name], options[:column_name]) if type
  change_column_sql = "ALTER TABLE #{quote_table_name(table_name)} MODIFY #{change_column_stmt}"
  execute(change_column_sql)

  change_column_comment(table_name, column_name, options[:comment]) if options.key?(:comment)
ensure
  clear_table_columns_cache(table_name)
end

#change_column_comment(table_name, column_name, comment_or_changes) ⇒ Object



506
507
508
509
510
# File 'lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb', line 506

def change_column_comment(table_name, column_name, comment_or_changes)
  clear_cache!
  comment = extract_new_comment_value(comment_or_changes)
  execute "COMMENT ON COLUMN #{quote_table_name(table_name)}.#{quote_column_name(column_name)} IS '#{comment}'"
end

#change_column_default(table_name, column_name, default_or_changes) ⇒ Object

:nodoc:



434
435
436
437
438
439
# File 'lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb', line 434

def change_column_default(table_name, column_name, default_or_changes) # :nodoc:
  default = extract_new_default_value(default_or_changes)
  execute "ALTER TABLE #{quote_table_name(table_name)} MODIFY #{quote_column_name(column_name)} DEFAULT #{quote(default)}"
ensure
  clear_table_columns_cache(table_name)
end

#change_column_null(table_name, column_name, null, default = nil) ⇒ Object

:nodoc:



441
442
443
444
445
446
447
448
449
# File 'lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb', line 441

def change_column_null(table_name, column_name, null, default = nil) # :nodoc:
  column = column_for(table_name, column_name)

  unless null || default.nil?
    execute("UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote(default)} WHERE #{quote_column_name(column_name)} IS NULL")
  end

  change_column table_name, column_name, column.sql_type, null: null
end

#change_table_comment(table_name, comment_or_changes) ⇒ Object



496
497
498
499
500
501
502
503
504
# File 'lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb', line 496

def change_table_comment(table_name, comment_or_changes)
  clear_cache!
  comment = extract_new_comment_value(comment_or_changes)
  if comment.nil?
    execute "COMMENT ON TABLE #{quote_table_name(table_name)} IS ''"
  else
    execute "COMMENT ON TABLE #{quote_table_name(table_name)} IS #{quote(comment)}"
  end
end

#column_comment(table_name, column_name) ⇒ Object

:nodoc:



528
529
530
531
532
533
534
535
536
537
# File 'lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb', line 528

def column_comment(table_name, column_name) # :nodoc:
  # TODO: it  does not exist in Abstract adapter
  (_owner, table_name) = _connection.describe(table_name)
  select_value(<<~SQL.squish, "SCHEMA", [bind_string("table_name", table_name), bind_string("column_name", column_name.upcase)])
    SELECT comments FROM all_col_comments
    WHERE owner = SYS_CONTEXT('userenv', 'current_schema')
      AND table_name = :table_name
      AND column_name = :column_name
  SQL
end

#columns(table_name) ⇒ Object



163
164
165
166
167
168
169
170
# File 'lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb', line 163

def columns(table_name)
  table_name = table_name.to_s
  if @columns_cache[table_name]
    @columns_cache[table_name]
  else
    @columns_cache[table_name] = super(table_name)
  end
end

#create_alter_table(name) ⇒ Object



621
622
623
# File 'lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb', line 621

def create_alter_table(name)
  OracleEnhanced::AlterTable.new create_table_definition(name)
end

#create_schema_dumper(options) ⇒ Object



629
630
631
# File 'lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb', line 629

def create_schema_dumper(options)
  OracleEnhanced::SchemaDumper.create(self, options)
end

#create_table(table_name, id: :primary_key, primary_key: nil, force: nil, **options) {|td| ... } ⇒ Object

Additional options for create_table method in migration files.

You can specify individual starting value in table creation migration file, e.g.:

create_table :users, :sequence_start_value => 100 do |t|
  # ...
end

You can also specify other sequence definition additional parameters, e.g.:

create_table :users, :sequence_start_value => “100 NOCACHE INCREMENT BY 10” do |t|
  # ...
end

Create primary key trigger (so that you can skip primary key value in INSERT statement). By default trigger name will be “table_name_pkt”, you can override the name with :trigger_name option (but it is not recommended to override it as then this trigger will not be detected by ActiveRecord model and it will still do prefetching of sequence value). Example:

create_table :users, :primary_key_trigger => true do |t|
  # ...
end

It is possible to add table and column comments in table creation migration files:

create_table :employees, :comment => “Employees and contractors” do |t|
  t.string      :first_name, :comment => “Given name”
  t.string      :last_name, :comment => “Surname”
end

Yields:

  • (td)


202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
# File 'lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb', line 202

def create_table(table_name, id: :primary_key, primary_key: nil, force: nil, **options)
  create_sequence = id != false
  td = create_table_definition(
    table_name, **options.extract!(:temporary, :options, :as, :comment, :tablespace, :organization)
  )

  if id && !td.as
    pk = primary_key || Base.get_primary_key(table_name.to_s.singularize)

    if pk.is_a?(Array)
      td.primary_keys pk
    else
      td.primary_key pk, id, **options
    end
  end

  # store that primary key was defined in create_table block
  unless create_sequence
    class << td
      attr_accessor :create_sequence
      def primary_key(*args)
        self.create_sequence = true
        super(*args)
      end
    end
  end

  yield td if block_given?
  create_sequence = create_sequence || td.create_sequence

  if force && data_source_exists?(table_name)
    drop_table(table_name, force: force, if_exists: true)
  else
    schema_cache.clear_data_source_cache!(table_name.to_s)
  end

  execute schema_creation.accept td

  create_sequence_and_trigger(table_name, options) if create_sequence

  if supports_comments? && !supports_comments_in_create?
    if table_comment = td.comment.presence
      change_table_comment(table_name, table_comment)
    end
    td.columns.each do |column|
      change_column_comment(table_name, column.name, column.comment) if column.comment.present?
    end
  end
  td.indexes.each { |c, o| add_index table_name, c, **o }

  rebuild_primary_key_index_to_default_tablespace(table_name, options)
end

#data_source_exists?(table_name) ⇒ Boolean

Returns:

  • (Boolean)


55
56
57
58
59
60
# File 'lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb', line 55

def data_source_exists?(table_name)
  (_owner, _table_name) = _connection.describe(table_name)
  true
rescue
  false
end

#data_sourcesObject



27
28
29
# File 'lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb', line 27

def data_sources
  super | synonyms.map(&:name)
end

#disable_referential_integrity(&block) ⇒ Object

REFERENTIAL INTEGRITY ====================================



601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
# File 'lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb', line 601

def disable_referential_integrity(&block) # :nodoc:
  old_constraints = select_all(<<~SQL.squish, "SCHEMA")
    SELECT constraint_name, owner, table_name
      FROM all_constraints
      WHERE constraint_type = 'R'
      AND status = 'ENABLED'
      AND owner = SYS_CONTEXT('userenv', 'current_schema')
  SQL
  begin
    old_constraints.each do |constraint|
      execute "ALTER TABLE #{quote_table_name(constraint["table_name"])} DISABLE CONSTRAINT #{quote_table_name(constraint["constraint_name"])}"
    end
    yield
  ensure
    old_constraints.each do |constraint|
      execute "ALTER TABLE #{quote_table_name(constraint["table_name"])} ENABLE CONSTRAINT #{quote_table_name(constraint["constraint_name"])}"
    end
  end
end

#drop_table(table_name, **options) ⇒ Object

:nodoc:



267
268
269
270
271
272
273
274
275
276
# File 'lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb', line 267

def drop_table(table_name, **options) # :nodoc:
  schema_cache.clear_data_source_cache!(table_name.to_s)
  execute "DROP TABLE #{quote_table_name(table_name)}#{' CASCADE CONSTRAINTS' if options[:force] == :cascade}"
  seq_name = options[:sequence_name] || default_sequence_name(table_name)
  execute "DROP SEQUENCE #{quote_table_name(seq_name)}" rescue nil
rescue ActiveRecord::StatementInvalid => e
  raise e unless options[:if_exists]
ensure
  clear_table_columns_cache(table_name)
end

#extract_foreign_key_action(specifier) ⇒ Object

:nodoc:



592
593
594
595
596
597
# File 'lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb', line 592

def extract_foreign_key_action(specifier) # :nodoc:
  case specifier
  when "CASCADE"; :cascade
  when "SET NULL"; :nullify
  end
end

#foreign_keys(table_name) ⇒ Object

get table foreign keys for schema dump



557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
# File 'lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb', line 557

def foreign_keys(table_name) # :nodoc:
  (_owner, desc_table_name) = _connection.describe(table_name)

  fk_info = select_all(<<~SQL.squish, "SCHEMA", [bind_string("desc_table_name", desc_table_name)])
    SELECT r.table_name to_table
          ,rc.column_name references_column
          ,cc.column_name
          ,c.constraint_name name
          ,c.delete_rule
      FROM all_constraints c, all_cons_columns cc,
           all_constraints r, all_cons_columns rc
     WHERE c.owner = SYS_CONTEXT('userenv', 'current_schema')
       AND c.table_name = :desc_table_name
       AND c.constraint_type = 'R'
       AND cc.owner = c.owner
       AND cc.constraint_name = c.constraint_name
       AND r.constraint_name = c.r_constraint_name
       AND r.owner = c.owner
       AND rc.owner = r.owner
       AND rc.constraint_name = r.constraint_name
       AND rc.position = cc.position
    ORDER BY name, to_table, column_name, references_column
  SQL

  fk_info.map do |row|
    options = {
      column: oracle_downcase(row["column_name"]),
      name: oracle_downcase(row["name"]),
      primary_key: oracle_downcase(row["references_column"])
    }
    options[:on_delete] = extract_foreign_key_action(row["delete_rule"])
    ActiveRecord::ConnectionAdapters::ForeignKeyDefinition.new(oracle_downcase(table_name), oracle_downcase(row["to_table"]), options)
  end
end

#index_name(table_name, options) ⇒ Object

returned shortened index name if default is too large



342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
# File 'lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb', line 342

def index_name(table_name, options) # :nodoc:
  default_name = super(table_name, options).to_s
  # sometimes options can be String or Array with column names
  options = {} unless options.is_a?(Hash)
  identifier_max_length = options[:identifier_max_length] || index_name_length
  return default_name if default_name.length <= identifier_max_length

  # remove 'index', 'on' and 'and' keywords
  shortened_name = "i_#{table_name}_#{Array(options[:column]) * '_'}"

  # leave just first three letters from each word
  if shortened_name.length > identifier_max_length
    shortened_name = shortened_name.split("_").map { |w| w[0, 3] }.join("_")
  end
  # generate unique name using hash function
  if shortened_name.length > identifier_max_length
    shortened_name = "i" + OpenSSL::Digest::SHA1.hexdigest(default_name)[0, identifier_max_length - 1]
  end
  @logger.warn "#{adapter_name} shortened default index name #{default_name} to #{shortened_name}" if @logger
  shortened_name
end

#index_name_exists?(table_name, index_name) ⇒ Boolean

Verify the existence of an index with a given name.

The default argument is returned if the underlying implementation does not define the indexes method, as there’s no way to determine the correct answer in that case.

Will always query database and not index cache.

Returns:

  • (Boolean)


370
371
372
373
374
375
376
377
378
379
380
# File 'lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb', line 370

def index_name_exists?(table_name, index_name)
  (_owner, table_name) = _connection.describe(table_name)
  result = select_value(<<~SQL.squish, "SCHEMA", [bind_string("table_name", table_name), bind_string("index_name", index_name.to_s.upcase)])
    SELECT 1 FROM all_indexes i
    WHERE i.owner = SYS_CONTEXT('userenv', 'current_schema')
       AND i.table_owner = SYS_CONTEXT('userenv', 'current_schema')
       AND i.table_name = :table_name
       AND i.index_name = :index_name
  SQL
  result == 1
end

#indexes(table_name) ⇒ Object

:nodoc:



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb', line 89

def indexes(table_name) # :nodoc:
  (_owner, table_name) = _connection.describe(table_name)
  default_tablespace_name = default_tablespace

  result = select_all(<<~SQL.squish, "SCHEMA", [bind_string("table_name", table_name)])
    SELECT LOWER(i.table_name) AS table_name, LOWER(i.index_name) AS index_name, i.uniqueness,
      i.index_type, i.ityp_owner, i.ityp_name, i.parameters,
      LOWER(i.tablespace_name) AS tablespace_name,
      LOWER(c.column_name) AS column_name, e.column_expression,
      atc.virtual_column
    FROM all_indexes i
      JOIN all_ind_columns c ON c.index_name = i.index_name AND c.index_owner = i.owner
      LEFT OUTER JOIN all_ind_expressions e ON e.index_name = i.index_name AND
        e.index_owner = i.owner AND e.column_position = c.column_position
      LEFT OUTER JOIN all_tab_cols atc ON i.table_name = atc.table_name AND
        c.column_name = atc.column_name AND i.owner = atc.owner AND atc.hidden_column = 'NO'
    WHERE i.owner = SYS_CONTEXT('userenv', 'current_schema')
       AND i.table_owner = SYS_CONTEXT('userenv', 'current_schema')
       AND i.table_name = :table_name
       AND NOT EXISTS (SELECT uc.index_name FROM all_constraints uc
        WHERE uc.index_name = i.index_name AND uc.owner = i.owner AND uc.constraint_type = 'P')
    ORDER BY i.index_name, c.column_position
  SQL

  current_index = nil
  all_schema_indexes = []

  result.each do |row|
    # have to keep track of indexes because above query returns dups
    # there is probably a better query we could figure out
    if current_index != row["index_name"]
      statement_parameters = nil
      if row["index_type"] == "DOMAIN" && row["ityp_owner"] == "CTXSYS" && row["ityp_name"] == "CONTEXT"
        procedure_name = default_datastore_procedure(row["index_name"])
        source = select_values(<<~SQL.squish, "SCHEMA", [bind_string("procedure_name", procedure_name.upcase)]).join
          SELECT text
          FROM all_source
          WHERE owner = SYS_CONTEXT('userenv', 'current_schema')
            AND name = :procedure_name
          ORDER BY line
        SQL
        if source =~ /-- add_context_index_parameters (.+)\n/
          statement_parameters = $1
        end
      end
      all_schema_indexes << OracleEnhanced::IndexDefinition.new(
        row["table_name"],
        row["index_name"],
        row["uniqueness"] == "UNIQUE",
        [],
        {},
        row["index_type"] == "DOMAIN" ? "#{row['ityp_owner']}.#{row['ityp_name']}" : nil,
        row["parameters"],
        statement_parameters,
        row["tablespace_name"] == default_tablespace_name ? nil : row["tablespace_name"])
      current_index = row["index_name"]
    end

    # Functional index columns and virtual columns both get stored as column expressions,
    # but re-creating a virtual column index as an expression (instead of using the virtual column's name)
    # results in a ORA-54018 error.  Thus, we only want the column expression value returned
    # when the column is not virtual.
    if row["column_expression"] && row["virtual_column"] != "YES"
      all_schema_indexes.last.columns << row["column_expression"]
    else
      all_schema_indexes.last.columns << row["column_name"].downcase
    end
  end

  # Return the indexes just for the requested table, since AR is structured that way
  table_name = table_name.downcase
  all_schema_indexes.select { |i| i.table == table_name }
end

#insert_versions_sql(versions) ⇒ Object

:nodoc:



278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
# File 'lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb', line 278

def insert_versions_sql(versions) # :nodoc:
  sm_table = quote_table_name(ActiveRecord::Base.connection.schema_migration.table_name)

  if supports_multi_insert?
    versions.inject(+"INSERT ALL\n") { |sql, version|
      sql << "INTO #{sm_table} (version) VALUES (#{quote(version)})\n"
    } << "SELECT * FROM DUAL\n"
  else
    if versions.is_a?(Array)
      # called from ActiveRecord::Base.connection#dump_schema_information
      versions.map { |version|
        "INSERT INTO #{sm_table} (version) VALUES (#{quote(version)})"
      }.join("\n\n/\n\n")
    else
      # called from ActiveRecord::Base.connection#assume_migrated_upto_version
      "INSERT INTO #{sm_table} (version) VALUES (#{quote(versions)})"
    end
  end
end

#materialized_viewsObject

:nodoc:



69
70
71
72
73
74
# File 'lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb', line 69

def materialized_views # :nodoc:
  select_values(<<~SQL.squish, "SCHEMA")
    SELECT
    LOWER(mview_name) FROM all_mviews WHERE owner = SYS_CONTEXT('userenv', 'current_schema')
  SQL
end

#remove_column(table_name, column_name, type = nil, options = {}) ⇒ Object

:nodoc:



482
483
484
485
486
# File 'lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb', line 482

def remove_column(table_name, column_name, type = nil, options = {}) # :nodoc:
  execute "ALTER TABLE #{quote_table_name(table_name)} DROP COLUMN #{quote_column_name(column_name)} CASCADE CONSTRAINTS"
ensure
  clear_table_columns_cache(table_name)
end

#remove_columns(table_name, *column_names, type: nil, **options) ⇒ Object

:nodoc:



488
489
490
491
492
493
494
# File 'lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb', line 488

def remove_columns(table_name, *column_names, type: nil, **options) # :nodoc:
  quoted_column_names = column_names.map { |column_name| quote_column_name(column_name) }.join(", ")

  execute "ALTER TABLE #{quote_table_name(table_name)} DROP (#{quoted_column_names}) CASCADE CONSTRAINTS"
ensure
  clear_table_columns_cache(table_name)
end

#remove_index(table_name, column_name = nil, **options) ⇒ Object

Remove the given index from the table. Gives warning if index does not exist



332
333
334
335
336
337
338
339
# File 'lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb', line 332

def remove_index(table_name, column_name = nil, **options) # :nodoc:
  return if options[:if_exists] && !index_exists?(table_name, column_name, **options)

  index_name = index_name_for_remove(table_name, column_name, options)
  # TODO: It should execute only when index_type == "UNIQUE"
  execute "ALTER TABLE #{quote_table_name(table_name)} DROP CONSTRAINT #{quote_column_name(index_name)}" rescue nil
  execute "DROP INDEX #{quote_column_name(index_name)}"
end

#remove_synonym(name) ⇒ Object

Remove existing synonym to table or view or sequence Example:

remove_synonym :posts, "blog.posts"


409
410
411
# File 'lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb', line 409

def remove_synonym(name)
  execute "DROP SYNONYM #{quote_table_name(name)}"
end

#rename_column(table_name, column_name, new_column_name) ⇒ Object

:nodoc:



475
476
477
478
479
480
# File 'lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb', line 475

def rename_column(table_name, column_name, new_column_name) # :nodoc:
  execute "ALTER TABLE #{quote_table_name(table_name)} RENAME COLUMN #{quote_column_name(column_name)} to #{quote_column_name(new_column_name)}"
  rename_column_indexes(table_name, column_name, new_column_name)
ensure
  clear_table_columns_cache(table_name)
end

#rename_index(table_name, old_name, new_name) ⇒ Object

:nodoc:



382
383
384
385
# File 'lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb', line 382

def rename_index(table_name, old_name, new_name) # :nodoc:
  validate_index_length!(table_name, new_name)
  execute "ALTER INDEX #{quote_column_name(old_name)} rename to #{quote_column_name(new_name)}"
end

#rename_table(table_name, new_name) ⇒ Object

:nodoc:



255
256
257
258
259
260
261
262
263
264
265
# File 'lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb', line 255

def rename_table(table_name, new_name) # :nodoc:
  if new_name.to_s.length > DatabaseLimits::IDENTIFIER_MAX_LENGTH
    raise ArgumentError, "New table name '#{new_name}' is too long; the limit is #{DatabaseLimits::IDENTIFIER_MAX_LENGTH} characters"
  end
  schema_cache.clear_data_source_cache!(table_name.to_s)
  schema_cache.clear_data_source_cache!(new_name.to_s)
  execute "RENAME #{quote_table_name(table_name)} TO #{quote_table_name(new_name)}"
  execute "RENAME #{quote_table_name("#{table_name}_seq")} TO #{default_sequence_name(new_name)}" rescue nil

  rename_table_indexes(table_name, new_name)
end

#synonymsObject

get synonyms for schema dump



77
78
79
80
81
82
83
84
85
86
87
# File 'lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb', line 77

def synonyms
  result = select_all(<<~SQL.squish, "SCHEMA")
    SELECT synonym_name, table_owner, table_name
    FROM all_synonyms where owner = SYS_CONTEXT('userenv', 'current_schema')
  SQL

  result.collect do |row|
     OracleEnhanced::SynonymDefinition.new(oracle_downcase(row["synonym_name"]),
     oracle_downcase(row["table_owner"]), oracle_downcase(row["table_name"]))
   end
end

#table_comment(table_name) ⇒ Object

:nodoc:



512
513
514
515
516
517
518
519
520
# File 'lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb', line 512

def table_comment(table_name) # :nodoc:
  # TODO
  (_owner, table_name) = _connection.describe(table_name)
  select_value(<<~SQL.squish, "SCHEMA", [bind_string("table_name", table_name)])
    SELECT comments FROM all_tab_comments
    WHERE owner = SYS_CONTEXT('userenv', 'current_schema')
      AND table_name = :table_name
  SQL
end

#table_exists?(table_name) ⇒ Boolean

Returns:

  • (Boolean)


31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb', line 31

def table_exists?(table_name)
  table_name = table_name.to_s
  if table_name.include?("@")
    # db link is not table
    false
  else
    default_owner = current_schema
  end
  real_name = OracleEnhanced::Quoting.valid_table_name?(table_name) ?
    table_name.upcase : table_name
  if real_name.include?(".")
    table_owner, table_name = real_name.split(".")
  else
    table_owner, table_name = default_owner, real_name
  end

  select_values(<<~SQL.squish, "SCHEMA", [bind_string("owner", table_owner), bind_string("table_name", table_name)]).any?
    SELECT owner, table_name
    FROM all_tables
    WHERE owner = :owner
    AND table_name = :table_name
  SQL
end

#table_options(table_name) ⇒ Object

:nodoc:



522
523
524
525
526
# File 'lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb', line 522

def table_options(table_name) # :nodoc:
  if comment = table_comment(table_name)
    { comment: comment }
  end
end

#tablesObject

SCHEMA STATEMENTS ========================================

see: abstract/schema_statements.rb



13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb', line 13

def tables # :nodoc:
  select_values(<<~SQL.squish, "SCHEMA")
    SELECT
    DECODE(table_name, UPPER(table_name), LOWER(table_name), table_name)
    FROM all_tables
    WHERE owner = SYS_CONTEXT('userenv', 'current_schema')
    AND secondary = 'N'
    minus
    SELECT DECODE(mview_name, UPPER(mview_name), LOWER(mview_name), mview_name)
    FROM all_mviews
    WHERE owner = SYS_CONTEXT('userenv', 'current_schema')
  SQL
end

#tablespace(table_name) ⇒ Object



547
548
549
550
551
552
553
554
# File 'lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb', line 547

def tablespace(table_name)
  select_value(<<~SQL.squish, "SCHEMA")
    SELECT tablespace_name
    FROM all_tables
    WHERE table_name='#{table_name.to_s.upcase}'
    AND owner = SYS_CONTEXT('userenv', 'current_schema')
  SQL
end

#type_to_sql(type, limit: nil, precision: nil, scale: nil) ⇒ Object

Maps logical Rails types to Oracle-specific data types.



540
541
542
543
544
545
# File 'lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb', line 540

def type_to_sql(type, limit: nil, precision: nil, scale: nil, **) # :nodoc:
  # Ignore options for :text, :ntext and :binary columns
  return super(type) if ["text", "ntext", "binary"].include?(type.to_s)

  super
end

#update_table_definition(table_name, base) ⇒ Object



625
626
627
# File 'lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb', line 625

def update_table_definition(table_name, base)
  OracleEnhanced::Table.new(table_name, base)
end

#viewsObject

:nodoc:



62
63
64
65
66
67
# File 'lib/active_record/connection_adapters/oracle_enhanced/schema_statements.rb', line 62

def views # :nodoc:
  select_values(<<~SQL.squish, "SCHEMA")
    SELECT
    LOWER(view_name) FROM all_views WHERE owner = SYS_CONTEXT('userenv', 'current_schema')
  SQL
end