Пример #1
0
/*
 * call-seq:
 *   logoff
 *
 * Disconnects from the Oracle server. The uncommitted transaction is
 * rollbacked.
 */
static VALUE oci8_svcctx_logoff(VALUE self)
{
    oci8_svcctx_t *svcctx = (oci8_svcctx_t *)DATA_PTR(self);
    sword rv;

    while (svcctx->base.children != NULL) {
        oci8_base_free(svcctx->base.children);
    }
    switch (svcctx->logon_type) {
    case T_IMPLICIT:
        oci_lc(OCITransRollback_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, OCI_DEFAULT));
        rv = OCILogoff_nb(svcctx, svcctx->base.hp.svc, oci8_errhp);
        svcctx->base.type = 0;
        svcctx->logon_type = T_NOT_LOGIN;
        if (rv != OCI_SUCCESS)
            oci8_raise(oci8_errhp, rv, NULL);
        svcctx->authhp = NULL;
        svcctx->srvhp = NULL;
        break;
    case T_EXPLICIT:
        oci_lc(OCITransRollback_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, OCI_DEFAULT));
        rv = OCISessionEnd_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, svcctx->authhp, OCI_DEFAULT);
        if (rv == OCI_SUCCESS) {
            rv = OCIServerDetach_nb(svcctx, svcctx->srvhp, oci8_errhp, OCI_DEFAULT);
        }
        svcctx->logon_type = T_NOT_LOGIN;
        if (rv != OCI_SUCCESS)
            oci8_raise(oci8_errhp, rv, NULL);
        break;
    case T_NOT_LOGIN:
        break;
    }
    return Qtrue;
}
Пример #2
0
static VALUE get_rowid_attr(rowid_arg_t *arg)
{
    oci8_base_t *base = arg->base;
    ub4 attrtype = arg->attrtype;
    char buf[MAX_ROWID_LEN];
    ub2 buflen;
    sword rv;

    /* get a rowid descriptor from OCIHandle */
    rv = OCIDescriptorAlloc(oci8_envhp, (dvoid*)&arg->ridp, OCI_DTYPE_ROWID, 0, NULL);
    if (rv != OCI_SUCCESS)
        oci8_env_raise(oci8_envhp, rv);
    rv = OCIAttrGet(base->hp.ptr, base->type, arg->ridp, 0, attrtype, oci8_errhp);
    if (rv != OCI_SUCCESS) {
        oci8_raise(oci8_errhp, rv, NULL);
    }
    /* convert the rowid descriptor to a string. */
    if (have_OCIRowidToChar) {
        /* If OCIRowidToChar is available, use it. */
        buflen = MAX_ROWID_LEN;
        rv = OCIRowidToChar(arg->ridp, TO_ORATEXT(buf), &buflen, oci8_errhp);
        if (rv != OCI_SUCCESS) {
            oci8_raise(oci8_errhp, rv, NULL);
        }
    } else {
        /* If OCIRowidToChar is not available, convert it on
         * Oracle Server.
         */
        oci8_base_t *svc;
        oci8_exec_sql_var_t define_var;
        oci8_exec_sql_var_t bind_var;

        /* search a connection from the handle */
        svc = base;
        while (svc->type != OCI_HTYPE_SVCCTX) {
            svc = svc->parent;
            if (svc == NULL) {
                rb_raise(rb_eRuntimeError, "No connection is found!!");
            }
        }
        /* :strval */
        define_var.valuep = buf;
        define_var.value_sz = sizeof(buf);
        define_var.dty = SQLT_CHR;
        define_var.indp = NULL;
        define_var.alenp = &buflen;
        /* :rowid */
        bind_var.valuep = &arg->ridp;
        bind_var.value_sz = sizeof(void *);
        bind_var.dty = SQLT_RDD;
        bind_var.indp = NULL;
        bind_var.alenp = NULL;
        /* convert the rowid descriptor to a string value by querying Oracle server. */
        oci8_exec_sql((oci8_svcctx_t*)svc, "SELECT :rid FROM dual", 1, &define_var, 1, &bind_var, 1);
        if (buflen == 0) {
            return Qnil;
        }
    }
    return rb_external_str_new_with_enc(buf, buflen, rb_usascii_encoding());
}
Пример #3
0
/*
=begin
--- OCIStmt#execute(svc [, iters [, mode]])
     execute statement at the ((<service context handle|OCISvcCtx>)).

     :svc
        ((<service context handle|OCISvcCtx>))
     :iters
        the number of iterations to execute.

        For select statement, if there are columns which is not defined
        by ((<OCIStmt#defineByPos>)) and this value is positive, it 
        raises exception. If zero, no exception. In any case you must define
        all columns before you call ((<OCIStmt#fetch>)).

        For non-select statement, use positive value.

        Default value is 0 for select statement, 1 for non-select statement.

        note: Current implemantation doesn't support array fetch and batch mode, so
        valid value is 0 or 1.
     :mode
        ((|OCI_DEFAULT|)), ((|OCI_BATCH_ERRORS|)), ((|OCI_COMMIT_ON_SUCCESS|)),
        ((|OCI_DESCRIBE_ONLY|)), ((|OCI_EXACT_FETCH|)), ((|OCI_PARSE_ONLY|)), 
        any combinations of previous values, or ((|OCI_STMT_SCROLLABLE_READONLY|)).
        Default value is ((|OCI_DEFAULT|)).

        ((|OCI_BATCH_ERRORS|)) and ((|OCI_STMT_SCROLLABLE_READONLY|)) are not
        supported by current implementation.

     correspond native OCI function: ((|OCIStmtExecute|))
=end
*/
static VALUE oci8_stmt_execute(int argc, VALUE *argv, VALUE self)
{
  VALUE vsvc;
  VALUE viters;
  VALUE vmode;
  oci8_handle_t *h;
  oci8_handle_t *svch;
  ub4 mode;
  ub4 iters;
  ub2 stmt_type;
  sword rv;

  rb_scan_args(argc, argv, "12", &vsvc, &viters, &vmode);
  Get_Handle(self, h); /* 0 */
  Check_Handle(vsvc, OCISvcCtx, svch); /* 1 */
  if (argc >= 2) {
    iters = NUM2UINT(viters); /* 2 */
  } else {
    rv = OCIAttrGet(h->hp, OCI_HTYPE_STMT, &stmt_type, 0, OCI_ATTR_STMT_TYPE, h->errhp);
    if (rv != OCI_SUCCESS) {
      oci8_raise(h->errhp, rv, h->hp);
    }
    if (stmt_type == OCI_STMT_SELECT) {
      /* for select statement, default value 0. */
      iters = 0;
    } else {
      /* for non-select statement, default value 0. */
      iters = 1;
    }
  }
  Get_Int_With_Default(argc, 3, vmode, mode, OCI_DEFAULT); /* 3 */

  if (iters > 1) {
    rb_raise(rb_eArgError, "current implementation doesn't support array fatch or batch mode");
  }

  rv = OCIStmtExecute(svch->hp, h->hp, h->errhp, iters, 0, NULL, NULL, mode);
  if (rv == OCI_ERROR) {
    sb4 errcode;
    OCIErrorGet(h->errhp, 1, NULL, &errcode, NULL, 0, OCI_HTYPE_ERROR);
    if (errcode == 1000) {
      /* run GC to close unreferred cursors when ORA-01000 (maximum open cursors exceeded). */
      rb_gc();
      rv = OCIStmtExecute(svch->hp, h->hp, h->errhp, iters, 0, NULL, NULL, mode);
    }
  }
  if (IS_OCI_ERROR(rv)) {
    oci8_raise(h->errhp, rv, h->hp);
  }
  return self;
}
Пример #4
0
/*
=begin
--- OCIStmt#fetch([nrows [, orientation [, mode]]])
     fetch data from select statement.
     fetched data are stored to previously defined ((<define handle|OCIDefine>)).

     :nrows
        number of rows to fetch. If zero, cancel the cursor.
        The default value is 1.

        Because array fetch is not supported, valid value is 0 or 1.

     :orientation
        orientation to fetch. ((|OCI_FETCH_NEXT|)) only valid.
        The default value is ((|OCI_FETCH_NEXT|)).

     :mode
        ((|OCI_DEFULT|)) only valid. 
        The default value is ((|OCI_DEFAULT|)).

     :return value
        array of define handles, which are defined previously,
        or nil when end of data.

     correspond native OCI function: ((|OCIStmtFetch|))
=end
*/
static VALUE oci8_stmt_fetch(int argc, VALUE *argv, VALUE self)
{
  VALUE vnrows;
  VALUE vorientation;
  VALUE vmode;
  oci8_handle_t *h;
  ub4 nrows;
  ub2 orientation;
  ub4 mode;
  sword rv;

  rb_scan_args(argc, argv, "03", &vnrows, &vorientation, &vmode);
  Get_Handle(self, h); /* 0 */
  Get_Int_With_Default(argc, 1, vnrows, nrows, 1); /* 1 */
  Get_Int_With_Default(argc, 2, vorientation, orientation, OCI_FETCH_NEXT); /* 2 */
  Get_Int_With_Default(argc, 3, vmode, mode, OCI_DEFAULT); /* 3 */

  rv = OCIStmtFetch(h->hp, h->errhp, nrows, orientation, mode);
  if (rv == OCI_NO_DATA) {
    return Qnil;
  }
  if (IS_OCI_ERROR(rv)) {
    oci8_raise(h->errhp, rv, h->hp);
  }
  return rb_ivar_get(self, oci8_id_define_array);
}  
Пример #5
0
VALUE oci8_get_sb2_attr(oci8_base_t *base, ub4 attrtype)
{
    sb2 val;
    sword rv;

    rv = OCIAttrGet(base->hp.ptr, base->type, &val, NULL, attrtype, oci8_errhp);
    if (rv != OCI_SUCCESS)
        oci8_raise(oci8_errhp, rv, NULL);
    return INT2FIX(val);
}
Пример #6
0
VALUE oci8_reset(VALUE self)
{
    oci8_handle_t *h;
    sword rv;

    Get_Handle(self, h); /* 0 */
    rv = OCIReset(h->hp, h->errhp);
    if (rv != OCI_SUCCESS)
        oci8_raise(h->errhp, rv, NULL);
    return self;
}
Пример #7
0
VALUE oci8_get_string_attr(oci8_base_t *base, ub4 attrtype)
{
    text *val;
    ub4 size;
    sword rv;

    rv = OCIAttrGet(base->hp.ptr, base->type, &val, &size, attrtype, oci8_errhp);
    if (rv != OCI_SUCCESS)
        oci8_raise(oci8_errhp, rv, NULL);
    return rb_external_str_new_with_enc(TO_CHARPTR(val), size, oci8_encoding);
}
Пример #8
0
/*
=begin
--- OCIServer#version()
     get server version.

     :return value
        string of server version. For example
          Oracle8 Release 8.0.5.0.0 - Production
          PL/SQL Release 8.0.5.0.0 - Production

     correspond native OCI function: ((|OCIServerVersion|))
=end
*/
VALUE oci8_server_version(VALUE self)
{
    oci8_handle_t *h;
    OraText buf[1024];
    sword rv;

    Get_Handle(self, h); /* 0 */
    rv = OCIServerVersion(h->hp, h->errhp, buf, sizeof(buf), h->type);
    if (rv != OCI_SUCCESS)
        oci8_raise(h->errhp, rv, NULL);
    return rb_str_new2(TO_CHARPTR(buf));
}
Пример #9
0
/*
=begin
--- OCISvcCtx#logoff()
     disconnect from Oracle.

     If you use ((<OCIServer#attach>)) and ((<OCISession#begin>)) to logon,
     use ((<OCIServer#detach>)) and ((<OCISession#end>)) instead.
     See also ((<Simplified Logon>)) and ((<Explicit Attach and Begin Session>)).

     correspond native OCI function: ((|OCILogoff|))
=end
*/
static VALUE oci8_svcctx_logoff(VALUE self)
{
  oci8_handle_t *h;
  sword rv;

  Get_Handle(self, h); /* 0 */

  rv = OCILogoff(h->hp, h->errhp);
  if (rv != OCI_SUCCESS)
    oci8_raise(h->errhp, rv, NULL);
  return self;
}
Пример #10
0
static VALUE oci8_close_all_files(VALUE self)
{
  oci8_handle_t *h;
  sword rv;

  Get_Handle(self, h); /* 0 */
  rv = OCILobFileCloseAll(h->hp, h->errhp);
  if (rv != OCI_SUCCESS) {
    oci8_raise(h->errhp, rv, NULL);
  }
  return self;
}
Пример #11
0
VALUE oci8_server_release(VALUE self)
{
    oci8_handle_t *h;
    OraText buf[1024];
    ub4 version = 0;
    sword rv;

    Get_Handle(self, h); /* 0 */
    rv = OCIServerRelease(h->hp, h->errhp, buf, sizeof(buf), h->type, &version);
    if (rv != OCI_SUCCESS)
        oci8_raise(h->errhp, rv, NULL);
    return rb_ary_new3(2, INT2FIX(version), rb_str_new2(buf));
}
Пример #12
0
/*
=begin
--- OCIStmt#bindByName(name, type [, length [, mode]])
     define the datatype of the bind variable by name.

     :name
        the name of the bind variable including colon.
     :type
        the type of the bind variable.
        ((|String|)), ((|Fixnum|)), ((|Integer|)), ((|Float|)), ((|Time|)),
        ((<OraDate>)), ((<OraNumber>)), or ((|OCI_TYPECODE_RAW|))
     :length
        When the 2nd argument is 
        * ((|String|)) or ((|OCI_TYPECODE_RAW|)),
          the max length of fetched data.
        * otherwise,
          its value is ignored.
     :mode
        ((|OCI_DEFAULT|)), or ((|OCI_DATA_AT_EXEC|)). But now available value is 
        ((|OCI_DEFAULT|)) only. Default value is ((|OCI_DEFAULT|))
     :return value
        newly created ((<bind handle|OCIBind>))

     for example
       stmt = env.alloc(OCIStmt)
       stmt.prepare("SELECT * FROM EMP
                      WHERE ename = :ENAME
                        AND sal > :SAL
                        AND hiredate >= :HIREDATE")
       b_ename = stmt.bindByName(":ENAME", String, 10)
       b_sal = stmt.bindByName(":SAL", Fixnum)
       b_hiredate = stmt.bindByName(":HIREDATE", OraDate)

     correspond native OCI function: ((|OCIBindByName|))
=end
 */
