require 'sequel'
Sequel.require 'adapters/shared/oracle'
# The oracle_schemata extension adds some schema related methods to the Oracle database adapater.
module Sequel
module Oracle
module DatabaseMethods
SELECT_INDEXES_SQL = %q{
SELECT i.index_name, i.status, i.uniqueness, ic.column_name
FROM all_indexes i
INNER JOIN all_ind_columns ic ON ic.index_owner = i.owner AND ic.index_name = i.index_name
WHERE i.table_name = ? AND i.dropped = 'NO' 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 status DESC, index_name, ic.column_position
}.freeze
SELECT_PRIMARY_KEY_SQL = %q{
SELECT c.constraint_name, c.index_name, c.status, cc.column_name
FROM all_constraints c
INNER JOIN all_cons_columns cc ON cc.owner = c.owner AND cc.constraint_name = c.constraint_name
WHERE c.table_name = ? AND c.constraint_type = 'P'
ORDER BY status DESC, constraint_name, cc.position
}.freeze
# Returns the indexes for the given table, excluding any primary keys.
def indexes(table)
m = output_identifier_meth
table = m[table]
ixs = Hash.new{|h,k| h[k] = {:table_name=>table, :columns=>[]}}
metadata_dataset.with_sql(SELECT_INDEXES_SQL, table.to_s.upcase).each do |r|
r = Hash[ r.map{|k,v| [k, (k==:index_name || k==:column_name) ? m[v] : v]} ]
ix = ixs[m.call r.delete(:index_name)]
ix[:valid] = r.delete(:status)=='VALID'
ix[:unique] = r.delete(:uniqueness)=='UNIQUE'
ix[:columns] << r.delete(:column_name)
ix.update r
end
ixs
end
# Returns the primary key for the given table, as a hash.
#
# * :enabled - Only look for keys that are enabled (true) or disabled (false). By default (nil),
# looks for all matching keys.
# * :all - Returns all matching keys. By default, returns the first matching key - provided
# that either there is only one key or that only the key is enabled.
# * :first - Returns the first matching key.
def primary_key(table, options={})
sql, m = SELECT_PRIMARY_KEY_SQL, output_identifier_meth
table, pks = m[table], []
pkh = Hash.new{|h,k| pks.push(h[k]=v={:table_name=>table, :columns=>[]}); v }
unless (z = options[:enabled]).nil?
sql = sql.sub /WHERE /, "WHERE c.status = #{z ? 'ENABLED' : 'DISABLED'}"
end
metadata_dataset.with_sql(sql, table.to_s.upcase).each do |r|
if options[:first] && pks.length==1 && r[:constraint_name] != pks[:constraint_name]
return pks.first
end
r = Hash[ r.map{|k,v| [k, (k==:status || v.nil? || v=='') ? v : m[v]]} ]
pk = pkh[m.call r[:constraint_name]]
pk[:enabled] = r.delete(:status)=='ENABLED'
pk[:columns] << r.delete(:column_name)
pk.update r
end
unless options[:all] or (pks.length>1 and pks[0][:enabled] != pks[1][:enabled])
return pks.first
end
pks
end
end
end
end