ruby-oci8 2.1.7 → 2.1.8

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.
@@ -2,7 +2,7 @@
2
2
  /*
3
3
  * oci8.h - part of ruby-oci8
4
4
  *
5
- * Copyright (C) 2002-2013 Kubo Takehiro <kubo@jiubao.org>
5
+ * Copyright (C) 2002-2014 Kubo Takehiro <kubo@jiubao.org>
6
6
  */
7
7
  #ifndef _RUBY_OCI_H_
8
8
  #define _RUBY_OCI_H_ 1
@@ -40,6 +40,7 @@ extern "C"
40
40
  #define ORAVER_10_1 ORAVERNUM(10, 1, 0, 0, 0)
41
41
  #define ORAVER_10_2 ORAVERNUM(10, 2, 0, 0, 0)
42
42
  #define ORAVER_11_1 ORAVERNUM(11, 1, 0, 0, 0)
43
+ #define ORAVER_12_1 ORAVERNUM(12, 1, 0, 0, 0)
43
44
 
44
45
  #include "extconf.h"
45
46
  #ifdef HAVE_TYPE_RB_ENCODING
@@ -116,6 +117,13 @@ typedef struct OCICPool OCICPool;
116
117
  #define RARRAY_LEN(obj) RARRAY(obj)->len
117
118
  #endif
118
119
 
120
+ #ifndef HAVE_RB_STR_SET_LEN
121
+ #define rb_str_set_len(s, l) do { \
122
+ RSTRING(s)->len = (l); \
123
+ RSTRING(s)->ptr[l] = '\0'; \
124
+ } while (0)
125
+ #endif
126
+
119
127
  /* new macros in ruby 1.9.
120
128
  * define compatible macros for ruby 1.8 or lower.
121
129
  */
