/* * call-seq: * onum.to_r -> rational * * Return the value as a <code>Rational</code>. * */ static VALUE onum_to_r(VALUE self) { VALUE x, y; int nshift = 0; OCINumber onum[2]; int current = 0; boolean is_int; chkerr(OCINumberAssign(oci8_errhp, _NUMBER(self), &onum[0])); for (;;) { chkerr(OCINumberIsInt(oci8_errhp, &onum[current], &is_int)); if (is_int) { break; } nshift++; chkerr(OCINumberShift(oci8_errhp, &onum[current], 1, &onum[1 - current])); current = 1 - current; } x = oci8_make_integer(&onum[current], oci8_errhp); if (nshift == 0) { y = INT2FIX(1); } else { y = rb_funcall(INT2FIX(10), rb_intern("**"), 1, INT2FIX(nshift)); } #ifdef T_RATIONAL return rb_Rational(x, y); #else if (!cRational) { rb_require("rational"); cRational = rb_const_get(rb_cObject, id_Rational); } return rb_funcall(rb_cObject, id_Rational, 2, x, y); #endif }
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))); } chkerr(OCINumberAssign(oci8_errhp, _NUMBER(rhs), _NUMBER(lhs))); return lhs; }
/* 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); chkerr(OCINumberAssign(errhp, s, d)); return obj; }
// todo - this relies on the fact that BindParNumber is BindParNumber now void ConvertorForRead::Fire(const BindParNumber &BP, SqlNumber &SN) { SN._ind = BP.indp[_row]; if(SN.is_not_null()) { sword res = OCICALL(OCINumberAssign(SN._env._errh, BP.get_ref(_row), &SN._val)); oci_check_error(__TROTL_HERE__, SN._env._errh, res); } // TODO raise exception here, if STMT.type==PL/SQL and BP._cnt > 1 //if(BP._cnt != 1) //std::cerr << "Warning assigning vector into scalar(" << BP._cnt << ")" << std::endl; };
/* 1 - success, 0 - error */ static int set_oci_number_from_num(OCINumber *result, VALUE num, int force, OCIError *errhp) { signed long sl; if (!RTEST(rb_obj_is_kind_of(num, rb_cNumeric))) rb_raise(rb_eTypeError, "expect Numeric but %s", rb_class2name(CLASS_OF(num))); if (rb_respond_to(num, id_finite_p) && !RTEST(rb_funcall(num, id_finite_p, 0))) { rb_raise(rb_eTypeError, "cannot accept number which isn't finite."); } switch (rb_type(num)) { case T_FIXNUM: /* set from long. */ sl = NUM2LONG(num); chkerr(OCINumberFromInt(errhp, &sl, sizeof(sl), OCI_NUMBER_SIGNED, result)); return 1; case T_FLOAT: /* set from double. */ oci8_dbl_to_onum(result, NUM2DBL(num), errhp); return 1; case T_BIGNUM: /* change via string. */ num = rb_big2str(num, 10); set_oci_number_from_str(result, num, Qnil, Qnil, errhp); return 1; } if (RTEST(rb_obj_is_instance_of(num, cOCINumber))) { /* OCI::Number */ chkerr(OCINumberAssign(errhp, DATA_PTR(num), result)); return 1; } if (rb_respond_to(num, id_split)) { /* BigDecimal */ VALUE split = rb_funcall(num, id_split, 0); if (TYPE(split) == T_ARRAY && RARRAY_LEN(split) == 4) { /* * sign, significant_digits, base, exponent = num.split * onum = sign * "0.#{significant_digits}".to_f * (base ** exponent) */ VALUE *ary = RARRAY_PTR(split); int sign; OCINumber digits; int exponent; int digits_len; OCINumber work; /* check sign */ if (TYPE(ary[0]) != T_FIXNUM) { goto is_not_big_decimal; } sign = FIX2INT(ary[0]); /* check digits */ StringValue(ary[1]); digits_len = RSTRING_LEN(ary[1]); set_oci_number_from_str(&digits, ary[1], Qnil, Qnil, errhp); /* check base */ if (TYPE(ary[2]) != T_FIXNUM || FIX2LONG(ary[2]) != 10) { goto is_not_big_decimal; } /* check exponent */ if (TYPE(ary[3]) != T_FIXNUM) { goto is_not_big_decimal; } exponent = FIX2INT(ary[3]); chkerr(OCINumberShift(errhp, &digits, exponent - digits_len, &work)); if (sign >= 0) { chkerr(OCINumberAssign(errhp, &work, result)); } else { chkerr(OCINumberNeg(errhp, &work, result)); } return 1; } } is_not_big_decimal: if (rb_respond_to(num, id_numerator) && rb_respond_to(num, id_denominator)) { /* Rational */ OCINumber numerator; OCINumber denominator; if (set_oci_number_from_num(&numerator, rb_funcall(num, id_numerator, 0), 0, errhp) && set_oci_number_from_num(&denominator, rb_funcall(num, id_denominator, 0), 0, errhp)) { chkerr(OCINumberDiv(errhp, &numerator, &denominator, result)); return 1; } } if (force) { /* change via string as a last resort. */ /* TODO: if error, raise TypeError instead of OCI::Error */ set_oci_number_from_str(result, num, Qnil, Qnil, errhp); return 1; } return 0; }