[ruby-oci8-commit] [320] trunk/ruby-oci8: * ext/oci8/bind.c, ext/oci8/oci8.h, ext/oci8/stmt.c: fix array DML

nobody at rubyforge.org nobody at rubyforge.org
Tue Feb 10 08:50:41 EST 2009


Revision: 320
Author:   kubo
Date:     2009-02-10 08:50:40 -0500 (Tue, 10 Feb 2009)

Log Message:
-----------
* ext/oci8/bind.c, ext/oci8/oci8.h, ext/oci8/stmt.c: fix array DML
    and DateTime object problem. It didn't work with bind classes
    which overwrite 'set' and 'get'. (Reported by Leo?\197?\161 Bitto)
* test/test_array_dml.rb: fix to test array DML and DateTime object.

Modified Paths:
--------------
    trunk/ruby-oci8/ChangeLog
    trunk/ruby-oci8/ext/oci8/bind.c
    trunk/ruby-oci8/ext/oci8/oci8.h
    trunk/ruby-oci8/ext/oci8/stmt.c
    trunk/ruby-oci8/test/test_array_dml.rb

Modified: trunk/ruby-oci8/ChangeLog
===================================================================
--- trunk/ruby-oci8/ChangeLog	2009-02-08 13:28:56 UTC (rev 319)
+++ trunk/ruby-oci8/ChangeLog	2009-02-10 13:50:40 UTC (rev 320)
@@ -1,3 +1,9 @@
+2009-02-10  KUBO Takehiro  <kubo at jiubao.org>
+	* ext/oci8/bind.c, ext/oci8/oci8.h, ext/oci8/stmt.c: fix array DML
+	    and DateTime object problem. It didn't work with bind classes
+	    which overwrite 'set' and 'get'. (Reported by Leoš Bitto)
+	* test/test_array_dml.rb: fix to test array DML and DateTime object.
+
 2009-02-08  KUBO Takehiro  <kubo at jiubao.org>
 	* VERSION: change version from 2.0-svn to 2.0.0 to pass ruby
 	    gem's version string validator.

Modified: trunk/ruby-oci8/ext/oci8/bind.c
===================================================================
--- trunk/ruby-oci8/ext/oci8/bind.c	2009-02-08 13:28:56 UTC (rev 319)
+++ trunk/ruby-oci8/ext/oci8/bind.c	2009-02-10 13:50:40 UTC (rev 320)
@@ -10,7 +10,6 @@
 #include "oci8.h"
 
 static ID id_bind_type;
-static ID id_set;
 
 static VALUE cOCI8BindTypeBase;
 
@@ -330,8 +329,11 @@
     SQLT_BDOUBLE
 };
 
-static inline VALUE oci8_get_data_at(const oci8_bind_class_t *obc, oci8_bind_t *obind, ub4 idx)
+static VALUE oci8_bind_get(VALUE self)
 {
+    oci8_bind_t *obind = DATA_PTR(self);
+    const oci8_bind_class_t *obc = (const oci8_bind_class_t *)obind->base.klass;
+    ub4 idx = obind->curar_idx;
     void **null_structp = NULL;
 
     if (NIL_P(obind->tdo)) {
@@ -345,26 +347,30 @@
     return obc->get(obind, (void*)((size_t)obind->valuep + obind->alloc_sz * idx), null_structp);
 }
 
-static VALUE oci8_get_data(VALUE self)
+VALUE oci8_bind_get_data(VALUE self)
 {
     oci8_bind_t *obind = DATA_PTR(self);
-    const oci8_bind_class_t *obc = (const oci8_bind_class_t *)obind->base.klass;
 
     if (obind->maxar_sz == 0) {
-        return oci8_get_data_at(obc, obind, 0);
+        obind->curar_idx = 0;
+        return rb_funcall(self, oci8_id_get, 0);
     } else {
         volatile VALUE ary = rb_ary_new2(obind->curar_sz);
         ub4 idx;
 
         for (idx = 0; idx < obind->curar_sz; idx++) {
-            rb_ary_store(ary, idx, oci8_get_data_at(obc, obind, idx));
+            obind->curar_idx = idx;
+            rb_ary_store(ary, idx, rb_funcall(self, oci8_id_get, 0));
         }
         return ary;
     }
 }
 
-static inline void oci8_set_data_at(const oci8_bind_class_t *obc, oci8_bind_t *obind, ub4 idx, VALUE val)
+static VALUE oci8_bind_set(VALUE self, VALUE val)
 {
+    oci8_bind_t *obind = DATA_PTR(self);
+    const oci8_bind_class_t *obc = (const oci8_bind_class_t *)obind->base.klass;
+    ub4 idx = obind->curar_idx;
 
     if (NIL_P(val)) {
         if (NIL_P(obind->tdo)) {
@@ -383,15 +389,16 @@
         }
         obc->set(obind, (void*)((size_t)obind->valuep + obind->alloc_sz * idx), null_structp, val);
     }
+    return self;
 }
 
-static VALUE oci8_set_data(VALUE self, VALUE val)
+void oci8_bind_set_data(VALUE self, VALUE val)
 {
     oci8_bind_t *obind = DATA_PTR(self);
-    const oci8_bind_class_t *obc = (const oci8_bind_class_t *)obind->base.klass;
 
     if (obind->maxar_sz == 0) {
-        oci8_set_data_at(obc, obind, 0, val);
+        obind->curar_idx = 0;
+        rb_funcall(self, oci8_id_set, 1, val);
     } else {
         ub4 size;
         ub4 idx;
@@ -402,11 +409,11 @@
             rb_raise(rb_eRuntimeError, "over the max array size");
         }
         for (idx = 0; idx < size; idx++) {
-            oci8_set_data_at(obc, obind, idx, RARRAY_PTR(val)[idx]);
+            obind->curar_idx = idx;
+            rb_funcall(self, oci8_id_set, 1, RARRAY_PTR(val)[idx]);
         }
         obind->curar_sz = size;
     }
-    return self;
 }
 
 static VALUE oci8_bind_initialize(VALUE self, VALUE svc, VALUE val, VALUE length, VALUE max_array_size)
