[ruby-oci8-commit] [339] trunk/ruby-oci8: * ext/oci8/apiwrap.yml, ext/oci8/env.c, ext/oci8/ extconf.rb,

nobody at rubyforge.org nobody at rubyforge.org
Fri Apr 17 04:17:44 EDT 2009


Revision: 339
Author:   kubo
Date:     2009-04-17 04:17:44 -0400 (Fri, 17 Apr 2009)

Log Message:
-----------
* ext/oci8/apiwrap.yml, ext/oci8/env.c, ext/oci8/extconf.rb,
  ext/oci8/oci8.h, ext/oci8/oci8lib.c: OCIEnv is initialized
    when it is needed. This makes a basis to enable an event
    notification after "require 'oci8'."
* test/test_all.rb: fix a bug added four days ago.

Modified Paths:
--------------
    trunk/ruby-oci8/ChangeLog
    trunk/ruby-oci8/ext/oci8/apiwrap.yml
    trunk/ruby-oci8/ext/oci8/env.c
    trunk/ruby-oci8/ext/oci8/extconf.rb
    trunk/ruby-oci8/ext/oci8/oci8.h
    trunk/ruby-oci8/ext/oci8/oci8lib.c
    trunk/ruby-oci8/test/test_all.rb

Modified: trunk/ruby-oci8/ChangeLog
===================================================================
--- trunk/ruby-oci8/ChangeLog	2009-04-14 11:58:26 UTC (rev 338)
+++ trunk/ruby-oci8/ChangeLog	2009-04-17 08:17:44 UTC (rev 339)
@@ -1,3 +1,10 @@
+2009-04-17  KUBO Takehiro  <kubo at jiubao.org>
+	* ext/oci8/apiwrap.yml, ext/oci8/env.c, ext/oci8/extconf.rb,
+	  ext/oci8/oci8.h, ext/oci8/oci8lib.c: OCIEnv is initialized
+	    when it is needed. This makes a basis to enable an event
+	    notification after "require 'oci8'."
+	* test/test_all.rb: fix a bug added four days ago.
+
 2009-04-14  KUBO Takehiro  <kubo at jiubao.org>
 	* ext/oci8/oci8.h, ext/oci8/oci8lib.c, ext/oci8/ocinumber.c,
 	  ext/oci8/metadata.c, ext/oci8/object.c: pass an OCIError to

Modified: trunk/ruby-oci8/ext/oci8/apiwrap.yml
===================================================================
--- trunk/ruby-oci8/ext/oci8/apiwrap.yml	2009-04-14 11:58:26 UTC (rev 338)
+++ trunk/ruby-oci8/ext/oci8/apiwrap.yml	2009-04-17 08:17:44 UTC (rev 339)
@@ -884,6 +884,18 @@
 # Oracle 8.1
 #
 
+# round trip: 0
+OCIEnvCreate:
+  :version: 810
+  :args:    - OCIEnv **envp
+            - ub4 mode
+            - dvoid *ctxp
+            - dvoid *(*malocfp)(dvoid *ctxp, size_t size)
+            - dvoid *(*ralocfp)(dvoid *ctxp, dvoid *memptr, size_t newsize)
+            - void   (*mfreefp)(dvoid *ctxp, dvoid *memptr)
+            - size_t xtramem_sz
+            - dvoid **usrmempp
+
 # round trip: 1
 OCILobClose_nb:
   :version: 810

Modified: trunk/ruby-oci8/ext/oci8/env.c
===================================================================
--- trunk/ruby-oci8/ext/oci8/env.c	2009-04-14 11:58:26 UTC (rev 338)
+++ trunk/ruby-oci8/ext/oci8/env.c	2009-04-17 08:17:44 UTC (rev 339)
@@ -1,10 +1,9 @@
 /* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
 /*
-  env.c - part of ruby-oci8
-
-  Copyright (C) 2002-2008 KUBO Takehiro <kubo at jiubao.org>
-
-*/
+ * env.c - part of ruby-oci8
+ *
+ * Copyright (C) 2002-2009 KUBO Takehiro <kubo at jiubao.org>
+ */
 #include "oci8.h"
 
 #if !defined(RUBY_VM)
@@ -12,8 +11,38 @@
 #include <util.h>
 #endif
 
-OCIEnv *oci8_envhp;
+#ifdef _WIN32
+#ifdef HAVE_RUBY_WIN32_H
+#include <ruby/win32.h> /* for rb_w32_getenv() */
+#else
+#include <win32/win32.h> /* for rb_w32_getenv() */
+#endif
+#endif
+
+#ifdef HAVE_RUBY_UTIL_H
+#include <ruby/util.h>
+#endif
+
 #ifdef RUBY_VM
