ruby-oci8 2.1.5 → 2.1.6

This diff has not been reviewed by any users.
Sign up to get free protection for your applications and to get access to all the features.
data/ChangeLog CHANGED
@@ -1,3 +1,105 @@
1
+ 2013-12-29 KUBO Takehiro <kubo@jiubao.org>
2
+ * NEWS: add changes between 2.1.6 and 2.1.5.
3
+ * VERSION: change the version to 2.1.6.
4
+
5
+ 2013-12-28 KUBO Takehiro <kubo@jiubao.org>
6
+ * ext/oci8/oraconf.rb: fix for Windows x64. OCI.lib for MSVC doesn't
7
+ work with mingw64 compilers. fix URL in the error message.
8
+
9
+ 2013-12-14 KUBO Takehiro <kubo@jiubao.org>
10
+ * lib/oci8/metadata.rb, test/test_metadata.rb: fix
11
+ OCI8::Metadata::Synonym#schema_name and #translated_name
12
+ for synonyms with a database link and without schema_name.
13
+
14
+ 2013-12-14 KUBO Takehiro <kubo@jiubao.org>
15
+ * test/*.rb: suppress warnings "MiniTest::Unit::TestCase is now Minitest::Test"
16
+ when minitest gem is installed.
17
+
18
+ 2013-12-14 KUBO Takehiro <kubo@jiubao.org>
19
+ * test/test_metadata.rb: fix tests in an environment where
20
+ the data size of "CAST('1' AS CHAR(1 char))" is wrong.
21
+
22
+ 2013-11-18 KUBO Takehiro <kubo@jiubao.org>
23
+ * ext/oci8/oraconf.rb: support cygwin x86_64.
24
+
25
+ 2013-11-10 KUBO Takehiro <kubo@jiubao.org>
26
+ * ext/oci8/error.c, ext/oci8/lob.c, ext/oci8/object.c, ext/oci8/oci8.h,
27
+ ext/oci8/oci8lib.c, ext/oci8/ocihandle.c, ext/oci8/stmt.c:
28
+ use rb_class_new_instance() instead of rb_funcall() with rb_intern("new").
29
+
30
+ 2013-11-09 KUBO Takehiro <kubo@jiubao.org>
31
+ * ext/oci8/error.c, ext/oci8/extconf.rb, ext/oci8/oci8.h:
32
+ append the full path of the Oracle client library when OCIEnvCreate
33
+ is failed such as "OCI Library Initialization Error - /path/to/libclntsh.so.12.1".
34
+
35
+ 2013-11-09 KUBO Takehiro <kubo@jiubao.org>
36
+ * ext/oci8/extconf.rb, lib/oci8.rb.in: support rubinius 2.x whose
37
+ RUBY_VERSION is 2.1.0.
38
+ * ext/oci8/oraconf.rb: reduce the size of libOCI.a created for cygwin.
39
+
40
+ 2013-11-09 KUBO Takehiro <kubo@jiubao.org>
41
+ * ext/oci8/extconf.rb, lib/oci8.rb.in: support ruby 2.1.0-preview1.
42
+ (requested by Yasuo Honda)
43
+
44
+ 2013-08-24 KUBO Takehiro <kubo@jiubao.org>
45
+ * ext/oci8/oraconf.rb: Use Dir.glob to find the Oracle instant client
46
+ NLS data file. Its name depends on the Oracle major version on
47
+ Windows.
48
+
49
+ 2013-08-03 KUBO Takehiro <kubo@jiubao.org>
50
+ * lib/oci8/metadata.rb: fix undefined method 'char_used?' when
51
+ OCI8::Metadata::Argument#inspect is called.
52
+ * test/test_metadata.rb: refactor and add tests for #inspect methods.
53
+ * test/test_package_type.rb: add some test data.
54
+
55
+ 2013-07-30 KUBO Takehiro <kubo@jiubao.org>
56
+ * ext/oci8/metadata.c, ext/oci8/ocihandle.c, test/test_metadata.rb:
57
+ Fix segmentation fault when metadata are accessed after the
58
+ session is disconnected.
59
+
60
+ 2013-07-24 KUBO Takehiro <kubo@jiubao.org>
61
+ * lib/oci8/metadata.rb, test/test_package_type.rb:
62
+ Add OCI8::Metadata::Type#package_name and
63
+ OCI8::Metadata::ArgBase#has_default?.
64
+
65
+ 2013-07-22 KUBO Takehiro <kubo@jiubao.org>
66
+ * ext/oci8/oci8lib.c, lib/oci8.rb.in, lib/oci8/metadata.rb: Add
67
+ OCI8::Metadata::Package:types to support package type
68
+ description. It is a new feature of Oracle 12c.
69
+ * test/setup_test_package.sql, test/test_all.rb,
70
+ test/test_package_type.rb: Add tests for package type description.
71
+
72
+ 2013-07-15 KUBO Takehiro <kubo@jiubao.org>
73
+ * test/*.rb: Use MiniTest instead of Test::Unit.
74
+
75
+ 2013-06-23 KUBO Takehiro <kubo@jiubao.org>
76
+ * lib/oci8/cursor.rb, lib/oci8/object.rb: fix to bind object types by
77
+ name as OCI8::Cursor#bind_param(pos, val, :named_type, typename).
78
+ * test/test_object.rb: fix to test OCI8::Cursor#bind_param(pos, val,
79
+ :named_type, typename).
80
+
81
+ 2013-06-23 KUBO Takehiro <kubo@jiubao.org>
82
+ * lib/oci8/metadata.rb: OCI8#describe_synonym and OCI8#describe_any
83
+ accept 'PUBLIC.XXX' as a public synonym name.
84
+ * test/test_metadata.rb: add tests for OCI8#describe_synonym.
85
+
86
+ 2013-06-11 KUBO Takehiro <kubo@jiubao.org>
87
+ * ruby-oci8.gemspec: fix ruby version checking in binary gem.
88
+ Gem::ruby_version of ruby 2.0.0p195 is 2.0.0.195, which
89
+ doesn't match '= 2.0.0'.
90
+ (github issue #36 reported by sodonnel)
91
+
92
+ 2013-03-30 KUBO Takehiro <kubo@jiubao.org>
93
+ * ext/oci8/oci8lib.c: fix potential SEGV when one connection
94
+ is used by more than two threads and temporary lobs are
95
+ freed by GC.
96
+
97
+ 2013-03-16 KUBO Takehiro <kubo@jiubao.org>
98
+ * ext/oci8/apiwrap.yml, ext/oci8/stmt.c: call OCIStmtPrepare2()
99
+ without GVL to prevent OCI8#parse from blocking ruby itself
100
+ while the connection is used by another thread even though
101
+ non-blocking mode is set.
102
+
1
103
  2013-03-09 KUBO Takehiro <kubo@jiubao.org>
2
104
  * ruby-oci8.gemspec: revert the previous commit because old
3
105
  rubygems doesn't support:
data/NEWS CHANGED
@@ -1,5 +1,46 @@
1
1
  # @markup markdown
2
2
 
3
+ 2.1.6
4
+ =====
5
+
6
+ New Features
7
+ ------------
8
+
9
+ ### Support ruby 2.1.0
10
+
11
+ ### Support cygwin x86_64
12
+
13
+ ### OCI8#describe_synonym and OCI8#describe_any accept 'PUBLIC.XXX' as a public synonym name.
14
+
15
+ Fixed Issues
16
+ ------------
17
+
18
+ - fix wrong return valus of OCI8::Metadata::Synonym#schema_name
19
+ and #translated_name for synonyms with a database link but
20
+ without schema_name.
21
+
22
+ - fix ruby version checking in binary gem. Gem::ruby_version of
23
+ ruby 2.0.0p195 is 2.0.0.195, which doesn't match '= 2.0.0'.
24
+
25
+ (github issue #36 reported by sodonnel)
26
+
27
+ - fix SEGV when metadata are accessed after the session is disconnected.
28
+
29
+ - fix undefined method 'char_used?' when OCI8::Metadata::Argument#inspect is called.
30
+
31
+ - fix tests in an environment where the data size of "CAST('1' AS CHAR(1 char))"
32
+ is wrong.
33
+
34
+ - suppress warnings "MiniTest::Unit::TestCase is now Minitest::Test"
35
+ when minitest gem is installed.
36
+
37
+ - fix SEGV when oci8lib.so is compiled by mingw64 without runtime-check option.
38
+ Note that binary gems are compiled with runtime-check to check available Oracle
39
+ client features at runtime.
40
+
41
+ - fix SEGV when one connection is used by more than two threads and temporary
42
+ lobs are freed by GC.
43
+
3
44
  2.1.5
4
45
  =====
5
46
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.1.5
1
+ 2.1.6
@@ -1343,7 +1343,7 @@ OCINlsCharSetNameToId:
1343
1343
  - dvoid *envhp
1344
1344
  - const oratext *name
1345
1345
 
1346
- OCIStmtPrepare2:
1346
+ OCIStmtPrepare2_nb:
1347
1347
  :version: 920
1348
1348
  :args:
1349
1349
  - OCISvcCtx *svchp
@@ -5,7 +5,17 @@
5
5
  Copyright (C) 2002-2012 KUBO Takehiro <kubo@jiubao.org>
6
6
 
7
7
  */
