[ruby-oci8-commit] [303] trunk/ruby-oci8: * ext/oci8/attr.c: rewrite code converting the rowid descriptor

nobody at rubyforge.org nobody at rubyforge.org
Tue Dec 30 08:39:05 EST 2008


Revision: 303
Author:   kubo
Date:     2008-12-30 08:39:05 -0500 (Tue, 30 Dec 2008)

Log Message:
-----------
* ext/oci8/attr.c: rewrite code converting the rowid descriptor
    to string representation by using oci8_exec_sql().
* ext/oci8/oci8.c, ext/oci8/oci8.h, ext/oci8/oci8lib.c,
  ext/oci8/stmt.c: add check code to ensure that the process id
    is not changed.

Modified Paths:
--------------
    trunk/ruby-oci8/ChangeLog
    trunk/ruby-oci8/ext/oci8/attr.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/stmt.c

Modified: trunk/ruby-oci8/ChangeLog
===================================================================
--- trunk/ruby-oci8/ChangeLog	2008-12-30 11:13:46 UTC (rev 302)
+++ trunk/ruby-oci8/ChangeLog	2008-12-30 13:39:05 UTC (rev 303)
@@ -1,4 +1,11 @@
 2008-12-30  KUBO Takehiro  <kubo at jiubao.org>
+	* ext/oci8/attr.c: rewrite code converting the rowid descriptor
+	    to string representation by using oci8_exec_sql().
+	* ext/oci8/oci8.c, ext/oci8/oci8.h, ext/oci8/oci8lib.c,
+	  ext/oci8/stmt.c: add check code to ensure that the process id
+	    is not changed.
+
+2008-12-30  KUBO Takehiro  <kubo at jiubao.org>
 	* ext/oci8/oraconf.rb: add code to check the cpu type of Mac OS X
 	    libclntsh.dylib.
 

Modified: trunk/ruby-oci8/ext/oci8/attr.c
===================================================================
--- trunk/ruby-oci8/ext/oci8/attr.c	2008-12-30 11:13:46 UTC (rev 302)
+++ trunk/ruby-oci8/ext/oci8/attr.c	2008-12-30 13:39:05 UTC (rev 303)
@@ -75,7 +75,6 @@
     oci8_base_t *base;
     ub4 attrtype;
     OCIRowid *ridp;
-    OCIStmt *stmtp;
 } rowid_arg_t;
 
 static VALUE get_rowid_attr(rowid_arg_t *arg)
@@ -86,7 +85,7 @@
     ub2 buflen;
     sword rv;
 
-	/* get a rowid descriptor from OCIHandle */
+    /* get a rowid descriptor from OCIHandle */
     rv = OCIDescriptorAlloc(oci8_envhp, (dvoid*)&arg->ridp, OCI_DTYPE_ROWID, 0, NULL);
     if (rv != OCI_SUCCESS)
         oci8_env_raise(oci8_envhp, rv);
@@ -107,9 +106,7 @@
          * Oracle Server.
          */
         oci8_base_t *svc;
-        OCIBind *bind1 = NULL;
-        OCIBind *bind2 = NULL;
-        sword rv;
+        oci8_exec_sql_var_t bind_vars[2];
 
         /* search a connection from the handle */
         svc = base;
@@ -119,43 +116,29 @@
                 rb_raise(rb_eRuntimeError, "No connection is found!!");
             }
         }
-        /*
-         * equivalent code:
-         *   cursor = conn.parse("BEGIN :1 := :2; END;")
-         *   cursor.bind(1, nil, String, MAX_ROWID_LEN)
-         *   cursor.bind(2, rowid, OCIRowid)
-         *   cursor.exec()
-         *   cursor[1] # => rowid's string representation
-         */
-#define ROWIDTOCHAR_SQL "BEGIN :1 := :2; END;"
-        buflen = 0;
-        rv = OCIHandleAlloc(oci8_envhp, (dvoid*)&arg->stmtp, OCI_HTYPE_STMT, 0, NULL);
-        if (rv != OCI_SUCCESS) {
-            oci8_env_raise(oci8_envhp, rv);
+        /* :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;
+        /* :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;
+        /* 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);
+        if (buflen == 0) {
+            return Qnil;
         }
-        oci_lc(OCIStmtPrepare(arg->stmtp, oci8_errhp, (text*)ROWIDTOCHAR_SQL, strlen(ROWIDTOCHAR_SQL), OCI_NTV_SYNTAX, OCI_DEFAULT));
-        oci_lc(OCIBindByPos(arg->stmtp, &bind1, oci8_errhp, 1, buf, MAX_ROWID_LEN, SQLT_STR, NULL, &buflen, 0, 0, 0, OCI_DEFAULT));
-        oci_lc(OCIBindByPos(arg->stmtp, &bind2, oci8_errhp, 2, (dvoid*)&arg->ridp, sizeof(void*), SQLT_RDD, NULL, NULL, 0, 0, 0, OCI_DEFAULT));
-        rv = OCIStmtExecute_nb((oci8_svcctx_t*)svc, svc->hp.svc, arg->stmtp, oci8_errhp, 1, 0, NULL, NULL, OCI_DEFAULT);
-        if (rv == OCI_ERROR) {
-            if (oci8_get_error_code(oci8_errhp) == 1000) {
-                /* run GC to close unreferred cursors
-                 * when ORA-01000 (maximum open cursors exceeded).
-                 */
-                rb_gc();
-                rv = OCIStmtExecute_nb((oci8_svcctx_t*)svc, svc->hp.svc, arg->stmtp, oci8_errhp, 1, 0, NULL, NULL, OCI_DEFAULT);
-            }
-        }
-        oci_lc(rv);
     }
     return rb_str_new(buf, buflen);
 }
 
 static VALUE rowid_ensure(rowid_arg_t *arg)
 {
-    if (arg->stmtp != NULL) {
-        OCIHandleFree(arg->stmtp, OCI_HTYPE_STMT);
-    }
     if (arg->ridp != NULL) {
         OCIDescriptorFree(arg->ridp, OCI_DTYPE_ROWID);
     }
@@ -168,6 +151,5 @@
     arg.base = base;
     arg.attrtype = attrtype;
     arg.ridp = NULL;
-    arg.stmtp = NULL;
     return rb_ensure(get_rowid_attr, (VALUE)&arg, rowid_ensure, (VALUE)&arg);
 }