+ub4 oci8_env_mode = OCI_OBJECT | OCI_THREADED;
+#else
+ub4 oci8_env_mode = OCI_OBJECT;
+#endif
+
+OCIEnv *oci8_global_envhp;
+
+OCIEnv *oci8_make_envhp(void)
+{
+    sword rv;
+
+    rv = OCIEnvCreate(&oci8_global_envhp, oci8_env_mode, NULL, NULL, NULL, NULL, 0, NULL);
+    if (rv != OCI_SUCCESS) {
+        oci8_raise_init_error();
+    }
+    return oci8_global_envhp;
+}
+
+#ifdef RUBY_VM
 /*
  * oci8_errhp is a thread local object in ruby 1.9.
  */
@@ -53,17 +82,23 @@
 /*
  * oci8_errhp is global in ruby 1.8.
  */
-OCIError *oci8_errhp;
+OCIError *oci8_global_errhp;
+
+OCIError *oci8_make_errhp(void)
+{
+    sword rv;
+
+    rv = OCIHandleAlloc(oci8_envhp, (dvoid *)&oci8_global_errhp, OCI_HTYPE_ERROR, 0, NULL);
+    if (rv != OCI_SUCCESS)
+        oci8_env_raise(oci8_envhp, rv);
+    return oci8_global_errhp;
+}
 #endif
 
 void Init_oci8_env(void)
 {
-    sword rv;
 #ifdef RUBY_VM
-    ub4 mode = OCI_OBJECT | OCI_THREADED;
     int error;
-#else
-    ub4 mode = OCI_OBJECT;
 #endif
 
 #if !defined(RUBY_VM) && !defined(_WIN32)
@@ -85,23 +120,38 @@
         }
     }
 #endif /* WIN32 */
-    rv = OCIInitialize(mode, NULL, NULL, NULL, NULL);
-    if (rv != OCI_SUCCESS) {
-        oci8_raise_init_error();
+
+    /* workaround code.
+     *
+     * When ORACLE_HOME ends with '/' and the Oracle client is
+     * an instant client lower than 10.2.0.3, OCIEvnCreate()
+     * doesn't work even though the combination of OCIInitialize()
+     * and OCIEnvInit() works fine. Delete the last slash for
+     * a workaround.
+     */
+    if (oracle_client_version < ORAVERNUM(10, 2, 0, 3, 0)) {
+#ifdef _WIN32
+#define DIR_SEP '\\'
+#else
+#define DIR_SEP '/'
+#endif
+        char *home = getenv("ORACLE_HOME");
+        if (home != NULL) {
+            size_t homelen = strlen(home);
+            if (homelen > 0 && home[homelen - 1] == DIR_SEP) {
+                home = ruby_strdup(home);
+                home[homelen - 1] = '\0';
+                ruby_setenv("ORACLE_HOME", home);
+                xfree(home);
+            }
+        }
     }
-    rv = OCIEnvInit(&oci8_envhp, OCI_DEFAULT, 0, NULL);
-    if (rv != OCI_SUCCESS) {
-        oci8_raise_init_error();
-    }
+
 #ifdef RUBY_VM
     id_thread_key = rb_intern("__oci8_errhp__");
     error = oci8_tls_key_init(&oci8_tls_key);
     if (error != 0) {
         rb_raise(rb_eRuntimeError, "Cannot create thread local key (errno = %d)", error);
     }
-#else /* RUBY_VM */
-    rv = OCIHandleAlloc(oci8_envhp, (dvoid *)&oci8_errhp, OCI_HTYPE_ERROR, 0, NULL);
-    if (rv != OCI_SUCCESS)
-        oci8_env_raise(oci8_envhp, rv);
 #endif
 }

Modified: trunk/ruby-oci8/ext/oci8/extconf.rb
===================================================================
--- trunk/ruby-oci8/ext/oci8/extconf.rb	2009-04-14 11:58:26 UTC (rev 338)
+++ trunk/ruby-oci8/ext/oci8/extconf.rb	2009-04-17 08:17:44 UTC (rev 339)
@@ -103,7 +103,6 @@
 have_header("intern.h")
 have_header("util.h")
 # ruby 1.9 headers
-have_header("ruby/util.h")
 have_type('rb_encoding', ['ruby/ruby.h', 'ruby/encoding.h'])
 
 # $! in C API

Modified: trunk/ruby-oci8/ext/oci8/oci8.h
===================================================================
--- trunk/ruby-oci8/ext/oci8/oci8.h	2009-04-14 11:58:26 UTC (rev 338)
+++ trunk/ruby-oci8/ext/oci8/oci8.h	2009-04-17 08:17:44 UTC (rev 339)
@@ -344,12 +344,24 @@
 #define UB4_TO_NUM UINT2NUM
 #endif
 
