ruby-oci8 2.0.6 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. data/ChangeLog +366 -19
  2. data/Makefile +2 -8
  3. data/NEWS +111 -0
  4. data/README +4 -85
  5. data/VERSION +1 -1
  6. data/dist-files +9 -2
  7. data/ext/oci8/.document +1 -0
  8. data/ext/oci8/apiwrap.c.tmpl +12 -2
  9. data/ext/oci8/apiwrap.yml +37 -21
  10. data/ext/oci8/attr.c +23 -74
  11. data/ext/oci8/bind.c +93 -225
  12. data/ext/oci8/connection_pool.c +201 -0
  13. data/ext/oci8/encoding.c +117 -24
  14. data/ext/oci8/env.c +5 -10
  15. data/ext/oci8/error.c +171 -189
  16. data/ext/oci8/extconf.rb +6 -2
  17. data/ext/oci8/lob.c +81 -79
  18. data/ext/oci8/metadata.c +42 -177
  19. data/ext/oci8/object.c +55 -28
  20. data/ext/oci8/oci8.c +426 -294
  21. data/ext/oci8/oci8.h +84 -51
  22. data/ext/oci8/oci8lib.c +75 -53
  23. data/ext/oci8/ocidatetime.c +67 -88
  24. data/ext/oci8/ocihandle.c +78 -37
  25. data/ext/oci8/ocinumber.c +166 -109
  26. data/ext/oci8/oraconf.rb +68 -157
  27. data/ext/oci8/oradate.c +2 -7
  28. data/ext/oci8/stmt.c +40 -183
  29. data/ext/oci8/thread_util.c +85 -0
  30. data/ext/oci8/thread_util.h +30 -0
  31. data/lib/oci8.rb.in +19 -13
  32. data/lib/oci8/.document +2 -0
  33. data/lib/oci8/bindtype.rb +62 -45
  34. data/lib/oci8/connection_pool.rb +118 -0
  35. data/lib/oci8/datetime.rb +304 -320
  36. data/lib/oci8/encoding-init.rb +62 -30
  37. data/lib/oci8/encoding.yml +3 -3
  38. data/lib/oci8/metadata.rb +552 -497
  39. data/lib/oci8/object.rb +9 -9
  40. data/lib/oci8/oci8.rb +161 -2
  41. data/lib/oci8/ocihandle.rb +427 -0
  42. data/lib/oci8/properties.rb +31 -1
  43. data/ruby-oci8.gemspec +10 -3
  44. data/test/README +41 -3
  45. data/test/config.rb +16 -0
  46. data/test/test_all.rb +3 -0
  47. data/test/test_bind_string.rb +106 -0
  48. data/test/test_break.rb +33 -7
  49. data/test/test_clob.rb +13 -10
  50. data/test/test_connection_pool.rb +125 -0
  51. data/test/test_connstr.rb +2 -2
  52. data/test/test_datetime.rb +26 -66
  53. data/test/test_encoding.rb +7 -3
  54. data/test/test_error.rb +88 -0
  55. data/test/test_metadata.rb +1356 -204
  56. data/test/test_oci8.rb +27 -8
  57. data/test/test_oranumber.rb +41 -0
  58. metadata +34 -9
  59. data/ext/oci8/xmldb.c +0 -383
@@ -2,10 +2,7 @@
2
2
  /*
3
3
  * ocidatetime.c
4
4
  *
5
- * $Author: kubo $
6
- * $Date: 2011-06-14 20:45:16 +0900 (Tue, 14 Jun 2011) $
7
- *
8
- * Copyright (C) 2005-2008 KUBO Takehiro <kubo@jiubao.org>
5
+ * Copyright (C) 2005-2011 KUBO Takehiro <kubo@jiubao.org>
9
6
  *
10
7
  */
11
8
  #include "oci8.h"
@@ -68,40 +65,12 @@ OCIDate *oci8_set_ocidate(OCIDate *od, VALUE val)
68
65
  return od;
69
66
  }
70
67
 
71
- static VALUE bind_ocidate_get(oci8_bind_t *obind, void *data, void *null_struct)
72
- {
73
- return oci8_make_ocidate((OCIDate *)data);
74
- }
75
-
76
- static void bind_ocidate_set(oci8_bind_t *obind, void *data, void **null_structp, VALUE val)
77
- {
78
- oci8_set_ocidate((OCIDate *)data, val);
79
- }
80
-
81
- static void bind_ocidate_init(oci8_bind_t *obind, VALUE svc, VALUE val, VALUE length)
68
+ static void bind_init_common(oci8_bind_t *obind, VALUE svc, VALUE val, VALUE length)
82
69
  {
83
- obind->value_sz = sizeof(OCIDate);
84
- obind->alloc_sz = sizeof(OCIDate);
70
+ obind->value_sz = sizeof(void *);
71
+ obind->alloc_sz = sizeof(void *);
85
72
  }
86
73
 
87
- static const oci8_bind_class_t bind_ocidate_class = {
88
- {
89
- NULL,
90
- oci8_bind_free,
91
- sizeof(oci8_bind_t)
92
- },
93
- bind_ocidate_get,
94
- bind_ocidate_set,
95
- bind_ocidate_init,
96
- NULL,
97
- NULL,
98
- NULL,
99
- NULL,
100
- SQLT_ODT,
101
- };
102
-
103
- #if defined RUNTIME_API_CHECK || ORACLE_CLIENT_VERSION >= ORAVER_9_0
104
-
105
74
  static void bind_init_elem_common(oci8_bind_t *obind, VALUE svc, ub4 type)
