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
@@ -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