module Sequel::Oracle::DatabaseMethods

Constants

AUTOINCREMENT
DATABASE_ERROR_REGEXPS
IGNORE_OWNERS
TEMPORARY
TRANSACTION_ISOLATION_LEVELS

Attributes

autosequence[RW]

Public Instance Methods

create_sequence(name, opts=OPTS) click to toggle source
# File lib/sequel/adapters/shared/oracle.rb, line 22
def create_sequence(name, opts=OPTS)
  self << create_sequence_sql(name, opts)
end
create_trigger(*args) click to toggle source
# File lib/sequel/adapters/shared/oracle.rb, line 26
def create_trigger(*args)
  self << create_trigger_sql(*args)
end
current_user() click to toggle source
# File lib/sequel/adapters/shared/oracle.rb, line 30
def current_user
  @current_user ||= metadata_dataset.get{sys_context('USERENV', 'CURRENT_USER')}
end
database_type() click to toggle source

Oracle uses the :oracle database type

# File lib/sequel/adapters/shared/oracle.rb, line 39
def database_type
  :oracle
end
drop_sequence(name) click to toggle source
# File lib/sequel/adapters/shared/oracle.rb, line 34
def drop_sequence(name)
  self << drop_sequence_sql(name)
end
foreign_key_list(table, opts=OPTS) click to toggle source
# File lib/sequel/adapters/shared/oracle.rb, line 43
def foreign_key_list(table, opts=OPTS)
  m = output_identifier_meth
  im = input_identifier_meth
  schema, table = schema_and_table(table)
  ds = metadata_dataset.
    from{[all_cons_columns.as(:pc), all_constraints.as(:p), all_cons_columns.as(:fc), all_constraints.as(:f)]}.
    where{{
      f[:table_name]=>im.call(table),
      f[:constraint_type]=>'R',
      p[:owner]=>f[:r_owner],
      p[:constraint_name]=>f[:r_constraint_name],
      pc[:owner]=>p[:owner],
      pc[:constraint_name]=>p[:constraint_name],
      pc[:table_name]=>p[:table_name],
      fc[:owner]=>f[:owner],
      fc[:constraint_name]=>f[:constraint_name],
      fc[:table_name]=>f[:table_name],
      fc[:position]=>pc[:position]}}.
    select{[p[:table_name].as(:table), pc[:column_name].as(:key), fc[:column_name].as(:column), f[:constraint_name].as(:name)]}.
    order{[:table, fc[:position]]}
  ds = ds.where{{f[:schema_name]=>im.call(schema)}} if schema

  fks = {}
  ds.each do |r|
    if fk = fks[r[:name]]
      fk[:columns] << m.call(r[:column])
      fk[:key] << m.call(r[:key])
    else
      fks[r[:name]] = {:name=>m.call(r[:name]), :columns=>[m.call(r[:column])], :table=>m.call(r[:table]), :key=>[m.call(r[:key])]}
    end
  end
  fks.values
end
freeze() click to toggle source
Calls superclass method
# File lib/sequel/adapters/shared/oracle.rb, line 77
def freeze
  current_user
  server_version
  @conversion_procs.freeze
  super
end
global_index_namespace?() click to toggle source

Oracle namespaces indexes per table.

# File lib/sequel/adapters/shared/oracle.rb, line 85
def global_index_namespace?
  false
end
server_version(server=nil) click to toggle source

The version of the Oracle server, used for determining capability.

# File lib/sequel/adapters/shared/oracle.rb, line 119
def server_version(server=nil)
  return @server_version if @server_version
  @server_version = synchronize(server) do |conn|
    (conn.server_version rescue nil) if conn.respond_to?(:server_version)
  end
  unless @server_version
    @server_version = if m = /(\d+)\.(\d+)\.?(\d+)?\.?(\d+)?/.match(fetch("select version from PRODUCT_COMPONENT_VERSION where lower(product) like 'oracle%'").single_value)
      (m[1].to_i*1000000) + (m[2].to_i*10000) + (m[3].to_i*100) + m[4].to_i
    else
      0
    end
  end
  @server_version
end
supports_deferrable_constraints?() click to toggle source

Oracle supports deferrable constraints.

# File lib/sequel/adapters/shared/oracle.rb, line 136
def supports_deferrable_constraints?
  true
end
supports_transaction_isolation_levels?() click to toggle source

Oracle supports transaction isolation levels.

# File lib/sequel/adapters/shared/oracle.rb, line 141
def supports_transaction_isolation_levels?
  true
