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
@@ -69,7 +69,9 @@ have_type('OCIInterval*', 'ociap.h')
69
69
  have_type('OCICallbackLobRead2', 'ociap.h')
70
70
  have_type('OCICallbackLobWrite2', 'ociap.h')
71
71
  have_type('OCIAdmin*', 'ociap.h')
72
+ have_type('OCIAuthInfo*', 'ociap.h')
72
73
  have_type('OCIMsg*', 'ociap.h')
74
+ have_type('OCICPool*', 'ociap.h')
73
75
 
74
76
  if with_config('oracle-version')
75
77
  oci_client_version = OCI8::OracleVersion.new(with_config('oracle-version')).to_i
@@ -84,10 +86,11 @@ if with_config('runtime-check')
84
86
  end
85
87
 
86
88
  $objs = ["oci8lib.o", "env.o", "error.o", "oci8.o", "ocihandle.o",
89
+ "connection_pool.o",
87
90
  "stmt.o", "bind.o", "metadata.o", "attr.o",
88
91
  "lob.o", "oradate.o",
89
92
  "ocinumber.o", "ocidatetime.o", "object.o", "apiwrap.o",
90
- "encoding.o", "xmldb.o", "oranumber_util.o"]
93
+ "encoding.o", "oranumber_util.o", "thread_util.o"]
91
94
 
92
95
  if RUBY_PLATFORM =~ /mswin32|cygwin|mingw32|bccwin32/
93
96
  $defs << "-DUSE_WIN32_C"
@@ -112,7 +115,7 @@ have_type('rb_encoding', ['ruby/ruby.h', 'ruby/encoding.h'])
112
115
  have_var("ruby_errinfo", "ruby.h") # ruby 1.8
113
116
  have_func("rb_errinfo", "ruby.h") # ruby 1.9
114
117
 
115
- have_type("rb_blocking_function_t", "ruby.h")
118
+ have_type("rb_blocking_function_t*", "ruby.h")
116
119
  have_func("rb_set_end_proc", "ruby.h")
117
120
  have_func("rb_class_superclass", "ruby.h")
118
121
  have_func("rb_thread_blocking_region", "ruby.h")
@@ -139,6 +142,7 @@ so_basename += Config::CONFIG["ruby_version"].gsub(/\W/, '')
139
142
 
140
143
  $defs << "-DInit_oci8lib=Init_#{so_basename}"
141
144
  $defs << "-Doci8lib=#{so_basename}"
145
+ $defs << "-DOCI8LIB_VERSION=\\\"#{RUBY_OCI8_VERSION}\\\""
142
146
  if defined? RUBY_ENGINE and RUBY_ENGINE == 'rbx'
143
147
  $defs << "-DCHAR_IS_NOT_A_SHORTCUT_TO_ID"
144
148
  end
@@ -41,7 +41,8 @@ static VALUE oci8_make_lob(VALUE klass, oci8_svcctx_t *svcctx, OCILobLocator *s)
41
41
  lob_obj = rb_funcall(klass, oci8_id_new, 1, svcctx->base.self);
42
42
  lob = DATA_PTR(lob_obj);
43
43
  /* If 's' is a temporary lob, use OCILobLocatorAssign instead. */
44
- oci_lc(OCILobAssign(oci8_envhp, oci8_errhp, s, &lob->base.hp.lob));
44
+ chker2(OCILobAssign(oci8_envhp, oci8_errhp, s, &lob->base.hp.lob),
45
+ &svcctx->base);
45
46
  return lob_obj;
46
47
  }
47
48
 
@@ -68,7 +69,7 @@ VALUE oci8_make_bfile(oci8_svcctx_t *svcctx, OCILobLocator *s)
68
69
  static void oci8_assign_lob(VALUE klass, oci8_svcctx_t *svcctx, VALUE lob, OCILobLocator **dest)
69
70
  {
70
71
  oci8_base_t *base = oci8_get_handle(lob, klass);
71
- oci_lc(OCILobLocatorAssign_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, base->hp.lob, dest));
72
+ chker2(OCILobLocatorAssign_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, base->hp.lob, dest), base);
72
73
  }
73
74
 
74
75
  void oci8_assign_clob(oci8_svcctx_t *svcctx, VALUE lob, OCILobLocator **dest)
@@ -102,7 +103,7 @@ static void oci8_lob_free(oci8_base_t *base)
102
103
  oci8_lob_t *lob = (oci8_lob_t *)base;
103
104
  boolean is_temporary;
104
105
 
105
- if (have_OCILobIsTemporary && lob->svchp != NULL
106
+ if (lob->svchp != NULL
106
107
  && OCILobIsTemporary(oci8_envhp, oci8_errhp, lob->base.hp.lob, &is_temporary) == OCI_SUCCESS
107
108
  && is_temporary) {
108
109
 
@@ -113,7 +114,7 @@ static void oci8_lob_free(oci8_base_t *base)
113
114
  lob->svchp = NULL;
114
115
  }
115
116
 
116
- static oci8_base_class_t oci8_lob_class = {
117
+ static oci8_base_vtable_t oci8_lob_vtable = {
117
118
  oci8_lob_mark,
118
119
  oci8_lob_free,
119
120
  sizeof(oci8_lob_t),
@@ -124,18 +125,18 @@ static ub4 oci8_lob_get_length(oci8_lob_t *lob)
124
125
  oci8_svcctx_t *svcctx = oci8_get_svcctx(lob->svc);
125
126
  ub4 len;
126
127
 
127
- oci_lc(OCILobGetLength_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, &len));
128
+ chker2(OCILobGetLength_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, &len),
129
+ &svcctx->base);
128
130
  return len;
129
131
  }
