class OCI8::Cursor

def self.select_number_as

def self.select_number_as
  case @@bind_unknown_number
  when OCI8::BindType::Fixnum
    return Fixnum
  when OCI8::BindType::Integer
    return Integer
  when OCI8::BindType::Float
    return Float
  end
end

def self.select_number_as=(val)

def self.select_number_as=(val)
  if val == Fixnum
    @@bind_unknown_number = OCI8::BindType::Fixnum
  elsif val == Integer
    @@bind_unknown_number = OCI8::BindType::Integer
  elsif val == Float
    @@bind_unknown_number = OCI8::BindType::Float
  else
    raise ArgumentError, "must be Fixnum, Integer or Float"
  end
end

def [](key)

Returns:
  • (Object) - the value of the bind variable

Parameters:
  • key (Object) -- bind key

Other tags:
    Example: implicitly bind -
    Example: explicitly bind by position -
    Example: explicitly bind by name -
def [](key)
  handle = @bind_handles[key]
  handle && handle.send(:get_data)
end

def []=(key, val)

Parameters:
  • val (Object) -- bind value
  • key (Object) -- bind key
def []=(key, val)
  handle = @bind_handles[key]
  return nil if handle.nil?
  if val.is_a? Array
    if @actual_array_size > 0 && val.length != @actual_array_size
      raise RuntimeError, "all binding arrays hould be the same size"
    end
    if @actual_array_size == 0 && val.length <= @max_array_size
      @actual_array_size = val.length
    end
  end
  handle.send(:set_data, val)
  val
end

def bind_param(key, param, type = nil, length = nil)

cursor.close()
cursor.exec()
cursor.bind_param(1, 'RAW_STRING', OCI8::RAW)
cursor = conn.parse("INSERT INTO raw_table(raw_column) VALUE (:1)")
example:

In case of binding a string as RAW, set OCI::RAW to +type+.

# bound as 7 bytes. So result is cut off at 7 byte.
# Though the length of :out is 8 bytes in PL/SQL block, it is
p cursor[':out'] # => 'DATA_OU'
cursor.exec()
cursor.bind_param(':out', nil, String, 7) # bind as String with width 7.
cursor.bind_param(':in', 'DATA') # bind as String with width 4.
cursor = conn.parse("BEGIN :out := :in || '_OUT'; END;")
example:

string whose length is enough to store or set the length.
+val+. When the bind variable is used as output, set the
In case of binding a string, set the string itself to

cursor.bind_param(1, nil, Float) # bind as Float, Initial value is NULL.
cursor.bind_param(1, nil, Fixnum) # bind as Fixnum, Initial value is NULL.
cursor.bind_param(1, 1234.0) # bind as Float, Initial value is 1234.0.
cursor.bind_param(1, 1234) # bind as Fixnum, Initial value is 1234.
example:

+type+ and Fixnum or Float to +val+.
not supported. If its initial value is NULL, please set nil to
To bind as number, Fixnum and Float are available, but Bignum is

cursor.bind_param(':ename', 'SMITH') # bind by name
# ...or...
cursor.bind_param(1, 'SMITH') # bind by position
cursor = conn.parse("SELECT * FROM emp WHERE ename = :ename")
example:

When key is string, it binds by the name of placeholder.
When key is number, it binds by position, which starts from 1.

Binds variables explicitly.
def bind_param(key, param, type = nil, length = nil)
  case param
  when Hash
  when Class
    param = {:value => nil,   :type => param, :length => length}
  else
    param = {:value => param, :type => type,  :length => length}
  end
  bindobj = make_bind_object(param)
  __bind(key, bindobj)
  if old = @bind_handles[key]
    old.send(:free)
  end
  @bind_handles[key] = bindobj
  self
end

def bind_param_array(key, var_array, type = nil, max_item_length = nil)

cursor.exec_array
cursor.bind_param_array(1, ['happy', 'new', 'year'], String, 30)
cursor.max_array_size = 3
cursor = conn.parse("INSERT INTO test_table VALUES (:str)")
@example

The max_array_size should be set before calling bind_param_array

When key is string, it binds by the name of placeholder.
When key is number, it binds by position, which starts from 1.

Binds array explicitly
def bind_param_array(key, var_array, type = nil, max_item_length = nil)
  raise "please call max_array_size= first." if @max_array_size.nil?
  raise "expect array as input param for bind_param_array." if !var_array.nil? && !(var_array.is_a? Array) 
  raise "the size of var_array should not be greater than max_array_size." if !var_array.nil? && var_array.size > @max_array_size
  if var_array.nil? 
    raise "all binding arrays should be the same size." unless @actual_array_size.nil? || @actual_array_size == 0
    @actual_array_size = 0
  else
    raise "all binding arrays should be the same size." unless @actual_array_size.nil? || var_array.size == @actual_array_size
    @actual_array_size = var_array.size if @actual_array_size.nil?
  end
  
  param = {:value => var_array, :type => type, :length => max_item_length, :max_array_size => @max_array_size}
  first_non_nil_elem = var_array.nil? ? nil : var_array.find{|x| x!= nil}
  
  if type.nil?
    if first_non_nil_elem.nil?
      raise "bind type is not given."
    else
      type = first_non_nil_elem.class
    end
  end
  
  bindclass = OCI8::BindType::Mapping[type]
  if bindclass.nil? and type.is_a? Class
    bindclass = OCI8::BindType::Mapping[type.to_s]
    OCI8::BindType::Mapping[type] = bindclass if bindclass
  end
  raise "unsupported dataType: #{type}" if bindclass.nil?
  bindobj = bindclass.create(@con, var_array, param, @max_array_size)
  __bind(key, bindobj)
  #
  if old = @bind_handles[key]
    old.send(:free)
  end
  @bind_handles[key] = bindobj
  self
