module OCI8::BindType

def check_type(val)

def check_type(val)
  raise ArgumentError, "invalid argument: #{val.class} (expect OCI8::BLOB)" unless val.is_a? OCI8::BLOB
end

def check_type(val)

def check_type(val)
  raise ArgumentError, "invalid argument: #{val.class} (expect OCI8::CLOB)" unless val.is_a? OCI8::CLOB
end

def check_type(val)

def check_type(val)
  raise ArgumentError, "invalid argument: #{val.class} (expect OCI8::NCLOB)" unless val.is_a? OCI8::NCLOB
end

def check_type(val)

def check_type(val)
  raise ArgumentError, "invalid argument: #{val.class} (expect OCI8::BFILE)" unless val.is_a? OCI8::BFILE
end

def decorate(b)

def decorate(b)
  def b.set(val)
    super(val && ::OraDate.new(val.year, val.mon, val.mday, val.hour, val.min, val.sec))
  end
  def b.get()
    (val = super()) && val.to_time
  end
end

def decorate(b)

def decorate(b)
  def b.set(val)
    super(val && ::OraDate.new(val.year, val.mon, val.mday))
  end
  def b.get()
    (val = super()) && val.to_date
  end
end

def decorate(b)

def decorate(b)
  def b.set(val)
    super(val && ::OraDate.new(val.year, val.mon, val.mday, val.hour, val.min, val.sec))
  end
  def b.get()
    (val = super()) && val.to_datetime
  end
end

def decorate(b)

def decorate(b)
  def b.set(val)
    check_type(val)
    val = val.instance_variable_get(:@locator)
    super(val)
  end
  def b.get()
    (val = super()) && OCI8::BLOB.new(@svc, val.clone(@svc))
  end
end

def decorate(b)

def decorate(b)
  def b.set(val)
    check_type(val)
    val = val.instance_variable_get(:@locator)
    super(val)
  end
  def b.get()
    (val = super()) && OCI8::CLOB.new(@svc, val.clone(@svc))
  end
end

def decorate(b)

def decorate(b)
  b.attrSet(OCI_ATTR_CHARSET_FORM, SQLCS_NCHAR)
  def b.set(val)
    check_type(val)
    val = val.instance_variable_get(:@locator)
    super(val)
  end
  def b.get()
    (val = super()) && OCI8::NCLOB.new(@svc, val.clone(@svc))
  end
end

def decorate(b)

def decorate(b)
  def b.set(val)
    check_type(val)
    val = val.instance_variable_get(:@locator)
    super(val)
  end
  def b.get()
    (val = super()) && OCI8::BFILE.new(@svc, val.clone(@svc))
  end
end

def decorate(b)

def decorate(b)
  def b.get()
    (val = super()) && OCI8::Cursor.new(@env, @svc, @ctx, val)
  end
  def b.pre_fetch_hook()
    set(@env.alloc(OCIStmt))
  end
end

def fix_type(env, val, length, precision, scale)

def fix_type(env, val, length, precision, scale)
  [OCI8::SQLT_CHR, val, length || (val.nil? ? nil : val.length)]
end

def fix_type(env, val, length, precision, scale)

def fix_type(env, val, length, precision, scale)
  [OCI8::SQLT_BIN, val, length || (val.nil? ? nil : val.length)]
end

def fix_type(env, val, length, precision, scale)

def fix_type(env, val, length, precision, scale)
  [OCI8::SQLT_DAT, val, nil]
end

def fix_type(env, val, length, precision, scale)

def fix_type(env, val, length, precision, scale)
  [OCI8::SQLT_DAT, val, nil]
end

def fix_type(env, val, length, precision, scale)

def fix_type(env, val, length, precision, scale)
  [OCI8::SQLT_DAT, val, nil]
end

def fix_type(env, val, length, precision, scale)

def fix_type(env, val, length, precision, scale)
  [OCI8::SQLT_DAT, val, nil]
end

def fix_type(env, val, length, precision, scale)

def fix_type(env, val, length, precision, scale)
  [::Float, val, nil]
end

def fix_type(env, val, length, precision, scale)

def fix_type(env, val, length, precision, scale)
  [SQLT_IBDOUBLE, val, nil]
end

def fix_type(env, val, length, precision, scale)

def fix_type(env, val, length, precision, scale)
  [::Fixnum, val, nil]
end

def fix_type(env, val, length, precision, scale)

def fix_type(env, val, length, precision, scale)
  [::Integer, val, nil]
end

def fix_type(env, val, length, precision, scale)

def fix_type(env, val, length, precision, scale)
  [::OraNumber, val, nil]
end

def fix_type(env, val, length, precision, scale)

def fix_type(env, val, length, precision, scale)
  if scale == -127
    if precision == 0
      # NUMBER declared without its scale and precision. (Oracle 9.2.0.3 or above)
      ::OCI8::BindType::Mapping[:number_no_prec_setting].fix_type(env, val, length, precision, scale)
    else
      # FLOAT or FLOAT(p)
      [::Float, val, nil]
    end
  elsif scale == 0
    if precision == 0
      # NUMBER whose scale and precision is unknown
      # or
      # NUMBER declared without its scale and precision. (Oracle 9.2.0.2 or below)
      ::OCI8::BindType::Mapping[:number_unknown_prec].fix_type(env, val, length, precision, scale)
    elsif precision <= 9
      # NUMBER(p, 0); p is less than or equals to the precision of Fixnum
      [::Fixnum, val, nil]
    else
      # NUMBER(p, 0); p is greater than the precision of Fixnum
      [::Integer, val, nil]
    end
  else
    # NUMBER(p, s)
    if precision < 15 # the precision of double.
      [::Float, val, nil]
    else
      # use BigDecimal instead?
      [::OraNumber, val, nil]
    end
  end
end

def fix_type(env, val, length, precision, scale)

def fix_type(env, val, length, precision, scale)
  [OCI8::SQLT_RDD, nil, val]
end

def fix_type(env, val, length, precision, scale)

def fix_type(env, val, length, precision, scale)
  unless val.nil?
    check_type(val)
    val = val.instance_variable_get(:@locator)
  end
  [OCI8::SQLT_BLOB, nil, val]
end

def fix_type(env, val, length, precision, scale)

def fix_type(env, val, length, precision, scale)
  unless val.nil?
    check_type(val)
    val = val.instance_variable_get(:@locator)
  end
  [OCI8::SQLT_CLOB, nil, val]
end

def fix_type(env, val, length, precision, scale)

def fix_type(env, val, length, precision, scale)
  unless val.nil?
    check_type(val)
    val = val.instance_variable_get(:@locator)
  end
  [OCI8::SQLT_CLOB, nil, val]
end

def fix_type(env, val, length, precision, scale)

def fix_type(env, val, length, precision, scale)
  unless val.nil?
    check_type(val)
    val = val.instance_variable_get(:@locator)
  end
  [OCI8::SQLT_BFILE, nil, val]
end

def fix_type(env, val, length, precision, scale)

def fix_type(env, val, length, precision, scale)
  [OCI8::SQLT_RSET, nil, val]
end