@@ -173,6 +181,46 @@ static inline volatile VALUE *rb_gc_guarded_ptr(volatile VALUE *ptr) {return ptr
173
181
  #endif
174
182
  #endif
175
183
 
184
+ /*
185
+ * Use TypedData on ruby 1.9.3 and later.
186
+ */
187
+ #ifndef HAVE_RB_DATA_TYPE_T_FUNCTION
188
+
189
+ /*
190
+ * Don't use TypedData even though ruby 1.9.2 has it because the
191
+ * definitions are slightly different from ruby 1.9.3 and later.
192
+ */
193
+ #define rb_data_type_t oci8_data_type_t
194
+ #undef TypedData_Make_Struct
195
+ #undef TypedData_Wrap_Struct
196
+ #undef TypedData_Get_Struct
197
+ #undef RTYPEDDATA_DATA
198
+ #undef RUBY_DEFAULT_FREE
199
+
200
+ /*
201
+ * To pass compilation on ruby 1.9.2 and earlier.
202
+ */
203
+ typedef struct oci8_data_type_struct rb_data_type_t;
204
+ struct oci8_data_type_struct {
205
+ const char *wrap_struct_name;
206
+ struct {
207
+ void (*dmark)(void*);
208
+ void (*dfree)(void*);
209
+ size_t (*dsize)(const void *);
210
+ } function;
211
+ const rb_data_type_t *parent;
212
+ void *data;
213
+ };
214
+ #define TypedData_Make_Struct(klass, type, data_type, sval) \
215
+ Data_Make_Struct((klass), type, (data_type)->function.dmark, (data_type)->function.dfree, (sval))
216
+ #define TypedData_Wrap_Struct(klass, data_type, sval) \
217
+ Data_Wrap_Struct((klass), (data_type)->function.dmark, (data_type)->function.dfree, (sval))
218
+ #define TypedData_Get_Struct(obj, type, data_type, sval) \
219
+ Data_Get_Struct((obj), type, (sval))
220
+ #define RTYPEDDATA_DATA(obj) DATA_PTR(obj)
221
+ #define RUBY_DEFAULT_FREE xfree
222
+ #endif
223
+
176
224
  /* a new function in ruby 1.9.3.
177
225
  * define a compatible macro for ruby 1.9.2 or lower.
178
226
  */
@@ -184,6 +232,21 @@ static inline volatile VALUE *rb_gc_guarded_ptr(volatile VALUE *ptr) {return ptr
184
232
  #endif
185
233
  #endif
186
234
 
235
+ /* new macros in ruby 2.1.0
236
+ */
237
+ #ifndef RARRAY_AREF
238
+ #define RARRAY_AREF(a, i) (RARRAY_PTR(a)[i])
239
+ #endif
240
+ #ifndef RARRAY_CONST_PTR
241
+ #define RARRAY_CONST_PTR(a) RARRAY_PTR(a)
242
+ #endif
243
+ #ifndef RB_OBJ_WRITE
244
+ #define RB_OBJ_WRITE(a, slot, b) do {*(slot) = (b);} while (0)
245
+ #endif
246
+ #ifndef RB_OBJ_WRITTEN
247
+ #define RB_OBJ_WRITTEN(a, oldv, b) do {(void)oldv;} while (0)
248
+ #endif
249
+
187
250
  #if defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL) || defined(HAVE_RB_THREAD_BLOCKING_REGION)
188
251
  #define NATIVE_THREAD_WITH_GVL 1
189
252
  #endif
@@ -270,6 +333,8 @@ static ALWAYS_INLINE char *to_charptr(OraText *c)
270
333
  #define RSTRING_ORATEXT(obj) TO_ORATEXT(RSTRING_PTR(obj))
271
334
  #define rb_str_new2_ora(str) rb_str_new2(TO_CHARPTR(str))
272
335
 
336
+ #define TO_BIND(obj) ((oci8_bind_t *)oci8_check_typeddata((obj), &oci8_bind_data_type, 1))
337
+
273
338
  /*
274
339
  * prevent rdoc from gathering the specified method.
275
340
  */
@@ -282,23 +347,22 @@ typedef struct {
282
347
  char buf[1];
283
348
  } oci8_vstr_t;
284
349
 
285
- typedef struct oci8_base_vtable oci8_base_vtable_t;
286
- typedef struct oci8_bind_vtable oci8_bind_vtable_t;
350
+ typedef struct oci8_handle_data_type oci8_handle_data_type_t;
351
+ typedef struct oci8_bind_data_type oci8_bind_data_type_t;
287
352
 
288
353
  typedef struct oci8_base oci8_base_t;
289
354
  typedef struct oci8_bind oci8_bind_t;
290
355
 
291
356
  /* The virtual method table of oci8_base_t */
292
- struct oci8_base_vtable {
293
- void (*mark)(oci8_base_t *base);
357
+ struct oci8_handle_data_type {
358
+ rb_data_type_t rb_data_type;
294
359
  void (*free)(oci8_base_t *base);
295
360
  size_t size;
296
- void (*init)(oci8_base_t *base);
297
361
  };
298
362
 
299
363
  /* The virtual method table of oci8_bind_t */
300
- struct oci8_bind_vtable {
301
- oci8_base_vtable_t base;
364
+ struct oci8_bind_data_type {
365
+ oci8_handle_data_type_t base;
302
366
  VALUE (*get)(oci8_bind_t *obind, void *data, void *null_struct);
303
367
  void (*set)(oci8_bind_t *obind, void *data, void **null_structp, VALUE val);
304
368
  void (*init)(oci8_bind_t *obind, VALUE svc, VALUE val, VALUE length);
@@ -311,12 +375,11 @@ struct oci8_bind_vtable {
311
375
  /* Class structure implemented by C language.
312
376
  * oci8_base_t represents OCIHandle and its subclasses.
313
377
  *
314
- * The vptr member points to a virtual method table.
315
- * See: http://en.wikipedia.org/wiki/Virtual_method_table
316
378
  */
317
379
  struct oci8_base {
318
- const oci8_base_vtable_t *vptr;
380
+ const oci8_handle_data_type_t *data_type;
319
381
  ub4 type;
382
+ ub1 closed;
320
383
  union {
321
384
  dvoid *ptr;
322
385
  OCISvcCtx *svc;
@@ -397,19 +460,6 @@ typedef struct {
397
460
  ub2 *alenp;
398
461
  } oci8_exec_sql_var_t;
399
462
 
400
- #define Check_Handle(obj, klass, hp) do { \
401
- if (!rb_obj_is_kind_of(obj, klass)) { \
402
- rb_raise(rb_eTypeError, "invalid argument %s (expect %s)", rb_class2name(CLASS_OF(obj)), rb_class2name(klass)); \
403
- } \
404
- Data_Get_Struct(obj, oci8_base_t, hp); \
405
- } while (0)
406
-
407
- #define Check_Object(obj, klass) do {\
408
- if (!rb_obj_is_kind_of(obj, klass)) { \
409
- rb_raise(rb_eTypeError, "invalid argument %s (expect %s)", rb_class2name(CLASS_OF(obj)), rb_class2name(klass)); \
410
- } \
411
- } while (0)
412
-
413
463
  #define oci8_raise(err, status, stmt) oci8_do_raise(err, status, stmt, __FILE__, __LINE__)
414
464
  #define oci8_env_raise(err, status) oci8_do_env_raise(err, status, __FILE__, __LINE__)
415
465
  #define oci8_raise_init_error() oci8_do_raise_init_error(__FILE__, __LINE__)
@@ -462,7 +512,6 @@ void Init_oci8_env(void);
462
512
  extern ID oci8_id_at_last_error;
463
513
  extern ID oci8_id_get;
464
514
  extern ID oci8_id_set;
465
- extern ID oci8_id_oci8_vtable;
466
515
  #ifdef CHAR_IS_NOT_A_SHORTCUT_TO_ID
467
516
  extern ID oci8_id_add_op; /* ID of the addition operator '+' */
468
517
  extern ID oci8_id_sub_op; /* ID of the subtraction operator '-' */
@@ -477,9 +526,9 @@ extern ID oci8_id_div_op; /* ID of the division operator '/' */
477
526
  extern int oci8_in_finalizer;
478
527
  extern VALUE oci8_cOCIHandle;
479
528
  void oci8_base_free(oci8_base_t *base);
480
- VALUE oci8_define_class(const char *name, oci8_base_vtable_t *vptr);
481
- VALUE oci8_define_class_under(VALUE outer, const char *name, oci8_base_vtable_t *vptr);
482
- VALUE oci8_define_bind_class(const char *name, const oci8_bind_vtable_t *vptr);
529
+ VALUE oci8_define_class(const char *name, const oci8_handle_data_type_t *data_type, VALUE (*alloc_func)(VALUE));
530
+ VALUE oci8_define_class_under(VALUE outer, const char *name, const oci8_handle_data_type_t *data_type, VALUE (*alloc_func)(VALUE));
531
+ VALUE oci8_define_bind_class(const char *name, const oci8_bind_data_type_t *data_type, VALUE (*alloc_func)(VALUE));
483
532
  void oci8_link_to_parent(oci8_base_t *base, oci8_base_t *parent);
484
533
  void oci8_unlink_from_parent(oci8_base_t *base);
485
534
  sword oci8_call_without_gvl(oci8_svcctx_t *svcctx, void *(*func)(void *), void *data);
@@ -487,7 +536,7 @@ sword oci8_exec_sql(oci8_svcctx_t *svcctx, const char *sql_text, ub4 num_define_
487
536
  #if defined RUNTIME_API_CHECK
488
537
  void *oci8_find_symbol(const char *symbol_name);
489
538
  #endif
490
- oci8_base_t *oci8_get_handle(VALUE obj, VALUE klass);
539
+ void *oci8_check_typeddata(VALUE obj, const oci8_handle_data_type_t *data_type, int error_if_closed);
491
540
 
492
541
  /* error.c */
493
542
  extern VALUE eOCIException;
@@ -501,7 +550,11 @@ NORETURN(void oci8_do_raise_by_msgno(ub4 msgno, const char *default_msg, const c
501
550
  void oci8_check_error_(sword status, oci8_base_t *base, OCIStmt *stmthp, const char *file, int line);
502
551
 
503
552
  /* ocihandle.c */
553
+ extern const oci8_handle_data_type_t oci8_handle_data_type;
504
554
  void Init_oci8_handle(void);
555
+ VALUE oci8_allocate_typeddata(VALUE klass, const oci8_handle_data_type_t *data_type);
556
+ void oci8_handle_cleanup(void *ptr);
557
+ size_t oci8_handle_size(const void *ptr);
505
558
 
506
559
  /* oci8.c */
507
560
  void Init_oci8(VALUE *out);
@@ -515,7 +568,6 @@ void oci8_check_pid_consistency(oci8_svcctx_t *svcctx);
515
568
  void Init_oci8_connection_pool(VALUE cOCI8);
516
569
 
517
570
  /* stmt.c */
518
- extern VALUE cOCIStmt;
519
571
  void Init_oci8_stmt(VALUE cOCI8);
520
572
 
521
573
  /* bind.c */
@@ -523,13 +575,13 @@ typedef struct {
523
575
  void *hp;
524
576
  VALUE obj;
525
577
  } oci8_hp_obj_t;
578
+ extern const oci8_handle_data_type_t oci8_bind_data_type;
526
579
  void oci8_bind_free(oci8_base_t *base);
527
580
  void oci8_bind_hp_obj_mark(oci8_base_t *base);
528
581
  void Init_oci8_bind(VALUE cOCI8BindTypeBase);
529
- oci8_bind_t *oci8_get_bind(VALUE obj);
530
582
 
531
583
  /* metadata.c */
532
- extern VALUE cOCI8MetadataBase;
584
+ extern const oci8_handle_data_type_t oci8_metadata_base_data_type;
533
585
  void Init_oci8_metadata(VALUE cOCI8);
534
586
  VALUE oci8_metadata_create(OCIParam *parmhp, VALUE svc, VALUE parent);
535
587
 
@@ -580,7 +632,6 @@ VALUE oci8_make_interval_ds(OCIInterval *s);
580
632
  void Init_oci_object(VALUE mOCI);
581
633
 
582
634
  /* attr.c */
583
- VALUE oci8_get_ub2_attr(oci8_base_t *base, ub4 attrtype, OCIStmt *stmtp);
584
635
  VALUE oci8_get_rowid_attr(oci8_base_t *base, ub4 attrtype, OCIStmt *stmtp);
585
636
 
586
637
  /* encoding.c */
@@ -591,6 +642,10 @@ extern int oci8_nls_ratio;
591
642
  /* win32.c */
592
643
  void Init_oci8_win32(VALUE cOCI8);
593
644
 
645
+ /* hook_funcs.c */
646
+ void oci8_install_hook_functions(void);
647
+ void oci8_shutdown_sockets(void);
648
+
594
649
  #ifdef HAVE_TYPE_RB_ENCODING
595
650
  extern rb_encoding *oci8_encoding;
596
651
 
@@ -1,6 +1,6 @@
1
1
  /* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
2
2
  /*
3
- * Copyright (C) 2002-2012 KUBO Takehiro <kubo@jiubao.org>
3
+ * Copyright (C) 2002-2015 Kubo Takehiro <kubo@jiubao.org>
4
4
  */
5
5
 
6
6
  #include "oci8.h"
@@ -11,7 +11,6 @@
11
11
  ID oci8_id_at_last_error;
12
12
  ID oci8_id_get;
13
13
  ID oci8_id_set;
14
- ID oci8_id_oci8_vtable;
15
14
  #ifdef CHAR_IS_NOT_A_SHORTCUT_TO_ID
16
15
  ID oci8_id_add_op;
17
16
  ID oci8_id_sub_op;
@@ -39,8 +38,8 @@ void oci8_base_free(oci8_base_t *base)
39
38
  oci8_base_free(base->children);
40
39
  }
41
40
  oci8_unlink_from_parent(base);
42
- if (base->vptr->free != NULL)
43
- base->vptr->free(base);
41
+ if (base->data_type->free != NULL)
42
+ base->data_type->free(base);
44
43
  if (base->type >= OCI_DTYPE_FIRST) {
45
44
  OCIDescriptorFree(base->hp.ptr, base->type);
46
45
  } else if (base->type == OCI_HTYPE_BIND || base->type == OCI_HTYPE_DEFINE) {
@@ -51,6 +50,7 @@ void oci8_base_free(oci8_base_t *base)
51
50
  OCIHandleFree(base->hp.ptr, base->type);
52
51
  }
53
52
  base->type = 0;
53
+ base->closed = 1;
54
54
  base->hp.ptr = NULL;
55
55
  }
56
56
 
@@ -58,9 +58,17 @@ void oci8_base_free(oci8_base_t *base)
58
58
  static void at_exit_func(VALUE val)
59
59
  {
60
60
  oci8_in_finalizer = 1;
61
+ #ifdef HAVE_PLTHOOK
62
+ oci8_shutdown_sockets();
63
+ #endif
61
64
  }
62
65
  #endif
63
66
 
67
+ static VALUE bind_base_alloc(VALUE klass)
68
+ {
69
+ rb_raise(rb_eNameError, "private method `new' called for %s:Class", rb_class2name(klass));
70
+ }
71
+
64
72
  #ifdef _WIN32
65
73
  __declspec(dllexport)
66
74
  #endif
@@ -88,7 +96,6 @@ Init_oci8lib()
88
96
  oci8_id_at_last_error = rb_intern("@last_error");
89
97
  oci8_id_get = rb_intern("get");
90
98
  oci8_id_set = rb_intern("set");
91
- oci8_id_oci8_vtable = rb_intern("__oci8_vtable__");
92
99
  #ifdef CHAR_IS_NOT_A_SHORTCUT_TO_ID
93
100
  oci8_id_add_op = rb_intern("+");
94
101
  oci8_id_sub_op = rb_intern("-");
@@ -115,7 +122,7 @@ Init_oci8lib()
115
122
  /* OCI8::BindType module */
116
123
  mOCI8BindType = rb_define_module_under(cOCI8, "BindType");
117
124
  /* OCI8::BindType::Base class */
118
- cOCI8BindTypeBase = rb_define_class_under(mOCI8BindType, "Base", oci8_cOCIHandle);
125
+ cOCI8BindTypeBase = oci8_define_class_under(mOCI8BindType, "Base", &oci8_bind_data_type, bind_base_alloc);
119
126
 
120
127
  /* Handle */
121
128
  Init_oci8_bind(cOCI8BindTypeBase);
@@ -149,33 +156,39 @@ Init_oci8lib()
149
156
  #endif
150
157
  }
151
158
 
152
- VALUE oci8_define_class(const char *name, oci8_base_vtable_t *vptr)
159
+ VALUE oci8_define_class(const char *name, const oci8_handle_data_type_t *data_type, VALUE (*alloc_func)(VALUE))
153
160
  {
154
- VALUE klass = rb_define_class(name, oci8_cOCIHandle);
155
- VALUE obj = Data_Wrap_Struct(rb_cObject, 0, 0, vptr);
156
- rb_ivar_set(klass, oci8_id_oci8_vtable, obj);
161
+ VALUE parent_class = rb_eval_string(data_type->rb_data_type.parent->wrap_struct_name);
162
+ VALUE klass = rb_define_class(name, parent_class);
163
+
164
+ rb_define_alloc_func(klass, alloc_func);
157
165
  return klass;
158
166
  }
159
167
 
160
- VALUE oci8_define_class_under(VALUE outer, const char *name, oci8_base_vtable_t *vptr)
168
+ VALUE oci8_define_class_under(VALUE outer, const char *name, const oci8_handle_data_type_t *data_type, VALUE (*alloc_func)(VALUE))
161
169
  {
162
- VALUE klass = rb_define_class_under(outer, name, oci8_cOCIHandle);
163
- VALUE obj = Data_Wrap_Struct(rb_cObject, 0, 0, vptr);
164
- rb_ivar_set(klass, oci8_id_oci8_vtable, obj);
170
+ VALUE parent_class = rb_eval_string(data_type->rb_data_type.parent->wrap_struct_name);
171
+ VALUE klass = rb_define_class_under(outer, name, parent_class);
172
+
173
+ rb_define_alloc_func(klass, alloc_func);
165
174
  return klass;
166
175
  }
167
176
 
168
- VALUE oci8_define_bind_class(const char *name, const oci8_bind_vtable_t *vptr)
177
+ VALUE oci8_define_bind_class(const char *name, const oci8_bind_data_type_t *data_type, VALUE (*alloc_func)(VALUE))
169
178
  {
170
- VALUE klass = rb_define_class_under(mOCI8BindType, name, cOCI8BindTypeBase);
171
- VALUE obj = Data_Wrap_Struct(rb_cObject, 0, 0, (void*)vptr);
172
- rb_ivar_set(klass, oci8_id_oci8_vtable, obj);
179
+ VALUE parent_class = rb_eval_string(data_type->base.rb_data_type.parent->wrap_struct_name);
180
+ VALUE klass = rb_define_class_under(mOCI8BindType, name, parent_class);
181
+
182
+ rb_define_alloc_func(klass, alloc_func);
173
183
  return klass;
174
184
  }
175
185
 
176
186
  void oci8_link_to_parent(oci8_base_t *base, oci8_base_t *parent)
177
187
  {
188
+ VALUE old_parent = Qundef;
189
+
178
190
  if (base->parent != NULL) {
191
+ old_parent = base->parent->self;
179
192
  oci8_unlink_from_parent(base);
180
193
  }
181
194
  if (parent->children == NULL) {
@@ -187,6 +200,8 @@ void oci8_link_to_parent(oci8_base_t *base, oci8_base_t *parent)
187
200
  parent->children->prev = base;
188
201
  }
189
202
  base->parent = parent;
203
+ RB_OBJ_WRITTEN(parent->self, Qundef, base->self);
204
+ RB_OBJ_WRITTEN(base->self, old_parent, parent->self);
190
205
  }
191
206
 
192
207
  void oci8_unlink_from_parent(oci8_base_t *base)
@@ -246,7 +261,7 @@ static VALUE protected_call(VALUE data)
246
261
  if (!NIL_P(parg->svcctx->executing_thread)) {
247
262
  rb_raise(rb_eRuntimeError, "executing in another thread");
248
263
  }
249
- parg->svcctx->executing_thread = rb_thread_current();
264
+ RB_OBJ_WRITE(parg->svcctx->base.self, &parg->svcctx->executing_thread, rb_thread_current());
250
265
  #ifdef HAVE_RB_THREAD_CALL_WITHOUT_GVL
251
266
  rv = (VALUE)rb_thread_call_without_gvl(parg->func, parg->data, oci8_unblock_func, parg->svcctx);
252
267
  #else
@@ -527,7 +542,7 @@ void *oci8_find_symbol(const char *symbol_name)
527
542
  };
528
543
  #define NUM_SONAMES (sizeof(sonames)/sizeof(sonames[0]))
529
544
  size_t idx;
530
- VALUE err = rb_ary_new();
545
+ volatile VALUE err = rb_ary_new();
531
546
 
532
547
  #ifdef _AIX
533
548
  #define DLOPEN_FLAG (RTLD_LAZY|RTLD_GLOBAL|RTLD_MEMBER)
@@ -543,10 +558,11 @@ void *oci8_find_symbol(const char *symbol_name)
543
558
  }
544
559
  if (handle == NULL) {
545
560
  VALUE msg;
561
+ const char *ary = RARRAY_CONST_PTR(err);
546
562
 
547
563
  msg = rb_str_buf_new(NUM_SONAMES * 50);
548
564
  for (idx = 0; idx < NUM_SONAMES; idx++) {
549
- const char *errmsg = RSTRING_PTR(RARRAY_PTR(err)[idx]);
565
+ const char *errmsg = RSTRING_PTR(arr[idx]);
550
566
  if (idx != 0) {
551
567
  rb_str_buf_cat2(msg, " ");
552
568
  }
@@ -557,7 +573,7 @@ void *oci8_find_symbol(const char *symbol_name)
557
573
  rb_str_buf_cat2(msg, sonames[idx]);
558
574
  rb_str_buf_cat2(msg, ": ");
559
575
  }
560
- rb_str_buf_append(msg, RARRAY_PTR(err)[idx]);
576
+ rb_str_buf_append(msg, arr[idx]);
561
577
  rb_str_buf_cat2(msg, ";");
562
578
  }
563
579
  rb_exc_raise(rb_exc_new3(rb_eLoadError, msg));
@@ -568,16 +584,31 @@ void *oci8_find_symbol(const char *symbol_name)
568
584
  }
569
585
  #endif /* RUNTIME_API_CHECK */
570
586
 
571
- oci8_base_t *oci8_get_handle(VALUE obj, VALUE klass)
587
+ void *oci8_check_typeddata(VALUE obj, const oci8_handle_data_type_t *data_type, int error_if_closed)
572
588
  {
589
+ #ifdef HAVE_RB_DATA_TYPE_T_FUNCTION
590
+ oci8_base_t *hp = Check_TypedStruct(obj, &data_type->rb_data_type);
591
+ #else
573
592
  oci8_base_t *hp;
593
+ const char *expected_type_name = data_type->rb_data_type.wrap_struct_name;
594
+ const rb_data_type_t *rb_data_type;
595
+ const rb_data_type_t *expected_rb_data_type = &data_type->rb_data_type;
574
596
 
575
- if (!rb_obj_is_kind_of(obj, klass)) {
576
- rb_raise(rb_eTypeError, "invalid argument %s (expect %s)",
577
- rb_obj_classname(obj), rb_class2name(klass));
597
+ if (TYPE(obj) != T_DATA || !rb_obj_is_kind_of(obj, oci8_cOCIHandle)) {
598
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected %s)",
599
+ rb_obj_classname(obj), expected_type_name);
578
600
  }
579
- Data_Get_Struct(obj, oci8_base_t, hp);
580
- if (hp->type == 0) {
601
+ hp = DATA_PTR(obj);
602
+ rb_data_type = &hp->data_type->rb_data_type;
603
+ while (rb_data_type != expected_rb_data_type) {
604
+ if (rb_data_type == NULL) {
605
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected %s)",
606
+ rb_obj_classname(obj), expected_type_name);
607
+ }
608
+ rb_data_type = rb_data_type->parent;
609
+ }
610
+ #endif
611
+ if (error_if_closed && hp->closed) {
581
612
  rb_raise(eOCIException, "%s was already closed.",
582
613
  rb_obj_classname(obj));
583
614
  }