end
tables(opts=OPTS) click to toggle source
# File lib/sequel/adapters/shared/oracle.rb, line 91
def tables(opts=OPTS)
  m = output_identifier_meth
  metadata_dataset.from(:all_tables).
    server(opts[:server]).
    where(:dropped=>'NO').
    exclude(:owner=>IGNORE_OWNERS).
    select(:table_name).
    map{|r| m.call(r[:table_name])}
end
view_exists?(name) click to toggle source
# File lib/sequel/adapters/shared/oracle.rb, line 110
def view_exists?(name) 
  m = input_identifier_meth
  metadata_dataset.from(:all_views).
    exclude(:owner=>IGNORE_OWNERS).
    where(:view_name=>m.call(name)).
    count > 0
end
views(opts=OPTS) click to toggle source
# File lib/sequel/adapters/shared/oracle.rb, line 101
def views(opts=OPTS) 
  m = output_identifier_meth
  metadata_dataset.from(:all_views).
    server(opts[:server]).
    exclude(:owner=>IGNORE_OWNERS).
    select(:view_name).
    map{|r| m.call(r[:view_name])}
end

Private Instance Methods

alter_table_sql(table, op) click to toggle source

Handle Oracle specific ALTER TABLE SQL

Calls superclass method
# File lib/sequel/adapters/shared/oracle.rb, line 148
def alter_table_sql(table, op)
  case op[:op]
  when :add_column
    if op[:primary_key]
      sqls = []
      sqls << alter_table_sql(table, op.merge(:primary_key=>nil))
      if op[:auto_increment]
        seq_name = default_sequence_name(table, op[:name])
        sqls << drop_sequence_sql(seq_name)
        sqls << create_sequence_sql(seq_name, op)
        sqls << "UPDATE #{quote_schema_table(table)} SET #{quote_identifier(op[:name])} = #{seq_name}.nextval"
      end
      sqls << "ALTER TABLE #{quote_schema_table(table)} ADD PRIMARY KEY (#{quote_identifier(op[:name])})"
      sqls
    else
       "ALTER TABLE #{quote_schema_table(table)} ADD #{column_definition_sql(op)}"
    end
  when :set_column_null
    "ALTER TABLE #{quote_schema_table(table)} MODIFY #{quote_identifier(op[:name])} #{op[:null] ? 'NULL' : 'NOT NULL'}"
  when :set_column_type
    "ALTER TABLE #{quote_schema_table(table)} MODIFY #{quote_identifier(op[:name])} #{type_literal(op)}"
  when :set_column_default
    "ALTER TABLE #{quote_schema_table(table)} MODIFY #{quote_identifier(op[:name])} DEFAULT #{literal(op[:default])}"
  else
    super(table, op)
  end
end
auto_increment_sql() click to toggle source
# File lib/sequel/adapters/shared/oracle.rb, line 176
def auto_increment_sql
  AUTOINCREMENT
end
create_sequence_sql(name, opts=OPTS) click to toggle source
# File lib/sequel/adapters/shared/oracle.rb, line 180
def create_sequence_sql(name, opts=OPTS)
  "CREATE SEQUENCE #{quote_identifier(name)} start with #{opts [:start_with]||1} increment by #{opts[:increment_by]||1} nomaxvalue"
end
create_table_from_generator(name, generator, options) click to toggle source
# File lib/sequel/adapters/shared/oracle.rb, line 184
def create_table_from_generator(name, generator, options)
  drop_statement, create_statements = create_table_sql_list(name, generator, options)
  (execute_ddl(drop_statement) rescue nil) if drop_statement
  create_statements.each{|sql| execute_ddl(sql)}
end
create_table_sql_list(name, generator, options=OPTS) click to toggle source
# File lib/sequel/adapters/shared/oracle.rb, line 190
def create_table_sql_list(name, generator, options=OPTS)
  statements = [create_table_sql(name, generator, options)]
  drop_seq_statement = nil
  generator.columns.each do |c|
    if c[:auto_increment]
      c[:sequence_name] ||= default_sequence_name(name, c[:name])
      unless c[:create_sequence] == false
        drop_seq_statement = drop_sequence_sql(c[:sequence_name])
        statements << create_sequence_sql(c[:sequence_name], c)
      end
      unless c[:create_trigger] == false
        c[:trigger_name] ||= "BI_#{name}_#{c[:name]}"
        trigger_definition = <<-end_sql
        BEGIN
          IF :NEW.#{quote_identifier(c[:name])} IS NULL THEN
            SELECT #{c[:sequence_name]}.nextval INTO :NEW.#{quote_identifier(c[:name])} FROM dual;
          END IF;
        END;
        end_sql
        statements << create_trigger_sql(name, c[:trigger_name], trigger_definition, {:events => [:insert]})
      end
    end
  end
  [drop_seq_statement, statements]