8
+ #if defined __linux && !defined(_GNU_SOURCE)
9
+ #define _GNU_SOURCE 1
10
+ #endif
8
11
  #include "oci8.h"
12
+ #ifdef HAVE_DLADDR
13
+ #include <dlfcn.h>
14
+ #endif
15
+ #ifdef __CYGWIN__
16
+ #undef boolean
17
+ #include <windows.h>
18
+ #endif
9
19
 
10
20
  #ifndef DLEXT
11
21
  #define DLEXT ".so"
@@ -84,6 +94,7 @@ static VALUE oci8_make_exc(dvoid *errhp, sword status, ub4 type, OCIStmt *stmthp
84
94
  VALUE parse_error_offset = Qnil;
85
95
  VALUE sql = Qnil;
86
96
  int rv;
97
+ VALUE args[4];
87
98
  int numarg = 1;
88
99
 
89
100
  switch (status) {
@@ -137,7 +148,11 @@ static VALUE oci8_make_exc(dvoid *errhp, sword status, ub4 type, OCIStmt *stmthp
137
148
  sql = rb_external_str_new_with_enc(TO_CHARPTR(text), size, oci8_encoding);
138
149
  }
139
150
  }
140
- exc = rb_funcall(exc, oci8_id_new, numarg, msg, INT2FIX(errcode), sql, parse_error_offset);
151
+ args[0] = msg;
152
+ args[1] = INT2FIX(errcode);
153
+ args[2] = sql;
154
+ args[3] = parse_error_offset;
155
+ exc = rb_class_new_instance(numarg, args, exc);
141
156
  return set_backtrace(exc, file, line);
142
157
  }
