[ruby-oci8-commit] [375] trunk/ruby-oci8: * ext/oci8/ocinumber.c: fix to support NNUMBERS with scale larger

nobody at rubyforge.org nobody at rubyforge.org
Tue Feb 2 08:14:32 EST 2010


Revision: 375
Author:   kubo
Date:     2010-02-02 08:14:30 -0500 (Tue, 02 Feb 2010)

Log Message:
-----------
* ext/oci8/ocinumber.c: fix to support NNUMBERS with scale larger
    than 38 by using scientific number notation to convert OraNumber
    to BigDecimal. OraNumber#to_i is also fixed.
    (reported by Raimonds Simanovskis)

Modified Paths:
--------------
    trunk/ruby-oci8/ChangeLog
    trunk/ruby-oci8/ext/oci8/ocinumber.c

Modified: trunk/ruby-oci8/ChangeLog
===================================================================
--- trunk/ruby-oci8/ChangeLog	2010-01-24 13:43:11 UTC (rev 374)
+++ trunk/ruby-oci8/ChangeLog	2010-02-02 13:14:30 UTC (rev 375)
@@ -1,3 +1,9 @@
+2010-02-02  KUBO Takehiro  <kubo at jiubao.org>
+	* ext/oci8/ocinumber.c: fix to support NNUMBERS with scale larger
+	    than 38 by using scientific number notation to convert OraNumber
+	    to BigDecimal. OraNumber#to_i is also fixed.
+	    (reported by Raimonds Simanovskis)
+
 2010-01-24  KUBO Takehiro  <kubo at jiubao.org>
 	* ext/oci8/error.c: Use OCIErrorGet() to retrieve the error message
 	    when the OCI return code is OCI_NO_DATA.

Modified: trunk/ruby-oci8/ext/oci8/ocinumber.c
===================================================================
--- trunk/ruby-oci8/ext/oci8/ocinumber.c	2010-01-24 13:43:11 UTC (rev 374)
+++ trunk/ruby-oci8/ext/oci8/ocinumber.c	2010-02-02 13:14:30 UTC (rev 375)
@@ -109,6 +109,7 @@
 static VALUE onum_to_f(VALUE self);
 static VALUE onum_to_r(VALUE self);
 static VALUE onum_to_d(VALUE self);
+static VALUE onum_to_d_real(OCINumber *num, OCIError *errhp);
 
 static VALUE onum_s_alloc(VALUE klass)
 {
@@ -136,13 +137,23 @@
     signed long sl;
     char buf[512];
     ub4 buf_size = sizeof(buf);
+    sword rv;
 
     if (OCINumberToInt(errhp, s, sizeof(sl), OCI_NUMBER_SIGNED, &sl) == OCI_SUCCESS) {
         return LONG2NUM(sl);
     }
-    oci_lc(OCINumberToText(errhp, s, NUMBER_FORMAT2, NUMBER_FORMAT2_LEN,
-                           NULL, 0, &buf_size, TO_ORATEXT(buf)));
-    return rb_cstr2inum(buf, 10);
+    /* convert to Integer via String */
+    rv = OCINumberToText(errhp, s, NUMBER_FORMAT2, NUMBER_FORMAT2_LEN,
+                         NULL, 0, &buf_size, TO_ORATEXT(buf));
+    if (rv == OCI_SUCCESS) {
+        return rb_cstr2inum(buf, 10);
+    }
+    if (rv == OCI_ERROR && oci8_get_error_code(errhp) == 22065) {
+        /* convert to Integer via BigDecimal as a last resort */
+        VALUE d = onum_to_d_real(s, errhp);
+        return rb_funcall(d, rb_intern("to_i"), 0);
+    }
+    oci8_raise(errhp, rv, NULL);
 }
 
 VALUE oci8_make_float(OCINumber *s, OCIError *errhp)
@@ -1195,11 +1206,23 @@
  */
 static VALUE onum_to_d(VALUE self)
 {
+    return onum_to_d_real(_NUMBER(self), 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 const char *fmt = "FM9.99999999999999999999999999999999999999EEEE";
+
     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));
+    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));
 }
 
 /*




More information about the ruby-oci8-commit mailing list