106
75
  {
107
76
  ub4 idx = 0;
@@ -132,7 +101,7 @@ static void bind_free_common(oci8_base_t *base, ub4 type)
132
101
  oci8_bind_free(base);
133
102
  }
134
103
 
135
- VALUE oci8_make_ocitimestamp_tz(OCIDateTime *dttm)
104
+ VALUE oci8_make_ocitimestamp(OCIDateTime *dttm, boolean have_tz)
136
105
  {
137
106
  sb2 year;
138
107
  ub1 month;
@@ -144,9 +113,11 @@ VALUE oci8_make_ocitimestamp_tz(OCIDateTime *dttm)
144
113
  sb1 tz_hour;
145
114
  sb1 tz_minute;
146
115
 
147
- oci_lc(OCIDateTimeGetDate(oci8_envhp, oci8_errhp, dttm, &year, &month, &day));
148
- oci_lc(OCIDateTimeGetTime(oci8_envhp, oci8_errhp, dttm, &hour, &minute, &sec, &fsec));
149
- oci_lc(OCIDateTimeGetTimeZoneOffset(oci8_envhp, oci8_errhp, dttm, &tz_hour, &tz_minute));
116
+ chkerr(OCIDateTimeGetDate(oci8_envhp, oci8_errhp, dttm, &year, &month, &day));
117
+ chkerr(OCIDateTimeGetTime(oci8_envhp, oci8_errhp, dttm, &hour, &minute, &sec, &fsec));
118
+ if (have_tz) {
119
+ chkerr(OCIDateTimeGetTimeZoneOffset(oci8_envhp, oci8_errhp, dttm, &tz_hour, &tz_minute));
120
+ }
150
121
  return rb_ary_new3(9,
151
122
  INT2FIX(year),
152
123
  INT2FIX(month),
@@ -155,8 +126,8 @@ VALUE oci8_make_ocitimestamp_tz(OCIDateTime *dttm)
155
126
  INT2FIX(minute),
156
127
  INT2FIX(sec),
157
128
  INT2FIX(fsec),
158
- INT2FIX(tz_hour),
159
- INT2FIX(tz_minute));
129
+ have_tz ? INT2FIX(tz_hour) : Qnil,
130
+ have_tz ? INT2FIX(tz_minute) : Qnil);
160
131
  }
161
132
 
162
133
  OCIDateTime *oci8_set_ocitimestamp_tz(OCIDateTime *dttm, VALUE val, VALUE svc)
@@ -229,7 +200,7 @@ OCIDateTime *oci8_set_ocitimestamp_tz(OCIDateTime *dttm, VALUE val, VALUE svc)
229
200
  tzlen = strlen(tz_str);
230
201
  }
231
202
  /* construct */