130
132
 
131
133
  static void lob_open(oci8_lob_t *lob)
132
134
  {
133
135
  if (lob->state == S_CLOSE) {
134
- if (have_OCILobOpen_nb) {
135
- oci8_svcctx_t *svcctx = oci8_get_svcctx(lob->svc);
136
+ oci8_svcctx_t *svcctx = oci8_get_svcctx(lob->svc);
136
137
 
137
- oci_lc(OCILobOpen_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, OCI_DEFAULT));
138
- }
138
+ chker2(OCILobOpen_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, OCI_DEFAULT),
139
+ &svcctx->base);
139
140
  lob->state = S_OPEN;
140
141
  }
141
142
  }
@@ -143,11 +144,10 @@ static void lob_open(oci8_lob_t *lob)
143
144
  static void lob_close(oci8_lob_t *lob)
144
145
  {
145
146
  if (lob->state == S_OPEN) {
146
- if (have_OCILobClose_nb) {
147
- oci8_svcctx_t *svcctx = oci8_get_svcctx(lob->svc);
147
+ oci8_svcctx_t *svcctx = oci8_get_svcctx(lob->svc);
148
148
 
149
- oci_lc(OCILobClose_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob));
150
- }
149
+ chker2(OCILobClose_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob),
150
+ &svcctx->base);
151
151
  lob->state = S_CLOSE;
152
152
  }
153
153
  }
@@ -157,7 +157,8 @@ static void bfile_close(oci8_lob_t *lob)
157
157
  if (lob->state == S_BFILE_OPEN) {
158
158
  oci8_svcctx_t *svcctx = oci8_get_svcctx(lob->svc);
159
159
 
160
- oci_lc(OCILobFileClose_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob));
160
+ chker2(OCILobFileClose_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob),
161
+ &svcctx->base);
161
162
  lob->state = S_BFILE_CLOSE;
162
163
  }
163
164
  }
@@ -192,15 +193,12 @@ static VALUE oci8_lob_do_initialize(int argc, VALUE *argv, VALUE self, ub1 csfrm
192
193
  lob->state = S_NO_OPEN_CLOSE;
193
194
  oci8_link_to_parent((oci8_base_t*)lob, (oci8_base_t*)DATA_PTR(svc));
194
195
  if (!NIL_P(val)) {
195
- if (have_OCILobCreateTemporary_nb) {
196
- oci8_svcctx_t *svcctx = oci8_get_svcctx(svc);
197
- OCI8StringValue(val);
198
- oci_lc(OCILobCreateTemporary_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, 0, csfrm, lobtype, TRUE, OCI_DURATION_SESSION));
199
- lob->svchp = oci8_get_oci_svcctx(svc);
200
- oci8_lob_write(self, val);
201
- } else {
202
- rb_raise(rb_eRuntimeError, "creating a temporary lob is not supported on this Oracle version");
203
- }
196
+ oci8_svcctx_t *svcctx = oci8_get_svcctx(svc);
197
+ OCI8StringValue(val);
198
+ chker2(OCILobCreateTemporary_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, 0, csfrm, lobtype, TRUE, OCI_DURATION_SESSION),
199
+ &svcctx->base);
200
+ lob->svchp = oci8_get_oci_svcctx(svc);
201
+ oci8_lob_write(self, val);
204
202
  }
205
203
  return Qnil;
206
204
  }
@@ -241,7 +239,8 @@ static VALUE oci8_lob_available_p(VALUE self)
241
239
  oci8_lob_t *lob = DATA_PTR(self);
242
240
  boolean is_initialized;
243
241
 
244
- oci_lc(OCILobLocatorIsInit(oci8_envhp, oci8_errhp, lob->base.hp.lob, &is_initialized));
242
+ chker2(OCILobLocatorIsInit(oci8_envhp, oci8_errhp, lob->base.hp.lob, &is_initialized),
243
+ &lob->base);
245
244
  return is_initialized ? Qtrue : Qfalse;
246
245
  }
247
246
 
@@ -302,7 +301,8 @@ static VALUE oci8_lob_truncate(VALUE self, VALUE len)
302
301
  oci8_svcctx_t *svcctx = oci8_get_svcctx(lob->svc);
303
302
 
304
303
  lob_open(lob);
305
- oci_lc(OCILobTrim_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, NUM2UINT(len)));
304
+ chker2(OCILobTrim_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, NUM2UINT(len)),
305
+ &svcctx->base);
306
306
  return self;
307
307
  }
308
308
 
@@ -354,11 +354,11 @@ static VALUE oci8_lob_read(int argc, VALUE *argv, VALUE self)
354
354
  }
355
355
  }
356
356
  }
357
- oci_lc(OCILobFileCloseAll_nb(svcctx, svcctx->base.hp.svc, oci8_errhp));
357
+ chker2(OCILobFileCloseAll_nb(svcctx, svcctx->base.hp.svc, oci8_errhp),
358
+ &svcctx->base);
358
359
  continue;
359
360
  }
360
- if (rv != OCI_SUCCESS)
361
- oci8_raise(oci8_errhp, rv, NULL);
361
+ chker2(rv, &svcctx->base);
362
362
  lob->state = S_BFILE_OPEN;
363
363
  }
364
364
  /* initialize buf in zeros everytime to check a nul characters. */
@@ -369,8 +369,9 @@ static VALUE oci8_lob_read(int argc, VALUE *argv, VALUE self)
369
369
  if (lob->state == S_BFILE_CLOSE)
370
370
  continue;
371
371
  }