end
create_trigger_sql(table, name, definition, opts=OPTS) click to toggle source
# File lib/sequel/adapters/shared/oracle.rb, line 216
def create_trigger_sql(table, name, definition, opts=OPTS)
  events = opts[:events] ? Array(opts[:events]) : [:insert, :update, :delete]
  sql = <<-end_sql
    CREATE#{' OR REPLACE' if opts[:replace]} TRIGGER #{quote_identifier(name)}
    #{opts[:after] ? 'AFTER' : 'BEFORE'} #{events.map{|e| e.to_s.upcase}.join(' OR ')} ON #{quote_schema_table(table)}
    REFERENCING NEW AS NEW FOR EACH ROW
    #{definition}
  end_sql
  sql
end
database_error_regexps() click to toggle source
# File lib/sequel/adapters/shared/oracle.rb, line 234
def database_error_regexps
  DATABASE_ERROR_REGEXPS
end
default_sequence_name(table, column) click to toggle source
# File lib/sequel/adapters/shared/oracle.rb, line 238
def default_sequence_name(table, column)
  "seq_#{table}_#{column}"
end
drop_sequence_sql(name) click to toggle source
# File lib/sequel/adapters/shared/oracle.rb, line 242
def drop_sequence_sql(name)
  "DROP SEQUENCE #{quote_identifier(name)}"
end
remove_cached_schema(table) click to toggle source
Calls superclass method
# File lib/sequel/adapters/shared/oracle.rb, line 246
def remove_cached_schema(table)
  Sequel.synchronize{@primary_key_sequences.delete(table)}
  super
end
sequence_for_table(table) click to toggle source
# File lib/sequel/adapters/shared/oracle.rb, line 261
def sequence_for_table(table)
  return nil unless autosequence
  Sequel.synchronize{return @primary_key_sequences[table] if @primary_key_sequences.has_key?(table)}

  begin
    sch = schema(table)
  rescue Sequel::Error
    return nil
  end

  pk = sch.select{|k, v| v[:primary_key]}
  pks = if pk.length == 1
    seq = "seq_#{table}_#{pk.first.first}"
    seq.to_sym unless from(:user_sequences).where(:sequence_name=>input_identifier_meth.call(seq)).empty?
  end
  Sequel.synchronize{@primary_key_sequences[table] = pks}
end
set_transaction_isolation_sql(level) click to toggle source

Oracle doesn't support READ UNCOMMITTED OR REPEATABLE READ transaction isolation levels, so upgrade to the next highest level in those cases.

# File lib/sequel/adapters/shared/oracle.rb, line 257
def set_transaction_isolation_sql(level)
  "SET TRANSACTION ISOLATION LEVEL #{TRANSACTION_ISOLATION_LEVELS[level]}"
end
supports_create_or_replace_view?() click to toggle source

Oracle supports CREATE OR REPLACE VIEW.

# File lib/sequel/adapters/shared/oracle.rb, line 280
def supports_create_or_replace_view?
  true
end
temporary_table_sql() click to toggle source

SQL fragment for showing a table is temporary

# File lib/sequel/adapters/shared/oracle.rb, line 304
def temporary_table_sql
  TEMPORARY
end
type_literal_generic_bignum_symbol(column) click to toggle source

Oracle's integer/:number type handles larger values than most other databases's bigint types, so it should be safe to use for Bignum.

# File lib/sequel/adapters/shared/oracle.rb, line 287
def type_literal_generic_bignum_symbol(column)
  :integer
end
type_literal_generic_time(column) click to toggle source

Oracle doesn't have a time type, so use timestamp for all time columns.

# File lib/sequel/adapters/shared/oracle.rb, line 293
def type_literal_generic_time(column)
  :timestamp
end
type_literal_generic_trueclass(column) click to toggle source

Oracle doesn't have a boolean type or even a reasonable facsimile. Using a char(1) seems to be the recommended way.

# File lib/sequel/adapters/shared/oracle.rb, line 299
def type_literal_generic_trueclass(column)
  :'char(1)'
end
uses_clob_for_text?() click to toggle source

Oracle uses clob for text types.

# File lib/sequel/adapters/shared/oracle.rb, line 309
def uses_clob_for_text?
  true
end
view_with_check_option_support() click to toggle source

Oracle supports views with check option, but not local.

# File lib/sequel/adapters/shared/oracle.rb, line 314
def view_with_check_option_support
  true
end