232
- oci_lc(OCIDateTimeConstruct(seshp ? (void*)seshp : (void*)oci8_envhp, oci8_errhp, dttm,
203
+ chkerr(OCIDateTimeConstruct(seshp ? (void*)seshp : (void*)oci8_envhp, oci8_errhp, dttm,
233
204
  (sb2)year,
234
205
  (ub1)month,
235
206
  (ub1)day,
@@ -241,9 +212,43 @@ OCIDateTime *oci8_set_ocitimestamp_tz(OCIDateTime *dttm, VALUE val, VALUE svc)
241
212
  return dttm;
242
213
  }
243
214
 
215
+ static VALUE bind_ocitimestamp_get(oci8_bind_t *obind, void *data, void *null_struct)
216
+ {
217
+ return oci8_make_ocitimestamp(*(OCIDateTime **)data, FALSE);
218
+ }
219
+
220
+ static void bind_ocitimestamp_set(oci8_bind_t *obind, void *data, void **null_structp, VALUE val)
221
+ {
222
+ oci8_set_ocitimestamp_tz(*(OCIDateTime **)data, val, Qnil);
223
+ }
224
+
225
+ static void bind_ocitimestamp_init_elem(oci8_bind_t *obind, VALUE svc)
226
+ {
227
+ bind_init_elem_common(obind, svc, OCI_DTYPE_TIMESTAMP);
228
+ }
229
+
230
+ static void bind_ocitimestamp_free(oci8_base_t *base)
231
+ {
232
+ bind_free_common(base, OCI_DTYPE_TIMESTAMP);
233
+ }
234
+
235
+ static const oci8_bind_vtable_t bind_ocitimestamp_vtable = {
236
+ {
237
+ NULL,
238
+ bind_ocitimestamp_free,
239
+ sizeof(oci8_bind_t)
240
+ },
241
+ bind_ocitimestamp_get,
242
+ bind_ocitimestamp_set,
243
+ bind_init_common,
244
+ bind_ocitimestamp_init_elem,
245
+ NULL,
246
+ SQLT_TIMESTAMP
247
+ };
248
+
244
249
  static VALUE bind_ocitimestamp_tz_get(oci8_bind_t *obind, void *data, void *null_struct)
245
250
  {
246
- return oci8_make_ocitimestamp_tz(*(OCIDateTime **)data);
251
+ return oci8_make_ocitimestamp(*(OCIDateTime **)data, TRUE);
247
252
  }
248
253
 
249
254
  static void bind_ocitimestamp_tz_set(oci8_bind_t *obind, void *data, void **null_structp, VALUE val)
@@ -260,8 +265,8 @@ static void bind_ocitimestamp_tz_set(oci8_bind_t *obind, void *data, void **null
260
265
  if (svcctx == NULL || svcctx->type != OCI_HTYPE_SVCCTX) {
261
266
  rb_raise(rb_eRuntimeError, "oci8lib.so internal error [%s:%d, %p, %d, %p, %d]",
262
267
  __FILE__, __LINE__,
263
- parent, parent ? parent->type : -1,
264
- svcctx, svcctx ? svcctx->type : -1);
268
+ parent, parent ? (int)parent->type : -1,
269
+ svcctx, svcctx ? (int)svcctx->type : -1);
265
270
  }
266
271
  oci8_set_ocitimestamp_tz(*(OCIDateTime **)data, val, svcctx->self);
267
272
  }
@@ -283,7 +288,7 @@ static void bind_ocitimestamp_tz_free(oci8_base_t *base)
283
288
  bind_free_common(base, OCI_DTYPE_TIMESTAMP_TZ);
284
289
  }
285
290
 
286
- static const oci8_bind_class_t bind_ocitimestamp_tz_class = {
291
+ static const oci8_bind_vtable_t bind_ocitimestamp_tz_vtable = {
287
292
  {
288
293
  NULL,
289
294
  bind_ocitimestamp_tz_free,
@@ -294,8 +299,6 @@ static const oci8_bind_class_t bind_ocitimestamp_tz_class = {
294
299
  bind_ocitimestamp_tz_init,
295
300
  bind_ocitimestamp_tz_init_elem,
296
301
  NULL,
297
- NULL,
298
- NULL,
299
302
  SQLT_TIMESTAMP_TZ
300
303
  };
301
304
 
@@ -304,7 +307,7 @@ VALUE oci8_make_ociinterval_ym(OCIInterval *s)
304
307
  sb4 year;
305
308
  sb4 month;
306
309
 
307
- oci_lc(OCIIntervalGetYearMonth(oci8_envhp, oci8_errhp, &year, &month, s));
310
+ chkerr(OCIIntervalGetYearMonth(oci8_envhp, oci8_errhp, &year, &month, s));
308
311
  return rb_ary_new3(2, INT2FIX(year), INT2FIX(month));
309
312
  }
310
313
 
@@ -320,12 +323,12 @@ OCIInterval *oci8_set_ociinterval_ym(OCIInterval *intvl, VALUE val)
320
323
  year = NUM2INT(RARRAY_PTR(val)[0]);
321
324
  month = NUM2INT(RARRAY_PTR(val)[1]);
322
325
  if (oracle_client_version >= ORAVERNUM(9, 2, 0, 3, 0)) {
323
- oci_lc(OCIIntervalSetYearMonth(oci8_envhp, oci8_errhp,
326
+ chkerr(OCIIntervalSetYearMonth(oci8_envhp, oci8_errhp,
324
327
  year, month, intvl));
325
328
  } else {
326
329
  /* Workaround for Bug 2227982 */
327
330
  char buf[64];
328
- char *sign = "";
331
+ const char *sign = "";
329
332
 
330
333
  if (year < 0 && month != 0) {
331
334
  year += 1;
@@ -337,7 +340,7 @@ OCIInterval *oci8_set_ociinterval_ym(OCIInterval *intvl, VALUE val)
337
340
  month = -month;
338
341
  }
339
342
  sprintf(buf, "%s%d-%d", sign, year, month);
340
- oci_lc(OCIIntervalFromText(oci8_envhp, oci8_errhp, (text*)buf, strlen(buf), intvl));
343
+ chkerr(OCIIntervalFromText(oci8_envhp, oci8_errhp, (text*)buf, strlen(buf), intvl));
341
344
  }
342
345
  return intvl;
343
346
  }
@@ -350,7 +353,7 @@ VALUE oci8_make_ociinterval_ds(OCIInterval *s)
350
353
  sb4 sec;
351
354
  sb4 fsec;
352
355
 
353
- oci_lc(OCIIntervalGetDaySecond(oci8_envhp, oci8_errhp, &day, &hour, &minute, &sec, &fsec, s));
356
+ chkerr(OCIIntervalGetDaySecond(oci8_envhp, oci8_errhp, &day, &hour, &minute, &sec, &fsec, s));
354
357
  return rb_ary_new3(5,
355
358
  INT2FIX(day), INT2FIX(hour),
356
359
  INT2FIX(minute), INT2FIX(sec),
@@ -375,12 +378,12 @@ OCIInterval *oci8_set_ociinterval_ds(OCIInterval *intvl, VALUE val)
375
378
  sec = NUM2INT(RARRAY_PTR(val)[3]);
376
379
  fsec = NUM2INT(RARRAY_PTR(val)[4]);
377
380
  if (oracle_client_version >= ORAVERNUM(9, 2, 0, 3, 0)) {
378
- oci_lc(OCIIntervalSetDaySecond(oci8_envhp, oci8_errhp,
381
+ chkerr(OCIIntervalSetDaySecond(oci8_envhp, oci8_errhp,
379
382
  day, hour, minute, sec, fsec, intvl));
380
383
  } else {
381
384
  /* Workaround for Bug 2227982 */
382
385
  char buf[64];
383
- char *sign = "";
386
+ const char *sign = "";
384
387
 
385
388
  if (day == 0) {
386
389
  if (hour < 0) {
@@ -398,7 +401,7 @@ OCIInterval *oci8_set_ociinterval_ds(OCIInterval *intvl, VALUE val)
398
401
  }
399
402
  }
400
403
  sprintf(buf, "%s%d %02d:%02d:%02d.%09d", sign, day, hour, minute, sec, fsec);
401
- oci_lc(OCIIntervalFromText(oci8_envhp, oci8_errhp, (text*)buf, strlen(buf), intvl));
404
+ chkerr(OCIIntervalFromText(oci8_envhp, oci8_errhp, (text*)buf, strlen(buf), intvl));
402
405
  }
403
406
  return intvl;
404
407
  }
@@ -414,12 +417,6 @@ static void bind_ociinterval_ym_set(oci8_bind_t *obind, void *data, void **null_
414
417
  oci8_set_ociinterval_ym(*(OCIInterval **)data, val);
415
418
  }
416
419
 
417
- static void bind_ociinterval_ym_init(oci8_bind_t *obind, VALUE svc, VALUE val, VALUE length)
418
- {
419
- obind->value_sz = sizeof(OCIInterval*);
420
- obind->alloc_sz = sizeof(OCIInterval*);
421
- }
422
-
423
420
  static void bind_ociinterval_ym_init_elem(oci8_bind_t *obind, VALUE svc)
424
421
  {
425
422
  bind_init_elem_common(obind, svc, OCI_DTYPE_INTERVAL_YM);
@@ -440,12 +437,6 @@ static void bind_ociinterval_ds_set(oci8_bind_t *obind, void *data, void **null_
440
437
  oci8_set_ociinterval_ds(*(OCIInterval **)data, val);
441
438
  }
442
439
 
443
- static void bind_ociinterval_ds_init(oci8_bind_t *obind, VALUE svc, VALUE val, VALUE length)
444
- {
445
- obind->value_sz = sizeof(OCIInterval *);
446
- obind->alloc_sz = sizeof(OCIInterval *);
447
- }
448
-
449
440
  static void bind_ociinterval_ds_init_elem(oci8_bind_t *obind, VALUE svc)
450
441
  {
451
442
  bind_init_elem_common(obind, svc, OCI_DTYPE_INTERVAL_DS);
@@ -456,7 +447,7 @@ static void bind_ociinterval_ds_free(oci8_base_t *base)
456
447
  bind_free_common(base, OCI_DTYPE_INTERVAL_DS);
457
448
  }
458
449
 
459
- static const oci8_bind_class_t bind_ociinterval_ym_class = {
450
+ static const oci8_bind_vtable_t bind_ociinterval_ym_vtable = {
460
451
  {
461
452
  NULL,
462
453
  bind_ociinterval_ym_free,
@@ -464,15 +455,13 @@ static const oci8_bind_class_t bind_ociinterval_ym_class = {
464
455
  },
465
456
  bind_ociinterval_ym_get,
466
457
  bind_ociinterval_ym_set,
467
- bind_ociinterval_ym_init,
458
+ bind_init_common,
468
459
  bind_ociinterval_ym_init_elem,
469
460
  NULL,
470
- NULL,
471
- NULL,
472
461
  SQLT_INTERVAL_YM
473
462
  };
474
463
 
475
- static const oci8_bind_class_t bind_ociinterval_ds_class = {
464
+ static const oci8_bind_vtable_t bind_ociinterval_ds_vtable = {
476
465
  {
477
466
  NULL,
478
467
  bind_ociinterval_ds_free,
@@ -480,26 +469,16 @@ static const oci8_bind_class_t bind_ociinterval_ds_class = {
480
469
  },
481
470
  bind_ociinterval_ds_get,
482
471
  bind_ociinterval_ds_set,
483
- bind_ociinterval_ds_init,
472
+ bind_init_common,
484
473
  bind_ociinterval_ds_init_elem,
485
474
  NULL,
486
- NULL,
487
- NULL,
488
475
  SQLT_INTERVAL_DS
489
476
  };
490
477
 
491
- #endif /* defined RUNTIME_API_CHECK || ORACLE_CLIENT_VERSION >= ORAVER_9_0 */
492
-
493
478
  void Init_oci_datetime(void)
494
479
  {
495
- oci8_define_bind_class("OCIDate", &bind_ocidate_class);
496
-
497
- #if defined RUNTIME_API_CHECK || ORACLE_CLIENT_VERSION >= ORAVER_9_0
498
- if (oracle_client_version >= ORAVER_9_0) {
499
- oci8_define_bind_class("OCITimestampTZ", &bind_ocitimestamp_tz_class);
500
- oci8_define_bind_class("OCIIntervalYM", &bind_ociinterval_ym_class);
501
- oci8_define_bind_class("OCIIntervalDS", &bind_ociinterval_ds_class);
502
- }
503
- #endif
504
-
480
+ oci8_define_bind_class("OCITimestamp", &bind_ocitimestamp_vtable);
481
+ oci8_define_bind_class("OCITimestampTZ", &bind_ocitimestamp_tz_vtable);
482
+ oci8_define_bind_class("OCIIntervalYM", &bind_ociinterval_ym_vtable);
483
+ oci8_define_bind_class("OCIIntervalDS", &bind_ociinterval_ds_vtable);
505
484
  }
@@ -2,7 +2,7 @@
2
2
  /*
3
3
  * ocihandle.c
4
4
  *
5
- * Copyright (C) 2009 KUBO Takehiro <kubo@jiubao.org>
5
+ * Copyright (C) 2009-2010 KUBO Takehiro <kubo@jiubao.org>
6
6
  *
7
7
  * implement OCIHandle
8
8
  *
@@ -26,7 +26,7 @@ static long check_data_range(VALUE val, long min, long max, const char *type)
26
26
  }
27
27
 
28
28
 
29
- static oci8_base_class_t oci8_base_class = {
29
+ static oci8_base_vtable_t oci8_base_vtable = {
30
30
  NULL,
31
31
  NULL,
32
32
  sizeof(oci8_base_t),
@@ -55,8 +55,8 @@ static VALUE oci8_handle_free(VALUE self)
55
55
 
56
56
  static void oci8_handle_mark(oci8_base_t *base)
57
57
  {
58
- if (base->klass->mark != NULL)
59
- base->klass->mark(base);
58
+ if (base->vptr->mark != NULL)
59
+ base->vptr->mark(base);
60
60
  }
61
61
 
62
62
  static void oci8_handle_cleanup(oci8_base_t *base)
@@ -76,29 +76,32 @@ static void oci8_handle_cleanup(oci8_base_t *base)
76
76
  static VALUE oci8_s_allocate(VALUE klass)
77
77
  {
78
78
  oci8_base_t *base;
79
- const oci8_base_class_t *base_class;
79
+ const oci8_base_vtable_t *vptr;
80
80
  VALUE superklass;
81
81
  VALUE obj;
82
82
 
83
83
  superklass = klass;
84
- while (!RTEST(rb_ivar_defined(superklass, oci8_id_oci8_class))) {
84
+ while (!RTEST(rb_ivar_defined(superklass, oci8_id_oci8_vtable))) {
85
85
  superklass = rb_class_superclass(superklass);
86
86
  if (superklass == rb_cObject)
87
87
  rb_raise(rb_eRuntimeError, "private method `new' called for %s:Class", rb_class2name(klass));
88
88
  }
89
- obj = rb_ivar_get(superklass, oci8_id_oci8_class);
90
- base_class = DATA_PTR(obj);
89
+ obj = rb_ivar_get(superklass, oci8_id_oci8_vtable);
90
+ vptr = DATA_PTR(obj);
91
91
 
92
- base = xmalloc(base_class->size);
93
- memset(base, 0, base_class->size);
92
+ base = xmalloc(vptr->size);
93
+ memset(base, 0, vptr->size);
94
94
 
95
95
  obj = Data_Wrap_Struct(klass, oci8_handle_mark, oci8_handle_cleanup, base);
96
96
  base->self = obj;
97
- base->klass = base_class;
97
+ base->vptr = vptr;
98
98
  base->parent = NULL;
99
99
  base->next = base;
100
100
  base->prev = base;
101
101
  base->children = NULL;
102
+ if (vptr->init != NULL) {
103
+ vptr->init(base);
104
+ }
102
105
  return obj;
103
106
  }
104
107
 
@@ -120,7 +123,7 @@ static VALUE attr_get_ub1(VALUE self, VALUE attr_type)
120
123
 
121
124
  v.dummy = MAGIC_NUMBER;
122
125
  Check_Type(attr_type, T_FIXNUM);
123
- oci_lc(OCIAttrGet(base->hp.ptr, base->type, &v.value, NULL, FIX2INT(attr_type), oci8_errhp));
126
+ chker2(OCIAttrGet(base->hp.ptr, base->type, &v.value, NULL, FIX2INT(attr_type), oci8_errhp), base);
124
127
  return INT2FIX(v.value);
125
128
  }
126
129
 
@@ -142,7 +145,7 @@ static VALUE attr_get_ub2(VALUE self, VALUE attr_type)
142
145
 
143
146
  v.dummy = MAGIC_NUMBER;
144
147
  Check_Type(attr_type, T_FIXNUM);
145
- oci_lc(OCIAttrGet(base->hp.ptr, base->type, &v.value, NULL, FIX2INT(attr_type), oci8_errhp));
148
+ chker2(OCIAttrGet(base->hp.ptr, base->type, &v.value, NULL, FIX2INT(attr_type), oci8_errhp), base);
146
149
  return INT2FIX(v.value);
147
150
  }
148
151
 
@@ -164,7 +167,7 @@ static VALUE attr_get_ub4(VALUE self, VALUE attr_type)
164
167
 
165
168
  v.dummy = MAGIC_NUMBER;
166
169
  Check_Type(attr_type, T_FIXNUM);
167
- oci_lc(OCIAttrGet(base->hp.ptr, base->type, &v.value, NULL, FIX2INT(attr_type), oci8_errhp));
170
+ chker2(OCIAttrGet(base->hp.ptr, base->type, &v.value, NULL, FIX2INT(attr_type), oci8_errhp), base);
168
171
  return UINT2NUM(v.value);
169
172
  }
170
173
 
@@ -186,7 +189,7 @@ static VALUE attr_get_ub8(VALUE self, VALUE attr_type)
186
189
 
187
190
  v.dummy = MAGIC_NUMBER;
188
191
  Check_Type(attr_type, T_FIXNUM);
189
- oci_lc(OCIAttrGet(base->hp.ptr, base->type, &v.value, NULL, FIX2INT(attr_type), oci8_errhp));
192
+ chker2(OCIAttrGet(base->hp.ptr, base->type, &v.value, NULL, FIX2INT(attr_type), oci8_errhp), base);
190
193
  return ULL2NUM(v.value);
191
194
  }
192
195
 
@@ -208,7 +211,7 @@ static VALUE attr_get_sb1(VALUE self, VALUE attr_type)
208
211
 
209
212
  v.dummy = MAGIC_NUMBER;
210
213
  Check_Type(attr_type, T_FIXNUM);
211
- oci_lc(OCIAttrGet(base->hp.ptr, base->type, &v.value, NULL, FIX2INT(attr_type), oci8_errhp));
214
+ chker2(OCIAttrGet(base->hp.ptr, base->type, &v.value, NULL, FIX2INT(attr_type), oci8_errhp), base);
212
215
  return INT2FIX(v.value);
213
216
  }
214
217
 
@@ -230,7 +233,7 @@ static VALUE attr_get_sb2(VALUE self, VALUE attr_type)
230
233
 
231
234
  v.dummy = MAGIC_NUMBER;
232
235
  Check_Type(attr_type, T_FIXNUM);
233
- oci_lc(OCIAttrGet(base->hp.ptr, base->type, &v.value, NULL, FIX2INT(attr_type), oci8_errhp));
236
+ chker2(OCIAttrGet(base->hp.ptr, base->type, &v.value, NULL, FIX2INT(attr_type), oci8_errhp), base);
234
237
  return INT2FIX(v.value);
235
238
  }
236
239
 
@@ -252,7 +255,7 @@ static VALUE attr_get_sb4(VALUE self, VALUE attr_type)
252
255
 
253
256
  v.dummy = MAGIC_NUMBER;
254
257
  Check_Type(attr_type, T_FIXNUM);
255
- oci_lc(OCIAttrGet(base->hp.ptr, base->type, &v.value, NULL, FIX2INT(attr_type), oci8_errhp));
258
+ chker2(OCIAttrGet(base->hp.ptr, base->type, &v.value, NULL, FIX2INT(attr_type), oci8_errhp), base);
256
259
  return INT2NUM(v.value);
257
260
  }
258
261
 
@@ -274,7 +277,7 @@ static VALUE attr_get_sb8(VALUE self, VALUE attr_type)
274
277
 
275
278
  v.dummy = MAGIC_NUMBER;
276
279
  Check_Type(attr_type, T_FIXNUM);
277
- oci_lc(OCIAttrGet(base->hp.ptr, base->type, &v.value, NULL, FIX2INT(attr_type), oci8_errhp));
280
+ chker2(OCIAttrGet(base->hp.ptr, base->type, &v.value, NULL, FIX2INT(attr_type), oci8_errhp), base);
278
281
  return LL2NUM(v.value);
279
282
  }
280
283
 
@@ -296,7 +299,7 @@ static VALUE attr_get_boolean(VALUE self, VALUE attr_type)
296
299
 
297
300
  v.dummy = MAGIC_NUMBER;
298
301
  Check_Type(attr_type, T_FIXNUM);
299
- oci_lc(OCIAttrGet(base->hp.ptr, base->type, &v.value, NULL, FIX2INT(attr_type), oci8_errhp));
302
+ chker2(OCIAttrGet(base->hp.ptr, base->type, &v.value, NULL, FIX2INT(attr_type), oci8_errhp), base);
300
303
  return v.value ? Qtrue : Qfalse;
301
304
  }
302
305
 
@@ -324,7 +327,7 @@ static VALUE attr_get_string(VALUE self, VALUE attr_type)
324
327
 
325
328
  v.dummy = MAGIC_NUMBER;
326
329
  Check_Type(attr_type, T_FIXNUM);
327
- oci_lc(OCIAttrGet(base->hp.ptr, base->type, &v.value, &size, FIX2INT(attr_type), oci8_errhp));
330
+ chker2(OCIAttrGet(base->hp.ptr, base->type, &v.value, &size, FIX2INT(attr_type), oci8_errhp), base);
328
331
  return rb_external_str_new_with_enc(v.value, size, oci8_encoding);
329
332
  }
330
333
 
@@ -351,7 +354,7 @@ static VALUE attr_get_binary(VALUE self, VALUE attr_type)
351
354
 
352
355
  v.dummy = 0;
353
356
  Check_Type(attr_type, T_FIXNUM);
354
- oci_lc(OCIAttrGet(base->hp.ptr, base->type, &v.value, &size, FIX2INT(attr_type), oci8_errhp));
357
+ chker2(OCIAttrGet(base->hp.ptr, base->type, &v.value, &size, FIX2INT(attr_type), oci8_errhp), base);
355
358
  return rb_tainted_str_new(v.value, size);
356
359
  }
357
360
 
@@ -378,10 +381,46 @@ static VALUE attr_get_integer(VALUE self, VALUE attr_type)
378
381
 
379
382
  v.dummy = 0;
380
383
  Check_Type(attr_type, T_FIXNUM);
381
- oci_lc(OCIAttrGet(base->hp.ptr, base->type, &v.value, &size, FIX2INT(attr_type), oci8_errhp));
384
+ chker2(OCIAttrGet(base->hp.ptr, base->type, &v.value, &size, FIX2INT(attr_type), oci8_errhp), base);
382
385
  return oci8_make_integer(v.value, oci8_errhp);
383
386
  }
384
387
 
388
+ /*
389
+ * call-seq:
390
+ * attr_get_oradate(attr_type) -> an OraDate
391
+ *
392
+ * <b>(new in 2.1.0)</b>
393
+ *
394
+ * Gets the value of an attribute as `ub1 *' datatype.
395
+ * The return value is converted to OraDate.
396
+ *
397
+ * <b>Caution:</b> If the specified attr_type's datatype is not a
398
+ * pointer type, it causes a segmentation fault.
399
+ */
400
+ static VALUE attr_get_oradate(VALUE self, VALUE attr_type)
401
+ {
402
+ oci8_base_t *base = DATA_PTR(self);
403
+ union {
404
+ ub1 *value;
405
+ ub8 dummy; /* padding for incorrect attrtype to protect the stack */
406
+ } v;
407
+ ub4 size = 0;
408
+ static VALUE cOraDate = Qnil;
409
+
410
+ v.dummy = 0;
411
+ Check_Type(attr_type, T_FIXNUM);
412
+ chker2(OCIAttrGet(base->hp.ptr, base->type, &v.value, &size, FIX2INT(attr_type), oci8_errhp), base);
413
+ if (NIL_P(cOraDate))
414
+ cOraDate = rb_eval_string("OraDate");
415
+ return rb_funcall(cOraDate, oci8_id_new, 6,
416
+ INT2FIX((v.value[0] - 100) * 100 + (v.value[1] - 100)),
417
+ INT2FIX(v.value[2]),
418
+ INT2FIX(v.value[3]),
419
+ INT2FIX(v.value[4] - 1),
420
+ INT2FIX(v.value[5] - 1),
421
+ INT2FIX(v.value[6] - 1));
422
+ }
423
+
385
424
  /*
386
425
  * call-seq:
387
426
  * attr_set_ub1(attr_type, attr_value)
@@ -402,7 +441,7 @@ static VALUE attr_set_ub1(VALUE self, VALUE attr_type, VALUE val)
402
441
  Check_Type(attr_type, T_FIXNUM);
403
442
  value = (ub1)check_data_range(val, 0, UCHAR_MAX, "ub1");
404
443
  /* set attribute */
405
- oci_lc(OCIAttrSet(base->hp.ptr, base->type, &value, sizeof(value), FIX2INT(attr_type), oci8_errhp));
444
+ chker2(OCIAttrSet(base->hp.ptr, base->type, &value, sizeof(value), FIX2INT(attr_type), oci8_errhp), base);
406
445
  return self;
407
446
  }
408
447
 
@@ -426,7 +465,7 @@ static VALUE attr_set_ub2(VALUE self, VALUE attr_type, VALUE val)
426
465
  Check_Type(attr_type, T_FIXNUM);
427
466
  value = (ub2)check_data_range(val, 0, USHRT_MAX, "ub2");
428
467
  /* set attribute */
429
- oci_lc(OCIAttrSet(base->hp.ptr, base->type, &value, sizeof(value), FIX2INT(attr_type), oci8_errhp));
468
+ chker2(OCIAttrSet(base->hp.ptr, base->type, &value, sizeof(value), FIX2INT(attr_type), oci8_errhp), base);
430
469
  return self;
431
470
  }
432
471
 
@@ -450,7 +489,7 @@ static VALUE attr_set_ub4(VALUE self, VALUE attr_type, VALUE val)
450
489
  Check_Type(attr_type, T_FIXNUM);
451
490
  value = NUM2UINT(val);
452
491
  /* set attribute */
453
- oci_lc(OCIAttrSet(base->hp.ptr, base->type, &value, sizeof(value), FIX2INT(attr_type), oci8_errhp));
492
+ chker2(OCIAttrSet(base->hp.ptr, base->type, &value, sizeof(value), FIX2INT(attr_type), oci8_errhp), base);
454
493
  return self;
455
494
  }
456
495
 
@@ -474,7 +513,7 @@ static VALUE attr_set_ub8(VALUE self, VALUE attr_type, VALUE val)
474
513
  Check_Type(attr_type, T_FIXNUM);
475
514
  value = NUM2ULL(val);
476
515
  /* set attribute */
477
- oci_lc(OCIAttrSet(base->hp.ptr, base->type, &value, sizeof(value), FIX2INT(attr_type), oci8_errhp));
516
+ chker2(OCIAttrSet(base->hp.ptr, base->type, &value, sizeof(value), FIX2INT(attr_type), oci8_errhp), base);
478
517
  return self;
479
518
  }
480
519
 
@@ -498,7 +537,7 @@ static VALUE attr_set_sb1(VALUE self, VALUE attr_type, VALUE val)
498
537
  Check_Type(attr_type, T_FIXNUM);
499
538
  value = (sb1)check_data_range(val, CHAR_MIN, CHAR_MAX, "sb1");
500
539
  /* set attribute */
501
- oci_lc(OCIAttrSet(base->hp.ptr, base->type, &value, sizeof(value), FIX2INT(attr_type), oci8_errhp));
540
+ chker2(OCIAttrSet(base->hp.ptr, base->type, &value, sizeof(value), FIX2INT(attr_type), oci8_errhp), base);
502
541
  return self;
503
542
  }
504
543
 
@@ -522,7 +561,7 @@ static VALUE attr_set_sb2(VALUE self, VALUE attr_type, VALUE val)
522
561
  Check_Type(attr_type, T_FIXNUM);
523
562
  value = (sb2)check_data_range(val, SHRT_MIN, SHRT_MAX, "sb2");
524
563
  /* set attribute */
525
- oci_lc(OCIAttrSet(base->hp.ptr, base->type, &value, sizeof(value), FIX2INT(attr_type), oci8_errhp));
564
+ chker2(OCIAttrSet(base->hp.ptr, base->type, &value, sizeof(value), FIX2INT(attr_type), oci8_errhp), base);
526
565
  return self;
527
566
  }
528
567
 
@@ -546,7 +585,7 @@ static VALUE attr_set_sb4(VALUE self, VALUE attr_type, VALUE val)
546
585
  Check_Type(attr_type, T_FIXNUM);
547
586
  value = NUM2INT(val);
548
587
  /* set attribute */
549
- oci_lc(OCIAttrSet(base->hp.ptr, base->type, &value, sizeof(value), FIX2INT(attr_type), oci8_errhp));
588
+ chker2(OCIAttrSet(base->hp.ptr, base->type, &value, sizeof(value), FIX2INT(attr_type), oci8_errhp), base);
550
589
  return self;
551
590
  }
552
591
 
@@ -570,7 +609,7 @@ static VALUE attr_set_sb8(VALUE self, VALUE attr_type, VALUE val)
570
609
  Check_Type(attr_type, T_FIXNUM);
571
610
  value = NUM2LL(val);
572
611
  /* set attribute */
573
- oci_lc(OCIAttrSet(base->hp.ptr, base->type, &value, sizeof(value), FIX2INT(attr_type), oci8_errhp));
612
+ chker2(OCIAttrSet(base->hp.ptr, base->type, &value, sizeof(value), FIX2INT(attr_type), oci8_errhp), base);
574
613
  return self;
575
614
  }
576
615
 
@@ -594,7 +633,7 @@ static VALUE attr_set_boolean(VALUE self, VALUE attr_type, VALUE val)
594
633
  Check_Type(attr_type, T_FIXNUM);
595
634
  value = RTEST(val) ? TRUE : FALSE;
596
635
  /* set attribute */
597
- oci_lc(OCIAttrSet(base->hp.ptr, base->type, &value, sizeof(value), FIX2INT(attr_type), oci8_errhp));
636
+ chker2(OCIAttrSet(base->hp.ptr, base->type, &value, sizeof(value), FIX2INT(attr_type), oci8_errhp), base);
598
637
  return self;
599
638
  }
600
639
 
@@ -616,7 +655,7 @@ static VALUE attr_set_string(VALUE self, VALUE attr_type, VALUE val)
616
655
  Check_Type(attr_type, T_FIXNUM);
617
656
  OCI8SafeStringValue(val);
618
657
  /* set attribute */
619
- oci_lc(OCIAttrSet(base->hp.ptr, base->type, RSTRING_PTR(val), RSTRING_LEN(val), FIX2INT(attr_type), oci8_errhp));
658
+ chker2(OCIAttrSet(base->hp.ptr, base->type, RSTRING_PTR(val), RSTRING_LEN(val), FIX2INT(attr_type), oci8_errhp), base);
620
659
  return self;
621
660
  }
622
661
 
@@ -636,7 +675,7 @@ static VALUE attr_set_binary(VALUE self, VALUE attr_type, VALUE val)
636
675
  Check_Type(attr_type, T_FIXNUM);
637
676
  SafeStringValue(val);
638
677
  /* set attribute */
639
- oci_lc(OCIAttrSet(base->hp.ptr, base->type, RSTRING_PTR(val), RSTRING_LEN(val), FIX2INT(attr_type), oci8_errhp));
678
+ chker2(OCIAttrSet(base->hp.ptr, base->type, RSTRING_PTR(val), RSTRING_LEN(val), FIX2INT(attr_type), oci8_errhp), base);
640
679
  return self;
641
680
  }