143
158
 
@@ -211,8 +226,28 @@ void oci8_do_env_raise(OCIEnv *envhp, sword status, const char *file, int line)
211
226
  void oci8_do_raise_init_error(const char *file, int line)
212
227
  {
213
228
  VALUE msg = rb_usascii_str_new_cstr("OCI Library Initialization Error");
214
- VALUE exc = rb_funcall(eOCIError, oci8_id_new, 2, msg, INT2FIX(-1));
215
-
229
+ VALUE exc;
230
+ const char *dll_path = NULL;
231
+ #if defined _WIN32 || defined __CYGWIN__
232
+ HMODULE hMod = GetModuleHandleA("OCI.DLL");
233
+ char buf[MAX_PATH];
234
+ if (hMod != NULL) {
235
+ if (GetModuleFileName(hMod, buf, sizeof(buf))) {
236
+ dll_path = buf;
237
+ }
238
+ }
239
+ #elif defined HAVE_DLADDR
240
+ void *addr = dlsym(RTLD_DEFAULT, "OCIEnvCreate");
241
+ Dl_info info;
242
+ if (addr != NULL && dladdr(addr, &info)) {
243
+ dll_path = info.dli_fname;
244
+ }
245
+ #endif
246
+ if (dll_path != NULL) {
247
+ msg = rb_str_buf_cat_ascii(msg, " - ");
248
+ msg = rb_enc_str_buf_cat(msg, dll_path, strlen(dll_path), rb_filesystem_encoding());
249
+ }
250
+ exc = rb_class_new_instance(1, &msg, eOCIError);
216
251
  rb_exc_raise(set_backtrace(exc, file, line));
217
252
  }