end

def bind_params(*bindvars)

def bind_params(*bindvars)
  bindvars.each_with_index do |val, i|
    if val.is_a? Array
      bind_param(i + 1, val[0], val[1], val[2])
    else
      bind_param(i + 1, val)
    end
  end
end

def close

close the cursor.
def close
  free()
  @names = nil
  @column_metadata = nil
end

def column_metadata

Other tags:
    Since: - 1.0.0

Returns:
  • (Array of OCI8::Metadata::Column) -
def column_metadata
  @column_metadata
end

def define(pos, type, length = nil)

cursor.exec()
cursor.define(2, Time) # fetch the second column as Time.
cursor.define(1, String, 20) # fetch the first column as String.
cursor = conn.parse("SELECT ename, hiredate FROM emp")
example:

when type is String.
method within parse and exec. pos starts from 1. lentgh is used
explicitly indicate the date type of fetched value. run this
def define(pos, type, length = nil)
  bindobj = make_bind_object(:type => type, :length => length)
  __define(pos, bindobj)
  if old = @define_handles[pos - 1]
    old.send(:free)
  end
  @define_handles[pos - 1] = bindobj
  self
end

def define_columns

def define_columns
  # http://docs.oracle.com/cd/E11882_01/appdev.112/e10646/ociaahan.htm#sthref5494
  num_cols = attr_get_ub4(18) # OCI_ATTR_PARAM_COUNT(18)
  1.upto(num_cols) do |i|
    parm = __paramGet(i)
    define_one_column(i, parm) unless @define_handles[i - 1]
    @column_metadata[i - 1] = parm
  end
  num_cols
end

def define_one_column(pos, param)

def define_one_column(pos, param)
  bindobj = make_bind_object(param)
  __define(pos, bindobj)
  if old = @define_handles[pos - 1]
    old.send(:free)
  end
  @define_handles[pos - 1] = bindobj
end

def exec(*bindvars)

variables.
though PL/SQL. Use OCI8::Cursor#[] explicitly to get bind
true. In contrast with OCI8#exec, it returns true even
In case of create, alter, drop and PL/SQL statement, it returns

number of processed rows.
In case of insert, update or delete statement, it returns the

select-list.
In case of select statement, it returns the number of the

insert, update and delete; create, alter, drop and PL/SQL.
return value depends on the type of sql statement: select;
Executes the SQL statement assigned the cursor. The type of
def exec(*bindvars)
  bind_params(*bindvars)
  case type
  when :select_stmt
    __execute(0)
    define_columns()
  else
    __execute(1)
    row_count
  end
end

def exec_array

Executes the SQL statement assigned the cursor with array binding
def exec_array
  raise "please call max_array_size= first." if @max_array_size.nil?
  if !@actual_array_size.nil? && @actual_array_size > 0
    __execute(@actual_array_size)
  else
    raise "please set non-nil values to array binding parameters"
  end
  case type
  when :update_stmt, :delete_stmt, :insert_stmt
    row_count
  else
    true
  end
end

def fetch

Returns:
  • (Array) -
def fetch
  if block_given?
    while row = fetch_one_row_as_array
      yield row
    end
    self
  else
    fetch_one_row_as_array
  end
end

def fetch_hash

Returns:
  • (Hash) - the hash keys are column names and hash values are column values
def fetch_hash
  if block_given?
    while row = fetch_one_row_as_hash()
      yield row
    end
  else
    fetch_one_row_as_hash
  end
end

def fetch_one_row_as_array

def fetch_one_row_as_array
  if __fetch(@con)
    @define_handles.collect do |handle|
      handle.send(:get_data)
    end
  else
    nil
  end
end

def fetch_one_row_as_hash

def fetch_one_row_as_hash
  if __fetch(@con)
    ret = {}
    get_col_names.each_with_index do |name, idx|
      ret[name] = @define_handles[idx].send(:get_data)
    end
    ret
  else
    nil
  end
end

def free_bind_handles

def free_bind_handles
  @bind_handles.each_value do |val|
    val.send(:free)
  end
  @bind_handles.clear
end

def get_col_names

method after exec.
Gets the names of select-list as array. Please use this
def get_col_names
  @names ||= @column_metadata.collect { |md| md.name }