static VALUE oci8_bind_by_name(int argc, VALUE *argv, VALUE self)
{
  VALUE vplaceholder;
  VALUE vtype;
  VALUE vlength;
  VALUE vmode;
  oci8_handle_t *h;
  oci8_string_t placeholder;
  oci8_bind_handle_t *bh;
  ub2 dty;
  ub4 mode;
  dvoid *indp;
  ub2 *rlenp;
  dvoid *valuep;
  OCIBind *bindhp = NULL;
  sword status;
  VALUE hash;
  VALUE obj;

  rb_scan_args(argc, argv, "22", &vplaceholder, &vtype, &vlength, &vmode);
  Get_Handle(self, h); /* 0 */
  Get_String(vplaceholder, placeholder); /* 1 */
  check_bind_type(OCI_HTYPE_BIND, h, vtype, vlength, &bh, &dty); /* 2, 3 */
  Get_Int_With_Default(argc, 4, vmode, mode, OCI_DEFAULT); /* 4 */

  if (mode & OCI_DATA_AT_EXEC) {
    indp = NULL;
    rlenp = NULL;
  } else {
    indp = &(bh->ind);
    rlenp = (bh->bind_type == BIND_STRING) ? NULL : &bh->rlen;
  }
  valuep = &bh->value;
  status = OCIBindByName(h->hp, &bindhp, h->errhp, placeholder.ptr, placeholder.len, valuep, bh->value_sz, dty, indp, rlenp, 0, 0, 0, mode);
  if (status != OCI_SUCCESS) {
    oci8_unlink((oci8_handle_t *)bh);
    bh->type = 0;
    oci8_raise(h->errhp, status, h->hp);
  }
  bh->type = OCI_HTYPE_BIND;
  bh->hp = bindhp;
  bh->errhp = h->errhp;
  obj = bh->self;
  hash = rb_ivar_get(self, oci8_id_bind_hash);
  if (hash == Qnil) {
    hash = rb_hash_new();
    rb_ivar_set(self, oci8_id_bind_hash, hash);
  }
  rb_hash_aset(hash, vplaceholder, obj);
  return obj;
}
Пример #13
0
/*
=begin
--- OCIStmt#defineByPos(position, type [, length [, mode]])
     define the datatype of fetched column.
     You must define all column's datatype, before you fetch data.

     :position
        the position of the column. It starts from 1.
     :type
        the type of column. 
        ((|String|)), ((|Fixnum|)), ((|Integer|)), ((|Float|)), ((|Time|)),
        ((<OraDate>)), ((<OraNumber>)), or ((|OCI_TYPECODE_RAW|))
     :length
        When the 2nd argument is 
        * ((|String|)) or ((|OCI_TYPECODE_RAW|)),
          the max length of fetched data.
        * otherwise,
          its value is ignored.
     :mode
        ((|OCI_DEFAULT|)), or ((|OCI_DYNAMIC_FETCH|)). But now available value is 
        ((|OCI_DEFAULT|)) only. Default value is ((|OCI_DEFAULT|))
     :return value
        newly created ((<define handle|OCIDefine>))

     correspond native OCI function: ((|OCIDefineByPos|))
=end
 */