642
681
 
@@ -659,7 +698,7 @@ static VALUE attr_set_integer(VALUE self, VALUE attr_type, VALUE val)
659
698
  Check_Type(attr_type, T_FIXNUM);
660
699
  oci8_set_integer(&value, val, oci8_errhp);
661
700
  /* set attribute */
662
- oci_lc(OCIAttrSet(base->hp.ptr, base->type, &value, sizeof(value), FIX2INT(attr_type), oci8_errhp));
701
+ chker2(OCIAttrSet(base->hp.ptr, base->type, &value, sizeof(value), FIX2INT(attr_type), oci8_errhp), base);
663
702
  return self;
664
703
  }
665
704
 
@@ -672,13 +711,14 @@ void Init_oci8_handle(void)
672
711
  *
673
712
  * OCIHandle is the abstract base class of OCI handles and
674
713
  * OCI descriptors; opaque data types of Oracle Call Interface.
714
+ * Don't use constants and methods defined in the class.
675
715
  */
676
716
  oci8_cOCIHandle = rb_define_class("OCIHandle", rb_cObject);
677
717
  rb_define_alloc_func(oci8_cOCIHandle, oci8_s_allocate);
678
718
  rb_define_method_nodoc(oci8_cOCIHandle, "initialize", oci8_handle_initialize, 0);
