ruby-oci8 2.1.7 → 2.1.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
  }