static VALUE oci8_define_by_pos(int argc, VALUE *argv, VALUE self)
{
  VALUE vposition;
  VALUE vtype;
  VALUE vlength;
  VALUE vmode;
  oci8_handle_t *h;
  ub4 position;
  oci8_bind_handle_t *bh;
  ub2 dty;
  ub4 mode;
  dvoid *indp;
  ub2 *rlenp;
  dvoid *valuep;
  OCIDefine *dfnhp = NULL;
  sword status;
  VALUE ary;
  VALUE obj;

  rb_scan_args(argc, argv, "22", &vposition, &vtype, &vlength, &vmode);
  Get_Handle(self, h); /* 0 */
  position = NUM2INT(vposition); /* 1 */
  check_bind_type(OCI_HTYPE_DEFINE, h, vtype, vlength, &bh, &dty); /* 2, 3 */
  Get_Int_With_Default(argc, 4, vmode, mode, OCI_DEFAULT); /* 4 */

  if (mode & OCI_DYNAMIC_FETCH) {
    indp = NULL;
    rlenp = NULL;
  } else {
    indp = &(bh->ind);
    rlenp = (bh->bind_type == BIND_STRING) ? NULL : &bh->rlen;
  }
  valuep = &bh->value;
  status = OCIDefineByPos(h->hp, &dfnhp, h->errhp, position, valuep, bh->value_sz, dty, indp, rlenp, 0, mode);
  if (status != OCI_SUCCESS) {
    oci8_unlink((oci8_handle_t *)bh);
    bh->type = 0;
    oci8_raise(h->errhp, status, h->hp);
  }
  bh->type = OCI_HTYPE_DEFINE;
  bh->hp = dfnhp;
  bh->errhp = h->errhp;
  obj = bh->self;
  ary = rb_ivar_get(self, oci8_id_define_array);
  if (ary == Qnil) {
    ary = rb_ary_new();
    rb_ivar_set(self, oci8_id_define_array, ary);
  }
  rb_ary_store(ary, position - 1, obj);
  return obj;
}
Пример #14
0
VALUE oci8_get_ub4_attr(oci8_base_t *base, ub4 attrtype)
{
    ub4 val;
    sword rv;

    rv = OCIAttrGet(base->hp.ptr, base->type, &val, NULL, attrtype, oci8_errhp);
    if (rv != OCI_SUCCESS)
        oci8_raise(oci8_errhp, rv, NULL);
#if SIZEOF_LONG > 4
    return LONG2FIX(val);
#else
    return ULONG2NUM(val);
#endif
}
Пример #15
0
/*
 *  call-seq:
 *     onum.to_char(fmt = nil, nls_params = nil)  -> string
 *
 *  Returns a string containing a representation of self.
 *  <i>fmt</i> and <i>nls_params</i> are same meanings with
 *  <code>TO_CHAR</code> of Oracle function.
 */
