[ruby-oci8-commit] [363] trunk/ruby-oci8: * ext/oci8/ocinumber.c: Add a global function OraNumber(obj) as a
nobody at rubyforge.org
nobody at rubyforge.org
Tue Oct 6 09:46:41 EDT 2009
Revision: 363
Author: kubo
Date: 2009-10-06 09:46:41 -0400 (Tue, 06 Oct 2009)
Log Message:
-----------
* ext/oci8/ocinumber.c: Add a global function OraNumber(obj) as a
shortcut of OraNumber.new(obj) as Rational and BigDecimal do.
Changes the return type of the four rules of arithmetic;
addition, subtraction, multiplication and division. It was
OraNumber, but now it depends on the operand.
* lib/oci8/bindtype.rb: Add OCI8::BindType::BigDecimal and
OCI8::BindType::Rational. Change the default data type for
number column which fit neither Integer nor Float from
OraNumber to BigDecimal.
* lib/oci8/oci8.rb: Fix for OCI8::BindType::Mapping to accept
a class name instead of the class object to support
OCI8::BindType::BigDecimal and OCI8::BindType::Rational without
requiring 'bigdecimal' and 'rational'.
* spec/oranumber_spec.rb: Add a spec file for OraNumber arithmetic.
* test/test_oci8.rb: Add tests for OCI8::BindType::BigDecimal and
OCI8::BindType::Rational.
Modified Paths:
--------------
trunk/ruby-oci8/ChangeLog
trunk/ruby-oci8/ext/oci8/ocinumber.c
trunk/ruby-oci8/lib/oci8/bindtype.rb
trunk/ruby-oci8/lib/oci8/oci8.rb
trunk/ruby-oci8/test/test_oci8.rb
Added Paths:
-----------
trunk/ruby-oci8/spec/oranumber_spec.rb
Modified: trunk/ruby-oci8/ChangeLog
===================================================================
--- trunk/ruby-oci8/ChangeLog 2009-10-04 14:04:01 UTC (rev 362)
+++ trunk/ruby-oci8/ChangeLog 2009-10-06 13:46:41 UTC (rev 363)
@@ -1,3 +1,21 @@
+2009-10-06 KUBO Takehiro <kubo at jiubao.org>
+ * ext/oci8/ocinumber.c: Add a global function OraNumber(obj) as a
+ shortcut of OraNumber.new(obj) as Rational and BigDecimal do.
+ Changes the return type of the four rules of arithmetic;
+ addition, subtraction, multiplication and division. It was
+ OraNumber, but now it depends on the operand.
+ * lib/oci8/bindtype.rb: Add OCI8::BindType::BigDecimal and
+ OCI8::BindType::Rational. Change the default data type for
+ number column which fit neither Integer nor Float from
+ OraNumber to BigDecimal.
+ * lib/oci8/oci8.rb: Fix for OCI8::BindType::Mapping to accept
+ a class name instead of the class object to support
+ OCI8::BindType::BigDecimal and OCI8::BindType::Rational without
+ requiring 'bigdecimal' and 'rational'.
+ * spec/oranumber_spec.rb: Add a spec file for OraNumber arithmetic.
+ * test/test_oci8.rb: Add tests for OCI8::BindType::BigDecimal and
+ OCI8::BindType::Rational.
+
2009-10-04 KUBO Takehiro <kubo at jiubao.org>
* ext/oci8/oci8.c: Add constants missing in Oracle client prior to 10g.
* ext/oci8/oraconf.rb:
Modified: trunk/ruby-oci8/ext/oci8/ocinumber.c
===================================================================
--- trunk/ruby-oci8/ext/oci8/ocinumber.c 2009-10-04 14:04:01 UTC (rev 362)
+++ trunk/ruby-oci8/ext/oci8/ocinumber.c 2009-10-06 13:46:41 UTC (rev 363)
@@ -21,7 +21,14 @@
static ID id_split;
static ID id_numerator;
static ID id_denominator;
+static ID id_Rational;
+static ID id_BigDecimal;
+#ifndef T_RATIONAL
+static VALUE cRational;
+#endif
+static VALUE cBigDecimal;
+
static VALUE cOCINumber;
static OCINumber const_p1; /* +1 */
static OCINumber const_p10; /* +10 */
@@ -51,6 +58,58 @@
#define _NUMBER(val) ((OCINumber *)DATA_PTR(val)) /* dangerous macro */
+#define RBOCI8_T_ORANUMBER (T_MASK + 1)
+#define RBOCI8_T_BIGDECIMAL (T_MASK + 2)
+#ifdef T_RATIONAL
+#define RBOCI8_T_RATIONAL T_RATIONAL
+#else
+#define RBOCI8_T_RATIONAL (T_MASK + 3)
+#endif
+
+static int rboci8_type(VALUE obj)
+{
+ int type = TYPE(obj);
+ VALUE klass;
+
+ switch (type) {
+#ifndef T_RATIONAL
+ case T_OBJECT:
+ klass = CLASS_OF(obj);
+ if (cRational != 0) {
+ if (klass == cRational) {
+ return RBOCI8_T_RATIONAL;
+ }
+ } else {
+ if (strcmp(rb_class2name(klass), "Rational") == 0) {
+ cRational = rb_const_get(rb_cObject, id_Rational);
+ return RBOCI8_T_RATIONAL;
+ }
+ }
+ break;
+#endif
+ case T_DATA:
+ klass = CLASS_OF(obj);
+ if (klass == cOCINumber) {
+ return RBOCI8_T_ORANUMBER;
+ }
+ if (cBigDecimal != 0) {
+ if (klass == cBigDecimal) {
+ return RBOCI8_T_BIGDECIMAL;
+ }
+ } else {
+ if (strcmp(rb_class2name(klass), "BigDecimal") == 0) {
+ cBigDecimal = rb_const_get(rb_cObject, id_BigDecimal);
+ return RBOCI8_T_BIGDECIMAL;
+ }
+ }
+ }
+ return type;
+}
+
+static VALUE onum_to_f(VALUE self);
+static VALUE onum_to_r(VALUE self);
+static VALUE onum_to_d(VALUE self);
+
static VALUE onum_s_alloc(VALUE klass)
{
VALUE obj;
@@ -573,6 +632,20 @@
return oci8_make_ocinumber(&r, errhp);
}
+
+/*
+ * call-seq:
+ * OraNumber(obj) -> oranumber
+ *
+ * Returns a new <code>OraNumber</code>.
+ */
+static VALUE onum_f_new(int argc, VALUE *argv, VALUE self)
+{
+ VALUE obj = rb_obj_alloc(cOCINumber);
+ rb_obj_call_init(obj, argc, argv);
+ return obj;
+}
+
static VALUE onum_initialize(int argc, VALUE *argv, VALUE self)
{
OCIError *errhp = oci8_errhp;
@@ -602,12 +675,26 @@
static VALUE onum_coerce(VALUE self, VALUE other)
{
- OCIError *errhp = oci8_errhp;
+ signed long sl;
OCINumber n;
- if (RTEST(rb_obj_is_kind_of(other, rb_cNumeric)))
- if (set_oci_number_from_num(&n, other, 0, errhp))
- return rb_assoc_new(oci8_make_ocinumber(&n, errhp), self);
+ switch(rboci8_type(other)) {
+ case T_FIXNUM:
+ sl = NUM2LONG(other);
+ oci_lc(OCINumberFromInt(oci8_errhp, &sl, sizeof(sl), OCI_NUMBER_SIGNED, &n));
+ return rb_assoc_new(oci8_make_ocinumber(&n, oci8_errhp), self);
+ case T_BIGNUM:
+ /* change via string. */
+ other = rb_big2str(other, 10);
+ set_oci_number_from_str(&n, other, Qnil, Qnil, oci8_errhp);
+ return rb_assoc_new(oci8_make_ocinumber(&n, oci8_errhp), self);
+ case T_FLOAT:
+ return rb_assoc_new(other, onum_to_f(self));
+ case RBOCI8_T_RATIONAL:
+ return rb_assoc_new(other, onum_to_r(self));
+ case RBOCI8_T_BIGDECIMAL:
+ return rb_assoc_new(other, onum_to_d(self));
+ }
rb_raise(rb_eTypeError, "Can't coerce %s to %s",
rb_class2name(CLASS_OF(other)), rb_class2name(cOCINumber));
}
@@ -616,7 +703,7 @@
* call-seq:
* -onum -> oranumber
*
- * Returns an <code>OraNumber</code>, negated.
+ * Returns a negated <code>OraNumber</code>.
*/
static VALUE onum_neg(VALUE self)
{
@@ -627,12 +714,12 @@
return oci8_make_ocinumber(&r, errhp);
}
+
/*
* call-seq:
- * onum + other -> oranumber
+ * onum + other -> number
*
- * Returns a new <code>OraNumber</code> which is the sum of <i>onum</i>
- * and <i>other</i>.
+ * Returns the sum of <i>onum</i> and <i>other</i>.
*/
static VALUE onum_add(VALUE lhs, VALUE rhs)
{
@@ -640,20 +727,33 @@
OCINumber n;
OCINumber r;
- /* change to OCINumber */
- if (!set_oci_number_from_num(&n, rhs, 0, errhp))
- return rb_num_coerce_bin(lhs, rhs, '+');
- /* add */
- oci_lc(OCINumberAdd(errhp, _NUMBER(lhs), &n, &r));
- return oci8_make_ocinumber(&r, errhp);
+ switch (rboci8_type(rhs)) {
+ case T_FIXNUM:
+ case T_BIGNUM:
+ if (set_oci_number_from_num(&n, rhs, 0, errhp)) {
+ oci_lc(OCINumberAdd(errhp, _NUMBER(lhs), &n, &r));
+ return oci8_make_ocinumber(&r, errhp);
+ }
+ break;
+ case RBOCI8_T_ORANUMBER:
+ oci_lc(OCINumberAdd(errhp, _NUMBER(lhs), _NUMBER(rhs), &r));
+ return oci8_make_ocinumber(&r, errhp);
+ case T_FLOAT:
+ return rb_funcall(onum_to_f(lhs), '+', 1, rhs);
+ case RBOCI8_T_RATIONAL:
+ return rb_funcall(onum_to_r(lhs), '+', 1, rhs);
+ case RBOCI8_T_BIGDECIMAL:
+ return rb_funcall(onum_to_d(lhs), '+', 1, rhs);
+ }
+ return rb_num_coerce_bin(lhs, rhs, '+');
}
/*
* call-seq:
- * onum - other -> oranumber
+ * onum - integer -> oranumber
+ * onum - numeric -> numeric
*
- * Returns a new <code>OraNumber</code> which is the difference of <i>onum</i>
- * and <i>other</i>.
+ * Returns the difference of <i>onum</i> and <i>other</i>.
*/
static VALUE onum_sub(VALUE lhs, VALUE rhs)
{
@@ -661,20 +761,32 @@
OCINumber n;
OCINumber r;
- /* change to OCINumber */
- if (!set_oci_number_from_num(&n, rhs, 0, errhp))
- return rb_num_coerce_bin(lhs, rhs, '-');
- /* subtracting */
- oci_lc(OCINumberSub(errhp, _NUMBER(lhs), &n, &r));
- return oci8_make_ocinumber(&r, errhp);
+ switch (rboci8_type(rhs)) {
+ case T_FIXNUM:
+ case T_BIGNUM:
+ if (set_oci_number_from_num(&n, rhs, 0, errhp)) {
+ oci_lc(OCINumberSub(errhp, _NUMBER(lhs), &n, &r));
+ return oci8_make_ocinumber(&r, errhp);
+ }
+ break;
+ case RBOCI8_T_ORANUMBER:
+ oci_lc(OCINumberSub(errhp, _NUMBER(lhs), _NUMBER(rhs), &r));
+ return oci8_make_ocinumber(&r, errhp);
+ case T_FLOAT:
+ return rb_funcall(onum_to_f(lhs), '-', 1, rhs);
+ case RBOCI8_T_RATIONAL:
+ return rb_funcall(onum_to_r(lhs), '-', 1, rhs);
+ case RBOCI8_T_BIGDECIMAL:
+ return rb_funcall(onum_to_d(lhs), '-', 1, rhs);
+ }
+ return rb_num_coerce_bin(lhs, rhs, '-');
}
/*
* call-seq:
- * onum * other -> oranumber
+ * onum * other -> number
*
- * Returns a new <code>OraNumber</code> which is the product of <i>onum</i>
- * and <i>other</i>.
+ * Returns the product of <i>onum</i> and <i>other</i>.
*/
static VALUE onum_mul(VALUE lhs, VALUE rhs)
{
@@ -682,20 +794,33 @@
OCINumber n;
OCINumber r;
- /* change to OCINumber */
- if (!set_oci_number_from_num(&n, rhs, 0, errhp))
- return rb_num_coerce_bin(lhs, rhs, '*');
- /* multiply */
- oci_lc(OCINumberMul(errhp, _NUMBER(lhs), &n, &r));
- return oci8_make_ocinumber(&r, errhp);
+ switch (rboci8_type(rhs)) {
+ case T_FIXNUM:
+ case T_BIGNUM:
+ if (set_oci_number_from_num(&n, rhs, 0, errhp)) {
+ oci_lc(OCINumberMul(errhp, _NUMBER(lhs), &n, &r));
+ return oci8_make_ocinumber(&r, errhp);
+ }
+ break;
+ case RBOCI8_T_ORANUMBER:
+ oci_lc(OCINumberMul(errhp, _NUMBER(lhs), _NUMBER(rhs), &r));
+ return oci8_make_ocinumber(&r, errhp);
+ case T_FLOAT:
+ return rb_funcall(onum_to_f(lhs), '*', 1, rhs);
+ case RBOCI8_T_RATIONAL:
+ return rb_funcall(onum_to_r(lhs), '*', 1, rhs);
+ case RBOCI8_T_BIGDECIMAL:
+ return rb_funcall(onum_to_d(lhs), '*', 1, rhs);
+ }
+ return rb_num_coerce_bin(lhs, rhs, '*');
}
/*
* call-seq:
- * onum / other -> oranumber
+ * onum / integer -> oranumber
+ * onum / numeric -> numeric
*
- * Returns a new <code>OraNumber</code> which is the result of dividing
- * <i>onum</i> by <i>other</i>.
+ * Returns the result of dividing <i>onum</i> by <i>other</i>.
*/
static VALUE onum_div(VALUE lhs, VALUE rhs)
{
@@ -704,16 +829,32 @@
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();
- /* division */
- oci_lc(OCINumberDiv(errhp, _NUMBER(lhs), &n, &r));
- return oci8_make_ocinumber(&r, errhp);
+ switch (rboci8_type(rhs)) {
+ case T_FIXNUM:
+ if (rhs == INT2FIX(0)) {
+ rb_num_zerodiv();
+ }
+ case T_BIGNUM:
+ if (set_oci_number_from_num(&n, rhs, 0, errhp)) {
+ oci_lc(OCINumberDiv(errhp, _NUMBER(lhs), &n, &r));
+ return oci8_make_ocinumber(&r, errhp);
+ }
+ break;
+ case RBOCI8_T_ORANUMBER:
+ oci_lc(OCINumberIsZero(errhp, _NUMBER(rhs), &is_zero));
+ if (is_zero) {
+ rb_num_zerodiv();
+ }
+ oci_lc(OCINumberDiv(errhp, _NUMBER(lhs), _NUMBER(rhs), &r));
+ return oci8_make_ocinumber(&r, errhp);
+ case T_FLOAT:
+ return rb_funcall(onum_to_f(lhs), '/', 1, rhs);
+ case RBOCI8_T_RATIONAL:
+ return rb_funcall(onum_to_r(lhs), '/', 1, rhs);
+ case RBOCI8_T_BIGDECIMAL:
+ return rb_funcall(onum_to_d(lhs), '/', 1, rhs);
+ }
+ return rb_num_coerce_bin(lhs, rhs, '/');
}
/*
@@ -975,7 +1116,7 @@
* call-seq:
* onum.to_i -> integer
*
- * Returns <i>onm</i> truncated to an <code>Integer</code>.
+ * Returns <i>onum</i> truncated to an <code>Integer</code>.
*/
static VALUE onum_to_i(VALUE self)
{
@@ -990,7 +1131,7 @@
* call-seq:
* onum.to_f -> float
*
- * Converts <i>onum</i> to a <code>Float</code>.
+ * Return the value as a <code>Float</code>.
*
*/
static VALUE onum_to_f(VALUE self)
@@ -1004,8 +1145,69 @@
/*
* 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;
+
+ oci_lc(OCINumberAssign(oci8_errhp, _NUMBER(self), &onum[0]));
+
+ for (;;) {
+ oci_lc(OCINumberIsInt(oci8_errhp, &onum[current], &is_int));
+ if (is_int) {
+ break;
+ }
+ nshift++;
+ oci_lc(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
+}
+
+/*
+ * call-seq:
+ * onum.to_d -> bigdecimal
+ *
+ * Return the value as a <code>BigDecimal</code>.
+ *
+ */
+static VALUE onum_to_d(VALUE self)
+{
+ if (!cBigDecimal) {
+ rb_require("bigdecimal");
+ cBigDecimal = rb_const_get(rb_cObject, id_BigDecimal);
+ }
+ return rb_funcall(rb_cObject, id_BigDecimal, 1, onum_to_s(self));
+}
+
+/*
+ * call-seq:
* onum.to_onum -> oranumber
*
+ * Returns self.
+ *
*/
static VALUE onum_to_onum(VALUE self)
{
@@ -1218,6 +1420,8 @@
id_split = rb_intern("split");
id_numerator = rb_intern("numerator");
id_denominator = rb_intern("denominator");
+ id_Rational = rb_intern("Rational");
+ id_BigDecimal = rb_intern("BigDecimal");
cOCINumber = rb_define_class("OraNumber", rb_cNumeric);
mMath = rb_define_module_under(cOCI8, "Math");
@@ -1275,6 +1479,7 @@
rb_define_alloc_func(cOCINumber, onum_s_alloc);
/* methods of OCI::Number */
+ rb_define_method(rb_cObject, "OraNumber", onum_f_new, -1);
rb_define_method_nodoc(cOCINumber, "initialize", onum_initialize, -1);
rb_define_method_nodoc(cOCINumber, "initialize_copy", onum_initialize_copy, 1);
rb_define_method_nodoc(cOCINumber, "coerce", onum_coerce, 1);
@@ -1302,6 +1507,8 @@
rb_define_method(cOCINumber, "to_char", onum_to_char, -1);
rb_define_method(cOCINumber, "to_i", onum_to_i, 0);
rb_define_method(cOCINumber, "to_f", onum_to_f, 0);
+ rb_define_method(cOCINumber, "to_r", onum_to_r, 0);
+ rb_define_method(cOCINumber, "to_d", onum_to_d, 0);
rb_define_method_nodoc(cOCINumber, "to_onum", onum_to_onum, 0);
rb_define_method(cOCINumber, "zero?", onum_zero_p, 0);
Modified: trunk/ruby-oci8/lib/oci8/bindtype.rb
===================================================================
--- trunk/ruby-oci8/lib/oci8/bindtype.rb 2009-10-04 14:04:01 UTC (rev 362)
+++ trunk/ruby-oci8/lib/oci8/bindtype.rb 2009-10-06 13:46:41 UTC (rev 363)
@@ -24,6 +24,28 @@
end
end
+ class BigDecimal < OCI8::BindType::OraNumber
+ @@bigdecimal_is_required = false
+ def get()
+ unless @@bigdecimal_is_required
+ require 'bigdecimal'
+ @@bigdecimal_is_required = true
+ end
+ (val = super()) && val.to_d
+ end
+ end
+
+ class Rational < OCI8::BindType::OraNumber
+ @@rational_is_required = false
+ def get()
+ unless @@rational_is_required
+ require 'rational'
+ @@rational_is_required = true
+ end
+ (val = super()) && val.to_r
+ end
+ end
+
# get/set Number (for OCI8::SQLT_NUM)
class Number
def self.create(con, val, param, max_array_size)
@@ -54,8 +76,8 @@
if precision < 15 # the precision of double.
klass = OCI8::BindType::Float
else
- # use BigDecimal instead?
- klass = OCI8::BindType::OraNumber
+ # use BigDecimal instead
+ klass = OCI8::BindType::BigDecimal
end
end
klass.new(con, val, nil, max_array_size)
@@ -156,6 +178,8 @@
# bind or explicitly define
OCI8::BindType::Mapping[String] = OCI8::BindType::String
OCI8::BindType::Mapping[OraNumber] = OCI8::BindType::OraNumber
+OCI8::BindType::Mapping['BigDecimal'] = OCI8::BindType::BigDecimal
+OCI8::BindType::Mapping['Rational'] = OCI8::BindType::Rational
OCI8::BindType::Mapping[Fixnum] = OCI8::BindType::Integer
OCI8::BindType::Mapping[Float] = OCI8::BindType::Float
OCI8::BindType::Mapping[Integer] = OCI8::BindType::Integer
@@ -263,9 +287,9 @@
# datatypes that have no explicit setting of their precision
# and scale.
#
-# The default mapping is Float for ruby-oci8 1.0. It is OraNumber
-# for ruby-oci8 2.0.
-OCI8::BindType::Mapping[:number_unknown_prec] = OCI8::BindType::OraNumber
+# The default mapping is Float for ruby-oci8 1.0, OraNumber for 2.0.0 ~ 2.0.2,
+# BigDecimal for 2.0.3 ~.
+OCI8::BindType::Mapping[:number_unknown_prec] = OCI8::BindType::BigDecimal
# mapping for number without precision and scale.
#
@@ -276,9 +300,9 @@
# note: This is available only on Oracle 9.2.0.3 or above.
# see: Oracle 9.2.0.x Patch Set Notes.
#
-# The default mapping is Float for ruby-oci8 1.0. It is OraNumber
-# for ruby-oci8 2.0.
-OCI8::BindType::Mapping[:number_no_prec_setting] = OCI8::BindType::OraNumber
+# The default mapping is Float for ruby-oci8 1.0, OraNumber for 2.0.0 ~ 2.0.2,
+# BigDecimal for 2.0.3 ~.
+OCI8::BindType::Mapping[:number_no_prec_setting] = OCI8::BindType::BigDecimal
if defined? OCI8::BindType::BinaryDouble
OCI8::BindType::Mapping[:binary_float] = OCI8::BindType::BinaryDouble
Modified: trunk/ruby-oci8/lib/oci8/oci8.rb
===================================================================
--- trunk/ruby-oci8/lib/oci8/oci8.rb 2009-10-04 14:04:01 UTC (rev 362)
+++ trunk/ruby-oci8/lib/oci8/oci8.rb 2009-10-06 13:46:41 UTC (rev 363)
@@ -343,6 +343,10 @@
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)
@@ -452,6 +456,10 @@
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
Added: trunk/ruby-oci8/spec/oranumber_spec.rb
===================================================================
--- trunk/ruby-oci8/spec/oranumber_spec.rb (rev 0)
+++ trunk/ruby-oci8/spec/oranumber_spec.rb 2009-10-06 13:46:41 UTC (rev 363)
@@ -0,0 +1,167 @@
+require 'bigdecimal'
+require 'rational'
+require File.join(File.dirname(__FILE__), 'spec_helper.rb')
+
+describe OraNumber do
+
+ it "should be converted to Flaot by to_f" do
+ OraNumber("0.25").to_f.should eql(0.25)
+ end
+
+ it "should be converted to Integer by to_i" do
+ OraNumber("7.25").to_i.should eql(7)
+ OraNumber("7.75").to_i.should eql(7)
+ end
+
+ it "should be converted to Rational by to_r" do
+ OraNumber("100000000000000.1").to_r.should eql(Rational(1000000000000001, 10))
+ end
+
+ it "should be converted to BigDecimal by to_d" do
+ OraNumber("100000000000000.1").to_d.should eql(BigDecimal("100000000000000.1"))
+ end
+
+ # OraNumber bin_op OraNumber
+ it "+ OraNumber should be an OraNumber" do
+ (OraNumber(2) + OraNumber(1)).should eql(OraNumber(3))
+ end
+
+ it "- OraNumber should be an OraNumber" do
+ (OraNumber(2) - OraNumber(1)).should eql(OraNumber(1))
+ end
+
+ it "* OraNumber should be an OraNumber" do
+ (OraNumber(2) * OraNumber(1)).should eql(OraNumber(2))
+ end
+
+ it "/ OraNumber should be an OraNumber" do
+ (OraNumber(2) / OraNumber(1)).should eql(OraNumber(2))
+ end
+
+ # OraNumber bin_op Fixnum
+ it "+ Fixnum should be an OraNumber" do
+ (OraNumber(2) + 1).should eql(OraNumber(3))
+ end
+
+ it "- Fixnum should be an OraNumber" do
+ (OraNumber(2) - 1).should eql(OraNumber(1))
+ end
+
+ it "* Fixnum should be an OraNumber" do
+ (OraNumber(2) * 1).should eql(OraNumber(2))
+ end
+
+ it "/ Fixnum should be an OraNumber" do
+ (OraNumber(2) / 1).should eql(OraNumber(2))
+ end
+
+ # OraNumber bin_op Bignum
+ it "+ Bignum should be an OraNumber" do
+ (OraNumber(2) + 100000000000000000000).should eql(OraNumber(100000000000000000002))
+ end
+
+ it "- Bignum should be an OraNumber" do
+ (OraNumber(2) - 100000000000000000000).should eql(OraNumber(-99999999999999999998))
+ end
+
+ it "* Bignum should be an OraNumber" do
+ (OraNumber(2) * 100000000000000000000).should eql(OraNumber(200000000000000000000))
+ end
+
+ it "/ Bignum should be an OraNumber" do
+ (OraNumber(2) / 100000000000000000000).should eql(OraNumber("0.00000000000000000002"))
+ end
+
+ # OraNumber bin_op Float
+ it "+ Float should be a Float" do
+ (OraNumber(2) + 1.0).should eql(3.0)
+ end
+
+ it "- Float should be a Float" do
+ (OraNumber(2) - 1.0).should eql(1.0)
+ end
+
+ it "* Float should be a Float" do
+ (OraNumber(2) * 1.0).should eql(2.0)
+ end
+
+ it "/ Float should be a Float" do
+ (OraNumber(2) / 1.0).should eql(2.0)
+ end
+
+ # OraNumber bin_op BigDecimal
+ it "+ BigDecimal should be a BigDecimal" do
+ (OraNumber(2) + BigDecimal("1")).should eql(BigDecimal("3"))
+ end
+
+ it "- BigDecimal should be a BigDecimal" do
+ (OraNumber(2) - BigDecimal("1")).should eql(BigDecimal("1"))
+ end
+
+ it "* BigDecimal should be a BigDecimal" do
+ (OraNumber(2) * BigDecimal("1")).should eql(BigDecimal("2"))
+ end
+
+ it "/ BigDecimal should be a BigDecimal" do
+ (OraNumber(2) / BigDecimal("1")).should eql(BigDecimal("2"))
+ end
+
+ # OraNumber bin_op Rational
+ it "+ Rational should be a Rational" do
+ (OraNumber(2) + Rational(1)).should eql(Rational(3))
+ end
+
+ it "- Rational should be a Rational" do
+ (OraNumber(2) - Rational(1)).should eql(Rational(1))
+ end
+
+ it "* Rational should be a Rational" do
+ (OraNumber(2) * Rational(1)).should eql(Rational(2))
+ end
+
+ it "/ Rational should be a Rational" do
+ (OraNumber(2) / Rational(1)).should eql(Rational(2))
+ end
+end
+
+describe Fixnum do
+ it "+ OraNumber should be an OraNumber" do
+ (2 + OraNumber(1)).should eql(OraNumber(3))
+ end
+
+ it "- OraNumber should be an OraNumber" do
+ (2 - OraNumber(1)).should eql(OraNumber(1))
+ end
+
+ it "* OraNumber should be an OraNumber" do
+ (2 * OraNumber(1)).should eql(OraNumber(2))
+ end
+
+ it "/ OraNumber should be an OraNumber" do
+ (2 / OraNumber(1)).should eql(OraNumber(2))
+ end
+end
+
+describe Bignum do
+ it "+ OraNumber should be an OraNumber" do
+ (100000000000000000000 + OraNumber(1)).should eql(OraNumber(100000000000000000001))
+ end
+end
+
+describe Float do
+ it "+ OraNumber should be a Float" do
+ (1.0 + OraNumber(1)).should eql(2.0)
+ end
+end
+
+describe BigDecimal do
+ it "+ OraNumber should be a BigDecimal" do
+ (BigDecimal("1") + OraNumber(1)).should eql(BigDecimal("2"))
+ end
+end
+
+describe Rational do
+ it "+ OraNumber should be a Rational" do
+ (Rational(1) + OraNumber(1)).should eql(Rational(2))
+ end
+end
Modified: trunk/ruby-oci8/test/test_oci8.rb
===================================================================
--- trunk/ruby-oci8/test/test_oci8.rb 2009-10-04 14:04:01 UTC (rev 362)
+++ trunk/ruby-oci8/test/test_oci8.rb 2009-10-06 13:46:41 UTC (rev 363)
@@ -359,10 +359,10 @@
assert_equal(row[2], 123456789012.34)
assert_equal(row[3], 1234567890123.45)
assert_equal(row[4], 1234.5)
- assert_instance_of(OraNumber, row[0])
+ assert_instance_of(BigDecimal, row[0])
assert_instance_of(Bignum, row[1])
assert_instance_of(Float, row[2])
- assert_instance_of(OraNumber, row[3])
+ assert_instance_of(BigDecimal, row[3])
assert_instance_of(Float, row[4])
end
drop_table('test_table')
@@ -372,6 +372,8 @@
src = [1, 1.2, BigDecimal("1.2"), Rational(12, 10)]
int = [1, 1, 1, 1]
flt = [1, 1.2, 1.2, 1.2]
+ dec = [BigDecimal("1"), BigDecimal("1.2"), BigDecimal("1.2"), BigDecimal("1.2")]
+ rat = [Rational(1), Rational(12, 10), Rational(12, 10), Rational(12, 10)]
cursor = @conn.parse("begin :1 := :2; end;")
@@ -382,6 +384,7 @@
cursor[2] = s
cursor.exec
assert_equal(cursor[1], flt[idx])
+ assert_kind_of(Float, cursor[1])
end
# Fixnum
@@ -391,6 +394,7 @@
cursor[2] = s
cursor.exec
assert_equal(cursor[1], int[idx])
+ assert_kind_of(Fixnum, cursor[1])
end
# Integer
@@ -400,7 +404,28 @@
cursor[2] = s
cursor.exec
assert_equal(cursor[1], int[idx])
+ assert_kind_of(Integer, cursor[1])
end
+
+ # BigDecimal
+ cursor.bind_param(1, nil, BigDecimal)
+ cursor.bind_param(2, nil, BigDecimal)
+ src.each_with_index do |s, idx|
+ cursor[2] = s
+ cursor.exec
+ assert_equal(cursor[1], dec[idx])
+ assert_kind_of(BigDecimal, cursor[1])
+ end
+
+ # Rational
+ cursor.bind_param(1, nil, Rational)
+ cursor.bind_param(2, nil, Rational)
+ src.each_with_index do |s, idx|
+ cursor[2] = s
+ cursor.exec
+ assert_equal(cursor[1], rat[idx])
+ assert_kind_of(Rational, cursor[1])
+ end
end
end # TestOCI8
More information about the ruby-oci8-commit
mailing list