679
719
  rb_define_private_method(oci8_cOCIHandle, "free", oci8_handle_free, 0);
680
- obj = Data_Wrap_Struct(rb_cObject, 0, 0, &oci8_base_class);
681
- rb_ivar_set(oci8_cOCIHandle, oci8_id_oci8_class, obj);
720
+ obj = Data_Wrap_Struct(rb_cObject, 0, 0, &oci8_base_vtable);
721
+ rb_ivar_set(oci8_cOCIHandle, oci8_id_oci8_vtable, obj);
682
722
 
683
723
  /* methods to get attributes */
684
724
  rb_define_private_method(oci8_cOCIHandle, "attr_get_ub1", attr_get_ub1, 1);
@@ -693,6 +733,7 @@ void Init_oci8_handle(void)
693
733
  rb_define_private_method(oci8_cOCIHandle, "attr_get_string", attr_get_string, 1);
694
734
  rb_define_private_method(oci8_cOCIHandle, "attr_get_binary", attr_get_binary, 1);
695
735
  rb_define_private_method(oci8_cOCIHandle, "attr_get_integer", attr_get_integer, 1);
736
+ rb_define_private_method(oci8_cOCIHandle, "attr_get_oradate", attr_get_oradate, 1);
696
737
 
697
738
  /* methods to set attributes */
698
739
  rb_define_private_method(oci8_cOCIHandle, "attr_set_ub1", attr_set_ub1, 2);