static VALUE onum_to_char(int argc, VALUE *argv, VALUE self)
{
    OCIError *errhp = oci8_errhp;
    VALUE fmt;
    VALUE nls_params;
    char buf[512];
    ub4 buf_size = sizeof(buf);
    oratext *fmt_ptr;
    oratext *nls_params_ptr;
    ub4 fmt_len;
    ub4 nls_params_len;
    sword rv;

    rb_scan_args(argc, argv, "02", &fmt /* nil */, &nls_params /* nil */);
    if (NIL_P(fmt)) {
        rv = oranumber_to_str(_NUMBER(self), buf, sizeof(buf));
        if (rv > 0) {
            return rb_usascii_str_new(buf, rv);
        }
        oranumber_dump(_NUMBER(self), buf);
        rb_raise(eOCIException, "Invalid internal number format: %s", buf);
    }
    StringValue(fmt);
    fmt_ptr = RSTRING_ORATEXT(fmt);
    fmt_len = RSTRING_LEN(fmt);
    if (NIL_P(nls_params)) {
        nls_params_ptr = NULL;
        nls_params_len = 0;
    } else {
        StringValue(nls_params);
        nls_params_ptr = RSTRING_ORATEXT(nls_params);
        nls_params_len = RSTRING_LEN(nls_params);
    }
    rv = OCINumberToText(errhp, _NUMBER(self),
                         fmt_ptr, fmt_len, nls_params_ptr, nls_params_len,
                         &buf_size, TO_ORATEXT(buf));
    if (rv == OCI_ERROR) {
        sb4 errcode;
        OCIErrorGet(errhp, 1, NULL, &errcode, NULL, 0, OCI_HTYPE_ERROR);
        if (errcode == 22065) {
            /* OCI-22065: number to text translation for the given format causes overflow */
            if (NIL_P(fmt)) /* implicit conversion */
                return rb_usascii_str_new_cstr("overflow");
        }
        oci8_raise(errhp, rv, NULL);
    }
    return rb_usascii_str_new(buf, buf_size);
}
Пример #16
0
static VALUE get_param(oci8_handle_t *hp, ub4 attr)
{
    OCIParam *parmhp;
    ub4 as = 0;
    oci8_handle_t *parmh;
    oci8_handle_t *parenth;
    sword rv;

    rv = OCIAttrGet(hp->hp, hp->type, &parmhp, &as, attr, hp->errhp);
    if (rv != OCI_SUCCESS)
        oci8_raise(hp->errhp, rv, NULL);

    for (parenth = hp; parenth->type == OCI_DTYPE_PARAM; parenth = parenth->parent);
    parmh = oci8_make_handle(OCI_DTYPE_PARAM, parmhp, hp->errhp, parenth, 0);
    return parmh->self;
}
Пример #17
0
static void call_session_end(oci8_svcctx_t *svcctx)
{
    sword rv = OCI_SUCCESS;

    if (svcctx->state & OCI8_STATE_SESSION_BEGIN_WAS_CALLED) {
        rv = OCISessionEnd_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, svcctx->session->hp.authhp, OCI_DEFAULT);
        svcctx->state &= ~OCI8_STATE_SESSION_BEGIN_WAS_CALLED;
    }
    if (svcctx->state & OCI8_STATE_SERVER_ATTACH_WAS_CALLED) {
        rv = OCIServerDetach_nb(svcctx, svcctx->server->hp.srvhp, oci8_errhp, OCI_DEFAULT);
        svcctx->state &= ~OCI8_STATE_SERVER_ATTACH_WAS_CALLED;
    }
    svcctx->logoff_method = NULL;
    if (rv != OCI_SUCCESS) {
        oci8_raise(oci8_errhp, rv, NULL);
    }
}
Пример #18
0
/*
=begin
--- OCIServer#detach([mode])
     detach from the database.

     :mode
        ((|OCI_DEFAULT|)) only valid. Default value is ((|OCI_DEFAULT|)).

     correspond native OCI function: ((|OCIServerDetach|))
=end
*/
static VALUE oci8_server_detach(int argc, VALUE *argv, VALUE self)
{
    VALUE vmode;
    oci8_handle_t *h;
    ub4 mode;
    sword rv;


    rb_scan_args(argc, argv, "01", &vmode);
    Get_Handle(self, h); /* 0 */
    Get_Int_With_Default(argc, 1, vmode, mode, OCI_DEFAULT); /* 1 */

    rv = OCIServerDetach(h->hp, h->errhp, mode);
    if (rv != OCI_SUCCESS)
        oci8_raise(h->errhp, rv, NULL);
    return self;
}
Пример #19
0
/*
=begin

--- OCISvcCtx#rollback([flags])
     rollback the transaction.

     :flags
        ((|OCI_DEFAULT|)) only valid. Default value is ((|OCI_DEFAULT|)).

     correspond native OCI function: ((|OCITransRollback|))
=end
*/
static VALUE oci8_trans_rollback(int argc, VALUE *argv, VALUE self)
{
  VALUE vflags;
  oci8_handle_t *h;
  ub4 flags;
  sword rv;

  rb_scan_args(argc, argv, "01", &vflags);
  Get_Handle(self, h); /* 0 */
  Get_Int_With_Default(argc, 1, vflags, flags, OCI_DEFAULT); /* 1 */

  rv = OCITransRollback(h->hp, h->errhp, flags);
  if (rv != OCI_SUCCESS) {
    oci8_raise(h->errhp, rv, NULL);
  }
  return self;
}
Пример #20
0
/*
=begin
--- OCISession#end(svc [, vmode])
     terminate user Authentication Context

     :svc
        ((<OCISvcCtx>)).
     :mode
        ((|OCI_DEFAULT|)) only valid. Defalt value is ((|OCI_DEFAULT|)).

     correspond native OCI function: ((|OCISessionEnd|))
=end
*/
static VALUE oci8_session_end(int argc, VALUE *argv, VALUE self)
{
  VALUE vsvc, vmode;
  oci8_handle_t *h;
  oci8_handle_t *svch;
  ub4 mode;
  sword rv;

  rb_scan_args(argc, argv, "11", &vsvc, &vmode);
  Get_Handle(self, h); /* 0 */
  Check_Handle(vsvc, OCISvcCtx, svch); /* 1 */
  Get_Int_With_Default(argc, 2, vmode, mode, OCI_DEFAULT); /* 2 */

  rv = OCISessionEnd(svch->hp, h->errhp, h->hp, mode);
  if (rv != OCI_SUCCESS)
    oci8_raise(h->errhp, rv, NULL);
  return self;
}
Пример #21
0
/*
 * call-seq:
 *   break
 *
 * Cancels the executing SQL.
 *
 * See also #non_blocking=.
 */