218
253
 
@@ -246,9 +281,11 @@ VALUE oci8_get_error_message(ub4 msgno, const char *default_msg)
246
281
  void oci8_do_raise_by_msgno(ub4 msgno, const char *default_msg, const char *file, int line)
247
282
  {
248
283
  VALUE msg = oci8_get_error_message(msgno, default_msg);
249
- VALUE exc = rb_funcall(eOCIError, oci8_id_new, 2, msg, INT2FIX(-1));
284
+ VALUE args[2];
285
+ args[0] = msg;
286
+ args[1] = INT2FIX(-1);
250
287
 
251
- rb_exc_raise(set_backtrace(exc, file, line));
288
+ rb_exc_raise(set_backtrace(rb_class_new_instance(2, args, eOCIError), file, line));
252
289
  }
253
290
 
254
291
  void oci8_check_error_(sword status, oci8_base_t *base, OCIStmt *stmthp, const char *file, int line)
@@ -103,6 +103,7 @@ if oraconf.cc_is_gcc
103
103
  end
104
104
 
105
105
  have_func("localtime_r")
106
+ have_func("dladdr")
106
107
 
107
108
  # ruby 1.8 headers
108
109
  have_header("intern.h")
@@ -121,6 +122,10 @@ have_func("rb_set_end_proc", "ruby.h")
121
122
  have_func("rb_class_superclass", "ruby.h")
122
123
  have_func("rb_thread_blocking_region", "ruby.h")
123
124
  have_func("rb_thread_call_without_gvl", "ruby/thread.h")
125
+ if (defined? RUBY_ENGINE) && RUBY_ENGINE == 'rbx'
126
+ have_func("rb_str_buf_cat_ascii", "ruby.h")
127
+ have_func("rb_enc_str_buf_cat", "ruby.h")
128
+ end
124
129
 
125
130
  # replace files