-/* env.c */
-extern OCIEnv *oci8_envhp;
+/* The folloiwng macros oci8_envhp and oci8_errhp are used
+ * as if they are defined as follows:
+ *
+ *   extern OCIEnv *oci8_envhp;
+ *   extern OCIError *oci8_errhp;
+ */
+#define oci8_envhp (LIKELY(oci8_global_envhp != NULL) ? oci8_global_envhp : oci8_make_envhp())
 #ifdef RUBY_VM
-/* oci8_errhp is a thread local object in ruby 1.9. */
 #define oci8_errhp oci8_get_errhp()
+#else
+#define oci8_errhp (LIKELY(oci8_global_errhp != NULL) ? oci8_global_errhp : oci8_make_errhp())
+#endif
 
+/* env.c */
+extern ub4 oci8_env_mode;
+extern OCIEnv *oci8_global_envhp;
+OCIEnv *oci8_make_envhp(void);
+#ifdef RUBY_VM
 extern oci8_tls_key_t oci8_tls_key; /* native thread key */
 OCIError *oci8_make_errhp(void);
 
@@ -360,8 +372,8 @@
 }
 
 #else
-/* oci8_errhp is global in ruby 1.8. */
-extern OCIError *oci8_errhp;
+extern OCIError *oci8_global_errhp;
+OCIError *oci8_make_errhp(void);
 #endif
 void Init_oci8_env(void);
 

Modified: trunk/ruby-oci8/ext/oci8/oci8lib.c
===================================================================
--- trunk/ruby-oci8/ext/oci8/oci8lib.c	2009-04-14 11:58:26 UTC (rev 338)
+++ trunk/ruby-oci8/ext/oci8/oci8lib.c	2009-04-17 08:17:44 UTC (rev 339)
@@ -108,6 +108,9 @@
 {
     VALUE cOCI8;
     VALUE obj;
+    OCIEnv *envhp;
+    OCIError *errhp;
+    sword rv;
 
 #ifdef RUNTIME_API_CHECK
     Init_oci8_apiwrap();
@@ -154,8 +157,35 @@
     Init_oci8_metadata(cOCI8);
     Init_oci8_lob(cOCI8);
 
+    /* allocate a temporary errhp to pass Init_oci_number() */
+    if (have_OCIEnvCreate) {
+        rv = OCIEnvCreate(&envhp, oci8_env_mode, NULL, NULL, NULL, NULL, 0, NULL);
+        if (rv != OCI_SUCCESS) {
+            oci8_raise_init_error();
+        }
+    } else {
+        rv = OCIInitialize(oci8_env_mode, NULL, NULL, NULL, NULL);
+        if (rv != OCI_SUCCESS) {
+            oci8_raise_init_error();
+        }
+        rv = OCIEnvInit(&oci8_global_envhp, OCI_DEFAULT, 0, NULL);
+        if (rv != OCI_SUCCESS) {
+            oci8_raise_init_error();
+        }
+    }
+    rv = OCIHandleAlloc(envhp, (dvoid *)&errhp, OCI_HTYPE_ERROR, 0, NULL);
+    if (rv != OCI_SUCCESS)
+        oci8_env_raise(envhp, rv);
+    Init_oci_number(cOCI8, errhp);
+    OCIHandleFree(errhp, OCI_HTYPE_ERROR);
+    if (have_OCIEnvCreate) {
+        OCIHandleFree(envhp, OCI_HTYPE_ENV);
+    } else {
+        /* Delayed OCIEnv initialization cannot be used on Oracle 8.0. */
+        oci8_global_envhp = envhp;
+    }
+
     Init_ora_date();
-    Init_oci_number(cOCI8, oci8_errhp);
     Init_oci_datetime();
     Init_oci_object(cOCI8);
     Init_oci_xmldb();
@@ -167,6 +197,10 @@
 #ifdef DEBUG_CORE_FILE
     signal(SIGSEGV, SIG_DFL);
 #endif
+
+    if (have_OCIEnvCreate && oci8_global_envhp != NULL) {
+        rb_raise(rb_eRuntimeError, "Internal Error: OCIEnv should not be initialized here.");
+    }
 }
 
 VALUE oci8_define_class(const char *name, oci8_base_class_t *base_class)

Modified: trunk/ruby-oci8/test/test_all.rb
===================================================================
--- trunk/ruby-oci8/test/test_all.rb	2009-04-14 11:58:26 UTC (rev 338)
+++ trunk/ruby-oci8/test/test_all.rb	2009-04-17 08:17:44 UTC (rev 339)
@@ -33,7 +33,7 @@
     require 'rubygems'
     require 'dbi'
   rescue LoadError
-    dbi_not_found = false
+    dbi_not_found = true
   end
 end
 unless dbi_not_found




More information about the ruby-oci8-commit mailing list