static VALUE oci8_break(VALUE self)
{
    oci8_svcctx_t *svcctx = DATA_PTR(self);
#ifndef HAVE_RB_THREAD_BLOCKING_REGION
    sword rv;
#endif

    if (NIL_P(svcctx->executing_thread)) {
        return Qfalse;
    }
#ifndef HAVE_RB_THREAD_BLOCKING_REGION
    rv = OCIBreak(svcctx->base.hp.ptr, oci8_errhp);
    if (rv != OCI_SUCCESS)
        oci8_raise(oci8_errhp, rv, NULL);
#endif
    rb_thread_wakeup(svcctx->executing_thread);
    return Qtrue;
}
Пример #22
0
/*
=begin
--- OCIServer#attach(dbname [, mode])
     attach to the database.
     :dbname
        the name of database.
     :mode
        ((|OCI_DEFAULT|)) or ((|OCI_CPOOL|))(Oracle 9i). Default value is ((|OCI_DEFAULT|)).

        This ruby module doesn't support the connection pooling provided by OCI,
        so ((|OCI_CPOOL|)) is invalid value for now.

     correspond native OCI function: ((|OCIServerAttach|))
=end
*/
static VALUE oci8_server_attach(int argc, VALUE *argv, VALUE self)
{
    VALUE vdbname, vmode;
    oci8_handle_t *h;
    oci8_string_t d;
    ub4 mode;
    sword rv;

    rb_scan_args(argc, argv, "11", &vdbname, &vmode);
    Get_Handle(self, h); /* 0 */
    Get_String(vdbname, d); /* 1 */
    Get_Int_With_Default(argc, 2, vmode, mode, OCI_DEFAULT); /* 2 */

    rv = OCIServerAttach(h->hp, h->errhp, d.ptr, d.len, mode);
    if (rv != OCI_SUCCESS)
        oci8_raise(h->errhp, rv, NULL);
    return self;
}
Пример #23
0
/*
=begin
--- OCIStmt#prepare(stmt [, language [, mode]])
     set and prepare SQL statement.

     :stmt
        SQL or PL/SQL statement
     :language
        ((|OCI_NTV_SYNTAX|)), ((|OCI_V7_SYNTAX|)), or ((|OCI_V8_SYNTAX|)).
        Default value is ((|OCI_NTV_SYNTAX|))
     :mode
        ((|OCI_DEFAULT|)) or ((|OCI_NO_SHARING|)). Default value is ((|OCI_DEFAULT|)).

        ((|OCI_NO_SHARING|)) disables ((<Shared Data Mode>)) for this statement.

     correspond native OCI function: ((|OCIStmtPrepare|))
=end
 */
