[ruby-oci8-commit] [343] trunk/ruby-oci8: * ext/oci8/error.c, ext/oci8/extconf.rb, ext/oci8/ oci8.h:

nobody at rubyforge.org nobody at rubyforge.org
Sun May 17 06:08:42 EDT 2009


Revision: 343
Author:   kubo
Date:     2009-05-17 06:08:39 -0400 (Sun, 17 May 2009)

Log Message:
-----------
* ext/oci8/error.c, ext/oci8/extconf.rb, ext/oci8/oci8.h:
    fix the native library name in error messages from oci8lib.so
    to oci8lib_18.so or oci8lib_191.so.
* ext/oci8/ocinumber.c, test/test_oranumber.rb: fix OraNumber.new
    to accept BigDecimal and Rational.
* ext/oci8/bind.c, test/test_oci8.rb: implicitly convert the
    specified number to Float when the bind handle is for Float.
* ext/oci8/attr.c: fix for Oracle client which doesn't have
    OCIRowidToChar().
* ext/oci8/oci8.c, test/test_appinfo.rb, test/test_all.rb, dist-files:
    add new methods OCI8#ping and OCI8#client_identifier=.
    add test cases.
* ext/oci8/oci8lib.c: fix a bug for Oracle 8.0.
* lib/oci8/oci8.rb: add a convenient method OCI8#select_one
    to fetch one row.

Modified Paths:
--------------
    trunk/ruby-oci8/ChangeLog
    trunk/ruby-oci8/dist-files
    trunk/ruby-oci8/ext/oci8/attr.c
    trunk/ruby-oci8/ext/oci8/bind.c
    trunk/ruby-oci8/ext/oci8/error.c
    trunk/ruby-oci8/ext/oci8/extconf.rb
    trunk/ruby-oci8/ext/oci8/oci8.c
    trunk/ruby-oci8/ext/oci8/oci8.h
    trunk/ruby-oci8/ext/oci8/oci8lib.c
    trunk/ruby-oci8/ext/oci8/ocinumber.c
    trunk/ruby-oci8/lib/oci8/oci8.rb
    trunk/ruby-oci8/test/test_all.rb
    trunk/ruby-oci8/test/test_oci8.rb
    trunk/ruby-oci8/test/test_oranumber.rb

Added Paths:
-----------
    trunk/ruby-oci8/test/test_appinfo.rb

Modified: trunk/ruby-oci8/ChangeLog
===================================================================
--- trunk/ruby-oci8/ChangeLog	2009-05-08 12:59:02 UTC (rev 342)
+++ trunk/ruby-oci8/ChangeLog	2009-05-17 10:08:39 UTC (rev 343)
@@ -1,3 +1,20 @@
+2009-05-17  KUBO Takehiro  <kubo at jiubao.org>
+	* ext/oci8/error.c, ext/oci8/extconf.rb, ext/oci8/oci8.h:
+	    fix the native library name in error messages from oci8lib.so
+	    to oci8lib_18.so or oci8lib_191.so.
+	* ext/oci8/ocinumber.c, test/test_oranumber.rb: fix OraNumber.new
+	    to accept BigDecimal and Rational.
+	* ext/oci8/bind.c, test/test_oci8.rb: implicitly convert the
+	    specified number to Float when the bind handle is for Float.
+	* ext/oci8/attr.c: fix for Oracle client which doesn't have
+	    OCIRowidToChar().
+	* ext/oci8/oci8.c, test/test_appinfo.rb, test/test_all.rb, dist-files:
+	    add new methods OCI8#ping and OCI8#client_identifier=.
+	    add test cases.
+	* ext/oci8/oci8lib.c: fix a bug for Oracle 8.0.
+	* lib/oci8/oci8.rb: add a convenient method OCI8#select_one
+	    to fetch one row.
+
 2009-04-18  KUBO Takehiro  <kubo at jiubao.org>
 	* lib/oci8/oci8.rb: move OCI8::BindType module to bindtype.rb.
 	* lib/oci8/bindtype.rb: added. This defines OCI8::BindType.

Modified: trunk/ruby-oci8/dist-files
===================================================================
--- trunk/ruby-oci8/dist-files	2009-05-08 12:59:02 UTC (rev 342)
+++ trunk/ruby-oci8/dist-files	2009-05-17 10:08:39 UTC (rev 343)
@@ -54,6 +54,7 @@
 test/README
 test/config.rb
 test/test_all.rb
+test/test_appinfo.rb
 test/test_array_dml.rb
 test/test_bind_raw.rb
 test/test_bind_time.rb

