ruby-oci8 2.0.6 → 2.1.0

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.
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);