ruby-oci8 2.1.5 → 2.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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",