class OCI8

def self.client_charset_name

Other tags:
    See: OCI8.encoding -

Other tags:
    Private: -

Returns:
  • (String) - client-side character set name

Other tags:
    Since: - 2.1.0
def self.client_charset_name
  @@client_charset_name
end

def self.in_cond(bind_name_prefix, array, type = nil, length = nil)

Returns:
  • (OCI8::InCondBindHelper) -

Parameters:
  • length (Integer) -- maximum bind length for string values. This is used as the fourth argument of {OCI8::Cursor#bind_param}.
  • type (Class) -- data type. This is used as the third argument of {OCI8::Cursor#bind_param}.
  • array (Object) -- an array of values to be bound.
  • bind_name_prefix (Symbol) -- prefix of the place holder name
def self.in_cond(bind_name_prefix, array, type = nil, length = nil)
  InCondBindHelper.new(bind_name_prefix, array, type, length)
end

def self.oracle_client_version

Other tags:
    See: OCI8#oracle_server_version -

Returns:
  • (OCI8::OracleVersion) - Oracle client version
def self.oracle_client_version
  @@oracle_client_version
end

def self.properties

Other tags:
    Since: - 2.0.5

Returns:
  • (a customized Hash) -
def self.properties
  @@properties
end

def database_charset_name

Returns:
  • (String) - Oracle database character set name

Other tags:
    Since: - 2.1.0
def database_charset_name
  charset_id2name(@server_handle.send(:attr_get_ub2, OCI_ATTR_CHARSET_ID))
end

def describe_any(object_name)

Returns:
  • (a subclass of OCI8::Metadata::Base) -

Parameters:
  • object_name (String) --
def describe_any(object_name)
  if /^PUBLIC\.(.*)/i =~ object_name
    md = __describe($1, OCI8::Metadata::Unknown, true)
    raise OCIError.new(4043, object_name) if md.obj_schema != 'PUBLIC'
    md
  else
    __describe(object_name, OCI8::Metadata::Unknown, true)
  end
end

def describe_database(database_name)

Returns:
  • (OCI8::Metadata::Database) -

Parameters:
  • database_name (String) --
def describe_database(database_name)
  __describe(database_name, OCI8::Metadata::Database, false)
end

def describe_function(function_name)

Returns:
  • (OCI8::Metadata::Function) -

Parameters:
  • function_name (String) --
def describe_function(function_name)
  __describe(function_name, OCI8::Metadata::Function, false)
end

def describe_package(package_name)

Returns:
  • (OCI8::Metadata::Package) -

Parameters:
  • package_name (String) --
def describe_package(package_name)
  __describe(package_name, OCI8::Metadata::Package, false)
end

def describe_procedure(procedure_name)

Returns:
  • (OCI8::Metadata::Procedure) -

Parameters:
  • procedure_name (String) --
def describe_procedure(procedure_name)
  __describe(procedure_name, OCI8::Metadata::Procedure, false)
end

def describe_schema(schema_name)

Returns:
  • (OCI8::Metadata::Schema) -

Parameters:
  • schema_name (String) --
def describe_schema(schema_name)
  __describe(schema_name, OCI8::Metadata::Schema, false)
end

def describe_sequence(sequence_name)

Returns:
  • (OCI8::Metadata::Sequence) -

Parameters:
  • sequence_name (String) --
def describe_sequence(sequence_name)
  __describe(sequence_name, OCI8::Metadata::Sequence, false)
end

def describe_synonym(synonym_name, check_public_also = true)

Returns:
  • (OCI8::Metadata::Synonym) -

Parameters:
  • synonym_name (String) --
def describe_synonym(synonym_name, check_public_also = true)
  if /^PUBLIC\.(.*)/i =~ synonym_name
    md = __describe($1, OCI8::Metadata::Synonym, true)
    raise OCIError.new(4043, synonym_name) if md.obj_schema != 'PUBLIC'
    md
  else
    __describe(synonym_name, OCI8::Metadata::Synonym, check_public_also)
  end
end

def describe_table(table_name, table_only = false)

Returns:
  • (OCI8::Metadata::Table or OCI8::Metadata::View) -

Parameters:
  • table_only (Boolean) -- (default: false)
  • table_name (String) --
def describe_table(table_name, table_only = false)
  if table_only
    # check my own tables only.
    __describe(table_name, OCI8::Metadata::Table, false)
  else
    # check tables, views, synonyms and public synonyms.
    # follow synonyms up to 20 times to prevent infinite loop
    # caused by recursive synonyms.
    recursive_level = 20
    recursive_level.times do
      metadata = __describe(table_name, OCI8::Metadata::Unknown, true)
      case metadata
      when OCI8::Metadata::Table, OCI8::Metadata::View
        return metadata
      when OCI8::Metadata::Synonym
        table_name = metadata.translated_name
        if metadata.obj_link and metadata.link.nil?
          # table_name is a synonym in a remote database for an object in the
          # remote database itself.
          table_name = "#{table_name}@#{metadata.obj_link}"
        end
      else
        raise OCIError.new(4043, table_name) # ORA-04043: object %s does not exist
      end
    end
    raise OCIError.new(36, recursive_level) # ORA-00036: maximum number of recursive SQL levels (%s) exceeded
  end
end

def describe_type(type_name)

Returns:
  • (OCI8::Metadata::Type) -

Parameters:
  • type_name (String) --
def describe_type(type_name)
  __describe(type_name, OCI8::Metadata::Type, false)
end

def describe_view(view_name)

Returns:
  • (OCI8::Metadata::View) -

Parameters:
  • view_name (String) --
def describe_view(view_name)
  __describe(view_name, OCI8::Metadata::View, false)
end

def exec(sql, *bindvars, &block)


conn.logoff
conn.exec('CREATE TABLE test (col1 CHAR(6))') # => 0
conn = OCI8.new('scott', 'tiger')
example:

conn.logoff
puts num_rows.to_s + ' rows were updated.'
num_rows = conn.exec('UPDATE emp SET sal = sal * 1.1')
conn = OCI8.new('scott', 'tiger')
example:

It returns the number of processed rows.
== Other SQL statements

conn.exec(sql, *bindvars) { |*outvars| outvars }
FYI, the following code do same on ruby-oci8 1.0 and ruby-oci8 2.0.

conn.logoff
end
puts num # => 123
puts str # => '0123'
conn.exec("BEGIN :str := TO_CHAR(:num, 'FM0999'); END;", 'ABCD', 123) do |str, num|
conn = OCI8.new('scott', 'tiger')

executed.
If a block is given, the bind variables' values are passed to the block after

conn.logoff
# => 1
conn.exec("BEGIN :str := TO_CHAR(:num, 'FM0999'); END;", 'ABCD', 123)
conn = OCI8.new('scott', 'tiger')
example:

It returns the number of processed rows.
== PL/SQL block (ruby-oci8 2.0)

If a block is given, it is ignored.

same with that of bind variables.
which may modified by PL/SQL statement. The order of array is
123". This method returns the array of these bind variables,
is 4 and whose value is 'ABCD'" and "the number whose value is
and :num. These initial values are "the string whose width
Above example uses two bind variables which names are :str

conn.logoff
# => ["0123", 123]
conn.exec("BEGIN :str := TO_CHAR(:num, 'FM0999'); END;", 'ABCD', 123)
conn = OCI8.new('scott', 'tiger')
example:

It returns the array of bind variables' values.
== PL/SQL block (ruby-oci8 1.0)

conn.logoff
puts num_rows.to_s + ' rows were processed.'
end
puts r.join(',')
num_rows = conn.exec('SELECT * FROM emp') do |r|
conn = OCI8.new('scott', 'tiger')
example:

data is passed to the block as array. NULL value becomes nil in ruby.
It acts as iterator and returns the processed row counts. Fetched
== select statements with a block

conn.logoff
cursor.close
end
puts r.join(',')
while r = cursor.fetch()
cursor = conn.exec('SELECT * FROM emp')
conn = OCI8.new('scott', 'tiger')
example:

It returns the instance of OCI8::Cursor.
== select statements without block

before execution.
When bindvars are specified, they are bound as bind variables

create, alter and drop; and PL/SQL.
the type of sql statement: select; insert, update and delete;
Executes the sql statement. The type of return value depends on
def exec(sql, *bindvars, &block)
  @last_error = nil
  exec_internal(sql, *bindvars, &block)
end

def exec_internal(sql, *bindvars)

Other tags:
    Private: -
def exec_internal(sql, *bindvars)
  begin
    cursor = parse(sql)
    ret = cursor.exec(*bindvars)
    case cursor.type
    when :select_stmt
      if block_given?
        cursor.fetch { |row| yield(row) }   # for each row
        ret = cursor.row_count()
      else
        ret = cursor
        cursor = nil # unset cursor to skip cursor.close in ensure block
        ret
      end
    when :begin_stmt, :declare_stmt # PL/SQL block
      if block_given?
        ary = []
        cursor.keys.sort.each do |key|
          ary << cursor[key]
        end
        yield(*ary)
      else
        ret
      end
    else
      ret # number of rows processed
    end
  ensure
    cursor.nil? || cursor.close
  end
end # exec

def get_tdo_by_class(klass)

Other tags:
    Private: -

Returns:
  • (OCI8::TDO) -

Parameters:
  • klass (class of an OCI8::Object::Base's subclass) --
def get_tdo_by_class(klass)
  @id_to_tdo ||= {}
  @name_to_tdo ||= {}
  tdo = @name_to_tdo[klass.typename]
  return tdo if tdo # found in the cache.
  metadata = describe_any(klass.typename)
  if metadata.is_a? OCI8::Metadata::Synonym
    metadata = describe_any(metadata.translated_name)
  end
  unless metadata.is_a? OCI8::Metadata::Type
    raise "unknown typename #{klass.typename}"
  end
  OCI8::TDO.new(self, metadata, klass)
end

def get_tdo_by_metadata(metadata)

Other tags:
    Private: -

Returns:
  • (OCI8::TDO) -

Parameters:
  • metadata (OCI8::Metadata::Base's subclass) --
def get_tdo_by_metadata(metadata)
  @id_to_tdo ||= {}
  @name_to_tdo ||= {}
  tdo = @id_to_tdo[metadata.tdo_id]
  return tdo if tdo
  schema_name = metadata.schema_name
  name = metadata.name
  full_name = schema_name + '.' + name
  klass = OCI8::Object::Base.get_class_by_typename(full_name)
  klass = OCI8::Object::Base.get_class_by_typename(name) if klass.nil?
  if klass.nil?
    if schema_name == username
      eval <<EOS
dule Object
class #{name.downcase.gsub(/(^|_)(.)/) { $2.upcase }} < OCI8::Object::Base
  set_typename('#{name}')
end
d
S
      klass = OCI8::Object::Base.get_class_by_typename(name)
    else
      eval <<EOS
dule Object
module #{schema_name.downcase.gsub(/(^|_)(.)/) { $2.upcase }}
  class #{name.downcase.gsub(/(^|_)(.)/) { $2.upcase }} < OCI8::Object::Base
    set_typename('#{full_name}')
  end
end
d
S
      klass = OCI8::Object::Base.get_class_by_typename(full_name)
    end
  end
  OCI8::TDO.new(self, metadata, klass)
end

def get_tdo_by_typename(typename)

Other tags:
    Private: -

Returns:
  • (OCI8::TDO) -

Parameters:
  • typename (String) --
def get_tdo_by_typename(typename)
  @name_to_tdo ||= {}
  tdo = @name_to_tdo[typename]
  return tdo if tdo
  metadata = describe_any(typename)
  if metadata.is_a? OCI8::Metadata::Synonym
    metadata = describe_any(metadata.translated_name)
  end
  unless metadata.is_a? OCI8::Metadata::Type
    raise "unknown typename #{typename}"
  end
  tdo = get_tdo_by_metadata(metadata)
  @name_to_tdo[typename] = tdo
  tdo
end

def initialize(*args)

Overloads:
  • initialize(username, password, dbname = nil, privilege = nil)
def initialize(*args)
  if args.length == 1
    username, password, dbname, privilege = parse_connect_string(args[0])
  else
    username, password, dbname, privilege = args
  end
  if username.nil? and password.nil?
    cred = OCI_CRED_EXT
  end
  auth_mode = to_auth_mode(privilege)
  stmt_cache_size = OCI8.properties[:statement_cache_size]
  stmt_cache_size = nil if stmt_cache_size == 0
  attach_mode = 0
  if dbname.is_a? OCI8::ConnectionPool
    @pool = dbname # to prevent GC from freeing the connection pool.
    dbname = dbname.send(:pool_name)
    attach_mode |= 0x0200 # OCI_CPOOL
  else
    tcp_connect_timeout = OCI8::properties[:tcp_connect_timeout]
    connect_timeout = OCI8::properties[:connect_timeout]
    tcp_keepalive = OCI8::properties[:tcp_keepalive]
    if tcp_connect_timeout || connect_timeout || tcp_keepalive
      dbname = to_connect_descriptor(dbname, tcp_connect_timeout, connect_timeout, tcp_keepalive)
    end
  end
  if stmt_cache_size
    # enable statement caching
    attach_mode |= 0x0004 # OCI_STMT_CACHE
  end
  # logon by the OCI function OCISessionBegin().
  allocate_handles()
  @session_handle.send(:attr_set_string, OCI_ATTR_USERNAME, username) if username
  @session_handle.send(:attr_set_string, OCI_ATTR_PASSWORD, password) if password
  if @@oracle_client_version >= ORAVER_11_1
    # Sets the driver name displayed in V$SESSION_CONNECT_INFO.CLIENT_DRIVER
    # if both the client and the server are Oracle 11g or upper.
    # Only the first 8 chracters "ruby-oci" are displayed when the Oracle
    # server version is lower than 12.0.1.2.
    # 424: OCI_ATTR_DRIVER_NAME
    @session_handle.send(:attr_set_string, 424, "ruby-oci8 : #{OCI8::VERSION}")
  end
  server_attach(dbname, attach_mode)
  if OCI8.oracle_client_version >= OCI8::ORAVER_11_1
    self.send_timeout = OCI8::properties[:send_timeout] if OCI8::properties[:send_timeout]
    self.recv_timeout = OCI8::properties[:recv_timeout] if OCI8::properties[:recv_timeout]
  end
  session_begin(cred ? cred : OCI_CRED_RDBMS, auth_mode)
  if stmt_cache_size
    # set statement cache size
    attr_set_ub4(176, stmt_cache_size) # 176: OCI_ATTR_STMTCACHESIZE
  end
  @prefetch_rows = 100
  @username = nil
end

def inspect

Other tags:
    Private: -
def inspect
  "#<OCI8:#{username}>"
end

def oracle_server_version

Returns:
  • (OCI8::OracleVersion) -

Other tags:
    See: OCI8.oracle_client_version -
def oracle_server_version
  @oracle_server_version ||= OCI8::OracleVersion.new(oracle_server_vernum)
end

def parse(sql)

Returns:
  • (OCI8::Cursor) -

Parameters:
  • sql (String) -- SQL statement
def parse(sql)
  @last_error = nil
  parse_internal(sql)
end

def parse_internal(sql)

Other tags:
    Private: -
def parse_internal(sql)
  cursor = OCI8::Cursor.new(self, sql)
  cursor
end

def prefetch_rows=(num)

Note: The default value had been 1 before ruby-oci8 2.2.0.

retrieving specified number of rows in one round trip.
prefetch buffer to reduce the number of network round trips by
When a select statement is executed, the OCI library allocate
Sets the prefetch rows size. The default value is 100.
def prefetch_rows=(num)
  @prefetch_rows = num
end

def recv_timeout

Other tags:
    Since: - 2.1.8 and Oracle 11.1

Other tags:
    See: #send_timeout -

Returns:
  • (Float) - seconds
def recv_timeout
  # OCI_ATTR_RECEIVE_TIMEOUT = 436
  @server_handle.send(:attr_get_ub4, 436).to_f / 1000
end

def recv_timeout

def recv_timeout
  raise NotImplementedError, 'recv_timeout is unimplemented in this Oracle version'
end

def recv_timeout=(timeout)

Other tags:
    Since: - 2.1.8 and Oracle 11.1

Other tags:
    See: #send_timeout= -

Returns:
  • (void) -

Parameters:
  • timeout (Float) --
def recv_timeout=(timeout)
  # OCI_ATTR_RECEIVE_TIMEOUT = 436
  @server_handle.send(:attr_set_ub4, 436, timeout * 1000)
end

def recv_timeout=(timeout)

def recv_timeout=(timeout)
  raise NotImplementedError, 'revc_timeout= is unimplemented in this Oracle version'
end

def select_one(sql, *bindvars)

Returns:
  • (Array) - an array of first row.

Parameters:
  • bindvars (Object) -- bind variables
  • sql (String) -- SQL statement
def select_one(sql, *bindvars)
  cursor = self.parse(sql)
  cursor.prefetch_rows = 1
  begin
    cursor.exec(*bindvars)
    row = cursor.fetch
  ensure
    cursor.close
  end
  return row
end

def send_timeout

Other tags:
    Since: - 2.1.8 and Oracle 11.1

Other tags:
    See: #recv_timeout -

Returns:
  • (Float) - seconds
def send_timeout
  # OCI_ATTR_SEND_TIMEOUT = 435
  @server_handle.send(:attr_get_ub4, 435).to_f / 1000
end

def send_timeout

def send_timeout
  raise NotImplementedError, 'send_timeout is unimplemented in this Oracle version'
end

def send_timeout=(timeout)

Other tags:
    Since: - 2.1.8 and Oracle 11.1

Other tags:
    See: #recv_timeout= -

Returns:
  • (void) -

Parameters:
  • timeout (Float) --
def send_timeout=(timeout)
  # OCI_ATTR_SEND_TIMEOUT = 435
  @server_handle.send(:attr_set_ub4, 435, timeout * 1000)
end

def send_timeout=(timeout)

def send_timeout=(timeout)
  raise NotImplementedError, 'send_timeout= is unimplemented in this Oracle version'
end

def to_auth_mode(privilege)

Other tags:
    Private: -
def to_auth_mode(privilege)
  case privilege
  when :SYSDBA
    0x00000002 # OCI_SYSDBA in oci.h
  when :SYSOPER
    0x00000004 # OCI_SYSOPER in oci.h
  when :SYSASM
    if OCI8.oracle_client_version < OCI8::ORAVER_11_1
      raise "SYSASM is not supported on Oracle version #{OCI8.oracle_client_version}"
    end
    0x00008000 # OCI_SYSASM in oci.h
  when :SYSBACKUP
    if OCI8.oracle_client_version < OCI8::ORAVER_12_1
      raise "SYSBACKUP is not supported on Oracle version #{OCI8.oracle_client_version}"
    end
    0x00020000 # OCI_SYSBKP in oci.h
  when :SYSDG
    if OCI8.oracle_client_version < OCI8::ORAVER_12_1
      raise "SYSDG is not supported on Oracle version #{OCI8.oracle_client_version}"
    end
    0x00040000 # OCI_SYSDGD in oci.h
  when :SYSKM
    if OCI8.oracle_client_version < OCI8::ORAVER_12_1
      raise "SYSKM is not supported on Oracle version #{OCI8.oracle_client_version}"
    end
    0x00080000 # OCI_SYSKMT in oci.h
  when nil
    0 # OCI_DEFAULT
  else
    raise "unknown privilege type #{privilege}"
  end
end

def to_connect_descriptor(database, tcp_connect_timeout, connect_timeout, tcp_keepalive)

Other tags:
    Private: -
def to_connect_descriptor(database, tcp_connect_timeout, connect_timeout, tcp_keepalive)
  if @@easy_connect_naming_regex =~ database && ($1 || $2 || $4 || $5 || $6 || $7)
    connect_data = []
    connect_data << "(SERVICE_NAME=#$5)"
    connect_data << "(SERVER=#$6)" if $6
    connect_data << "(INSTANCE_NAME=#$7)" if $7
    desc = []
    desc << "(CONNECT_DATA=#{connect_data.join})"
    desc << "(ADDRESS=(PROTOCOL=TCP)(HOST=#{$2 || $3})(PORT=#{$4 || 1521}))"
    if tcp_connect_timeout
      desc << "(TRANSPORT_CONNECT_TIMEOUT=#{tcp_connect_timeout})"
    end
    if connect_timeout
      desc << "(CONNECT_TIMEOUT=#{connect_timeout})"
    end
    if tcp_keepalive
      desc << "(ENABLE=BROKEN)"
    end
    "(DESCRIPTION=#{desc.join})"
  else
    database
  end
end

def username

def username
  @username || begin
    exec('select user from dual') do |row|
      @username = row[0]
    end
    @username
  end
end