static VALUE oci8_stmt_prepare(int argc, VALUE *argv, VALUE self)
{
  VALUE vsql, vlanguage, vmode;
  oci8_handle_t *h;
  oci8_string_t s;
  ub4 language;
  ub4 mode;
  sword rv;
  VALUE ary;
  VALUE hash;
  int i;

  rb_scan_args(argc, argv, "12", &vsql, &vlanguage, &vmode);
  Get_Handle(self, h); /* 0 */
  Get_String(vsql, s); /* 1 */
  Get_Int_With_Default(argc, 2, vlanguage, language, OCI_NTV_SYNTAX); /* 2 */
  Get_Int_With_Default(argc, 3, vmode, mode, OCI_DEFAULT); /* 3 */

  /* when a new statement is prepared, OCI implicitly free the previous 
   * statement's define and bind handles. 
   * But ruby's object don't know it. So free these handles in advance.
   */
  /* free define handles */
  ary = rb_ivar_get(self, oci8_id_define_array);
  if (ary != Qnil) {
    for (i = 0;i < RARRAY_LEN(ary);i++) {
      if (RARRAY_PTR(ary)[i] != Qnil)
	oci8_handle_free(RARRAY_PTR(ary)[i]);
    }
    rb_ivar_set(self, oci8_id_define_array, Qnil);
  }
  /* free bind handles */
  hash = rb_ivar_get(self, oci8_id_bind_hash);
  if (hash != Qnil) {
    rb_iterate(oci8_each_value, hash, oci8_handle_free, Qnil);
    rb_ivar_set(self, oci8_id_bind_hash, Qnil);
  }

  rv = OCIStmtPrepare(h->hp, h->errhp, s.ptr, s.len, language, mode);
  if (IS_OCI_ERROR(rv)) {
    oci8_raise(h->errhp, rv, h->hp);
  }
  return self;
}
Пример #24
0
/* THIS WILL BE DELETED IN FUTURE RELEASE. */
static VALUE oci8_describe_any(VALUE self, VALUE vdsc, VALUE vname, VALUE vtype)
{
  oci8_handle_t *h;
  oci8_handle_t *dsch;
  oci8_string_t name;
  ub1 type;
  sword rv;

  Get_Handle(self, h); /* 0 */
  Check_Handle(vdsc, OCIDescribe, dsch); /* 1 */
  Get_String(vname, name); /* 2 */
  type = FIX2INT(vtype); /* 3 */

  rv = OCIDescribeAny(h->hp, h->errhp, name.ptr, name.len, OCI_OTYPE_NAME, OCI_DEFAULT, type, dsch->hp);
  if (rv != OCI_SUCCESS) {
    oci8_raise(h->errhp, rv, NULL);
  }
  return self;
}
Пример #25
0
/*
=begin
--- OCISvcCtx#passwordChange(username, old_password, new_password [, mode])
     :username
        the username.
     :old_password
        old password of the user.
     :new_password
        new password of the user.
     :mode
        ((|OCI_DEFAULT|)) or ((|OCI_AUTH|)). Default value is ((|OCI_DEFAULT|)).

        For most cases, use default value. If you want to know detail,
        see "Oracle Call Interface Programmer's Guide".

     correspond native OCI function: ((|OCIPasswordChange|))
=end
*/
static VALUE oci8_password_change(int argc, VALUE *argv, VALUE self)
{
  VALUE vusername, vopasswd, vnpasswd, vmode;
  oci8_handle_t *h;
  oci8_string_t username, opasswd, npasswd;
  ub4 mode;
  sword rv;

  rb_scan_args(argc, argv, "31", &vusername, &vopasswd, &vnpasswd, &vmode);
  Get_Handle(self, h); /* 0 */
  Get_String(vusername, username); /* 1 */
  Get_String(vopasswd, opasswd); /* 2 */
  Get_String(vnpasswd, npasswd); /* 3 */
  Get_Int_With_Default(argc, 4, vmode, mode, OCI_DEFAULT); /* 4 */

  rv = OCIPasswordChange(h->hp, h->errhp, username.ptr, username.len,
			 opasswd.ptr, opasswd.len, npasswd.ptr, npasswd.len, mode);
  if (rv != OCI_SUCCESS) {
    oci8_raise(h->errhp, rv, NULL);
  }
  return self;
}
Пример #26
0
static VALUE oci8_lob_clone(VALUE self)
{
    oci8_lob_t *lob = DATA_PTR(self);
    oci8_lob_t *newlob;
    VALUE newobj;
    sword rv;
    boolean is_temporary;

    newobj = rb_funcall(CLASS_OF(self), oci8_id_new, 1, lob->svc);
    newlob = DATA_PTR(newobj);
    if (have_OCILobLocatorAssign_nb && have_OCILobIsTemporary
            && OCILobIsTemporary(oci8_envhp, oci8_errhp, lob->base.hp.lob, &is_temporary) == OCI_SUCCESS
            && is_temporary) {
        oci8_svcctx_t *svcctx = oci8_get_svcctx(lob->svc);
        rv = OCILobLocatorAssign_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, &newlob->base.hp.lob);
    } else {
        rv = OCILobAssign(oci8_envhp, oci8_errhp, lob->base.hp.lob, &newlob->base.hp.lob);
    }
    if (rv != OCI_SUCCESS) {
        oci8_raise(oci8_errhp, rv, NULL);
    }
    return newobj;
}
Пример #27
0
static VALUE oci8_lob_read(int argc, VALUE *argv, VALUE self)
{
    oci8_lob_t *lob = DATA_PTR(self);
    oci8_svcctx_t *svcctx = oci8_get_svcctx(lob->svc);
    ub4 length;
    ub4 nchar;
    ub4 amt;
    sword rv;
    char buf[8192];
    size_t buf_size_in_char;
    VALUE size;
    VALUE v = rb_ary_new();

    rb_scan_args(argc, argv, "01", &size);
    length = oci8_lob_get_length(lob);
    if (length <= lob->pos) /* EOF */
        return Qnil;
    length -= lob->pos;
    if (NIL_P(size)) {
        nchar = length; /* read until EOF */
    } else {
        nchar = NUM2UINT(size);
        if (nchar > length)
            nchar = length;
    }
    amt = nchar;
    buf_size_in_char = sizeof(buf) / lob->char_width;
    do {
        if (lob->state == S_BFILE_CLOSE) {
            rv = OCILobFileOpen_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, OCI_FILE_READONLY);
            if (rv == OCI_ERROR && oci8_get_error_code(oci8_errhp) == 22290) {
                /* ORA-22290: operation would exceed the maximum number of opened files or LOBs */
                /* close all opened BFILE implicitly. */
                oci8_base_t *base;
                for (base = &lob->base; base != &lob->base; base = base->next) {
                    if (base->type == OCI_DTYPE_LOB) {
                        oci8_lob_t *tmp = (oci8_lob_t *)base;
                        if (tmp->state == S_BFILE_OPEN) {
                            tmp->state = S_BFILE_CLOSE;
                        }
                    }
                }
                oci_lc(OCILobFileCloseAll_nb(svcctx, svcctx->base.hp.svc, oci8_errhp));
                continue;
            }
            if (rv != OCI_SUCCESS)
                oci8_raise(oci8_errhp, rv, NULL);
            lob->state = S_BFILE_OPEN;
        }
        /* initialize buf in zeros everytime to check a nul characters. */
        memset(buf, 0, sizeof(buf));
        rv = OCILobRead_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, &amt, lob->pos + 1, buf, sizeof(buf), NULL, NULL, 0, lob->csfrm);
        if (rv == OCI_ERROR && oci8_get_error_code(oci8_errhp) == 22289) {
            /* ORA-22289: cannot perform FILEREAD operation on an unopened file or LOB */
            if (lob->state == S_BFILE_CLOSE)
                continue;
        }
        if (rv != OCI_SUCCESS && rv != OCI_NEED_DATA)
            oci8_raise(oci8_errhp, rv, NULL);

        /* Workaround when using Oracle 10.2.0.4 or 11.1.0.6 client and
         * variable-length character set (e.g. AL32UTF8).
         *
         * When the above mentioned condition, amt may be shorter. So
         * amt is increaded until a nul character to know the actually
         * read size.
         */
        while (amt < sizeof(buf) && buf[amt] != '\0') {
            amt++;
        }

        if (amt == 0)
            break;
        /* for fixed size charset, amt is the number of characters stored in buf. */
        if (amt > buf_size_in_char)
            rb_raise(eOCIException, "Too large buffer fetched or you set too large size of a character.");
        amt *= lob->char_width;
        rb_ary_push(v, rb_str_new(buf, amt));
    } while (rv == OCI_NEED_DATA);
    lob->pos += nchar;
    if (nchar == length) {
        lob_close(lob);
        bfile_close(lob);
    }
    if (RARRAY_LEN(v) == 0) {
        return Qnil;
    }
    v = rb_ary_join(v, Qnil);
    OBJ_TAINT(v);
    if (lob->lobtype == OCI_TEMP_CLOB) {
        /* set encoding */
        rb_enc_associate(v, oci8_encoding);
        return rb_str_conv_enc(v, oci8_encoding, rb_default_internal_encoding());
    } else {
        /* ASCII-8BIT */
        return v;
    }
}
Пример #28
0
/*
 * call-seq:
 *   new(username, password, dbname = nil, privilege = nil)
 *
 * Connects to an Oracle database server by +username+ and +password+
 * at +dbname+ as +privilege+.
 *
 * === connecting to the local server
 *
 * Set +username+ and +password+ or pass "username/password" as a
 * single argument.
 *
 *   OCI8.new('scott', 'tiger')
 * or
 *   OCI8.new('scott/tiger')
 *
 * === connecting to a remote server
 *
 * Set +username+, +password+ and +dbname+ or pass
 * "username/password@dbname" as a single argument.
 *
 *   OCI8.new('scott', 'tiger', 'orcl.world')
 * or
 *   OCI8.new('scott/[email protected]')
 *
 * The +dbname+ is a net service name or an easy connectection
 * identifier. The former is a name listed in the file tnsnames.ora.
 * Ask to your DBA if you don't know what it is. The latter has the
 * syntax as "//host:port/service_name".
 *
 *   OCI8.new('scott', 'tiger', '//remote-host:1521/XE')
 * or
 *   OCI8.new('scott/tiger@//remote-host:1521/XE')
 *
 * === connecting as a privileged user
 *
 * Set :SYSDBA or :SYSOPER to +privilege+, otherwise
 * "username/password as sysdba" or "username/password as sysoper"
 * as a single argument.
 *
 *   OCI8.new('sys', 'change_on_install', nil, :SYSDBA)
 * or
 *   OCI8.new('sys/change_on_install as sysdba')
 *
 * === external OS authentication
 *
 * Set nil to +username+ and +password+, or "/" as a single argument.
 *
 *   OCI8.new(nil, nil)
 * or
 *   OCI8.new('/')
 *
 * To connect to a remote host:
 *
 *   OCI8.new(nil, nil, 'dbname')
 * or
 *   OCI8.new('/@dbname')
 *
 * === proxy authentication
 *
 * Enclose end user's username with square brackets and add it at the
 * end of proxy user's username.
 *
 *   OCI8.new('proxy_user_name[end_user_name]', 'proxy_password')
 * or
 *   OCI8.new('proxy_user_name[end_user_name]/proxy_password')
 *
 */
