From nobody at rubyforge.org Fri Sep 30 08:11:19 2011 From: nobody at rubyforge.org (nobody at rubyforge.org) Date: Fri, 30 Sep 2011 08:11:19 -0400 (EDT) Subject: [ruby-oci8-commit] [448] trunk/ruby-oci8: run connection-pool cleanup functions in a native thread not to block GC. Message-ID: <20110930121119.D3EB41858379@rubyforge.org> Revision: 448 Author: kubo Date: 2011-09-30 08:11:16 -0400 (Fri, 30 Sep 2011) Log Message: ----------- run connection-pool cleanup functions in a native thread not to block GC. use xfree() instead of free() to release memory allocated by xmalloc(). Modified Paths: -------------- trunk/ruby-oci8/ChangeLog trunk/ruby-oci8/ext/oci8/connection_pool.c trunk/ruby-oci8/ext/oci8/oci8.c Modified: trunk/ruby-oci8/ChangeLog =================================================================== --- trunk/ruby-oci8/ChangeLog 2011-08-31 14:12:45 UTC (rev 447) +++ trunk/ruby-oci8/ChangeLog 2011-09-30 12:11:16 UTC (rev 448) @@ -1,3 +1,9 @@ +2011-09-30 KUBO Takehiro + * ext/oci8/connection_pool.c: run connection-pool cleanup functions + in a native thread not to block GC. + * ext/oci8/oci8.c: use xfree() instead of free() to release memory + allocated by xmalloc(). + 2011-08-31 KUBO Takehiro * ext/oci8/env.c, ext/oci8/extconf.rb, ext/oci8/oci8.c, ext/oci8/oci8.h, ext/oci8/oci8lib.c, ext/oci8/thread_util.c, ext/oci8/thread_util.h: Modified: trunk/ruby-oci8/ext/oci8/connection_pool.c =================================================================== --- trunk/ruby-oci8/ext/oci8/connection_pool.c 2011-08-31 14:12:45 UTC (rev 447) +++ trunk/ruby-oci8/ext/oci8/connection_pool.c 2011-09-30 12:11:16 UTC (rev 448) @@ -21,9 +21,18 @@ rb_gc_mark(cpool->pool_name); } +static VALUE cpool_free_thread(void *arg) +{ + OCIConnectionPoolDestroy((OCICPool *)arg, oci8_errhp, OCI_DEFAULT); + OCIHandleFree(arg, OCI_HTYPE_CPOOL); + return 0; +} + static void oci8_cpool_free(oci8_base_t *base) { - OCIConnectionPoolDestroy(base->hp.poolhp, oci8_errhp, OCI_DEFAULT); + oci8_run_native_thread(cpool_free_thread, base->hp.poolhp); + base->type = 0; + base->hp.ptr = NULL; } static void oci8_cpool_init(oci8_base_t *base) Modified: trunk/ruby-oci8/ext/oci8/oci8.c =================================================================== --- trunk/ruby-oci8/ext/oci8/oci8.c 2011-08-31 14:12:45 UTC (rev 447) +++ trunk/ruby-oci8/ext/oci8/oci8.c 2011-09-30 12:11:16 UTC (rev 448) @@ -267,7 +267,7 @@ OCITransRollback(sla->svchp, errhp, OCI_DEFAULT); rv = OCILogoff(sla->svchp, errhp); - free(sla); + xfree(sla); return (VALUE)rv; } @@ -325,7 +325,7 @@ if (cla->svchp != NULL) { OCIHandleFree(cla->svchp, OCI_HTYPE_SVCCTX); } - free(cla); + xfree(cla); return (VALUE)rv; } From nobody at rubyforge.org Fri Sep 30 08:18:25 2011 From: nobody at rubyforge.org (nobody at rubyforge.org) Date: Fri, 30 Sep 2011 08:18:25 -0400 (EDT) Subject: [ruby-oci8-commit] [449] trunk/ruby-oci8: clear an executuing thread information in a connection when a SQL Message-ID: <20110930121825.63F99185837A@rubyforge.org> Revision: 449 Author: kubo Date: 2011-09-30 08:18:23 -0400 (Fri, 30 Sep 2011) Log Message: ----------- clear an executuing thread information in a connection when a SQL executions is canceled by Thread#kill or Timeout::timeout. (reported by Aaron Qian) See: http://rubyforge.org/forum/forum.php?thread_id=50112&forum_id=1078 Modified Paths: -------------- trunk/ruby-oci8/ChangeLog trunk/ruby-oci8/ext/oci8/apiwrap.c.tmpl trunk/ruby-oci8/ext/oci8/oci8lib.c trunk/ruby-oci8/test/test_break.rb Modified: trunk/ruby-oci8/ChangeLog =================================================================== --- trunk/ruby-oci8/ChangeLog 2011-09-30 12:11:16 UTC (rev 448) +++ trunk/ruby-oci8/ChangeLog 2011-09-30 12:18:23 UTC (rev 449) @@ -1,4 +1,11 @@ 2011-09-30 KUBO Takehiro + * ext/oci8/apiwrap.c.tmpl, ext/oci8/oci8lib.c, test/test_break.rb: + clear an executuing thread information in a connection when a SQL + executions is canceled by Thread#kill or Timeout::timeout. + (reported by Aaron Qian) + See: http://rubyforge.org/forum/forum.php?thread_id=50112&forum_id=1078 + +2011-09-30 KUBO Takehiro * ext/oci8/connection_pool.c: run connection-pool cleanup functions in a native thread not to block GC. * ext/oci8/oci8.c: use xfree() instead of free() to release memory Modified: trunk/ruby-oci8/ext/oci8/apiwrap.c.tmpl =================================================================== --- trunk/ruby-oci8/ext/oci8/apiwrap.c.tmpl 2011-09-30 12:11:16 UTC (rev 448) +++ trunk/ruby-oci8/ext/oci8/apiwrap.c.tmpl 2011-09-30 12:18:23 UTC (rev 449) @@ -4,6 +4,12 @@ %> #define API_WRAP_C 1 #include "apiwrap.h" +#ifdef HAVE_RB_THREAD_BLOCKING_REGION +#define BLOCKING_FUNCTION_EPILOGUE(svcctx) do { (svcctx)->executing_thread = Qnil; } while (0) +#else +#define BLOCKING_FUNCTION_EPILOGUE(svcctx) do { } while (0) +#endif + <% prev_name = '' funcs.each do |f| @@ -33,6 +39,7 @@ * <%=f.name%>_nb */ typedef struct { + oci8_svcctx_t *svcctx; <% f.ret != 'void' %> <%= f.ret %> rv; @@ -56,9 +63,11 @@ %> data->rv = <%=f.name%>(<%= f.args.collect do |a| 'data->' + a.name; end.join(', ') %>); <% end %> <% if f.ret == 'sword' -%> return (VALUE)data->rv; +%> BLOCKING_FUNCTION_EPILOGUE(data->svcctx); + return (VALUE)data->rv; <% else -%> return (VALUE)0; +%> BLOCKING_FUNCTION_EPILOGUE(data->svcctx); + return (VALUE)0; <% end %> } #else @@ -69,6 +78,7 @@ { if (have_<%=f.name%>_nb) { oci8_<%=f.name%>_data_t data; + data.svcctx = svcctx; <% f.args.each do |a| %> data.<%=a.name%> = <%=a.name%>; <% end Modified: trunk/ruby-oci8/ext/oci8/oci8lib.c =================================================================== --- trunk/ruby-oci8/ext/oci8/oci8lib.c 2011-09-30 12:11:16 UTC (rev 448) +++ trunk/ruby-oci8/ext/oci8/oci8lib.c 2011-09-30 12:18:23 UTC (rev 449) @@ -246,8 +246,8 @@ rb_raise(rb_eRuntimeError /* FIXME */, "executing in another thread"); } svcctx->executing_thread = rb_thread_current(); + /* Note: executing_thread is cleard at the end of the blocking function. */ rv = (sword)rb_thread_blocking_region(func, data, oci8_unblock_func, svcctx); - svcctx->executing_thread = Qnil; if (rv == OCI_ERROR) { if (oci8_get_error_code(oci8_errhp) == 1013) { rb_raise(eOCIBreak, "Canceled by user request."); @@ -261,14 +261,20 @@ #else /* HAVE_RB_THREAD_BLOCKING_REGION */ /* ruby 1.8 */ -sword oci8_blocking_region(oci8_svcctx_t *svcctx, rb_blocking_function_t func, void *data) +typedef struct { + oci8_svcctx_t *svcctx; + rb_blocking_function_t *func; + void *data; +} blocking_region_arg_t; + +static VALUE blocking_function_execute(blocking_region_arg_t *arg) { + oci8_svcctx_t *svcctx = arg->svcctx; + rb_blocking_function_t *func = arg->func; + void *data = arg->data; struct timeval tv; sword rv; - if (!NIL_P(svcctx->executing_thread)) { - rb_raise(rb_eRuntimeError /* FIXME */, "executing in another thread"); - } tv.tv_sec = 0; tv.tv_usec = 10000; svcctx->executing_thread = rb_thread_current(); @@ -279,8 +285,7 @@ } if (rv == OCI_ERROR) { if (oci8_get_error_code(oci8_errhp) == 1013) { - if (have_OCIReset) - OCIReset(svcctx->base.hp.ptr, oci8_errhp); + OCIReset(svcctx->base.hp.ptr, oci8_errhp); svcctx->executing_thread = Qnil; rb_raise(eOCIBreak, "Canceled by user request."); } @@ -288,6 +293,30 @@ svcctx->executing_thread = Qnil; return rv; } + +static VALUE blocking_function_ensure(oci8_svcctx_t *svcctx) +{ + if (!NIL_P(svcctx->executing_thread)) { + /* The thread is killed. */ + OCIBreak(svcctx->base.hp.ptr, oci8_errhp); + OCIReset(svcctx->base.hp.ptr, oci8_errhp); + svcctx->executing_thread = Qnil; + } + return Qnil; +} + +sword oci8_blocking_region(oci8_svcctx_t *svcctx, rb_blocking_function_t func, void *data) +{ + blocking_region_arg_t arg; + + arg.svcctx = svcctx; + arg.func = func; + arg.data = data; + if (!NIL_P(svcctx->executing_thread)) { + rb_raise(rb_eRuntimeError, "executing in another thread"); + } + return (sword)rb_ensure(blocking_function_execute, (VALUE)&arg, blocking_function_ensure, (VALUE)svcctx); +} #endif /* HAVE_RB_THREAD_BLOCKING_REGION */ typedef struct { Modified: trunk/ruby-oci8/test/test_break.rb =================================================================== --- trunk/ruby-oci8/test/test_break.rb 2011-09-30 12:11:16 UTC (rev 448) +++ trunk/ruby-oci8/test/test_break.rb 2011-09-30 12:18:23 UTC (rev 449) @@ -1,6 +1,7 @@ # High-level API require 'oci8' require 'test/unit' +require 'timeout' require File.dirname(__FILE__) + '/config' class TestBreak < Test::Unit::TestCase @@ -79,4 +80,16 @@ expect[SEND_BREAK] = TIME_TO_BREAK do_test_ocibreak(@conn, expect) end + + def test_timeout + @conn.non_blocking = true + start_time = Time.now + assert_raise(Timeout::Error) do + Timeout.timeout(1) do + @conn.exec("BEGIN DBMS_LOCK.SLEEP(10); END;") + end + end + @conn.exec("BEGIN NULL; END;") + assert_operator(Time.now, :<, start_time + 2) + end end From nobody at rubyforge.org Fri Sep 30 23:14:45 2011 From: nobody at rubyforge.org (nobody at rubyforge.org) Date: Fri, 30 Sep 2011 23:14:45 -0400 (EDT) Subject: [ruby-oci8-commit] [450] trunk/ruby-oci8: rename oci8_*_class to oci8_*_vtable because they correspond to Message-ID: <20111001031445.C9FC41D78101@rubyforge.org> Revision: 450 Author: kubo Date: 2011-09-30 23:14:45 -0400 (Fri, 30 Sep 2011) Log Message: ----------- rename oci8_*_class to oci8_*_vtable because they correspond to virtual method tables (vtable) in C++. Modified Paths: -------------- trunk/ruby-oci8/ChangeLog trunk/ruby-oci8/ext/oci8/bind.c trunk/ruby-oci8/ext/oci8/connection_pool.c trunk/ruby-oci8/ext/oci8/lob.c trunk/ruby-oci8/ext/oci8/metadata.c trunk/ruby-oci8/ext/oci8/object.c 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/ocidatetime.c trunk/ruby-oci8/ext/oci8/ocihandle.c trunk/ruby-oci8/ext/oci8/ocinumber.c trunk/ruby-oci8/ext/oci8/oradate.c trunk/ruby-oci8/ext/oci8/stmt.c Modified: trunk/ruby-oci8/ChangeLog =================================================================== --- trunk/ruby-oci8/ChangeLog 2011-09-30 12:18:23 UTC (rev 449) +++ trunk/ruby-oci8/ChangeLog 2011-10-01 03:14:45 UTC (rev 450) @@ -1,3 +1,11 @@ +2011-10-01 KUBO Takehiro + * ext/oci8/bind.c, ext/oci8/connection_pool.c, ext/oci8/lob.c, + ext/oci8/metadata.c, ext/oci8/object.c, ext/oci8/oci8.c, ext/oci8/oci8.h, + ext/oci8/oci8lib.c, ext/oci8/ocidatetime.c, ext/oci8/ocihandle.c, + ext/oci8/ocinumber.c, ext/oci8/oradate.c, ext/oci8/stmt.c: + rename oci8_*_class to oci8_*_vtable because they correspond to + virtual method tables (vtable) in C++. + 2011-09-30 KUBO Takehiro * ext/oci8/apiwrap.c.tmpl, ext/oci8/oci8lib.c, test/test_break.rb: clear an executuing thread information in a connection when a SQL Modified: trunk/ruby-oci8/ext/oci8/bind.c =================================================================== --- trunk/ruby-oci8/ext/oci8/bind.c 2011-09-30 12:18:23 UTC (rev 449) +++ trunk/ruby-oci8/ext/oci8/bind.c 2011-10-01 03:14:45 UTC (rev 450) @@ -102,7 +102,7 @@ oci_lc(OCIAttrSet(obind->base.hp.ptr, obind->base.type, (void*)&obs->csfrm, 0, OCI_ATTR_CHARSET_FORM, oci8_errhp)); } -static const oci8_bind_class_t bind_string_class = { +static const oci8_bind_vtable_t bind_string_vtable = { { NULL, oci8_bind_free, @@ -139,7 +139,7 @@ vstr->size = RSTRING_LEN(val); } -static const oci8_bind_class_t bind_raw_class = { +static const oci8_bind_vtable_t bind_raw_vtable = { { NULL, oci8_bind_free, @@ -176,7 +176,7 @@ #ifndef SQLT_BDOUBLE #define SQLT_BDOUBLE 22 #endif -static const oci8_bind_class_t bind_binary_double_class = { +static const oci8_bind_vtable_t bind_binary_double_vtable = { { NULL, oci8_bind_free, @@ -193,7 +193,7 @@ 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; + const oci8_bind_vtable_t *vptr = (const oci8_bind_vtable_t *)obind->base.vptr; ub4 idx = obind->curar_idx; void **null_structp = NULL; @@ -201,7 +201,7 @@ if (obind->u.inds[idx] != 0) return Qnil; } - return obc->get(obind, (void*)((size_t)obind->valuep + obind->alloc_sz * idx), null_structp); + return vptr->get(obind, (void*)((size_t)obind->valuep + obind->alloc_sz * idx), null_structp); } VALUE oci8_bind_get_data(VALUE self) @@ -226,7 +226,7 @@ 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; + const oci8_bind_vtable_t *vptr = (const oci8_bind_vtable_t *)obind->base.vptr; ub4 idx = obind->curar_idx; if (NIL_P(val)) { @@ -245,7 +245,7 @@ null_structp = &obind->u.null_structs[idx]; *(OCIInd*)obind->u.null_structs[idx] = 0; } - obc->set(obind, (void*)((size_t)obind->valuep + obind->alloc_sz * idx), null_structp, val); + vptr->set(obind, (void*)((size_t)obind->valuep + obind->alloc_sz * idx), null_structp, val); } return self; } @@ -277,7 +277,7 @@ static VALUE oci8_bind_initialize(VALUE self, VALUE svc, VALUE val, VALUE length, VALUE max_array_size) { oci8_bind_t *obind = DATA_PTR(self); - const oci8_bind_class_t *bind_class = (const oci8_bind_class_t *)obind->base.klass; + const oci8_bind_vtable_t *bind_class = (const oci8_bind_vtable_t *)obind->base.vptr; ub4 cnt = 1; obind->tdo = Qnil; @@ -349,10 +349,10 @@ rb_define_method(cOCI8BindTypeBase, "set", oci8_bind_set, 1); /* register primitive data types. */ - oci8_define_bind_class("String", &bind_string_class); - oci8_define_bind_class("RAW", &bind_raw_class); + oci8_define_bind_class("String", &bind_string_vtable); + oci8_define_bind_class("RAW", &bind_raw_vtable); if (oracle_client_version >= ORAVER_10_1) { - oci8_define_bind_class("BinaryDouble", &bind_binary_double_class); + oci8_define_bind_class("BinaryDouble", &bind_binary_double_vtable); } } Modified: trunk/ruby-oci8/ext/oci8/connection_pool.c =================================================================== --- trunk/ruby-oci8/ext/oci8/connection_pool.c 2011-09-30 12:18:23 UTC (rev 449) +++ trunk/ruby-oci8/ext/oci8/connection_pool.c 2011-10-01 03:14:45 UTC (rev 450) @@ -42,7 +42,7 @@ cpool->pool_name = Qnil; } -static oci8_base_class_t oci8_cpool_class = { +static oci8_base_vtable_t oci8_cpool_vtable = { oci8_cpool_mark, oci8_cpool_free, sizeof(oci8_base_t), @@ -189,7 +189,7 @@ cOCIConnectionPool = rb_define_class_under(cOCI8, "ConnectionPool", cOCIHandle); #endif - cOCIConnectionPool = oci8_define_class_under(cOCI8, "ConnectionPool", &oci8_cpool_class); + cOCIConnectionPool = oci8_define_class_under(cOCI8, "ConnectionPool", &oci8_cpool_vtable); rb_define_private_method(cOCIConnectionPool, "initialize", oci8_cpool_initialize, -1); rb_define_method(cOCIConnectionPool, "reinitialize", oci8_cpool_reinitialize, 3); Modified: trunk/ruby-oci8/ext/oci8/lob.c =================================================================== --- trunk/ruby-oci8/ext/oci8/lob.c 2011-09-30 12:18:23 UTC (rev 449) +++ trunk/ruby-oci8/ext/oci8/lob.c 2011-10-01 03:14:45 UTC (rev 450) @@ -113,7 +113,7 @@ lob->svchp = NULL; } -static oci8_base_class_t oci8_lob_class = { +static oci8_base_vtable_t oci8_lob_vtable = { oci8_lob_mark, oci8_lob_free, sizeof(oci8_lob_t), @@ -631,9 +631,9 @@ */ typedef struct { - oci8_bind_class_t bind; + oci8_bind_vtable_t bind; VALUE *klass; -} oci8_bind_lob_class_t; +} oci8_bind_lob_vtable_t; static VALUE bind_lob_get(oci8_bind_t *obind, void *data, void *null_struct) { @@ -644,10 +644,10 @@ static void bind_lob_set(oci8_bind_t *obind, void *data, void **null_structp, VALUE val) { oci8_hp_obj_t *oho = (oci8_hp_obj_t *)data; - const oci8_bind_lob_class_t *klass = (const oci8_bind_lob_class_t *)obind->base.klass; + const oci8_bind_lob_vtable_t *vptr = (const oci8_bind_lob_vtable_t *)obind->base.vptr; oci8_base_t *h; - if (!rb_obj_is_kind_of(val, *klass->klass)) - rb_raise(rb_eArgError, "Invalid argument: %s (expect %s)", rb_class2name(CLASS_OF(val)), rb_class2name(*klass->klass)); + if (!rb_obj_is_kind_of(val, *vptr->klass)) + rb_raise(rb_eArgError, "Invalid argument: %s (expect %s)", rb_class2name(CLASS_OF(val)), rb_class2name(*vptr->klass)); h = DATA_PTR(val); oho->hp = h->hp.ptr; oho->obj = val; @@ -661,13 +661,13 @@ static void bind_lob_init_elem(oci8_bind_t *obind, VALUE svc) { - const oci8_bind_lob_class_t *klass = (const oci8_bind_lob_class_t *)obind->base.klass; + const oci8_bind_lob_vtable_t *vptr = (const oci8_bind_lob_vtable_t *)obind->base.vptr; oci8_hp_obj_t *oho = (oci8_hp_obj_t *)obind->valuep; oci8_base_t *h; ub4 idx = 0; do { - oho[idx].obj = rb_funcall(*klass->klass, oci8_id_new, 1, svc); + oho[idx].obj = rb_funcall(*vptr->klass, oci8_id_new, 1, svc); h = DATA_PTR(oho[idx].obj); oho[idx].hp = h->hp.ptr; } while (++idx < obind->maxar_sz); @@ -680,7 +680,7 @@ oci_lc(OCIAttrSet(obind->base.hp.ptr, obind->base.type, (void*)&csfrm, 0, OCI_ATTR_CHARSET_FORM, oci8_errhp)); } -static const oci8_bind_lob_class_t bind_clob_class = { +static const oci8_bind_lob_vtable_t bind_clob_vtable = { { { oci8_bind_hp_obj_mark, @@ -697,7 +697,7 @@ &cOCI8CLOB }; -static const oci8_bind_lob_class_t bind_nclob_class = { +static const oci8_bind_lob_vtable_t bind_nclob_vtable = { { { oci8_bind_hp_obj_mark, @@ -715,7 +715,7 @@ &cOCI8NCLOB }; -static const oci8_bind_lob_class_t bind_blob_class = { +static const oci8_bind_lob_vtable_t bind_blob_vtable = { { { oci8_bind_hp_obj_mark, @@ -732,7 +732,7 @@ &cOCI8BLOB }; -static const oci8_bind_lob_class_t bind_bfile_class = { +static const oci8_bind_lob_vtable_t bind_bfile_vtable = { { { oci8_bind_hp_obj_mark, @@ -758,7 +758,7 @@ seek_cur = rb_eval_string("::IO::SEEK_CUR"); seek_end = rb_eval_string("::IO::SEEK_END"); - cOCI8LOB = oci8_define_class_under(cOCI8, "LOB", &oci8_lob_class); + cOCI8LOB = oci8_define_class_under(cOCI8, "LOB", &oci8_lob_vtable); cOCI8CLOB = rb_define_class_under(cOCI8, "CLOB", cOCI8LOB); cOCI8NCLOB = rb_define_class_under(cOCI8, "NCLOB", cOCI8LOB); cOCI8BLOB = rb_define_class_under(cOCI8, "BLOB", cOCI8LOB); @@ -795,8 +795,8 @@ rb_define_method(cOCI8BFILE, "size=", oci8_bfile_error, 1); rb_define_method(cOCI8BFILE, "write", oci8_bfile_error, 1); - oci8_define_bind_class("CLOB", &bind_clob_class.bind); - oci8_define_bind_class("NCLOB", &bind_nclob_class.bind); - oci8_define_bind_class("BLOB", &bind_blob_class.bind); - oci8_define_bind_class("BFILE", &bind_bfile_class.bind); + oci8_define_bind_class("CLOB", &bind_clob_vtable.bind); + oci8_define_bind_class("NCLOB", &bind_nclob_vtable.bind); + oci8_define_bind_class("BLOB", &bind_blob_vtable.bind); + oci8_define_bind_class("BFILE", &bind_bfile_vtable.bind); } Modified: trunk/ruby-oci8/ext/oci8/metadata.c =================================================================== --- trunk/ruby-oci8/ext/oci8/metadata.c 2011-09-30 12:18:23 UTC (rev 449) +++ trunk/ruby-oci8/ext/oci8/metadata.c 2011-10-01 03:14:45 UTC (rev 450) @@ -191,7 +191,7 @@ #endif } -oci8_base_class_t oci8_metadata_class = { +oci8_base_vtable_t oci8_metadata_vtable = { oci8_metadata_mark, NULL, sizeof(oci8_metadata_t), @@ -200,7 +200,7 @@ void Init_oci8_metadata(VALUE cOCI8) { mOCI8Metadata = rb_define_module_under(cOCI8, "Metadata"); - cOCI8MetadataBase = oci8_define_class_under(mOCI8Metadata, "Base", &oci8_metadata_class); + cOCI8MetadataBase = oci8_define_class_under(mOCI8Metadata, "Base", &oci8_metadata_vtable); ptype_to_class = rb_hash_new(); class_to_ptype = rb_hash_new(); rb_global_variable(&ptype_to_class); Modified: trunk/ruby-oci8/ext/oci8/object.c =================================================================== --- trunk/ruby-oci8/ext/oci8/object.c 2011-09-30 12:18:23 UTC (rev 449) +++ trunk/ruby-oci8/ext/oci8/object.c 2011-10-01 03:14:45 UTC (rev 450) @@ -88,7 +88,7 @@ return self; } -static oci8_base_class_t oci8_tdo_class = { +static oci8_base_vtable_t oci8_tdo_vtable = { oci8_tdo_mark, oci8_tdo_free, sizeof(oci8_base_t) @@ -536,7 +536,7 @@ *ind = 0; } -static oci8_base_class_t oci8_named_type_class = { +static oci8_base_vtable_t oci8_named_type_vtable = { oci8_named_type_mark, oci8_named_type_free, sizeof(oci8_named_type_t) @@ -645,7 +645,7 @@ } } -static const oci8_bind_class_t bind_named_type_class = { +static const oci8_bind_vtable_t bind_named_type_vtable = { { bind_named_type_mark, bind_named_type_free, @@ -666,7 +666,7 @@ id_set_attributes = rb_intern("attributes="); /* OCI8::TDO */ - cOCI8TDO = oci8_define_class_under(cOCI8, "TDO", &oci8_tdo_class); + cOCI8TDO = oci8_define_class_under(cOCI8, "TDO", &oci8_tdo_vtable); rb_define_private_method(cOCI8TDO, "setup", oci8_tdo_setup, 2); rb_define_const(cOCI8TDO, "ATTR_STRING", INT2FIX(ATTR_STRING)); rb_define_const(cOCI8TDO, "ATTR_RAW", INT2FIX(ATTR_RAW)); @@ -695,7 +695,7 @@ rb_define_const(cOCI8TDO, "ALIGNMENT_OF_DOUBLE", INT2FIX(ALIGNMENT_OF(double))); /* OCI8::NamedType */ - cOCI8NamedType = oci8_define_class_under(cOCI8, "NamedType", &oci8_named_type_class); + cOCI8NamedType = oci8_define_class_under(cOCI8, "NamedType", &oci8_named_type_vtable); rb_define_method(cOCI8NamedType, "initialize", oci8_named_type_initialize, 0); rb_define_method(cOCI8NamedType, "tdo", oci8_named_type_tdo, 0); rb_define_private_method(cOCI8NamedType, "get_attribute", oci8_named_type_get_attribute, 4); @@ -704,12 +704,12 @@ rb_define_method(cOCI8NamedType, "null=", oci8_named_type_set_null, 1); /* OCI8::NamedCollection */ - cOCI8NamedCollection = oci8_define_class_under(cOCI8, "NamedCollection", &oci8_named_type_class); + cOCI8NamedCollection = oci8_define_class_under(cOCI8, "NamedCollection", &oci8_named_type_vtable); rb_define_method(cOCI8NamedCollection, "initialize", oci8_named_type_initialize, 0); rb_define_method(cOCI8NamedCollection, "tdo", oci8_named_type_tdo, 0); rb_define_private_method(cOCI8NamedCollection, "get_coll_element", oci8_named_coll_get_coll_element, 2); rb_define_private_method(cOCI8NamedCollection, "set_coll_element", oci8_named_coll_set_coll_element, 3); /* OCI8::BindType::NamedType */ - cOCI8BindNamedType = oci8_define_bind_class("NamedType", &bind_named_type_class); + cOCI8BindNamedType = oci8_define_bind_class("NamedType", &bind_named_type_vtable); } Modified: trunk/ruby-oci8/ext/oci8/oci8.c =================================================================== --- trunk/ruby-oci8/ext/oci8/oci8.c 2011-09-30 12:18:23 UTC (rev 449) +++ trunk/ruby-oci8/ext/oci8/oci8.c 2011-10-01 03:14:45 UTC (rev 450) @@ -51,7 +51,7 @@ base->hp.ptr = NULL; } -static oci8_base_class_t oci8_svcctx_associate_class = { +static oci8_base_vtable_t oci8_svcctx_associate_vtable = { NULL, oci8_svcctx_associate_free, sizeof(oci8_svcctx_associate_t), @@ -121,7 +121,7 @@ svcctx->long_read_len = INT2FIX(65535); } -static oci8_base_class_t oci8_svcctx_class = { +static oci8_base_vtable_t oci8_svcctx_vtable = { NULL, oci8_svcctx_free, sizeof(oci8_svcctx_t), @@ -1106,9 +1106,9 @@ oci8_cOCIHandle = rb_define_class("OCIHandle", rb_cObject); cOCI8 = rb_define_class("OCI8", oci8_cOCIHandle); #endif - cOCI8 = oci8_define_class("OCI8", &oci8_svcctx_class); - cSession = oci8_define_class_under(cOCI8, "Session", &oci8_svcctx_associate_class); - cServer = oci8_define_class_under(cOCI8, "Server", &oci8_svcctx_associate_class); + cOCI8 = oci8_define_class("OCI8", &oci8_svcctx_vtable); + cSession = oci8_define_class_under(cOCI8, "Session", &oci8_svcctx_associate_vtable); + cServer = oci8_define_class_under(cOCI8, "Server", &oci8_svcctx_associate_vtable); id_at_session_handle = rb_intern("@session_handle"); id_at_server_handle = rb_intern("@server_handle"); Modified: trunk/ruby-oci8/ext/oci8/oci8.h =================================================================== --- trunk/ruby-oci8/ext/oci8/oci8.h 2011-09-30 12:18:23 UTC (rev 449) +++ trunk/ruby-oci8/ext/oci8/oci8.h 2011-10-01 03:14:45 UTC (rev 450) @@ -237,21 +237,23 @@ char buf[1]; } oci8_vstr_t; -typedef struct oci8_base_class oci8_base_class_t; -typedef struct oci8_bind_class oci8_bind_class_t; +typedef struct oci8_base_vtable oci8_base_vtable_t; +typedef struct oci8_bind_vtable oci8_bind_vtable_t; typedef struct oci8_base oci8_base_t; typedef struct oci8_bind oci8_bind_t; -struct oci8_base_class { +/* The virtual method table of oci8_base_t */ +struct oci8_base_vtable { void (*mark)(oci8_base_t *base); void (*free)(oci8_base_t *base); size_t size; void (*init)(oci8_base_t *base); }; -struct oci8_bind_class { - oci8_base_class_t base; +/* The virtual method table of oci8_bind_t */ +struct oci8_bind_vtable { + oci8_base_vtable_t base; VALUE (*get)(oci8_bind_t *obind, void *data, void *null_struct); void (*set)(oci8_bind_t *obind, void *data, void **null_structp, VALUE val); void (*init)(oci8_bind_t *obind, VALUE svc, VALUE val, VALUE length); @@ -261,7 +263,14 @@ void (*post_bind_hook)(oci8_bind_t *obind); }; +/* Class structure implemented by C language. + * oci8_base_t represents OCIHandle and its subclasses. + * + * The vptr member points to a virtual method table. + * See: http://en.wikipedia.org/wiki/Virtual_method_table + */ struct oci8_base { + const oci8_base_vtable_t *vptr; ub4 type; union { dvoid *ptr; @@ -278,13 +287,18 @@ OCIDescribe *dschp; } hp; VALUE self; - const oci8_base_class_t *klass; oci8_base_t *parent; oci8_base_t *next; oci8_base_t *prev; oci8_base_t *children; }; +/* Class structure implemented by C language. + * This represents OCI8::BindType::Base's subclasses. + * + * This is a subclass of oci8_base_t because the first member + * base is oci8_base_t itself. + */ struct oci8_bind { oci8_base_t base; void *valuep; @@ -401,7 +415,7 @@ extern ID oci8_id_get; extern ID oci8_id_set; extern ID oci8_id_keys; -extern ID oci8_id_oci8_class; +extern ID oci8_id_oci8_vtable; #ifdef CHAR_IS_NOT_A_SHORTCUT_TO_ID extern ID oci8_id_add_op; /* ID of the addition operator '+' */ extern ID oci8_id_sub_op; /* ID of the subtraction operator '-' */ @@ -416,9 +430,9 @@ extern int oci8_in_finalizer; extern VALUE oci8_cOCIHandle; void oci8_base_free(oci8_base_t *base); -VALUE oci8_define_class(const char *name, oci8_base_class_t *klass); -VALUE oci8_define_class_under(VALUE outer, const char *name, oci8_base_class_t *klass); -VALUE oci8_define_bind_class(const char *name, const oci8_bind_class_t *oci8_bind_class); +VALUE oci8_define_class(const char *name, oci8_base_vtable_t *vptr); +VALUE oci8_define_class_under(VALUE outer, const char *name, oci8_base_vtable_t *vptr); +VALUE oci8_define_bind_class(const char *name, const oci8_bind_vtable_t *vptr); void oci8_link_to_parent(oci8_base_t *base, oci8_base_t *parent); void oci8_unlink_from_parent(oci8_base_t *base); sword oci8_blocking_region(oci8_svcctx_t *svcctx, rb_blocking_function_t func, void *data); Modified: trunk/ruby-oci8/ext/oci8/oci8lib.c =================================================================== --- trunk/ruby-oci8/ext/oci8/oci8lib.c 2011-09-30 12:18:23 UTC (rev 449) +++ trunk/ruby-oci8/ext/oci8/oci8lib.c 2011-10-01 03:14:45 UTC (rev 450) @@ -14,7 +14,7 @@ ID oci8_id_get; ID oci8_id_set; ID oci8_id_keys; -ID oci8_id_oci8_class; +ID oci8_id_oci8_vtable; #ifdef CHAR_IS_NOT_A_SHORTCUT_TO_ID ID oci8_id_add_op; ID oci8_id_sub_op; @@ -34,8 +34,8 @@ oci8_base_free(base->children); } oci8_unlink_from_parent(base); - if (base->klass->free != NULL) - base->klass->free(base); + if (base->vptr->free != NULL) + base->vptr->free(base); if (base->type >= OCI_DTYPE_FIRST) OCIDescriptorFree(base->hp.ptr, base->type); else if (base->type >= OCI_HTYPE_FIRST) @@ -79,7 +79,7 @@ oci8_id_get = rb_intern("get"); oci8_id_set = rb_intern("set"); oci8_id_keys = rb_intern("keys"); - oci8_id_oci8_class = rb_intern("__oci8_class__"); + oci8_id_oci8_vtable = rb_intern("__oci8_vtable__"); #ifdef CHAR_IS_NOT_A_SHORTCUT_TO_ID oci8_id_add_op = rb_intern("+"); oci8_id_sub_op = rb_intern("-"); @@ -144,27 +144,27 @@ #endif } -VALUE oci8_define_class(const char *name, oci8_base_class_t *base_class) +VALUE oci8_define_class(const char *name, oci8_base_vtable_t *vptr) { VALUE klass = rb_define_class(name, oci8_cOCIHandle); - VALUE obj = Data_Wrap_Struct(rb_cObject, 0, 0, base_class); - rb_ivar_set(klass, oci8_id_oci8_class, obj); + VALUE obj = Data_Wrap_Struct(rb_cObject, 0, 0, vptr); + rb_ivar_set(klass, oci8_id_oci8_vtable, obj); return klass; } -VALUE oci8_define_class_under(VALUE outer, const char *name, oci8_base_class_t *base_class) +VALUE oci8_define_class_under(VALUE outer, const char *name, oci8_base_vtable_t *vptr) { VALUE klass = rb_define_class_under(outer, name, oci8_cOCIHandle); - VALUE obj = Data_Wrap_Struct(rb_cObject, 0, 0, base_class); - rb_ivar_set(klass, oci8_id_oci8_class, obj); + VALUE obj = Data_Wrap_Struct(rb_cObject, 0, 0, vptr); + rb_ivar_set(klass, oci8_id_oci8_vtable, obj); return klass; } -VALUE oci8_define_bind_class(const char *name, const oci8_bind_class_t *bind_class) +VALUE oci8_define_bind_class(const char *name, const oci8_bind_vtable_t *vptr) { VALUE klass = rb_define_class_under(mOCI8BindType, name, cOCI8BindTypeBase); - VALUE obj = Data_Wrap_Struct(rb_cObject, 0, 0, (void*)bind_class); - rb_ivar_set(klass, oci8_id_oci8_class, obj); + VALUE obj = Data_Wrap_Struct(rb_cObject, 0, 0, (void*)vptr); + rb_ivar_set(klass, oci8_id_oci8_vtable, obj); return klass; } Modified: trunk/ruby-oci8/ext/oci8/ocidatetime.c =================================================================== --- trunk/ruby-oci8/ext/oci8/ocidatetime.c 2011-09-30 12:18:23 UTC (rev 449) +++ trunk/ruby-oci8/ext/oci8/ocidatetime.c 2011-10-01 03:14:45 UTC (rev 450) @@ -252,7 +252,7 @@ bind_free_common(base, OCI_DTYPE_TIMESTAMP_TZ); } -static const oci8_bind_class_t bind_ocitimestamp_tz_class = { +static const oci8_bind_vtable_t bind_ocitimestamp_tz_vtable = { { NULL, bind_ocitimestamp_tz_free, @@ -423,7 +423,7 @@ bind_free_common(base, OCI_DTYPE_INTERVAL_DS); } -static const oci8_bind_class_t bind_ociinterval_ym_class = { +static const oci8_bind_vtable_t bind_ociinterval_ym_vtable = { { NULL, bind_ociinterval_ym_free, @@ -437,7 +437,7 @@ SQLT_INTERVAL_YM }; -static const oci8_bind_class_t bind_ociinterval_ds_class = { +static const oci8_bind_vtable_t bind_ociinterval_ds_vtable = { { NULL, bind_ociinterval_ds_free, @@ -453,7 +453,7 @@ void Init_oci_datetime(void) { - oci8_define_bind_class("OCITimestampTZ", &bind_ocitimestamp_tz_class); - oci8_define_bind_class("OCIIntervalYM", &bind_ociinterval_ym_class); - oci8_define_bind_class("OCIIntervalDS", &bind_ociinterval_ds_class); + oci8_define_bind_class("OCITimestampTZ", &bind_ocitimestamp_tz_vtable); + oci8_define_bind_class("OCIIntervalYM", &bind_ociinterval_ym_vtable); + oci8_define_bind_class("OCIIntervalDS", &bind_ociinterval_ds_vtable); } Modified: trunk/ruby-oci8/ext/oci8/ocihandle.c =================================================================== --- trunk/ruby-oci8/ext/oci8/ocihandle.c 2011-09-30 12:18:23 UTC (rev 449) +++ trunk/ruby-oci8/ext/oci8/ocihandle.c 2011-10-01 03:14:45 UTC (rev 450) @@ -26,7 +26,7 @@ } -static oci8_base_class_t oci8_base_class = { +static oci8_base_vtable_t oci8_base_vtable = { NULL, NULL, sizeof(oci8_base_t), @@ -55,8 +55,8 @@ static void oci8_handle_mark(oci8_base_t *base) { - if (base->klass->mark != NULL) - base->klass->mark(base); + if (base->vptr->mark != NULL) + base->vptr->mark(base); } static void oci8_handle_cleanup(oci8_base_t *base) @@ -76,31 +76,31 @@ static VALUE oci8_s_allocate(VALUE klass) { oci8_base_t *base; - const oci8_base_class_t *base_class; + const oci8_base_vtable_t *vptr; VALUE superklass; VALUE obj; superklass = klass; - while (!RTEST(rb_ivar_defined(superklass, oci8_id_oci8_class))) { + while (!RTEST(rb_ivar_defined(superklass, oci8_id_oci8_vtable))) { superklass = rb_class_superclass(superklass); if (superklass == rb_cObject) rb_raise(rb_eRuntimeError, "private method `new' called for %s:Class", rb_class2name(klass)); } - obj = rb_ivar_get(superklass, oci8_id_oci8_class); - base_class = DATA_PTR(obj); + obj = rb_ivar_get(superklass, oci8_id_oci8_vtable); + vptr = DATA_PTR(obj); - base = xmalloc(base_class->size); - memset(base, 0, base_class->size); + base = xmalloc(vptr->size); + memset(base, 0, vptr->size); obj = Data_Wrap_Struct(klass, oci8_handle_mark, oci8_handle_cleanup, base); base->self = obj; - base->klass = base_class; + base->vptr = vptr; base->parent = NULL; base->next = base; base->prev = base; base->children = NULL; - if (base_class->init != NULL) { - base_class->init(base); + if (vptr->init != NULL) { + vptr->init(base); } return obj; } @@ -717,8 +717,8 @@ rb_define_alloc_func(oci8_cOCIHandle, oci8_s_allocate); rb_define_method_nodoc(oci8_cOCIHandle, "initialize", oci8_handle_initialize, 0); rb_define_private_method(oci8_cOCIHandle, "free", oci8_handle_free, 0); - obj = Data_Wrap_Struct(rb_cObject, 0, 0, &oci8_base_class); - rb_ivar_set(oci8_cOCIHandle, oci8_id_oci8_class, obj); + obj = Data_Wrap_Struct(rb_cObject, 0, 0, &oci8_base_vtable); + rb_ivar_set(oci8_cOCIHandle, oci8_id_oci8_vtable, obj); /* methods to get attributes */ rb_define_private_method(oci8_cOCIHandle, "attr_get_ub1", attr_get_ub1, 1); Modified: trunk/ruby-oci8/ext/oci8/ocinumber.c =================================================================== --- trunk/ruby-oci8/ext/oci8/ocinumber.c 2011-09-30 12:18:23 UTC (rev 449) +++ trunk/ruby-oci8/ext/oci8/ocinumber.c 2011-10-01 03:14:45 UTC (rev 450) @@ -1454,7 +1454,7 @@ } while (++idx < obind->maxar_sz); } -static const oci8_bind_class_t bind_ocinumber_class = { +static const oci8_bind_vtable_t bind_ocinumber_vtable = { { NULL, oci8_bind_free, @@ -1468,7 +1468,7 @@ SQLT_VNU, }; -static const oci8_bind_class_t bind_integer_class = { +static const oci8_bind_vtable_t bind_integer_vtable = { { NULL, oci8_bind_free, @@ -1482,7 +1482,7 @@ SQLT_VNU, }; -static const oci8_bind_class_t bind_float_class = { +static const oci8_bind_vtable_t bind_float_vtable = { { NULL, oci8_bind_free, @@ -1613,9 +1613,9 @@ rb_define_method(cOCINumber, "_dump", onum__dump, -1); rb_define_singleton_method(cOCINumber, "_load", onum_s_load, 1); - oci8_define_bind_class("OraNumber", &bind_ocinumber_class); - oci8_define_bind_class("Integer", &bind_integer_class); - oci8_define_bind_class("Float", &bind_float_class); + oci8_define_bind_class("OraNumber", &bind_ocinumber_vtable); + oci8_define_bind_class("Integer", &bind_integer_vtable); + oci8_define_bind_class("Float", &bind_float_vtable); } OCINumber *oci8_get_ocinumber(VALUE num) Modified: trunk/ruby-oci8/ext/oci8/oradate.c =================================================================== --- trunk/ruby-oci8/ext/oci8/oradate.c 2011-09-30 12:18:23 UTC (rev 449) +++ trunk/ruby-oci8/ext/oci8/oradate.c 2011-10-01 03:14:45 UTC (rev 450) @@ -557,7 +557,7 @@ } while (++idx < obind->maxar_sz); } -static const oci8_bind_class_t bind_oradate_class = { +static const oci8_bind_vtable_t bind_oradate_vtable = { { NULL, oci8_bind_free, @@ -610,5 +610,5 @@ rb_define_method(cOraDate, "_dump", ora_date_dump, -1); rb_define_singleton_method(cOraDate, "_load", ora_date_s_load, 1); - oci8_define_bind_class("OraDate", &bind_oradate_class); + oci8_define_bind_class("OraDate", &bind_oradate_vtable); } Modified: trunk/ruby-oci8/ext/oci8/stmt.c =================================================================== --- trunk/ruby-oci8/ext/oci8/stmt.c 2011-09-30 12:18:23 UTC (rev 449) +++ trunk/ruby-oci8/ext/oci8/stmt.c 2011-10-01 03:14:45 UTC (rev 450) @@ -53,7 +53,7 @@ stmt->defns = Qnil; } -static oci8_base_class_t oci8_stmt_class = { +static oci8_base_vtable_t oci8_stmt_vtable = { oci8_stmt_mark, oci8_stmt_free, sizeof(oci8_stmt_t), @@ -99,7 +99,7 @@ oci8_stmt_t *stmt = TO_STMT(self); ub4 position; oci8_bind_t *obind; - const oci8_bind_class_t *bind_class; + const oci8_bind_vtable_t *vptr; sword status; position = NUM2INT(vposition); /* 1 */ @@ -107,8 +107,8 @@ if (obind->base.hp.dfn != NULL) { oci8_base_free(&obind->base); /* TODO: OK? */ } - bind_class = (const oci8_bind_class_t *)obind->base.klass; - status = OCIDefineByPos(stmt->base.hp.stmt, &obind->base.hp.dfn, oci8_errhp, position, obind->valuep, obind->value_sz, bind_class->dty, NIL_P(obind->tdo) ? obind->u.inds : NULL, NULL, 0, OCI_DEFAULT); + vptr = (const oci8_bind_vtable_t *)obind->base.vptr; + status = OCIDefineByPos(stmt->base.hp.stmt, &obind->base.hp.dfn, oci8_errhp, position, obind->valuep, obind->value_sz, vptr->dty, NIL_P(obind->tdo) ? obind->u.inds : NULL, NULL, 0, OCI_DEFAULT); if (status != OCI_SUCCESS) { oci8_raise(oci8_errhp, status, stmt->base.hp.ptr); } @@ -120,8 +120,8 @@ if (NIL_P(obind->tdo) && obind->maxar_sz > 0) { oci_lc(OCIDefineArrayOfStruct(obind->base.hp.dfn, oci8_errhp, obind->alloc_sz, sizeof(sb2), 0, 0)); } - if (bind_class->post_bind_hook != NULL) { - bind_class->post_bind_hook(obind); + if (vptr->post_bind_hook != NULL) { + vptr->post_bind_hook(obind); } if (position - 1 < RARRAY_LEN(stmt->defns)) { VALUE old_value = RARRAY_PTR(stmt->defns)[position - 1]; @@ -140,7 +140,7 @@ ub4 placeholder_len = 0; ub4 position = 0; oci8_bind_t *obind; - const oci8_bind_class_t *bind_class; + const oci8_bind_vtable_t *vptr; sword status; VALUE old_value; void *indp; @@ -167,7 +167,7 @@ if (obind->base.hp.bnd != NULL) { oci8_base_free(&obind->base); /* TODO: OK? */ } - bind_class = (const oci8_bind_class_t *)obind->base.klass; + vptr = (const oci8_bind_vtable_t *)obind->base.vptr; indp = NIL_P(obind->tdo) ? obind->u.inds : NULL; if (obind->maxar_sz == 0) { @@ -176,9 +176,9 @@ curelep = &obind->curar_sz; } if (placeholder_ptr == (char*)-1) { - status = OCIBindByPos(stmt->base.hp.stmt, &obind->base.hp.bnd, oci8_errhp, position, obind->valuep, obind->value_sz, bind_class->dty, indp, NULL, 0, 0, 0, OCI_DEFAULT); + status = OCIBindByPos(stmt->base.hp.stmt, &obind->base.hp.bnd, oci8_errhp, position, obind->valuep, obind->value_sz, vptr->dty, indp, NULL, 0, 0, 0, OCI_DEFAULT); } else { - status = OCIBindByName(stmt->base.hp.stmt, &obind->base.hp.bnd, oci8_errhp, TO_ORATEXT(placeholder_ptr), placeholder_len, obind->valuep, obind->value_sz, bind_class->dty, indp, NULL, 0, 0, 0, OCI_DEFAULT); + status = OCIBindByName(stmt->base.hp.stmt, &obind->base.hp.bnd, oci8_errhp, TO_ORATEXT(placeholder_ptr), placeholder_len, obind->valuep, obind->value_sz, vptr->dty, indp, NULL, 0, 0, 0, OCI_DEFAULT); } if (status != OCI_SUCCESS) { oci8_raise(oci8_errhp, status, stmt->base.hp.stmt); @@ -191,8 +191,8 @@ if (NIL_P(obind->tdo) && obind->maxar_sz > 0) { oci_lc(OCIBindArrayOfStruct(obind->base.hp.bnd, oci8_errhp, obind->alloc_sz, sizeof(sb2), 0, 0)); } - if (bind_class->post_bind_hook != NULL) { - bind_class->post_bind_hook(obind); + if (vptr->post_bind_hook != NULL) { + vptr->post_bind_hook(obind); } old_value = rb_hash_aref(stmt->binds, vplaceholder); if (!NIL_P(old_value)) { @@ -276,15 +276,15 @@ sword rv; long idx; oci8_bind_t *obind; - const oci8_bind_class_t *bind_class; + const oci8_bind_vtable_t *vptr; if (stmt->base.children != NULL) { obind = (oci8_bind_t *)stmt->base.children; do { if (obind->base.type == OCI_HTYPE_DEFINE) { - bind_class = (const oci8_bind_class_t *)obind->base.klass; - if (bind_class->pre_fetch_hook != NULL) { - bind_class->pre_fetch_hook(obind, stmt->svc); + vptr = (const oci8_bind_vtable_t *)obind->base.vptr; + if (vptr->pre_fetch_hook != NULL) { + vptr->pre_fetch_hook(obind, stmt->svc); } } obind = (oci8_bind_t *)obind->base.next; @@ -610,7 +610,7 @@ } while (++idx < obind->maxar_sz); } -static const oci8_bind_class_t bind_stmt_class = { +static const oci8_bind_vtable_t bind_stmt_vtable = { { oci8_bind_hp_obj_mark, oci8_bind_free, @@ -631,7 +631,7 @@ cOCI8 = rb_define_class("OCI8", cOCIHandle); cOCIStmt = rb_define_class_under(cOCI8, "Cursor", cOCIHandle); #endif - cOCIStmt = oci8_define_class_under(cOCI8, "Cursor", &oci8_stmt_class); + cOCIStmt = oci8_define_class_under(cOCI8, "Cursor", &oci8_stmt_vtable); oci8_sym_select_stmt = ID2SYM(rb_intern("select_stmt")); oci8_sym_update_stmt = ID2SYM(rb_intern("update_stmt")); @@ -668,5 +668,5 @@ rb_define_private_method(cOCIStmt, "__defined?", oci8_stmt_defined_p, 1); rb_define_method(cOCIStmt, "prefetch_rows=", oci8_stmt_set_prefetch_rows, 1); - oci8_define_bind_class("Cursor", &bind_stmt_class); + oci8_define_bind_class("Cursor", &bind_stmt_vtable); }