@@ -438,7 +445,7 @@
         bind_class->init_elem(obind, svc);
     }
     if (!NIL_P(val)) {
-        rb_funcall(self, id_set, 1, val);
+        oci8_bind_set_data(self, val);
     }
     return Qnil;
 }
@@ -474,11 +481,10 @@
 {
     cOCI8BindTypeBase = klass;
     id_bind_type = rb_intern("bind_type");
-    id_set = rb_intern("set");
 
     rb_define_method(cOCI8BindTypeBase, "initialize", oci8_bind_initialize, 4);
-    rb_define_method(cOCI8BindTypeBase, "get", oci8_get_data, 0);
-    rb_define_method(cOCI8BindTypeBase, "set", oci8_set_data, 1);
+    rb_define_method(cOCI8BindTypeBase, "get", oci8_bind_get, 0);
+    rb_define_method(cOCI8BindTypeBase, "set", oci8_bind_set, 1);
 
     /* register primitive data types. */
     oci8_define_bind_class("String", &bind_string_class);

Modified: trunk/ruby-oci8/ext/oci8/oci8.h
===================================================================
--- trunk/ruby-oci8/ext/oci8/oci8.h	2009-02-08 13:28:56 UTC (rev 319)
+++ trunk/ruby-oci8/ext/oci8/oci8.h	2009-02-10 13:50:40 UTC (rev 320)
@@ -241,6 +241,7 @@
     sb4 alloc_sz; /* size of a element. */
     ub4 maxar_sz; /* maximum array size. */
     ub4 curar_sz; /* current array size. */
+    ub4 curar_idx;/* current array index. */
     VALUE tdo;
     union {
         void **null_structs;
@@ -375,6 +376,8 @@
 void oci8_bind_hp_obj_mark(oci8_base_t *base);
 void Init_oci8_bind(VALUE cOCI8BindTypeBase);
 oci8_bind_t *oci8_get_bind(VALUE obj);
+void oci8_bind_set_data(VALUE self, VALUE val);
+VALUE oci8_bind_get_data(VALUE self);
 
 /* metadata.c */
 extern VALUE cOCI8MetadataBase;

Modified: trunk/ruby-oci8/ext/oci8/stmt.c
===================================================================
--- trunk/ruby-oci8/ext/oci8/stmt.c	2009-02-08 13:28:56 UTC (rev 319)
+++ trunk/ruby-oci8/ext/oci8/stmt.c	2009-02-10 13:50:40 UTC (rev 320)
@@ -25,7 +25,6 @@
 static ID id_empty_p;
 static ID id_at_con;
 static ID id_clear;
-static ID id_set;
 
 VALUE cOCIStmt;
 
@@ -428,7 +427,7 @@
 #endif /* USE_DYNAMIC_FETCH */
     ary = rb_ary_new2(RARRAY_LEN(stmt->defns));
     for (idx = 0; idx < RARRAY_LEN(stmt->defns); idx++) {
-        rb_ary_store(ary, idx, rb_funcall(RARRAY_PTR(stmt->defns)[idx], oci8_id_get, 0));
+        rb_ary_store(ary, idx, oci8_bind_get_data(RARRAY_PTR(stmt->defns)[idx]));
     }
     return ary;
 }
@@ -599,7 +598,7 @@
     if (NIL_P(obj)) {
         return Qnil;
     }
-    return rb_funcall(obj, oci8_id_get, 0);
+    return oci8_bind_get_data(obj);
 }
 
 /*
@@ -650,8 +649,8 @@
             rb_ivar_set(self, id_at_actual_array_size, INT2NUM(bind_array_size));
         }
     }     
-
-    return rb_funcall(obj, oci8_id_set, 1, val);
+    oci8_bind_set_data(obj, val);
+    return val;
 }
 
 /*
@@ -781,7 +780,6 @@
     id_at_con = rb_intern("@con");
     id_empty_p = rb_intern("empty?");
     id_clear = rb_intern("clear");
-    id_set = rb_intern("set");
 
     rb_define_private_method(cOCIStmt, "initialize", oci8_stmt_initialize, -1);
     rb_define_private_method(cOCIStmt, "__define", oci8_define_by_pos, 2);

Modified: trunk/ruby-oci8/test/test_array_dml.rb
===================================================================
--- trunk/ruby-oci8/test/test_array_dml.rb	2009-02-08 13:28:56 UTC (rev 319)
+++ trunk/ruby-oci8/test/test_array_dml.rb	2009-02-10 13:50:40 UTC (rev 320)
@@ -22,7 +22,8 @@
    N NUMBER(10, 2),
    D DATE,
    INT NUMBER(30), 
-   BIGNUM NUMBER(30))
+   BIGNUM NUMBER(30),
+   T TIMESTAMP)
 STORAGE (
    INITIAL 4k
    NEXT 4k
@@ -31,23 +32,25 @@
    PCTINCREASE 0)
 EOS
     @conn.exec(sql)
-    cursor = @conn.parse("INSERT INTO test_table VALUES (:C, :V, :N, :D, :INT, :BIGNUM)")
+    cursor = @conn.parse("INSERT INTO test_table VALUES (:C, :V, :N, :D, :INT, :BIGNUM, :T)")
     max_array_size = 3
     cursor.max_array_size= max_array_size
     
     cursor.bind_param_array(1, nil, String)
     cursor.bind_param_array(2, nil ,String)
     cursor.bind_param_array(3, nil, Fixnum)
-    cursor.bind_param_array(4, nil, OraDate)    
+    cursor.bind_param_array(4, nil, OraDate)
     cursor.bind_param_array(5, nil, Integer)
     cursor.bind_param_array(6, nil, Bignum)
-    
+    cursor.bind_param_array(7, nil, DateTime)
+
     c_arr = Array.new
     v_arr = Array.new
     n_arr = Array.new
     d_arr = Array.new
     int_arr = Array.new
     bignum_arr = Array.new
+    t_arr = Array.new
     
     1.upto(30) do |i|
       c_arr << format("%10d", i * 10)
@@ -56,6 +59,7 @@
       d_arr <<  OraDate.new(2000 + i, 12, 24, 23, 59, 59)
       int_arr << i * 11111111111
       bignum_arr << i * 10000000000
+      t_arr <<  DateTime.new(2000 + i, 12, 24, 23, 59, 59)
       
       if i%max_array_size == 0
         cursor[1] = c_arr
@@ -64,15 +68,24 @@
         cursor[4] = d_arr
         cursor[5] = int_arr
         cursor[6] = bignum_arr
+        cursor[7] = t_arr
         
         r = cursor.exec_array
         assert_equal(max_array_size, r)
+        assert_equal(c_arr, cursor[1])
+        assert_equal(v_arr, cursor[2])
+        assert_equal(n_arr, cursor[3])
+        assert_equal(d_arr, cursor[4])
+        assert_equal(int_arr, cursor[5])
+        assert_equal(bignum_arr, cursor[6])
+        assert_equal(t_arr, cursor[7])
         c_arr.clear
         v_arr.clear
         n_arr.clear
         d_arr.clear
         int_arr.clear
         bignum_arr.clear
+        t_arr.clear
       end
     end
     cursor.close
@@ -81,7 +94,7 @@
     cursor.define(5, Integer)
     cursor.define(6, Bignum)
     cursor.exec
-    assert_equal(["C","V","N","D","INT","BIGNUM"], cursor.get_col_names)
+    assert_equal(["C","V","N","D","INT","BIGNUM","T"], cursor.get_col_names)
     1.upto(30) do |i|
       rv = cursor.fetch
       assert_equal(format("%10d", i * 10), rv[0])
@@ -91,6 +104,7 @@
       assert_equal(tm, rv[3])
       assert_equal(i * 11111111111, rv[4])
       assert_equal(i * 10000000000, rv[5])
+      assert_equal(tm, rv[6])
     end
     assert_nil(cursor.fetch)
     drop_table('test_table')




More information about the ruby-oci8-commit mailing list