372
- if (rv != OCI_SUCCESS && rv != OCI_NEED_DATA)
373
- oci8_raise(oci8_errhp, rv, NULL);
372
+ if (rv != OCI_SUCCESS && rv != OCI_NEED_DATA) {
373
+ chker2(rv, &svcctx->base);
374
+ }
374
375
 
375
376
  /* Workaround when using Oracle 10.2.0.4 or 11.1.0.6 client and
376
377
  * variable-length character set (e.g. AL32UTF8).
@@ -426,7 +427,8 @@ static VALUE oci8_lob_write(VALUE self, VALUE data)
426
427
  }
427
428
  RB_GC_GUARD(data);
428
429
  amt = RSTRING_LEN(data);
429
- oci_lc(OCILobWrite_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, &amt, lob->pos + 1, RSTRING_PTR(data), amt, OCI_ONE_PIECE, NULL, NULL, 0, lob->csfrm));
430
+ chker2(OCILobWrite_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, &amt, lob->pos + 1, RSTRING_PTR(data), amt, OCI_ONE_PIECE, NULL, NULL, 0, lob->csfrm),
431
+ &svcctx->base);
430
432
  lob->pos += amt;
431
433
  return UINT2NUM(amt);
432
434
  }
@@ -459,16 +461,13 @@ static VALUE oci8_lob_flush(VALUE self)
459
461
 
460
462
  static VALUE oci8_lob_get_chunk_size(VALUE self)
461
463
  {
462
- if (have_OCILobGetChunkSize_nb) {
463
- oci8_lob_t *lob = DATA_PTR(self);
464
- oci8_svcctx_t *svcctx = oci8_get_svcctx(lob->svc);
465
- ub4 len;
464
+ oci8_lob_t *lob = DATA_PTR(self);
465
+ oci8_svcctx_t *svcctx = oci8_get_svcctx(lob->svc);
466
+ ub4 len;
466
467
 
467
- oci_lc(OCILobGetChunkSize_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, &len));
468
- return UINT2NUM(len);
469
- } else {
470
- rb_notimplement();
471
- }
468
+ chker2(OCILobGetChunkSize_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, &len),
469
+ &svcctx->base);
470
+ return UINT2NUM(len);
472
471
  }
473
472
 
474
473
  static VALUE oci8_lob_clone(VALUE self)
@@ -476,21 +475,17 @@ static VALUE oci8_lob_clone(VALUE self)
476
475
  oci8_lob_t *lob = DATA_PTR(self);
477
476
  oci8_lob_t *newlob;
478
477
  VALUE newobj;
479
- sword rv;
480
478
  boolean is_temporary;
481
479
 
482
480
  newobj = rb_funcall(CLASS_OF(self), oci8_id_new, 1, lob->svc);
483
481
  newlob = DATA_PTR(newobj);
484
- if (have_OCILobLocatorAssign_nb && have_OCILobIsTemporary
485
- && OCILobIsTemporary(oci8_envhp, oci8_errhp, lob->base.hp.lob, &is_temporary) == OCI_SUCCESS
486
- && is_temporary) {
482
+ if (OCILobIsTemporary(oci8_envhp, oci8_errhp, lob->base.hp.lob, &is_temporary) == OCI_SUCCESS
483
+ && is_temporary) {
487
484
  oci8_svcctx_t *svcctx = oci8_get_svcctx(lob->svc);
488
- rv = OCILobLocatorAssign_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, &newlob->base.hp.lob);
485
+ chker2(OCILobLocatorAssign_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, &newlob->base.hp.lob),
486
+ &svcctx->base);
489
487
  } else {
490
- rv = OCILobAssign(oci8_envhp, oci8_errhp, lob->base.hp.lob, &newlob->base.hp.lob);
491
- }
492
- if (rv != OCI_SUCCESS) {
493
- oci8_raise(oci8_errhp, rv, NULL);
488
+ chker2(OCILobAssign(oci8_envhp, oci8_errhp, lob->base.hp.lob, &newlob->base.hp.lob), &lob->base);
494
489
  }
495
490
  return newobj;
496
491
  }
@@ -517,7 +512,8 @@ static void oci8_bfile_get_name(VALUE self, VALUE *dir_alias_p, VALUE *filename_
517
512
  VALUE dir_alias;
518
513
  VALUE filename;
519
514
 
520
- oci_lc(OCILobFileGetName(oci8_envhp, oci8_errhp, lob->base.hp.lob, TO_ORATEXT(d_buf), &d_length, TO_ORATEXT(f_buf), &f_length));
515
+ chker2(OCILobFileGetName(oci8_envhp, oci8_errhp, lob->base.hp.lob, TO_ORATEXT(d_buf), &d_length, TO_ORATEXT(f_buf), &f_length),
516
+ &lob->base);
521
517
  dir_alias = rb_external_str_new_with_enc(d_buf, d_length, oci8_encoding);
522
518
  filename = rb_external_str_new_with_enc(f_buf, f_length, oci8_encoding);
523
519
  rb_ivar_set(self, id_dir_alias, dir_alias);
@@ -542,9 +538,10 @@ static void oci8_bfile_set_name(VALUE self, VALUE dir_alias, VALUE filename)
542
538
  if (RSTRING_LEN(filename) > UB2MAXVAL) {
543
539
  rb_raise(rb_eRuntimeError, "filename is too long.");
544
540
  }
545
- oci_lc(OCILobFileSetName(oci8_envhp, oci8_errhp, &lob->base.hp.lob,
541
+ chker2(OCILobFileSetName(oci8_envhp, oci8_errhp, &lob->base.hp.lob,
546
542
  RSTRING_ORATEXT(dir_alias), (ub2)RSTRING_LEN(dir_alias),
547
- RSTRING_ORATEXT(filename), (ub2)RSTRING_LEN(filename)));
543
+ RSTRING_ORATEXT(filename), (ub2)RSTRING_LEN(filename)),
544
+ &lob->base);
548
545
  }
549
546
 
550
547
  static VALUE oci8_bfile_initialize(int argc, VALUE *argv, VALUE self)
@@ -553,10 +550,14 @@ static VALUE oci8_bfile_initialize(int argc, VALUE *argv, VALUE self)
553
550
  VALUE svc;
554
551
  VALUE dir_alias;
555
552
  VALUE filename;
553
+ int rv;
556
554
 
557
555
  rb_scan_args(argc, argv, "12", &svc, &dir_alias, &filename);
558
556
  TO_SVCCTX(svc); /* check argument type */