Modified: trunk/ruby-oci8/ext/oci8/attr.c
===================================================================
--- trunk/ruby-oci8/ext/oci8/attr.c	2009-05-08 12:59:02 UTC (rev 342)
+++ trunk/ruby-oci8/ext/oci8/attr.c	2009-05-17 10:08:39 UTC (rev 343)
@@ -106,7 +106,8 @@
          * Oracle Server.
          */
         oci8_base_t *svc;
-        oci8_exec_sql_var_t bind_vars[2];
+        oci8_exec_sql_var_t define_var;
+        oci8_exec_sql_var_t bind_var;
 
         /* search a connection from the handle */
         svc = base;
@@ -117,19 +118,19 @@
             }
         }
         /* :strval */
-        bind_vars[0].valuep = buf;
-        bind_vars[0].value_sz = sizeof(buf);
-        bind_vars[0].dty = SQLT_CHR;
-        bind_vars[0].indp = NULL;
-        bind_vars[0].alenp = &buflen;
+        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_vars[1].valuep = &arg->ridp;
-        bind_vars[1].value_sz = sizeof(void *);
-        bind_vars[1].dty = SQLT_RDD;
-        bind_vars[1].indp = NULL;
-        bind_vars[1].alenp = NULL;
+        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, "BEGIN :strval := :rowid; END;", 0, NULL, 2, bind_vars, 1);
+        oci8_exec_sql((oci8_svcctx_t*)svc, "SELECT :rid FROM dual", 1, &define_var, 1, &bind_var, 1);
         if (buflen == 0) {
             return Qnil;
         }

Modified: trunk/ruby-oci8/ext/oci8/bind.c
===================================================================
--- trunk/ruby-oci8/ext/oci8/bind.c	2009-05-08 12:59:02 UTC (rev 342)
+++ trunk/ruby-oci8/ext/oci8/bind.c	2009-05-17 10:08:39 UTC (rev 343)
@@ -284,8 +284,8 @@
 
 static void bind_float_set(oci8_bind_t *obind, void *data, void **null_structp, VALUE val)
 {
-    Check_Type(val, T_FLOAT);
-    *(double*)data = RFLOAT_VALUE(val);
+    /* val is converted to Float if it isn't Float. */
+    *(double*)data = RFLOAT_VALUE(rb_Float(val));
 }
 
 static void bind_float_init(oci8_bind_t *obind, VALUE svc, VALUE val, VALUE length)