end

def initialize(conn, sql = nil)

Parameters:
  • sql (String) -- SQL statement
  • conn (OCI8) -- connection

Other tags:
    Note: - Don't use this constructor. Use {OCI8#parse} instead.
def initialize(conn, sql = nil)
  @bind_handles = {}
  @define_handles = []
  @column_metadata = []
  @names = nil
  @con = conn
  @max_array_size = nil
  __initialize(conn, sql) # Initialize the internal C structure.
end

def keys

Returns:
  • (Array) - bind variable keys
def keys
  @bind_handles.keys
end

def make_bind_object(param)

def make_bind_object(param)
  case param
  when Hash
    key = param[:type]
    val = param[:value]
    max_array_size = param[:max_array_size]
    if key.nil?
      if val.nil?
        raise "bind type is not given."
      elsif val.is_a? OCI8::Object::Base
        key = :named_type
        param = @con.get_tdo_by_class(val.class)
      else
        key = val.class
      end
    elsif key.class == Class && key < OCI8::Object::Base
      param = @con.get_tdo_by_class(key)
      key = :named_type
    elsif key == :named_type
      param = @con.get_tdo_by_typename(param[:length])
    end
  when OCI8::Metadata::Base
    key = param.data_type
    case key
    when :named_type
      if param.type_name == 'XMLTYPE'
        key = :xmltype
      else
        param = @con.get_tdo_by_metadata(param.type_metadata)
      end
    end
  else
    raise "unknown param #{param.intern}"
  end
  bindclass = OCI8::BindType::Mapping[key]
  if bindclass.nil? and key.is_a? Class
    bindclass = OCI8::BindType::Mapping[key.to_s]
    OCI8::BindType::Mapping[key] = bindclass if bindclass
  end
  raise "unsupported datatype: #{key}" if bindclass.nil?
  bindclass.create(@con, val, param, max_array_size)
end

def max_array_size=(size)

all the binding arrays are required to be the same size
Instance variable actual_array_size holds the size of the arrays users actually binds through bind_param_array

All the binds will be clean from cursor if instance variable max_array_size is set before

Set the maximum array size for bind_param_array
def max_array_size=(size)
  raise "expect positive number for max_array_size." if size.nil? && size <=0
  free_bind_handles()  if !@max_array_size.nil?
  @max_array_size = size
  @actual_array_size = nil
end

def prefetch_rows=(rows)

Parameters:
  • rows (Fixnum) -- The number of rows to be prefetched
def prefetch_rows=(rows)
  attr_set_ub4(11, rows) # OCI_ATTR_PREFETCH_ROWS(11)
end

def row_count

Returns:
  • (Integer) -
def row_count
  # http://docs.oracle.com/cd/E11882_01/appdev.112/e10646/ociaahan.htm#sthref5498
  attr_get_ub4(9) # OCI_ATTR_ROW_COUNT(9)
end

def statement

Other tags:
    Since: - 2.1.3

Returns:
  • (String) - prepared SQL statement

Other tags:
    Note: -
def statement
  # The magic number 144 is OCI_ATTR_STATEMENT.
  # See http://docs.oracle.com/cd/E11882_01/appdev.112/e10646/ociaahan.htm#sthref5503
  attr_get_string(144)
end

def type


[ruby-oci8 1.0] OCI8::STMT_* are Fixnums. (1, 2, 3, etc.)
[ruby-oci8 2.0] OCI8::STMT_* are Symbols. (:select_stmt, :update_stmt, etc.)

Changes between ruby-oci8 1.0 and 2.0.

* Other Fixnum value undocumented in Oracle manuals.
* OCI8::STMT_DECLARE (PL/SQL block which starts with a DECLARE keyword)
* OCI8::STMT_BEGIN (PL/SQL block which starts with a BEGIN keyword)
* OCI8::STMT_ALTER
* OCI8::STMT_DROP
* OCI8::STMT_CREATE
* OCI8::STMT_INSERT
* OCI8::STMT_DELETE
* OCI8::STMT_UPDATE
* OCI8::STMT_SELECT
gets the type of SQL statement as follows.
def type
  # http://docs.oracle.com/cd/E11882_01/appdev.112/e10646/ociaahan.htm#sthref5506
  stmt_type = attr_get_ub2(24) # OCI_ATTR_STMT_TYPE(24)
  case stmt_type
  when 1 # OCI_STMT_SELECT
    :select_stmt
  when 2 # OCI_STMT_UPDATE
    :update_stmt
  when 3 # OCI_STMT_DELETE
    :delete_stmt
  when 4 # OCI_STMT_INSERT
    :insert_stmt
  when 5 # OCI_STMT_CREATE
    :create_stmt
  when 6 # OCI_STMT_DROP
    :drop_stmt
  when 7 # OCI_STMT_ALTER
    :alter_stmt
  when 8 # OCI_STMT_BEGIN
    :begin_stmt
  when 9 # OCI_STMT_DECLARE
    :declare_stmt
  else
    stmt_type
  end
end