559
- oci_lc(OCIDescriptorAlloc(oci8_envhp, &lob->base.hp.ptr, OCI_DTYPE_LOB, 0, NULL));
557
+ rv = OCIDescriptorAlloc(oci8_envhp, &lob->base.hp.ptr, OCI_DTYPE_LOB, 0, NULL);
558
+ if (rv != OCI_SUCCESS) {
559
+ oci8_env_raise(oci8_envhp, rv);
560
+ }
560
561
  lob->base.type = OCI_DTYPE_LOB;
561
562
  lob->svc = svc;
562
563
  lob->pos = 0;
@@ -617,7 +618,8 @@ static VALUE oci8_bfile_exists_p(VALUE self)
617
618
  oci8_svcctx_t *svcctx = oci8_get_svcctx(lob->svc);
618
619
  boolean flag;
619
620
 
620
- oci_lc(OCILobFileExists_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, &flag));
621
+ chker2(OCILobFileExists_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, &flag),
622
+ &svcctx->base);
621
623
  return flag ? Qtrue : Qfalse;
622
624
  }
623
625
 
@@ -631,9 +633,9 @@ static VALUE oci8_bfile_error(VALUE self, VALUE dummy)
631
633
  */
632
634
 
633
635
  typedef struct {
634
- oci8_bind_class_t bind;
636
+ oci8_bind_vtable_t bind;
635
637
  VALUE *klass;
636
- } oci8_bind_lob_class_t;
638
+ } oci8_bind_lob_vtable_t;
637
639
 
638
640
  static VALUE bind_lob_get(oci8_bind_t *obind, void *data, void *null_struct)