Modified: trunk/ruby-oci8/ext/oci8/error.c
===================================================================
--- trunk/ruby-oci8/ext/oci8/error.c	2009-05-08 12:59:02 UTC (rev 342)
+++ trunk/ruby-oci8/ext/oci8/error.c	2009-05-17 10:08:39 UTC (rev 343)
@@ -157,7 +157,7 @@
 #endif
     backtrace = rb_funcall(rb_cObject, oci8_id_caller, 0);
     if (TYPE(backtrace) == T_ARRAY) {
-        snprintf(errmsg, sizeof(errmsg), "%s:%d:in oci8lib.so", file, line);
+        snprintf(errmsg, sizeof(errmsg), "%s:%d:in " STRINGIZE(oci8lib) DLEXT, file, line);
         errmsg[sizeof(errmsg) - 1] = '\0';
         rb_ary_unshift(backtrace, rb_usascii_str_new_cstr(errmsg));
         rb_funcall(exc, oci8_id_set_backtrace, 1, backtrace);

Modified: trunk/ruby-oci8/ext/oci8/extconf.rb
===================================================================
--- trunk/ruby-oci8/ext/oci8/extconf.rb	2009-05-08 12:59:02 UTC (rev 342)
+++ trunk/ruby-oci8/ext/oci8/extconf.rb	2009-05-17 10:08:39 UTC (rev 343)
@@ -127,6 +127,7 @@
   raise 'unsupported ruby version: ' + RUBY_VERSION
 end
 $defs << "-DInit_oci8lib=Init_#{so_basename}"
+$defs << "-Doci8lib=#{so_basename}"
 
 create_header()
 

Modified: trunk/ruby-oci8/ext/oci8/oci8.c
===================================================================
--- trunk/ruby-oci8/ext/oci8/oci8.c	2009-05-08 12:59:02 UTC (rev 342)
+++ trunk/ruby-oci8/ext/oci8/oci8.c	2009-05-17 10:08:39 UTC (rev 343)
@@ -17,6 +17,10 @@
 #endif
 #endif
 
+#ifndef OCI_ATTR_CLIENT_IDENTIFIER
+#define OCI_ATTR_CLIENT_IDENTIFIER 278
+#endif
+
 /*
  * Document-class: OCI8
  *
@@ -556,6 +560,83 @@
     }
 }
 
+/*
+ * call-seq:
+ *   ping -> true or false
+ *
+ * Verifies that the Oracle connection is alive.
+ *
+ * OCI8#ping also can be used to flush all the pending OCI client-side calls
+ * to the server if any exist. See: OCI8#client_identifier=.
+ *
+ * For Oracle 10.2 client or upper, a dummy round trip call is made by a newly
+ * added OCI function in Oracle 10.2.
+ *
+ * For Oracle 10.1 client or lower, a simple PL/SQL block "BEGIN NULL; END;"
+ * is executed to make a round trip call.
+ */
+static VALUE oci8_ping(VALUE self)
+{
+    oci8_svcctx_t *svcctx = oci8_get_svcctx(self);
+    if (have_OCIPing_nb) {
+        /* Oracle 10.2 or upper */
+        oci_lc(OCIPing_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, OCI_DEFAULT));
+    } else {
+        /* Oracle 10.1 or lower */
+        oci8_exec_sql(svcctx, "BEGIN NULL; END;", 0U, NULL, 0U, NULL, 1);
+    }
+    return self;
+}
+
+/*
+ * call-seq:
+ *   client_identifier = string
+ *
+ * Sets the CLIENT_IDENTIFIER column in the V$SESSION dictionary view.
+ * This can be up to 64 bytes long. The first character should not be ':'.
+ *
+ * If the Oracle client is 9i or upper, the change is not reflected to the
+ * server immediately. It is postponed until the next round trip call for
+ * example OCI8#exec, OCI8#ping, etc.
+ *
+ * This call is equivalent to "DBMS_SESSION.SET_IDENTIFIER(client_id VARCHAR2);"
+ * and available when the server is Oracle 9i or upper.
+ */
+static VALUE oci8_set_client_identifier(VALUE self, VALUE val)
+{
+    OCISession *sess = oci8_get_oci_session(self);
+    char *ptr;
+    ub4 size;
+
+    if (!NIL_P(val)) {
+        OCI8SafeStringValue(val);
+        ptr = RSTRING_PTR(val);
+        size = RSTRING_LEN(val);
+    } else {
+        ptr = "";
+        size = 0;
+    }
+    if (oracle_client_version >= 900) {
+        if (size > 0 && ptr[0] == ':') {
+            rb_raise(rb_eArgError, "client identifier should not start with ':'.");
+        }
+        oci_lc(OCIAttrSet(sess, OCI_HTYPE_SESSION, ptr,
+                          size, OCI_ATTR_CLIENT_IDENTIFIER, oci8_errhp));
+    } else {
+        oci8_exec_sql_var_t bind_vars[1];
+
+        /* :client_id */
+        bind_vars[0].valuep = ptr;
+        bind_vars[0].value_sz = size;
+        bind_vars[0].dty = SQLT_CHR;
+        bind_vars[0].indp = NULL;
+        bind_vars[0].alenp = NULL;
+
+        oci8_exec_sql(oci8_get_svcctx(self), "BEGIN DBMS_SESSION.SET_IDENTIFIER(:client_id); END;", 0, NULL, 1, bind_vars, 1);
+    }
+    return val;
+}
+
 VALUE Init_oci8(void)
 {
     cOCI8 = oci8_define_class("OCI8", &oci8_svcctx_class);
@@ -589,6 +670,8 @@
     rb_define_method(cOCI8, "break", oci8_break, 0);
     rb_define_method(cOCI8, "prefetch_rows=", oci8_set_prefetch_rows, 1);
     rb_define_private_method(cOCI8, "oracle_server_vernum", oci8_oracle_server_vernum, 0);
+    rb_define_method(cOCI8, "ping", oci8_ping, 0);
+    rb_define_method(cOCI8, "client_identifier=", oci8_set_client_identifier, 1);
     return cOCI8;
 }
 

Modified: trunk/ruby-oci8/ext/oci8/oci8.h
===================================================================
--- trunk/ruby-oci8/ext/oci8/oci8.h	2009-05-08 12:59:02 UTC (rev 342)
+++ trunk/ruby-oci8/ext/oci8/oci8.h	2009-05-17 10:08:39 UTC (rev 343)
@@ -117,6 +117,9 @@
 #ifndef RFLOAT_VALUE
 #define RFLOAT_VALUE(obj) RFLOAT(obj)->value
 #endif