Modified: trunk/ruby-oci8/ext/oci8/oci8.c
===================================================================
--- trunk/ruby-oci8/ext/oci8/oci8.c	2008-12-30 11:13:46 UTC (rev 302)
+++ trunk/ruby-oci8/ext/oci8/oci8.c	2008-12-30 13:39:05 UTC (rev 303)
@@ -6,7 +6,17 @@
  *
  */
 #include "oci8.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h> /* getpid() */
+#endif
 
+#ifdef WIN32
+#ifndef getpid
+extern rb_pid_t rb_w32_getpid(void);
+#define getpid() rb_w32_getpid()
+#endif
+#endif
+
 /*
  * Document-class: OCI8
  *
@@ -236,6 +246,7 @@
     default:
         break;
     }
+    svcctx->pid = getpid();
     svcctx->is_autocommit = 0;
 #ifdef RUBY_VM
     svcctx->non_blocking = 0;
@@ -565,3 +576,11 @@
     }
     return svcctx->authhp;
 }
+
+void oci8_check_pid_consistency(oci8_svcctx_t *svcctx)
+{
+    if (svcctx->pid != getpid()) {
+        rb_raise(rb_eRuntimeError, "The connection cannot be reused in the forked process.");
+    }
+}
+

Modified: trunk/ruby-oci8/ext/oci8/oci8.h
===================================================================
--- trunk/ruby-oci8/ext/oci8/oci8.h	2008-12-30 11:13:46 UTC (rev 302)
+++ trunk/ruby-oci8/ext/oci8/oci8.h	2008-12-30 13:39:05 UTC (rev 303)
@@ -12,9 +12,18 @@
 #include "intern.h"
 #endif
 
+#ifndef rb_pid_t
+#ifdef WIN32
+#define rb_pid_t int
+#else
+#define rb_pid_t pid_t
+#endif
+#endif
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <assert.h>
+
 #ifdef __cplusplus
 extern "C"
 {
@@ -234,6 +243,7 @@
     enum logon_type_t logon_type;
     OCISession *authhp;
     OCIServer *srvhp;
+    rb_pid_t pid;
     char is_autocommit;
 #ifdef RUBY_VM
     char non_blocking;
@@ -335,6 +345,7 @@
 oci8_svcctx_t *oci8_get_svcctx(VALUE obj);
 OCISvcCtx *oci8_get_oci_svcctx(VALUE obj);
 OCISession *oci8_get_oci_session(VALUE obj);
+void oci8_check_pid_consistency(oci8_svcctx_t *svcctx);
 #define TO_SVCCTX oci8_get_oci_svcctx
 #define TO_SESSION oci8_get_oci_session
 

Modified: trunk/ruby-oci8/ext/oci8/oci8lib.c
===================================================================
--- trunk/ruby-oci8/ext/oci8/oci8lib.c	2008-12-30 11:13:46 UTC (rev 302)
+++ trunk/ruby-oci8/ext/oci8/oci8lib.c	2008-12-30 13:39:05 UTC (rev 303)
@@ -317,6 +317,8 @@
 sword oci8_exec_sql(oci8_svcctx_t *svcctx, const char *sql_text, ub4 num_define_vars, oci8_exec_sql_var_t *define_vars, ub4 num_bind_vars, oci8_exec_sql_var_t *bind_vars, int raise_on_error)
 {
     cb_arg_t arg;
+
+    oci8_check_pid_consistency(svcctx);
     arg.svcctx = svcctx;
     arg.sql_text = sql_text;
     arg.num_define_vars = num_define_vars;

Modified: trunk/ruby-oci8/ext/oci8/stmt.c
===================================================================
--- trunk/ruby-oci8/ext/oci8/stmt.c	2008-12-30 11:13:46 UTC (rev 302)
+++ trunk/ruby-oci8/ext/oci8/stmt.c	2008-12-30 13:39:05 UTC (rev 303)
@@ -67,7 +67,7 @@
 
     rb_scan_args(argc, argv, "11", &svc, &sql);
 
-    oci8_get_svcctx(svc); /* check argument */
+    oci8_check_pid_consistency(oci8_get_svcctx(svc));
     if (argc > 1)
         StringValue(sql);
 




More information about the ruby-oci8-commit mailing list