[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