+#ifndef STRINGIZE
+#define STRINGIZE(name) #name
+#endif
 
 /* new functions in ruby 1.9.
  * define compatible macros for ruby 1.8 or lower.

Modified: trunk/ruby-oci8/ext/oci8/oci8lib.c
===================================================================
--- trunk/ruby-oci8/ext/oci8/oci8lib.c	2009-05-08 12:59:02 UTC (rev 342)
+++ trunk/ruby-oci8/ext/oci8/oci8lib.c	2009-05-17 10:08:39 UTC (rev 343)
@@ -168,7 +168,7 @@
         if (rv != OCI_SUCCESS) {
             oci8_raise_init_error();
         }
-        rv = OCIEnvInit(&oci8_global_envhp, OCI_DEFAULT, 0, NULL);
+        rv = OCIEnvInit(&envhp, OCI_DEFAULT, 0, NULL);
         if (rv != OCI_SUCCESS) {
             oci8_raise_init_error();
         }

Modified: trunk/ruby-oci8/ext/oci8/ocinumber.c
===================================================================
--- trunk/ruby-oci8/ext/oci8/ocinumber.c	2009-05-08 12:59:02 UTC (rev 342)
+++ trunk/ruby-oci8/ext/oci8/ocinumber.c	2009-05-17 10:08:39 UTC (rev 343)
@@ -17,6 +17,10 @@
 
 static ID id_power; /* rb_intern("**") */
 static ID id_cmp;   /* rb_intern("<=>") */
+static ID id_finite_p;
+static ID id_split;
+static ID id_numerator;
+static ID id_denominator;
 
 static VALUE cOCINumber;
 static OCINumber const_p1;   /*  +1 */
@@ -147,6 +151,9 @@
 
     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. */
@@ -169,6 +176,74 @@
         oci_lc(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]);