126
131
  replace = {
@@ -158,8 +163,6 @@ when 'ruby'
158
163
  # if it wasn't explicitly changed by the configure option --with-ruby-version.
159
164
  #
160
165
  case RUBY_VERSION
161
- when /^2\.0/
162
- so_basename += RUBY_VERSION.gsub(/\W/, '')
163
166
  when /^1\.9\.0/
164
167
  raise 'unsupported ruby version: 1.9.0'
165
168
  when /^1\.9/
@@ -167,20 +170,10 @@ when 'ruby'
167
170
  when /^1\.8/
168
171
  so_basename += '18'
169
172
  else
170
- raise 'unsupported ruby version: ' + RUBY_VERSION
173
+ so_basename += RUBY_VERSION.gsub(/\W/, '')
171
174
  end
172
175
  when 'rbx'
173
- # "rbx -X18" and "rbx -X19" use different C header files.
174
- case RUBY_VERSION
175
- when /^2\.0/
176
- so_basename += 'rbx20'
177
- when /^1\.9/
178
- so_basename += 'rbx19'
179
- when /^1\.8/
180
- so_basename += 'rbx18'
181
- else
182
- raise 'unsupported language mode: ' + RUBY_VERSION
183
- end
176
+ so_basename += 'rbx'
184
177
  when 'jruby'
185
178
  raise "Ruby-oci8 doesn't support jruby because its C extension support is in development in jruby 1.6 and deprecated in jruby 1.7."
186
179
  else
@@ -52,7 +52,7 @@ static VALUE oci8_make_lob(VALUE klass, oci8_svcctx_t *svcctx, OCILobLocator *s)
52
52
  boolean is_temp;
53
53
  VALUE lob_obj;
54
54
 
55
- lob_obj = rb_funcall(klass, oci8_id_new, 1, svcctx->base.self);
55
+ lob_obj = rb_class_new_instance(1, &svcctx->base.self, klass);
56
56
  lob = DATA_PTR(lob_obj);
57
57
  /* If 's' is a temporary lob, use OCILobLocatorAssign instead. */
58
58
  chker2(OCILobIsTemporary(oci8_envhp, oci8_errhp, s, &is_temp), &svcctx->base);
@@ -719,10 +719,10 @@ static VALUE oci8_lob_clone(VALUE self)
719
719
  {
720
720
  oci8_lob_t *lob = DATA_PTR(self);
721
721
  oci8_lob_t *newlob;
722
- VALUE newobj;
722
+ VALUE newobj = lob->svcctx ? lob->svcctx->base.self : Qnil;
723
723
  boolean is_temporary;
724
724
 
725
- newobj = rb_funcall(CLASS_OF(self), oci8_id_new, 1, lob->svcctx ? lob->svcctx->base.self : Qnil);
725
+ newobj = rb_class_new_instance(1, &newobj, CLASS_OF(self));
726
726
  newlob = DATA_PTR(newobj);
727
727
  if (OCILobIsTemporary(oci8_envhp, oci8_errhp, lob->base.hp.lob, &is_temporary) == OCI_SUCCESS
728
728
  && is_temporary) {
@@ -992,7 +992,7 @@ static void bind_lob_init_elem(oci8_bind_t *obind, VALUE svc)
992
992
  ub4 idx = 0;
993
993
 
994
994
  do {
995
- oho[idx].obj = rb_funcall(*vptr->klass, oci8_id_new, 1, svc);
995
+ oho[idx].obj = rb_class_new_instance(1, &svc, *vptr->klass);
996
996
  h = DATA_PTR(oho[idx].obj);
997
997
  oho[idx].hp = h->hp.ptr;
998
998
  } while (++idx < obind->maxar_sz);
@@ -154,6 +154,7 @@ static VALUE oci8_do_describe(VALUE self, void *objptr, ub4 objlen, ub1 objtype,
154
154
  chker2(OCIDescribeAny_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, objptr, objlen,
155
155
  objtype, OCI_DEFAULT, (ub1)FIX2INT(type), desc->hp.dschp),
156
156
  &svcctx->base);
157
+ oci8_link_to_parent(desc, &svcctx->base);
157
158
  chker2(OCIAttrGet(desc->hp.dschp, OCI_HTYPE_DESCRIBE, &parmhp, 0, OCI_ATTR_PARAM, oci8_errhp),
158
159
  &svcctx->base);
159
160
  return oci8_metadata_create(parmhp, self, obj);
@@ -183,7 +183,7 @@ static VALUE get_attribute(VALUE self, VALUE datatype, VALUE typeinfo, void *dat
183
183
  case ATTR_NAMED_TYPE:
184
184
  Check_Object(typeinfo, cOCI8TDO);
185
185
  /* Be carefull. Don't use *tmp_obj* out of this function. */
186
- tmp_obj = rb_funcall(cOCI8NamedType, oci8_id_new, 0);
186
+ tmp_obj = rb_class_new_instance(0, NULL, cOCI8NamedType);
187
187
  obj = DATA_PTR(tmp_obj);
188
188
  obj->tdo = typeinfo;
189
189
  obj->instancep = (char**)&data;
@@ -195,7 +195,7 @@ static VALUE get_attribute(VALUE self, VALUE datatype, VALUE typeinfo, void *dat
195
195
  case ATTR_NAMED_COLLECTION:
196
196
  Check_Object(typeinfo, cOCI8TDO);
197
197
  /* Be carefull. Don't use *tmp_obj* out of this function. */
198
- tmp_obj = rb_funcall(cOCI8NamedCollection, oci8_id_new, 0);
198
+ tmp_obj = rb_class_new_instance(0, NULL, cOCI8NamedCollection);
199
199
  obj = DATA_PTR(tmp_obj);
200
200
  obj->tdo = typeinfo;
201
201
  obj->instancep = (char**)data;
@@ -506,7 +506,7 @@ static void set_attribute(VALUE self, VALUE datatype, VALUE typeinfo, void *data
506
506
  case ATTR_NAMED_TYPE:
507
507
  Check_Object(typeinfo, cOCI8TDO);
508
508
  /* Be carefull. Don't use *tmp_obj* out of this function. */
509
- tmp_obj = rb_funcall(cOCI8NamedType, oci8_id_new, 0);
509
+ tmp_obj = rb_class_new_instance(0, NULL, cOCI8NamedType);
510
510
  obj = DATA_PTR(tmp_obj);
511
511
  obj->tdo = typeinfo;
512
512
  obj->instancep = (char**)&data;
@@ -518,7 +518,7 @@ static void set_attribute(VALUE self, VALUE datatype, VALUE typeinfo, void *data
518
518
  case ATTR_NAMED_COLLECTION:
519
519
  Check_Object(typeinfo, cOCI8TDO);
520
520
  /* Be carefull. Don't use *tmp_obj* out of this function. */
521
- tmp_obj = rb_funcall(cOCI8NamedCollection, oci8_id_new, 0);
521
+ tmp_obj = rb_class_new_instance(0, NULL, cOCI8NamedCollection);
522
522
  obj = DATA_PTR(tmp_obj);
523
523
  obj->tdo = typeinfo;
524
524
  obj->instancep = (char**)data;
@@ -626,7 +626,7 @@ static void bind_named_type_init_elem(oci8_bind_t *obind, VALUE svc)
626
626
  }
627
627
  svcctx = oci8_get_svcctx(svc);
628
628
  do {
629
- oho[idx].obj = rb_funcall(klass, oci8_id_new, 0);
629
+ oho[idx].obj = rb_class_new_instance(0, NULL, klass);
630
630
  obj = DATA_PTR(oho[idx].obj);
631
631
  obj->tdo = obind->tdo;
632
632
  obj->instancep = (char**)&oho[idx].hp;
@@ -150,13 +150,26 @@ static inline volatile VALUE *rb_gc_guarded_ptr(volatile VALUE *ptr) {return ptr
150
150
  #endif
151
151
 
152
152
  #ifndef HAVE_TYPE_RB_ENCODING
153
+ /* ruby 1.8, rubinuis 1.2 */
153
154
  #define rb_enc_associate(str, enc) do {} while(0)
155
+ #define rb_enc_str_buf_cat(str, ptr, len, enc) rb_str_buf_cat((str), (ptr), (len))
154
156
  #define rb_external_str_new_with_enc(ptr, len, enc) rb_tainted_str_new((ptr), (len))
155
157
  #define rb_locale_str_new_cstr(ptr) rb_str_new2(ptr)
158
+ #define rb_str_buf_cat_ascii(str, ptr) rb_str_buf_cat2((str), (ptr))
156
159
  #define rb_str_conv_enc(str, from, to) (str)
157
160
  #define rb_str_export_to_enc(str, enc) (str)
158
161
  #define rb_usascii_str_new(ptr, len) rb_str_new((ptr), (len))
159
162
  #define rb_usascii_str_new_cstr(ptr) rb_str_new2(ptr)
163
+ #elif defined RBX_CAPI_RUBY_H
164
+ /* rubinius 2.0 */
165
+ #ifndef HAVE_RB_ENC_STR_BUF_CAT
166
+ #define rb_enc_str_buf_cat(str, ptr, len, enc) \
167
+ rb_str_concat((str), rb_enc_str_new((ptr), (len), (enc)))
168
+ #endif
169
+ #ifndef HAVE_RB_STR_BUF_CAT_ASCII
170
+ #define rb_str_buf_cat_ascii(str, ptr) \
171
+ rb_str_concat((str), rb_usascii_str_new_cstr(ptr))
172
+ #endif
160
173
  #endif
161
174
 
162
175
  /* a new function in ruby 1.9.3.
@@ -446,7 +459,6 @@ void Init_oci8_env(void);
446
459
 
447
460
  /* oci8lib.c */
448
461
  extern ID oci8_id_at_last_error;
449
- extern ID oci8_id_new;
450
462
  extern ID oci8_id_get;
451
463
  extern ID oci8_id_set;
452
464
  extern ID oci8_id_oci8_vtable;
@@ -9,7 +9,6 @@
9
9
  #endif
10
10
 
11
11
  ID oci8_id_at_last_error;
12
- ID oci8_id_new;
13
12
  ID oci8_id_get;
14
13
  ID oci8_id_set;
15
14
  ID oci8_id_oci8_vtable;
@@ -87,7 +86,6 @@ Init_oci8lib()
87
86
  #endif
88
87
 
89
88
  oci8_id_at_last_error = rb_intern("@last_error");
90
- oci8_id_new = rb_intern("new");
91
89
  oci8_id_get = rb_intern("get");
92
90
  oci8_id_set = rb_intern("set");
93
91
  oci8_id_oci8_vtable = rb_intern("__oci8_vtable__");
@@ -234,64 +232,83 @@ static void *free_temp_lob(void *user_data)
234
232
  return (void*)(VALUE)rv;
235
233
  }
236
234
 
235
+ typedef struct protected_call_arg {
236
+ void *(*func)(void *);
237
+ void *data;
238
+ oci8_svcctx_t *svcctx;
239
+ } protected_call_arg_t;
240
+
241
+ static VALUE protected_call(VALUE data)
242
+ {
243
+ struct protected_call_arg *parg = (struct protected_call_arg*)data;
244
+ VALUE rv;
245
+
246
+ if (!NIL_P(parg->svcctx->executing_thread)) {
247
+ rb_raise(rb_eRuntimeError, "executing in another thread");
248
+ }
249
+ parg->svcctx->executing_thread = rb_thread_current();
250
+ #ifdef HAVE_RB_THREAD_CALL_WITHOUT_GVL
251
+ rv = (VALUE)rb_thread_call_without_gvl(parg->func, parg->data, oci8_unblock_func, parg->svcctx);
252
+ #else
253
+ rv = rb_thread_blocking_region((VALUE(*)(void*))parg->func, parg->data, oci8_unblock_func, parg->svcctx);
254
+ #endif
255
+ if ((sword)rv == OCI_ERROR) {
256
+ if (oci8_get_error_code(oci8_errhp) == 1013) {
257
+ rb_raise(eOCIBreak, "Canceled by user request.");
258
+ }
259
+ }
260
+ return rv;
261
+ }
262
+
237
263
  /* ruby 1.9 */
238
264
  sword oci8_call_without_gvl(oci8_svcctx_t *svcctx, void *(*func)(void *), void *data)
239
265
  {
240
266
  OCIError *errhp = oci8_errhp;
267
+ protected_call_arg_t parg;
268
+ sword rv;
269
+ int state;
241
270
 
242
271
  if (!NIL_P(svcctx->executing_thread)) {
243
- rb_raise(rb_eRuntimeError /* FIXME */, "executing in another thread");
272
+ rb_raise(rb_eRuntimeError, "executing in another thread");
244
273
  }
245
-
246
274
  if (!svcctx->suppress_free_temp_lobs) {
247
- oci8_temp_lob_t *lob = svcctx->temp_lobs;
248
- while (lob != NULL) {
249
- oci8_temp_lob_t *lob_next = lob->next;
275
+ oci8_temp_lob_t *lob;
276
+ while ((lob = svcctx->temp_lobs) != NULL) {
277
+ svcctx->temp_lobs = lob->next;
250
278
 
251
279
  if (svcctx->non_blocking) {
252
280
  free_temp_lob_arg_t arg;
253
- sword rv;
254
281
 
255
282
  arg.svcctx = svcctx;
256
283
  arg.svchp = svcctx->base.hp.svc;
257
284
  arg.errhp = errhp;
258
285
  arg.lob = lob->lob;
259
286
 
260
- svcctx->executing_thread = rb_thread_current();
261
- #ifdef HAVE_RB_THREAD_CALL_WITHOUT_GVL
262
- rv = (sword)(VALUE)rb_thread_call_without_gvl(free_temp_lob, &arg, oci8_unblock_func, svcctx);
263
- #else
264
- rv = (sword)rb_thread_blocking_region((VALUE(*)(void*))free_temp_lob, &arg, oci8_unblock_func, svcctx);
265
- #endif
266
- if (rv == OCI_ERROR) {
267
- if (oci8_get_error_code(errhp) == 1013) {
268
- rb_raise(eOCIBreak, "Canceled by user request.");
269
- }
287
+ parg.svcctx = svcctx;
288
+ parg.func = free_temp_lob;
289
+ parg.data = &arg;
290
+
291
+ rb_protect(protected_call, (VALUE)&parg, &state);
292
+ if (state) {
293
+ lob->next = svcctx->temp_lobs;
294
+ svcctx->temp_lobs = lob;
295
+ rb_jump_tag(state);
270
296
  }
271
297
  } else {
272
298
  OCILobFreeTemporary(svcctx->base.hp.svc, errhp, lob->lob);
273
299
  }
274
300
  OCIDescriptorFree(lob->lob, OCI_DTYPE_LOB);
275
-
276
301
  xfree(lob);
277
- svcctx->temp_lobs = lob = lob_next;
278
302
  }
279
303
  }
280
304
 
281
305
  if (svcctx->non_blocking) {
282
- sword rv;
283
-
284
- svcctx->executing_thread = rb_thread_current();
285
- /* Note: executing_thread is cleard at the end of the blocking function. */
286
- #ifdef HAVE_RB_THREAD_CALL_WITHOUT_GVL
287
- rv = (sword)(VALUE)rb_thread_call_without_gvl(func, data, oci8_unblock_func, svcctx);
288
- #else
289
- rv = (sword)rb_thread_blocking_region((VALUE(*)(void*))func, data, oci8_unblock_func, svcctx);
290
- #endif
291
- if (rv == OCI_ERROR) {
292
- if (oci8_get_error_code(errhp) == 1013) {
293
- rb_raise(eOCIBreak, "Canceled by user request.");
294
- }
306
+ parg.svcctx = svcctx;
307
+ parg.func = func;
308
+ parg.data = data;
309
+ rv = (sword)rb_protect(protected_call, (VALUE)&parg, &state);
310
+ if (state) {
311
+ rb_jump_tag(state);
295
312
  }
296
313
  return rv;
297
314
  } else {
@@ -489,16 +506,19 @@ void *oci8_find_symbol(const char *symbol_name)
489
506
  "libclntsh.a(shr.o)",
490
507
  #elif defined(__hppa)
491
508
  /* HP-UX(PA-RISC) */
509
+ "libclntsh.sl.12.1",
492
510
  "libclntsh.sl.11.1",
493
511
  "libclntsh.sl.10.1",
494
512
  "libclntsh.sl.9.0",
495
513
  "libclntsh.sl.8.0",
496
514
  #elif defined(__APPLE__)
497
515
  /* Mac OS X */
516
+ "libclntsh.dylib.12.1",
498
517
  "libclntsh.dylib.11.1",
499
518
  "libclntsh.dylib.10.1",
500
519
  #else
501
520
  /* Linux, Solaris and HP-UX(IA64) */
521
+ "libclntsh.so.12.1",
502
522
  "libclntsh.so.11.1",
503
523
  "libclntsh.so.10.1",
504
524
  "libclntsh.so.9.0",