639
641
  {
@@ -644,10 +646,10 @@ static VALUE bind_lob_get(oci8_bind_t *obind, void *data, void *null_struct)
644
646
  static void bind_lob_set(oci8_bind_t *obind, void *data, void **null_structp, VALUE val)
645
647
  {
646
648
  oci8_hp_obj_t *oho = (oci8_hp_obj_t *)data;
647
- const oci8_bind_lob_class_t *klass = (const oci8_bind_lob_class_t *)obind->base.klass;
649
+ const oci8_bind_lob_vtable_t *vptr = (const oci8_bind_lob_vtable_t *)obind->base.vptr;
648
650
  oci8_base_t *h;
649
- if (!rb_obj_is_kind_of(val, *klass->klass))
650
- rb_raise(rb_eArgError, "Invalid argument: %s (expect %s)", rb_class2name(CLASS_OF(val)), rb_class2name(*klass->klass));
651
+ if (!rb_obj_is_kind_of(val, *vptr->klass))
652
+ rb_raise(rb_eArgError, "Invalid argument: %s (expect %s)", rb_class2name(CLASS_OF(val)), rb_class2name(*vptr->klass));
651
653
  h = DATA_PTR(val);
652
654
  oho->hp = h->hp.ptr;
653
655
  oho->obj = val;
@@ -661,19 +663,27 @@ static void bind_lob_init(oci8_bind_t *obind, VALUE svc, VALUE val, VALUE length
661
663
 
662
664
  static void bind_lob_init_elem(oci8_bind_t *obind, VALUE svc)
663
665
  {
664
- const oci8_bind_lob_class_t *klass = (const oci8_bind_lob_class_t *)obind->base.klass;
666
+ const oci8_bind_lob_vtable_t *vptr = (const oci8_bind_lob_vtable_t *)obind->base.vptr;
665
667
  oci8_hp_obj_t *oho = (oci8_hp_obj_t *)obind->valuep;
666
668
  oci8_base_t *h;
667
669
  ub4 idx = 0;
668
670
 
669
671
  do {
670
- oho[idx].obj = rb_funcall(*klass->klass, oci8_id_new, 1, svc);
672
+ oho[idx].obj = rb_funcall(*vptr->klass, oci8_id_new, 1, svc);
671
673
  h = DATA_PTR(oho[idx].obj);
672
674
  oho[idx].hp = h->hp.ptr;
673
675
  } while (++idx < obind->maxar_sz);
674
676
  }
675
677
 
676
- static const oci8_bind_lob_class_t bind_clob_class = {
678
+ static void bind_lob_post_bind_hook_for_nclob(oci8_bind_t *obind)
679
+ {
680
+ ub1 csfrm = SQLCS_NCHAR;
681
+
682
+ chker2(OCIAttrSet(obind->base.hp.ptr, obind->base.type, (void*)&csfrm, 0, OCI_ATTR_CHARSET_FORM, oci8_errhp),
683
+ &obind->base);
684
+ }
685
+
686
+ static const oci8_bind_lob_vtable_t bind_clob_vtable = {
677
687
  {
678
688
  {
679
689
  oci8_bind_hp_obj_mark,
@@ -685,14 +695,12 @@ static const oci8_bind_lob_class_t bind_clob_class = {
685
695
  bind_lob_init,
686
696
  bind_lob_init_elem,
687
697
  NULL,
688
- NULL,
689
- NULL,
690
698
  SQLT_CLOB
691
699
  },
692
700
  &cOCI8CLOB
693
701
  };
694
702
 
695
- static const oci8_bind_lob_class_t bind_nclob_class = {
703
+ static const oci8_bind_lob_vtable_t bind_nclob_vtable = {
696
704
  {
697
705
  {
698
706
  oci8_bind_hp_obj_mark,
@@ -704,15 +712,13 @@ static const oci8_bind_lob_class_t bind_nclob_class = {
704
712
  bind_lob_init,
705
713
  bind_lob_init_elem,
706
714
  NULL,
707
- NULL,
708
- NULL,
709
715
  SQLT_CLOB,
710
- SQLCS_NCHAR,
716
+ bind_lob_post_bind_hook_for_nclob,
711
717
  },
712
718
  &cOCI8NCLOB
713
719
  };
714
720
 
715
- static const oci8_bind_lob_class_t bind_blob_class = {
721
+ static const oci8_bind_lob_vtable_t bind_blob_vtable = {
716
722
  {
717
723
  {
718
724
  oci8_bind_hp_obj_mark,
@@ -724,14 +730,12 @@ static const oci8_bind_lob_class_t bind_blob_class = {
724
730
  bind_lob_init,
725
731
  bind_lob_init_elem,
726
732
  NULL,
727
- NULL,
728
- NULL,
729
733
  SQLT_BLOB
730
734
  },
731
735
  &cOCI8BLOB
732
736
  };
733
737
 
734
- static const oci8_bind_lob_class_t bind_bfile_class = {
738
+ static const oci8_bind_lob_vtable_t bind_bfile_vtable = {
735
739
  {
736
740
  {
737
741
  oci8_bind_hp_obj_mark,
@@ -743,8 +747,6 @@ static const oci8_bind_lob_class_t bind_bfile_class = {
743
747
  bind_lob_init,
744
748
  bind_lob_init_elem,
745
749
  NULL,
746
- NULL,
747
- NULL,
748
750
  SQLT_BFILE
749
751
  },
750
752
  &cOCI8BFILE
@@ -759,7 +761,7 @@ void Init_oci8_lob(VALUE cOCI8)
759
761
  seek_cur = rb_eval_string("::IO::SEEK_CUR");
760
762
  seek_end = rb_eval_string("::IO::SEEK_END");
761
763
 
762
- cOCI8LOB = oci8_define_class_under(cOCI8, "LOB", &oci8_lob_class);
764
+ cOCI8LOB = oci8_define_class_under(cOCI8, "LOB", &oci8_lob_vtable);
763
765
  cOCI8CLOB = rb_define_class_under(cOCI8, "CLOB", cOCI8LOB);
764
766
  cOCI8NCLOB = rb_define_class_under(cOCI8, "NCLOB", cOCI8LOB);
765
767
  cOCI8BLOB = rb_define_class_under(cOCI8, "BLOB", cOCI8LOB);
@@ -796,8 +798,8 @@ void Init_oci8_lob(VALUE cOCI8)
796
798
  rb_define_method(cOCI8BFILE, "size=", oci8_bfile_error, 1);
797
799
  rb_define_method(cOCI8BFILE, "write", oci8_bfile_error, 1);
798
800
 
799
- oci8_define_bind_class("CLOB", &bind_clob_class.bind);
800
- oci8_define_bind_class("NCLOB", &bind_nclob_class.bind);
801
- oci8_define_bind_class("BLOB", &bind_blob_class.bind);
802
- oci8_define_bind_class("BFILE", &bind_bfile_class.bind);
801
+ oci8_define_bind_class("CLOB", &bind_clob_vtable.bind);
802
+ oci8_define_bind_class("NCLOB", &bind_nclob_vtable.bind);
803
+ oci8_define_bind_class("BLOB", &bind_blob_vtable.bind);
804
+ oci8_define_bind_class("BFILE", &bind_bfile_vtable.bind);
803
805
  }
@@ -40,7 +40,7 @@ VALUE oci8_metadata_create(OCIParam *parmhp, VALUE svc, VALUE parent)
40
40
 
41
41
  p = oci8_get_handle(parent, oci8_cOCIHandle);
42
42
 
43
- oci_lc(OCIAttrGet(parmhp, OCI_DTYPE_PARAM, &ptype, &size, OCI_ATTR_PTYPE, oci8_errhp));
43
+ chker2(OCIAttrGet(parmhp, OCI_DTYPE_PARAM, &ptype, &size, OCI_ATTR_PTYPE, oci8_errhp), p);
44
44
  klass = rb_hash_aref(ptype_to_class, INT2FIX(ptype));
45
45
  if (NIL_P(klass))
46
46
  rb_raise(rb_eRuntimeError, "unknown parameter type %d", ptype);
@@ -69,150 +69,16 @@ static VALUE metadata_s_register_ptype(VALUE klass, VALUE ptype)
69
69
  return Qnil;
70
70
  }
71
71
 
72
- static VALUE metadata_get_ub1(VALUE self, VALUE idx)
73
- {
74
- oci8_base_t *base = DATA_PTR(self);
75
- ub1 value = 0;
76
- ub4 size = sizeof(value);
77
-
78
- oci_lc(OCIAttrGet(base->hp.ptr, base->type, &value, &size, FIX2INT(idx), oci8_errhp));
79
- if (size != 1) {
80
- rb_raise(rb_eRuntimeError, "Invalid attribute size. expect 1, but %d", size);
81
- }
82
- return INT2FIX(value);
83
- }
84
-
85
- static VALUE metadata_get_ub2(VALUE self, VALUE idx)
86
- {
87
- oci8_base_t *base = DATA_PTR(self);
88
- ub2 value = 0;
89
- ub4 size = sizeof(value);
90
-
91
- oci_lc(OCIAttrGet(base->hp.ptr, base->type, &value, &size, FIX2INT(idx), oci8_errhp));
92
- if (size != 2) {
93
- rb_raise(rb_eRuntimeError, "Invalid attribute size. expect 2, but %d", size);
94
- }
95
- return INT2FIX(value);
96
- }
97
-
98
- /* get ub2 without size check. */
99
- static VALUE metadata_get_ub2_nc(VALUE self, VALUE idx)
100
- {
101
- oci8_base_t *base = DATA_PTR(self);
102
- ub2 value = 0;
103
-
104
- oci_lc(OCIAttrGet(base->hp.ptr, base->type, &value, 0, FIX2INT(idx), oci8_errhp));
105
- return INT2FIX(value);
106
- }
107
-
108
- static VALUE metadata_get_ub4(VALUE self, VALUE idx)
109
- {
110
- oci8_base_t *base = DATA_PTR(self);
111
- ub4 value = 0;
112
- ub4 size = sizeof(value);
113
-
114
- oci_lc(OCIAttrGet(base->hp.ptr, base->type, &value, &size, FIX2INT(idx), oci8_errhp));
115
- if (size != 4) {
116
- rb_raise(rb_eRuntimeError, "Invalid attribute size. expect 4, but %d", size);
117
- }
118
- #if SIZEOF_LONG > 4
119
- return INT2FIX(value);
120
- #else
121
- return UINT2NUM(value);
122
- #endif
123
- }
124
-
125
- static VALUE metadata_get_sb1(VALUE self, VALUE idx)
126
- {
127
- oci8_base_t *base = DATA_PTR(self);
128
- sb1 value = 0;
129
- ub4 size = sizeof(value);
130
-
131
- oci_lc(OCIAttrGet(base->hp.ptr, base->type, &value, &size, FIX2INT(idx), oci8_errhp));
132
- if (size != 1) {
133
- rb_raise(rb_eRuntimeError, "Invalid attribute size. expect 1, but %d", size);
134
- }
135
- return INT2FIX(value);
136
- }
137
-
138
- static VALUE metadata_get_sb2(VALUE self, VALUE idx)
139
- {
140
- oci8_base_t *base = DATA_PTR(self);
141
- sb2 value = 0;
142
- ub4 size = sizeof(value);
143
-
144
- oci_lc(OCIAttrGet(base->hp.ptr, base->type, &value, &size, FIX2INT(idx), oci8_errhp));
145
- if (size != 2) {
146
- rb_raise(rb_eRuntimeError, "Invalid attribute size. expect 2, but %d", size);
147
- }
148
- return INT2FIX(value);
149
- }
150
-
151
- static VALUE metadata_get_sb4(VALUE self, VALUE idx)
152
- {
153
- oci8_base_t *base = DATA_PTR(self);
154
- sb4 value = 0;
155
- ub4 size = sizeof(value);
156
-
157
- oci_lc(OCIAttrGet(base->hp.ptr, base->type, &value, &size, FIX2INT(idx), oci8_errhp));
158
- if (size != 4) {
159
- rb_raise(rb_eRuntimeError, "Invalid attribute size. expect 4, but %d", size);
160
- }
161
- #if SIZEOF_LONG > 4
162
- return INT2FIX(value);
163
- #else
164
- return INT2NUM(value);
165
- #endif
166
- }
167
-
168
- static VALUE metadata_get_text(VALUE self, VALUE idx)
169
- {
170
- oci8_metadata_t *md = DATA_PTR(self);
171
- oci8_svcctx_t *svcctx = oci8_get_svcctx(md->svc);
172
- text *value;
173
- ub4 size;
174
-
175
- /* remote call sometimes? */
176
- oci_lc(OCIAttrGet_nb(svcctx, md->base.hp.ptr, md->base.type, &value, &size, FIX2INT(idx), oci8_errhp));
177
- return rb_external_str_new_with_enc(TO_CHARPTR(value), size, oci8_encoding);
178
- }
179
-
180
- static VALUE metadata_get_oradate(VALUE self, VALUE idx)
181
- {
182
- oci8_base_t *base = DATA_PTR(self);
183
- ub1 *value;
184
- ub4 size = 7;
185
- static VALUE cOraDate = Qnil;
186
- VALUE obj;
187
-
188
- oci_lc(OCIAttrGet(base->hp.ptr, base->type, &value, &size, FIX2INT(idx), oci8_errhp));
189
- if (size != 7) {
190
- rb_raise(rb_eRuntimeError, "Invalid attribute size. expect 7, but %d", size);
191
- }
192
- if (NIL_P(cOraDate))
193
- cOraDate = rb_eval_string("OraDate");
194
- obj = rb_funcall(cOraDate, oci8_id_new, 0);
195
- memcpy(DATA_PTR(obj), value, 7);
196
- return obj;
197
- }
198
-
199
- static VALUE metadata_get_oraint(VALUE self, VALUE idx)
200
- {
201
- oci8_base_t *base = DATA_PTR(self);
202
- ub1 *value;
203
- ub4 size = 21;
204
- OCINumber on;
205
-
206
- oci_lc(OCIAttrGet(base->hp.ptr, base->type, &value, &size, FIX2INT(idx), oci8_errhp));
207
- if (size >= 22) {
208
- rb_raise(rb_eRuntimeError, "Invalid attribute size. expect less than 22, but %d", size);
209
- }
210
- memset(&on, 0, sizeof(on));
211
- on.OCINumberPart[0] = size;
212
- memcpy(&on.OCINumberPart[1], value, size);
213
- return oci8_make_integer(&on, oci8_errhp);
214
- }
215
-
72
+ /*
73
+ * call-seq:
74
+ * __param(attr_type) -> metadata information or nil
75
+ *
76
+ * Gets the value of the attribute specified by +attr_type+
77
+ * as an instance of an OCI8::Metadata::Base's subclass.
78
+ *
79
+ * <b>Caution:</b> If the specified attr_type's datatype is not a
80
+ * metadata, it causes a segmentation fault.
81
+ */
216
82
  static VALUE metadata_get_param(VALUE self, VALUE idx)
217
83
  {
218
84
  oci8_metadata_t *md = DATA_PTR(self);
@@ -220,11 +86,16 @@ static VALUE metadata_get_param(VALUE self, VALUE idx)
220
86
  OCIParam *value;
221
87
  ub4 size = sizeof(value);
222
88
 
223
- /* remote call? */
224
- oci_lc(OCIAttrGet_nb(svcctx, md->base.hp.ptr, md->base.type, &value, &size, FIX2INT(idx), oci8_errhp));
89
+ Check_Type(idx, T_FIXNUM);
90
+ /* Is it remote call? */
91
+ chker2(OCIAttrGet_nb(svcctx, md->base.hp.ptr, md->base.type, &value, &size, FIX2INT(idx), oci8_errhp),
92
+ &svcctx->base);
225
93
  if (size != sizeof(OCIParam *)) {
226
94
  rb_raise(rb_eRuntimeError, "Invalid attribute size. expect %d, but %d", (sb4)sizeof(OCIParam *), size);
227
95
  }
96
+ if (value == NULL) {
97
+ return Qnil;
98
+ }
228
99
  return oci8_metadata_create(value, md->svc, self);
229
100
  }
230
101
 
@@ -233,17 +104,11 @@ static VALUE metadata_get_param_at(VALUE self, VALUE idx)
233
104
  oci8_metadata_t *md = DATA_PTR(self);
234
105
  OCIParam *value;
235
106
 
236
- oci_lc(OCIParamGet(md->base.hp.ptr, md->base.type, oci8_errhp, (dvoid *)&value, FIX2INT(idx)));
107
+ chker2(OCIParamGet(md->base.hp.ptr, md->base.type, oci8_errhp, (dvoid *)&value, FIX2INT(idx)),
108
+ &md->base);
237
109
  return oci8_metadata_create(value, md->svc, self);
238
110
  }
239
111
 
240
- static VALUE metadata_get_charset_name(VALUE self, VALUE charset_id)
241
- {
242
- oci8_metadata_t *md = DATA_PTR(self);
243
-
244
- return oci8_charset_id2name(md->svc, charset_id);
245
- }
246
-
247
112
  static VALUE metadata_get_con(VALUE self)
248
113
  {
249
114
  oci8_metadata_t *md = DATA_PTR(self);
@@ -263,22 +128,29 @@ static VALUE oci8_do_describe(VALUE self, void *objptr, ub4 objlen, ub1 objtype,
263
128
  VALUE type;
264
129
  VALUE obj;
265
130
  oci8_base_t *desc;
131
+ int rv;
266
132
 
267
133
  /* make a describe handle object */
268
134
  obj = rb_obj_alloc(oci8_cOCIHandle);
269
135
  desc = DATA_PTR(obj);
270
- oci_lc(OCIHandleAlloc(oci8_envhp, (dvoid *)&desc->hp.dschp, OCI_HTYPE_DESCRIBE, 0, 0));
136
+ rv = OCIHandleAlloc(oci8_envhp, (dvoid *)&desc->hp.dschp, OCI_HTYPE_DESCRIBE, 0, 0);
137
+ if (rv != OCI_SUCCESS) {
138
+ oci8_env_raise(oci8_envhp, rv);
139
+ }
271
140
  desc->type = OCI_HTYPE_DESCRIBE;
272
141
 
273
142
  type = rb_hash_aref(class_to_ptype, klass);
274
143
  if (RTEST(check_public)) {
275
144
  sb4 val = -1;
276
145
  /* size of OCI_ATTR_DESC_PUBLIC is undocumented. */
277
- oci_lc(OCIAttrSet(desc->hp.dschp, OCI_HTYPE_DESCRIBE, &val, 0, OCI_ATTR_DESC_PUBLIC, oci8_errhp));
146
+ chker2(OCIAttrSet(desc->hp.dschp, OCI_HTYPE_DESCRIBE, &val, 0, OCI_ATTR_DESC_PUBLIC, oci8_errhp),
147
+ &svcctx->base);
278
148
  }
279
- oci_lc(OCIDescribeAny_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, objptr, objlen,
280
- objtype, OCI_DEFAULT, (ub1)FIX2INT(type), desc->hp.dschp));
281
- oci_lc(OCIAttrGet(desc->hp.dschp, OCI_HTYPE_DESCRIBE, &parmhp, 0, OCI_ATTR_PARAM, oci8_errhp));
149
+ chker2(OCIDescribeAny_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, objptr, objlen,
150
+ objtype, OCI_DEFAULT, (ub1)FIX2INT(type), desc->hp.dschp),
151
+ &svcctx->base);
152
+ chker2(OCIAttrGet(desc->hp.dschp, OCI_HTYPE_DESCRIBE, &parmhp, 0, OCI_ATTR_PARAM, oci8_errhp),
153
+ &svcctx->base);
282
154
  return oci8_metadata_create(parmhp, self, obj);
283
155
  }
284
156
 
@@ -298,7 +170,8 @@ static VALUE metadata_get_type_metadata(VALUE self, VALUE klass)
298
170
  OCIRef *ref = NULL;
299
171
 
300
172
  /* remote call */
301
- oci_lc(OCIAttrGet_nb(svcctx, md->base.hp.ptr, md->base.type, &ref, NULL, OCI_ATTR_REF_TDO, oci8_errhp));
173
+ chker2(OCIAttrGet_nb(svcctx, md->base.hp.ptr, md->base.type, &ref, NULL, OCI_ATTR_REF_TDO, oci8_errhp),
174
+ &svcctx->base);
302
175
  return oci8_do_describe(md->svc, ref, 0, OCI_OTYPE_REF, klass, Qfalse);
303
176
  }
304
177
 
@@ -309,11 +182,14 @@ static VALUE metadata_get_tdo_id(VALUE self)
309
182
  OCIRef *tdo_ref = NULL;
310
183
  void *tdo;
311
184
 
312
- oci_lc(OCIAttrGet_nb(svcctx, md->base.hp.ptr, md->base.type, &tdo_ref, NULL, OCI_ATTR_REF_TDO, oci8_errhp));
185
+ chker2(OCIAttrGet_nb(svcctx, md->base.hp.ptr, md->base.type, &tdo_ref, NULL, OCI_ATTR_REF_TDO, oci8_errhp),
186
+ &svcctx->base);
313
187
  if (tdo_ref == NULL)
314
188
  return Qnil;
315
- oci_lc(OCIObjectPin_nb(svcctx, oci8_envhp, oci8_errhp, tdo_ref, 0, OCI_PIN_ANY, OCI_DURATION_SESSION, OCI_LOCK_NONE, &tdo));
316
- oci_lc(OCIObjectUnpin(oci8_envhp, oci8_errhp, tdo));
189
+ chker2(OCIObjectPin_nb(svcctx, oci8_envhp, oci8_errhp, tdo_ref, 0, OCI_PIN_ANY, OCI_DURATION_SESSION, OCI_LOCK_NONE, &tdo),
190
+ &svcctx->base);
191
+ chker2(OCIObjectUnpin(oci8_envhp, oci8_errhp, tdo),
192
+ &svcctx->base);
317
193
  #if SIZEOF_LONG == SIZEOF_VOIDP
318
194
  return ((VALUE)tdo | (VALUE)1);
319
195
  #else
@@ -321,7 +197,7 @@ static VALUE metadata_get_tdo_id(VALUE self)
321
197
  #endif
322
198
  }
323
199
 
324
- oci8_base_class_t oci8_metadata_class = {
200
+ oci8_base_vtable_t oci8_metadata_vtable = {
325
201
  oci8_metadata_mark,
326
202
  NULL,
327
203
  sizeof(oci8_metadata_t),
@@ -330,26 +206,15 @@ oci8_base_class_t oci8_metadata_class = {
330
206
  void Init_oci8_metadata(VALUE cOCI8)
331
207
  {
332
208
  mOCI8Metadata = rb_define_module_under(cOCI8, "Metadata");
333
- cOCI8MetadataBase = oci8_define_class_under(mOCI8Metadata, "Base", &oci8_metadata_class);
209
+ cOCI8MetadataBase = oci8_define_class_under(mOCI8Metadata, "Base", &oci8_metadata_vtable);
334
210
  ptype_to_class = rb_hash_new();
335
211
  class_to_ptype = rb_hash_new();
336
212
  rb_global_variable(&ptype_to_class);
337
213
  rb_global_variable(&class_to_ptype);
338
214
 
339
215
  rb_define_singleton_method(cOCI8MetadataBase, "register_ptype", metadata_s_register_ptype, 1);
340
- rb_define_private_method(cOCI8MetadataBase, "__ub1", metadata_get_ub1, 1);
341
- rb_define_private_method(cOCI8MetadataBase, "__ub2", metadata_get_ub2, 1);
342
- rb_define_private_method(cOCI8MetadataBase, "__ub2_nc", metadata_get_ub2_nc, 1);
343
- rb_define_private_method(cOCI8MetadataBase, "__ub4", metadata_get_ub4, 1);
344
- rb_define_private_method(cOCI8MetadataBase, "__sb1", metadata_get_sb1, 1);
345
- rb_define_private_method(cOCI8MetadataBase, "__sb2", metadata_get_sb2, 1);
346
- rb_define_private_method(cOCI8MetadataBase, "__sb4", metadata_get_sb4, 1);
347
- rb_define_private_method(cOCI8MetadataBase, "__text", metadata_get_text, 1);
348
- rb_define_private_method(cOCI8MetadataBase, "__oradate", metadata_get_oradate, 1);
349
- rb_define_private_method(cOCI8MetadataBase, "__oraint", metadata_get_oraint, 1);
350
216
  rb_define_private_method(cOCI8MetadataBase, "__param", metadata_get_param, 1);
351
217
  rb_define_private_method(cOCI8MetadataBase, "__param_at", metadata_get_param_at, 1);
352
- rb_define_private_method(cOCI8MetadataBase, "__charset_name", metadata_get_charset_name, 1);
353
218
  rb_define_private_method(cOCI8MetadataBase, "__con", metadata_get_con, 0);
354
219
  rb_define_private_method(cOCI8MetadataBase, "__is_implicit?", metadata_is_implicit_p, 0);
355
220