+
+            if (have_OCINumberShift) {
+                /* Oracle 8.1 or upper */
+                oci_lc(OCINumberShift(errhp, &digits, exponent - digits_len, &work));
+            } else {
+                /* Oracle 8.0 */
+                int n = 10;
+                OCINumber base;
+                OCINumber exp;
+
+                oci_lc(OCINumberFromInt(errhp, &n, sizeof(n), OCI_NUMBER_SIGNED, &base));
+                oci_lc(OCINumberIntPower(errhp, &base, exponent - digits_len, &exp));
+                oci_lc(OCINumberMul(errhp, &digits, &exp, &work));
+            }
+            if (sign >= 0) {
+                oci_lc(OCINumberAssign(errhp, &work, result));
+            } else {
+                oci_lc(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)) {
+            oci_lc(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 */
@@ -1139,6 +1214,10 @@
 
     id_power = rb_intern("**");
     id_cmp = rb_intern("<=>");
+    id_finite_p = rb_intern("finite?");
+    id_split = rb_intern("split");
+    id_numerator = rb_intern("numerator");
+    id_denominator = rb_intern("denominator");
 
     cOCINumber = rb_define_class("OraNumber", rb_cNumeric);
     mMath = rb_define_module_under(cOCI8, "Math");

Modified: trunk/ruby-oci8/lib/oci8/oci8.rb
===================================================================
--- trunk/ruby-oci8/lib/oci8/oci8.rb	2009-05-08 12:59:02 UTC (rev 342)
+++ trunk/ruby-oci8/lib/oci8/oci8.rb	2009-05-17 10:08:39 UTC (rev 343)
@@ -129,6 +129,20 @@
     end
   end # exec
 
+  # :call-seq:
+  #   select_one(sql, *bindvars) -> first_one_row
+  #
+  def select_one(sql, *bindvars)
+    cursor = self.parse(sql)
+    begin
+      cursor.exec(*bindvars)
+      row = cursor.fetch
+    ensure
+      cursor.close
+    end
+    return row
+  end
+
   def username
     @username || begin
       exec('select user from dual') do |row|

Modified: trunk/ruby-oci8/test/test_all.rb
===================================================================
--- trunk/ruby-oci8/test/test_all.rb	2009-05-08 12:59:02 UTC (rev 342)
+++ trunk/ruby-oci8/test/test_all.rb	2009-05-17 10:08:39 UTC (rev 343)
@@ -19,6 +19,7 @@
 require "#{srcdir}/test_metadata"
 require "#{srcdir}/test_array_dml"
 require "#{srcdir}/test_rowid"
+require "#{srcdir}/test_appinfo"
 require "#{srcdir}/test_oracle_version"
 
 if OCI8.respond_to? :encoding

Added: trunk/ruby-oci8/test/test_appinfo.rb
===================================================================
--- trunk/ruby-oci8/test/test_appinfo.rb	                        (rev 0)
+++ trunk/ruby-oci8/test/test_appinfo.rb	2009-05-17 10:08:39 UTC (rev 343)
@@ -0,0 +1,29 @@
+require 'oci8'
+require 'test/unit'
+require File.dirname(__FILE__) + '/config'
+
+class TestAppInfo < Test::Unit::TestCase
+
+  def setup
+    @conn = get_oci8_connection
+  end
+
+  def test_set_client_identifier
+    # set client_id
+    client_id = "ruby-oci8:#{Process.pid()}"
+    @conn.client_identifier = client_id
+    assert_equal(client_id, @conn.select_one("SELECT SYS_CONTEXT('USERENV', 'CLIENT_IDENTIFIER') FROM DUAL")[0]);
+    # check the first character
+    assert_raise ArgumentError do
+      @conn.client_identifier = ':bad_identifier'
+    end
+
+    # clear client_id
+    @conn.client_identifier = nil
+    assert_nil(@conn.select_one("SELECT SYS_CONTEXT('USERENV', 'CLIENT_IDENTIFIER') FROM DUAL")[0]);
+  end
+
+  def teardown
+    @conn.logoff
+  end
+end

Modified: trunk/ruby-oci8/test/test_oci8.rb
===================================================================
--- trunk/ruby-oci8/test/test_oci8.rb	2009-05-08 12:59:02 UTC (rev 342)
+++ trunk/ruby-oci8/test/test_oci8.rb	2009-05-17 10:08:39 UTC (rev 343)
@@ -1,6 +1,8 @@
 require 'oci8'
 require 'test/unit'
 require File.dirname(__FILE__) + '/config'
+require 'bigdecimal'
+require 'rational'
 
 class TestOCI8 < Test::Unit::TestCase
 
@@ -366,4 +368,39 @@
     drop_table('test_table')
   end
 
+  def test_bind_number_with_implicit_conversions
+    src = [1, 1.2, BigDecimal("1.2"), Rational(12, 10)]
+    int = [1, 1, 1, 1]
+    flt = [1, 1.2, 1.2, 1.2]
+
+    cursor = @conn.parse("begin :1 := :2; end;")
+
+    # Float
+    cursor.bind_param(1, nil, Float)
+    cursor.bind_param(2, nil, Float)
+    src.each_with_index do |s, idx|
+      cursor[2] = s
+      cursor.exec
+      assert_equal(cursor[1], flt[idx])
+    end
+
+    # Fixnum
+    cursor.bind_param(1, nil, Fixnum)
+    cursor.bind_param(2, nil, Fixnum)
+    src.each_with_index do |s, idx|
+      cursor[2] = s
+      cursor.exec
+      assert_equal(cursor[1], int[idx])
+    end
+
+    # Integer
+    cursor.bind_param(1, nil, Integer)
+    cursor.bind_param(2, nil, Integer)
+    src.each_with_index do |s, idx|
+      cursor[2] = s
+      cursor.exec
+      assert_equal(cursor[1], int[idx])
+    end
+  end
+
 end # TestOCI8

Modified: trunk/ruby-oci8/test/test_oranumber.rb
===================================================================
--- trunk/ruby-oci8/test/test_oranumber.rb	2009-05-08 12:59:02 UTC (rev 342)
+++ trunk/ruby-oci8/test/test_oranumber.rb	2009-05-17 10:08:39 UTC (rev 343)
@@ -3,6 +3,8 @@
 require 'test/unit'
 require File.dirname(__FILE__) + '/config'
 require 'yaml'
+require 'bigdecimal'
+require 'rational'
 
 class TestOraNumber < Test::Unit::TestCase
 
@@ -480,4 +482,26 @@
       assert_equal(expected_val, actual_val, x)
     end
   end
+
+  def test_new_from_bigdecimal
+    ["+Infinity", "-Infinity", "NaN"].each do |n|
+      assert_raise TypeError do
+        OraNumber.new(BigDecimal.new(n))
+      end
+    end
+
+    LARGE_RANGE_VALUES.each do |val|
+      assert_equal(val, OraNumber.new(BigDecimal.new(val)).to_s)
+    end
+  end
+
+  def test_new_from_rational
+    [
+     [Rational(1, 2), "0.5"],
+     [Rational(3, 5), "0.6"],
+     [Rational(10, 3), "3.3333333333333333333333333333333333333"],
+    ].each do |ary|
+      assert_equal(ary[1], OraNumber.new(ary[0]).to_s)
+    end
+  end
 end




More information about the ruby-oci8-commit mailing list