/* * call-seq: * onum % other -> oranumber * * Returns the modulo after division of <i>onum</i> by <i>other</i>. */ static VALUE onum_mod(VALUE lhs, VALUE rhs) { OCIError *errhp = oci8_errhp; OCINumber n; OCINumber r; boolean is_zero; /* change to OCINumber */ if (!set_oci_number_from_num(&n, rhs, 0, errhp)) return rb_num_coerce_bin(lhs, rhs, '%'); /* check whether argument is not zero. */ oci_lc(OCINumberIsZero(errhp, &n, &is_zero)); if (is_zero) rb_num_zerodiv(); /* modulo */ oci_lc(OCINumberMod(errhp, _NUMBER(lhs), &n, &r)); return oci8_make_ocinumber(&r, errhp); }
static VALUE onum_initialize_copy(VALUE lhs, VALUE rhs) { if (!RTEST(rb_obj_is_instance_of(rhs, CLASS_OF(lhs)))) { rb_raise(rb_eTypeError, "invalid type: expected %s but %s", rb_class2name(CLASS_OF(lhs)), rb_class2name(CLASS_OF(rhs))); } oci_lc(OCINumberAssign(oci8_errhp, _NUMBER(rhs), _NUMBER(lhs))); return lhs; }
OCISession *oci8_get_oci_session(VALUE obj) { oci8_svcctx_t *svcctx = oci8_get_svcctx(obj); if (svcctx->authhp == NULL) { oci_lc(OCIAttrGet(svcctx->base.hp.ptr, OCI_HTYPE_SVCCTX, &svcctx->authhp, 0, OCI_ATTR_SESSION, oci8_errhp)); } return svcctx->authhp; }
/* construct an ruby object(OCI::Number) from C structure (OCINumber). */ VALUE oci8_make_ocinumber(OCINumber *s, OCIError *errhp) { VALUE obj; OCINumber *d; obj = Data_Make_Struct(cOCINumber, OCINumber, NULL, xfree, d); oci_lc(OCINumberAssign(errhp, s, d)); return obj; }
/* * call-seq: * OCI8::Math.exp(x) -> oranumber * * Returns e**x. */ static VALUE omath_exp(VALUE obj, VALUE num) { OCIError *errhp = oci8_errhp; OCINumber n; OCINumber r; oci_lc(OCINumberExp(errhp, TO_OCINUM(&n, num, errhp), &r)); return oci8_make_ocinumber(&r, errhp); }
/* * call-seq: * OCI8::Math.tan(x) -> oranumber * * Returns the tangent of <i>x</i> (expressed in radians). */ static VALUE omath_tan(VALUE obj, VALUE radian) { OCIError *errhp = oci8_errhp; OCINumber r; OCINumber rv; oci_lc(OCINumberTan(errhp, TO_OCINUM(&r, radian, errhp), &rv)); return oci8_make_ocinumber(&rv, errhp); }
/* * call-seq: * non_blocking = true or false * * Sets +true+ to enable non-blocking mode, +false+ otherwise. * The default setting depends on the ruby version and ruby-oci8 * version. * * When the connection is in blocking mode (non_blocking = false), * SQL executions block not only the thread, but also the ruby * process. It makes the whole application stop while a SQL execution * needs long time. * * When in non-blocking mode (non_blocking = true), SQL executions * block only the thread. It does't prevent other threads. * A SQL execution which blocks a thread can be canceled by * OCI8#break. * * === ruby 1.9 * The default setting is +true+ if the ruby-oci8 version is 2.0.3 or * upper, +false+ otherwise. * * Ruby-oci8 makes the connection non-blocking by releasing ruby * interpreter's GVL (Global VM Lock or Giant VM Lock) while OCI * functions which may need more than one network round trips are in * execution. * * === ruby 1.8 * The default setting is +false+. * * Ruby-oci8 makes the connection non-blocking by polling the return * values of OCI functions. When an OCI function returns * OCI_STILL_EXECUTING, the thread sleeps for 10 milli seconds to make * a time for other threads to run. The sleep time is doubled up to * 640 milli seconds as the function returns the same value. * */ static VALUE oci8_set_non_blocking(VALUE self, VALUE val) { oci8_svcctx_t *svcctx = DATA_PTR(self); #ifdef RUBY_VM svcctx->non_blocking = RTEST(val); #else sb1 non_blocking; if (svcctx->srvhp == NULL) { oci_lc(OCIAttrGet(svcctx->base.hp.ptr, OCI_HTYPE_SVCCTX, &svcctx->srvhp, 0, OCI_ATTR_SERVER, oci8_errhp)); } oci_lc(OCIAttrGet(svcctx->srvhp, OCI_HTYPE_SERVER, &non_blocking, 0, OCI_ATTR_NONBLOCKING_MODE, oci8_errhp)); if ((RTEST(val) && !non_blocking) || (!RTEST(val) && non_blocking)) { /* toggle blocking / non-blocking. */ oci_lc(OCIAttrSet(svcctx->srvhp, OCI_HTYPE_SERVER, 0, 0, OCI_ATTR_NONBLOCKING_MODE, oci8_errhp)); } #endif return val; }
/* * call-seq: * onum.truncate -> integer * onum.truncate(decplace) -> oranumber * * Truncates <i>onum</i> to the <code>Integer</code> when no argument. * Truncates <i>onum</i> to a specified decimal place <i>decplace</i> when one argument. */ static VALUE onum_trunc(int argc, VALUE *argv, VALUE self) { OCIError *errhp = oci8_errhp; VALUE decplace; OCINumber r; rb_scan_args(argc, argv, "01", &decplace /* 0 */); oci_lc(OCINumberTrunc(errhp, _NUMBER(self), NIL_P(decplace) ? 0 : NUM2INT(decplace), &r)); return oci8_make_ocinumber(&r, errhp); }
/* * call-seq: * attr_set_binary(attr_type, string_value) * * <b>(new in 2.0.4)</b> * * Sets the value of an attribute as `ub1 *' datatype. */ static VALUE attr_set_binary(VALUE self, VALUE attr_type, VALUE val) { oci8_base_t *base = DATA_PTR(self); /* validate arguments */ Check_Type(attr_type, T_FIXNUM); SafeStringValue(val); /* set attribute */ oci_lc(OCIAttrSet(base->hp.ptr, base->type, RSTRING_PTR(val), RSTRING_LEN(val), FIX2INT(attr_type), oci8_errhp)); return self; }
/* * call-seq: * OCI8::Math.asin(x) -> oranumber * * Computes the arc sine of <i>x</i>. Returns 0..PI. */ static VALUE omath_asin(VALUE obj, VALUE num) { OCIError *errhp = oci8_errhp; OCINumber n; OCINumber r; sword sign; set_oci_number_from_num(&n, num, 1, errhp); /* check upper bound */ oci_lc(OCINumberCmp(errhp, &n, &const_p1, &sign)); if (sign > 0) rb_raise(rb_eRangeError, "out of range for asin"); /* check lower bound */ oci_lc(OCINumberCmp(errhp, &n, &const_m1, &sign)); if (sign < 0) rb_raise(rb_eRangeError, "out of range for asin"); /* asin */ oci_lc(OCINumberArcSin(errhp, &n, &r)); return oci8_make_ocinumber(&r, errhp); }
static void lob_open(oci8_lob_t *lob) { if (lob->state == S_CLOSE) { if (have_OCILobOpen_nb) { oci8_svcctx_t *svcctx = oci8_get_svcctx(lob->svc); oci_lc(OCILobOpen_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, OCI_DEFAULT)); } lob->state = S_OPEN; } }
static void lob_close(oci8_lob_t *lob) { if (lob->state == S_OPEN) { if (have_OCILobClose_nb) { oci8_svcctx_t *svcctx = oci8_get_svcctx(lob->svc); oci_lc(OCILobClose_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob)); } lob->state = S_CLOSE; } }
static VALUE oci8_make_lob(VALUE klass, oci8_svcctx_t *svcctx, OCILobLocator *s) { oci8_lob_t *lob; VALUE lob_obj; lob_obj = rb_funcall(klass, oci8_id_new, 1, svcctx->base.self); lob = DATA_PTR(lob_obj); /* If 's' is a temporary lob, use OCILobLocatorAssign instead. */ oci_lc(OCILobAssign(oci8_envhp, oci8_errhp, s, &lob->base.hp.lob)); return lob_obj; }
/* * call-seq: * attr_set_integer(attr_type, number) * * <b>(new in 2.0.4)</b> * * Sets the value of an attribute as `ub1 *' datatype. * +number+ is converted to internal Oracle NUMBER format before * it is set. */ static VALUE attr_set_integer(VALUE self, VALUE attr_type, VALUE val) { oci8_base_t *base = DATA_PTR(self); OCINumber value; /* validate arguments */ Check_Type(attr_type, T_FIXNUM); oci8_set_integer(&value, val, oci8_errhp); /* set attribute */ oci_lc(OCIAttrSet(base->hp.ptr, base->type, &value, sizeof(value), FIX2INT(attr_type), oci8_errhp)); return self; }
/* * call-seq: * attr_set_boolean(attr_type, attr_value) * * <b>(new in 2.0.4)</b> * * Sets the value of an attribute as `boolean' datatype. * * <b>Caution:</b> If the specified attr_type's datatype is a * pointer type, it causes a segmentation fault. */ static VALUE attr_set_boolean(VALUE self, VALUE attr_type, VALUE val) { oci8_base_t *base = DATA_PTR(self); boolean value; /* validate arguments */ Check_Type(attr_type, T_FIXNUM); value = RTEST(val) ? TRUE : FALSE; /* set attribute */ oci_lc(OCIAttrSet(base->hp.ptr, base->type, &value, sizeof(value), FIX2INT(attr_type), oci8_errhp)); return self; }
/* * call-seq: * attr_set_sb2(attr_type, attr_value) * * <b>(new in 2.0.4)</b> * * Sets the value of an attribute as `sb2' datatype. * * <b>Caution:</b> If the specified attr_type's datatype is a * pointer type, it causes a segmentation fault. */ static VALUE attr_set_sb2(VALUE self, VALUE attr_type, VALUE val) { oci8_base_t *base = DATA_PTR(self); sb2 value; /* validate arguments */ Check_Type(attr_type, T_FIXNUM); value = (sb2)check_data_range(val, SHRT_MIN, SHRT_MAX, "sb2"); /* set attribute */ oci_lc(OCIAttrSet(base->hp.ptr, base->type, &value, sizeof(value), FIX2INT(attr_type), oci8_errhp)); return self; }
/* * call-seq: * attr_set_ub8(attr_type, attr_value) * * <b>(new in 2.0.4)</b> * * Sets the value of an attribute as `ub8' datatype. * * <b>Caution:</b> If the specified attr_type's datatype is a * pointer type, it causes a segmentation fault. */ static VALUE attr_set_ub8(VALUE self, VALUE attr_type, VALUE val) { oci8_base_t *base = DATA_PTR(self); ub8 value; /* validate arguments */ Check_Type(attr_type, T_FIXNUM); value = NUM2ULL(val); /* set attribute */ oci_lc(OCIAttrSet(base->hp.ptr, base->type, &value, sizeof(value), FIX2INT(attr_type), oci8_errhp)); return self; }
/* * call-seq: * non_blocking? -> true or false * * Returns +true+ if the connection is in non-blocking mode, +false+ * otherwise. * * See also #non_blocking=. */ static VALUE oci8_non_blocking_p(VALUE self) { oci8_svcctx_t *svcctx = DATA_PTR(self); #ifdef HAVE_RB_THREAD_BLOCKING_REGION return svcctx->non_blocking ? Qtrue : Qfalse; #else sb1 non_blocking; oci_lc(OCIAttrGet(svcctx->srvhp, OCI_HTYPE_SERVER, &non_blocking, 0, OCI_ATTR_NONBLOCKING_MODE, oci8_errhp)); return non_blocking ? Qtrue : Qfalse; #endif }
/* * call-seq: * attr_get_sb4(attr_type) -> integer * * <b>(new in 2.0.4)</b> * * Gets the value of an attribute as `sb4' datatype. */ static VALUE attr_get_sb4(VALUE self, VALUE attr_type) { oci8_base_t *base = DATA_PTR(self); union { sb4 value; ub8 dummy; } v; v.dummy = MAGIC_NUMBER; Check_Type(attr_type, T_FIXNUM); oci_lc(OCIAttrGet(base->hp.ptr, base->type, &v.value, NULL, FIX2INT(attr_type), oci8_errhp)); return INT2NUM(v.value); }
/* * call-seq: * attr_get_boolean(attr_type) -> true or false * * <b>(new in 2.0.4)</b> * * Gets the value of an attribute as `boolean' datatype. */ static VALUE attr_get_boolean(VALUE self, VALUE attr_type) { oci8_base_t *base = DATA_PTR(self); union { boolean value; ub8 dummy; /* padding for incorrect attrtype to protect the stack */ } v; v.dummy = MAGIC_NUMBER; Check_Type(attr_type, T_FIXNUM); oci_lc(OCIAttrGet(base->hp.ptr, base->type, &v.value, NULL, FIX2INT(attr_type), oci8_errhp)); return v.value ? Qtrue : Qfalse; }
static VALUE oci8_lob_get_chunk_size(VALUE self) { if (have_OCILobGetChunkSize_nb) { oci8_lob_t *lob = DATA_PTR(self); oci8_svcctx_t *svcctx = oci8_get_svcctx(lob->svc); ub4 len; oci_lc(OCILobGetChunkSize_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, &len)); return UINT2NUM(len); } else { rb_notimplement(); } }
/* * 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); while (svcctx->base.children != NULL) { oci8_base_free(svcctx->base.children); } if (svcctx->logoff_method != NULL) { oci_lc(OCITransRollback_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, OCI_DEFAULT)); svcctx->logoff_method(svcctx); } return Qtrue; }
/* * call-seq: * attr_get_string(attr_type) -> string * * <b>(new in 2.0.4)</b> * * Gets the value of an attribute as `oratext *' datatype. * The return value is converted to Encoding.default_internal or * tagged with OCI8.encoding when the ruby version is 1.9. * * <b>Caution:</b> If the specified attr_type's datatype is not a * pointer type, it causes a segmentation fault. */ static VALUE attr_get_string(VALUE self, VALUE attr_type) { oci8_base_t *base = DATA_PTR(self); union { char *value; ub8 dummy; /* padding for incorrect attrtype to protect the stack */ } v; ub4 size = 0; v.dummy = MAGIC_NUMBER; Check_Type(attr_type, T_FIXNUM); oci_lc(OCIAttrGet(base->hp.ptr, base->type, &v.value, &size, FIX2INT(attr_type), oci8_errhp)); return rb_external_str_new_with_enc(v.value, size, oci8_encoding); }
/* * call-seq: * attr_get_binary(attr_type) -> string * * <b>(new in 2.0.4)</b> * * Gets the value of an attribute as `ub1 *' datatype. * The return value is tagged with ASCII-8BIT when the ruby version is 1.9. * * <b>Caution:</b> If the specified attr_type's datatype is not a * pointer type, it causes a segmentation fault. */ static VALUE attr_get_binary(VALUE self, VALUE attr_type) { oci8_base_t *base = DATA_PTR(self); union { char *value; ub8 dummy; /* padding for incorrect attrtype to protect the stack */ } v; ub4 size = 0; v.dummy = 0; Check_Type(attr_type, T_FIXNUM); oci_lc(OCIAttrGet(base->hp.ptr, base->type, &v.value, &size, FIX2INT(attr_type), oci8_errhp)); return rb_tainted_str_new(v.value, size); }
/* * call-seq: * attr_get_integer(attr_type) -> integer * * <b>(new in 2.0.4)</b> * * Gets the value of an attribute as `ub1 *' datatype. * The return value is converted to Integer from internal Oracle NUMBER format. * * <b>Caution:</b> If the specified attr_type's datatype is not a * pointer type, it causes a segmentation fault. */ static VALUE attr_get_integer(VALUE self, VALUE attr_type) { oci8_base_t *base = DATA_PTR(self); union { OCINumber *value; ub8 dummy; /* padding for incorrect attrtype to protect the stack */ } v; ub4 size = 0; v.dummy = 0; Check_Type(attr_type, T_FIXNUM); oci_lc(OCIAttrGet(base->hp.ptr, base->type, &v.value, &size, FIX2INT(attr_type), oci8_errhp)); return oci8_make_integer(v.value, oci8_errhp); }
/* Converts to BigDecimal via number in scientific notation */ static VALUE onum_to_d_real(OCINumber *num, OCIError *errhp) { char buf[64]; ub4 buf_size = sizeof(buf); const char *fmt = "FM9.99999999999999999999999999999999999999EEEE"; if (!cBigDecimal) { rb_require("bigdecimal"); cBigDecimal = rb_const_get(rb_cObject, id_BigDecimal); } oci_lc(OCINumberToText(errhp, num, (const oratext *)fmt, strlen(fmt), NULL, 0, &buf_size, TO_ORATEXT(buf))); return rb_funcall(rb_cObject, id_BigDecimal, 1, rb_usascii_str_new(buf, buf_size)); }
VALUE oci8_make_ociinterval_ds(OCIInterval *s) { sb4 day; sb4 hour; sb4 minute; sb4 sec; sb4 fsec; oci_lc(OCIIntervalGetDaySecond(oci8_envhp, oci8_errhp, &day, &hour, &minute, &sec, &fsec, s)); return rb_ary_new3(5, INT2FIX(day), INT2FIX(hour), INT2FIX(minute), INT2FIX(sec), INT2FIX(fsec)); }
/* * call-seq: * onum.round -> integer * onum.round(decplace) -> oranumber * * Rounds <i>onum</i> to the nearest <code>Integer</code> when no argument. * Rounds <i>onum</i> to a specified decimal place <i>decplace</i> when one argument. * * OraNumber.new(1.234).round(1) #=> 1.2 * OraNumber.new(1.234).round(2) #=> 1.23 * OraNumber.new(1.234).round(3) #=> 1.234 */ static VALUE onum_round(int argc, VALUE *argv, VALUE self) { OCIError *errhp = oci8_errhp; VALUE decplace; OCINumber r; rb_scan_args(argc, argv, "01", &decplace /* 0 */); oci_lc(OCINumberRound(errhp, _NUMBER(self), NIL_P(decplace) ? 0 : NUM2INT(decplace), &r)); if (argc == 0) { return oci8_make_integer(&r, errhp); } else { return oci8_make_ocinumber(&r, errhp); } }
static void oci8_bfile_set_name(VALUE self, VALUE dir_alias, VALUE filename) { oci8_lob_t *lob = DATA_PTR(self); bfile_close(lob); if (RSTRING_LEN(dir_alias) > UB2MAXVAL) { rb_raise(rb_eRuntimeError, "dir_alias is too long."); } if (RSTRING_LEN(filename) > UB2MAXVAL) { rb_raise(rb_eRuntimeError, "filename is too long."); } oci_lc(OCILobFileSetName(oci8_envhp, oci8_errhp, &lob->base.hp.lob, RSTRING_ORATEXT(dir_alias), (ub2)RSTRING_LEN(dir_alias), RSTRING_ORATEXT(filename), (ub2)RSTRING_LEN(filename))); }
/* * 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); while (svcctx->base.children != NULL) { oci8_base_free(svcctx->base.children); } if (svcctx->logoff_strategy != NULL) { const oci8_logoff_strategy_t *strategy = svcctx->logoff_strategy; void *data = strategy->prepare(svcctx); svcctx->base.type = 0; svcctx->logoff_strategy = NULL; oci_lc(oci8_blocking_region(svcctx, strategy->execute, data)); } return Qtrue; }