static VALUE oci8_svcctx_initialize(int argc, VALUE *argv, VALUE self)
{
    VALUE vusername;
    VALUE vpassword;
    VALUE vdbname;
    VALUE vmode;
    oci8_svcctx_t *svcctx = DATA_PTR(self);
    sword rv;
    enum logon_type_t logon_type = T_IMPLICIT;
    ub4 cred = OCI_CRED_RDBMS;
    ub4 mode = OCI_DEFAULT;
    OCISvcCtx *svchp = NULL;

    svcctx->executing_thread = Qnil;
    if (argc == 1) {
        oci8_do_parse_connect_string(argv[0], &vusername, &vpassword, &vdbname, &vmode);
    } else {
        rb_scan_args(argc, argv, "22", &vusername, &vpassword, &vdbname, &vmode);
    }

    rb_ivar_set(self, id_at_prefetch_rows, Qnil);
    rb_ivar_set(self, id_at_username, Qnil);
    if (NIL_P(vusername) && NIL_P(vpassword)) {
        /* external credential */
        logon_type = T_EXPLICIT;
        cred = OCI_CRED_EXT;
    } else {
        /* RDBMS credential */
        OCI8SafeStringValue(vusername); /* 1 */
        OCI8SafeStringValue(vpassword); /* 2 */
    }
    if (!NIL_P(vdbname)) {
        OCI8SafeStringValue(vdbname); /* 3 */
    }
    if (!NIL_P(vmode)) { /* 4 */
        logon_type = T_EXPLICIT;
        Check_Type(vmode, T_SYMBOL);
        if (vmode == sym_SYSDBA) {
            mode = OCI_SYSDBA;
        } else if (vmode == sym_SYSOPER) {
            mode = OCI_SYSOPER;
        } else {
            rb_raise(rb_eArgError, "invalid privilege name %s (expect :SYSDBA or :SYSOPER)", rb_id2name(SYM2ID(vmode)));
        }
    }
    switch (logon_type) {
    case T_IMPLICIT:
        rv = OCILogon_nb(svcctx, oci8_envhp, oci8_errhp, &svchp,
                         RSTRING_ORATEXT(vusername), RSTRING_LEN(vusername),
                         RSTRING_ORATEXT(vpassword), RSTRING_LEN(vpassword),
                         NIL_P(vdbname) ? NULL : RSTRING_ORATEXT(vdbname),
                         NIL_P(vdbname) ? 0 : RSTRING_LEN(vdbname));
        svcctx->base.hp.svc = svchp;
        svcctx->base.type = OCI_HTYPE_SVCCTX;
        svcctx->logon_type = T_IMPLICIT;
        if (rv != OCI_SUCCESS) {
            oci8_raise(oci8_errhp, rv, NULL);
        }
        break;
    case T_EXPLICIT:
        /* allocate OCI handles. */
        rv = OCIHandleAlloc(oci8_envhp, &svcctx->base.hp.ptr, OCI_HTYPE_SVCCTX, 0, 0);
        if (rv != OCI_SUCCESS)
            oci8_env_raise(oci8_envhp, rv);
        svcctx->base.type = OCI_HTYPE_SVCCTX;
        rv = OCIHandleAlloc(oci8_envhp, (void*)&svcctx->authhp, OCI_HTYPE_SESSION, 0, 0);
        if (rv != OCI_SUCCESS)
            oci8_env_raise(oci8_envhp, rv);
        rv = OCIHandleAlloc(oci8_envhp, (void*)&svcctx->srvhp, OCI_HTYPE_SERVER, 0, 0);
        if (rv != OCI_SUCCESS)
            oci8_env_raise(oci8_envhp, rv);

        /* set username and password to OCISession. */
        if (cred == OCI_CRED_RDBMS) {
            oci_lc(OCIAttrSet(svcctx->authhp, OCI_HTYPE_SESSION,
                              RSTRING_PTR(vusername), RSTRING_LEN(vusername),
                              OCI_ATTR_USERNAME, oci8_errhp));
            oci_lc(OCIAttrSet(svcctx->authhp, OCI_HTYPE_SESSION,
                              RSTRING_PTR(vpassword), RSTRING_LEN(vpassword),
                              OCI_ATTR_PASSWORD, oci8_errhp));
        }

        /* attach to server and set to OCISvcCtx. */
        rv = OCIServerAttach_nb(svcctx, svcctx->srvhp, oci8_errhp,
                                NIL_P(vdbname) ? NULL : RSTRING_ORATEXT(vdbname),
                                NIL_P(vdbname) ? 0 : RSTRING_LEN(vdbname), OCI_DEFAULT);
        if (rv != OCI_SUCCESS)
            oci8_raise(oci8_errhp, rv, NULL);
        oci_lc(OCIAttrSet(svcctx->base.hp.ptr, OCI_HTYPE_SVCCTX, svcctx->srvhp, 0, OCI_ATTR_SERVER, oci8_errhp));

        /* begin session. */
        rv = OCISessionBegin_nb(svcctx, svcctx->base.hp.ptr, oci8_errhp, svcctx->authhp, cred, mode);
        if (rv != OCI_SUCCESS)
            oci8_raise(oci8_errhp, rv, NULL);
        oci_lc(OCIAttrSet(svcctx->base.hp.ptr, OCI_HTYPE_SVCCTX, svcctx->authhp, 0, OCI_ATTR_SESSION, oci8_errhp));
        svcctx->logon_type = T_EXPLICIT;
        break;
    default:
        break;
    }
    svcctx->pid = getpid();
    svcctx->is_autocommit = 0;
#ifdef RUBY_VM
    svcctx->non_blocking = 1;
#endif
    svcctx->long_read_len = INT2FIX(65535);
    return Qnil;
}