ruby-oci8 2.2.0.2 → 2.2.12

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 (83) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +1 -6
  3. data/ChangeLog +600 -0
  4. data/NEWS +426 -35
  5. data/README.md +27 -9
  6. data/dist-files +13 -2
  7. data/docs/bind-array-to-in_cond.md +38 -0
  8. data/docs/conflicts-local-connections-and-processes.md +98 -0
  9. data/docs/hanging-after-inactivity.md +63 -0
  10. data/docs/install-binary-package.md +15 -11
  11. data/docs/install-full-client.md +18 -21
  12. data/docs/install-instant-client.md +45 -27
  13. data/docs/install-on-osx.md +31 -117
  14. data/docs/ldap-auth-and-function-interposition.md +123 -0
  15. data/docs/number-type-mapping.md +79 -0
  16. data/docs/platform-specific-issues.md +17 -50
  17. data/docs/report-installation-issue.md +11 -8
  18. data/docs/timeout-parameters.md +94 -0
  19. data/ext/oci8/apiwrap.c.tmpl +2 -5
  20. data/ext/oci8/apiwrap.rb +6 -1
  21. data/ext/oci8/apiwrap.yml +39 -143
  22. data/ext/oci8/attr.c +4 -2
  23. data/ext/oci8/bind.c +421 -9
  24. data/ext/oci8/connection_pool.c +3 -3
  25. data/ext/oci8/encoding.c +5 -5
  26. data/ext/oci8/env.c +8 -2
  27. data/ext/oci8/error.c +24 -16
  28. data/ext/oci8/extconf.rb +35 -63
  29. data/ext/oci8/hook_funcs.c +274 -61
  30. data/ext/oci8/lob.c +31 -75
  31. data/ext/oci8/metadata.c +8 -6
  32. data/ext/oci8/object.c +119 -29
  33. data/ext/oci8/oci8.c +46 -133
  34. data/ext/oci8/oci8.h +40 -123
  35. data/ext/oci8/oci8lib.c +178 -46
  36. data/ext/oci8/ocihandle.c +37 -37
  37. data/ext/oci8/ocinumber.c +24 -35
  38. data/ext/oci8/oraconf.rb +168 -337
  39. data/ext/oci8/oradate.c +19 -19
  40. data/ext/oci8/plthook.h +10 -0
  41. data/ext/oci8/plthook_elf.c +433 -268
  42. data/ext/oci8/plthook_osx.c +40 -9
  43. data/ext/oci8/plthook_win32.c +16 -1
  44. data/ext/oci8/stmt.c +52 -17
  45. data/ext/oci8/win32.c +4 -22
  46. data/lib/oci8/bindtype.rb +10 -17
  47. data/lib/oci8/check_load_error.rb +57 -10
  48. data/lib/oci8/compat.rb +5 -1
  49. data/lib/oci8/connection_pool.rb +74 -3
  50. data/lib/oci8/cursor.rb +70 -31
  51. data/lib/oci8/metadata.rb +9 -1
  52. data/lib/oci8/object.rb +14 -1
  53. data/lib/oci8/oci8.rb +184 -58
  54. data/lib/oci8/ocihandle.rb +0 -16
  55. data/lib/oci8/oracle_version.rb +11 -1
  56. data/lib/oci8/properties.rb +55 -0
  57. data/lib/oci8/version.rb +1 -1
  58. data/lib/oci8.rb +48 -4
  59. data/lib/ruby-oci8.rb +1 -0
  60. data/pre-distclean.rb +1 -3
  61. data/ruby-oci8.gemspec +4 -9
  62. data/setup.rb +11 -2
  63. data/test/README.md +37 -0
  64. data/test/config.rb +8 -1
  65. data/test/setup_test_object.sql +42 -14
  66. data/test/setup_test_package.sql +59 -0
  67. data/test/test_all.rb +4 -0
  68. data/test/test_bind_array.rb +70 -0
  69. data/test/test_bind_boolean.rb +99 -0
  70. data/test/test_bind_integer.rb +47 -0
  71. data/test/test_break.rb +11 -9
  72. data/test/test_clob.rb +5 -17
  73. data/test/test_connstr.rb +142 -0
  74. data/test/test_datetime.rb +8 -3
  75. data/test/test_metadata.rb +2 -1
  76. data/test/test_object.rb +99 -18
  77. data/test/test_oci8.rb +170 -46
  78. data/test/test_oranumber.rb +12 -6
  79. data/test/test_package_type.rb +17 -3
  80. data/test/test_properties.rb +17 -0
  81. metadata +45 -55
  82. data/docs/osx-install-dev-tools.png +0 -0
  83. data/test/README +0 -42
data/ext/oci8/lob.c CHANGED
@@ -26,8 +26,6 @@ static VALUE seek_end;
26
26
 
27
27
  enum state {
28
28
  S_NO_OPEN_CLOSE,
29
- S_OPEN,
30
- S_CLOSE,
31
29
  S_BFILE_CLOSE,
32
30
  S_BFILE_OPEN,
33
31
  };
@@ -266,28 +264,6 @@ static ub8 oci8_lob_get_length(oci8_lob_t *lob)
266
264
  return len;
267
265
  }
268
266
 
269
- static void lob_open(oci8_lob_t *lob)
270
- {
271
- if (lob->state == S_CLOSE) {
272
- oci8_svcctx_t *svcctx = check_svcctx(lob);
273
-
274
- chker2(OCILobOpen_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, OCI_DEFAULT),
275
- &svcctx->base);
276
- lob->state = S_OPEN;
277
- }
278
- }
279
-
280
- static void lob_close(oci8_lob_t *lob)
281
- {
282
- if (lob->state == S_OPEN) {
283
- oci8_svcctx_t *svcctx = check_svcctx(lob);
284
-
285
- chker2(OCILobClose_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob),
286
- &svcctx->base);
287
- lob->state = S_CLOSE;
288
- }
289
- }
290
-
291
267
  static void bfile_close(oci8_lob_t *lob)
292
268
  {
293
269
  if (lob->state == S_BFILE_OPEN) {
@@ -368,7 +344,6 @@ static void bfile_close(oci8_lob_t *lob)
368
344
  static VALUE oci8_lob_close(VALUE self)
369
345
  {
370
346
  oci8_lob_t *lob = TO_LOB(self);
371
- lob_close(lob);
372
347
  oci8_base_free(&lob->base);
373
348
  return self;
374
349
  }
@@ -591,7 +566,6 @@ static VALUE oci8_lob_truncate(VALUE self, VALUE len)
591
566
  oci8_lob_t *lob = TO_LOB(self);
592
567
  oci8_svcctx_t *svcctx = check_svcctx(lob);
593
568
 
594
- lob_open(lob);
595
569
  chker2(OCILobTrim2_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, NUM2ULL(len)),
596
570
  &svcctx->base);
597
571
  return self;
@@ -665,10 +639,9 @@ static VALUE oci8_lob_read(int argc, VALUE *argv, VALUE self)
665
639
  {
666
640
  oci8_lob_t *lob = TO_LOB(self);
667
641
  oci8_svcctx_t *svcctx = check_svcctx(lob);
668
- ub8 lob_length;
669
- ub8 read_len;
670
642
  ub8 pos = lob->pos;
671
- long strbufsiz;
643
+ long strbufsiz = 512;
644
+ ub8 sz;
672
645
  ub8 byte_amt;
673
646
  ub8 char_amt;
674
647
  sword rv;
@@ -678,36 +651,21 @@ static VALUE oci8_lob_read(int argc, VALUE *argv, VALUE self)
678
651
  ub1 piece = OCI_FIRST_PIECE;
679
652
 
680
653
  rb_scan_args(argc, argv, "01", &size);
681
- lob_length = oci8_lob_get_length(lob);
682
- if (lob_length == 0 && NIL_P(size)) {
683
- return rb_usascii_str_new("", 0);
684
- }
685
- if (lob_length <= pos) /* EOF */
686
- return Qnil;
687
654
  if (NIL_P(size)) {
688
- read_len = lob_length - pos;
655
+ sz = UB4MAXVAL;
689
656
  } else {
690
- ub8 sz = NUM2ULL(size);
691
- read_len = MIN(sz, lob_length - pos);
657
+ sz = NUM2ULL(size);
658
+ }
659
+ if (lob->state == S_BFILE_CLOSE) {
660
+ open_bfile(svcctx, lob, errhp);
692
661
  }
662
+ read_more_data:
693
663
  if (lob->lobtype == OCI_TEMP_CLOB) {
694
664
  byte_amt = 0;
695
- char_amt = read_len;
696
- if (oci8_nls_ratio == 1) {
697
- strbufsiz = MIN(read_len, ULONG_MAX);
698
- } else {
699
- strbufsiz = MIN(read_len + read_len / 8, ULONG_MAX);
700
- }
701
- if (strbufsiz <= 10) {
702
- strbufsiz = 10;
703
- }
665
+ char_amt = sz;
704
666
  } else {
705
- byte_amt = read_len;
667
+ byte_amt = sz;
706
668
  char_amt = 0;
707
- strbufsiz = MIN(read_len, ULONG_MAX);
708
- }
709
- if (lob->state == S_BFILE_CLOSE) {
710
- open_bfile(svcctx, lob, errhp);
711
669
  }
712
670
  do {
713
671
  VALUE strbuf = rb_str_buf_new(strbufsiz);
@@ -737,23 +695,30 @@ static VALUE oci8_lob_read(int argc, VALUE *argv, VALUE self)
737
695
  }
738
696
  rb_str_set_len(strbuf, byte_amt);
739
697
  rb_ary_push(v, strbuf);
698
+ if (strbufsiz < 128 * 1024 * 1024) {
699
+ strbufsiz *= 2;
700
+ }
740
701
  } while (rv == OCI_NEED_DATA);
741
702
 
742
- if (pos >= lob_length) {
743
- lob_close(lob);
744
- bfile_close(lob);
703
+ if (NIL_P(size) && pos - lob->pos == sz) {
704
+ lob->pos = pos;
705
+ piece = OCI_FIRST_PIECE;
706
+ goto read_more_data;
745
707
  }
746
708
  lob->pos = pos;
747
709
  switch (RARRAY_LEN(v)) {
748
710
  case 0:
749
- return Qnil;
711
+ if (NIL_P(size) && pos == 0) {
712
+ return rb_usascii_str_new("", 0);
713
+ } else {
714
+ return Qnil;
715
+ }
750
716
  case 1:
751
717
  v = RARRAY_AREF(v, 0);
752
718
  break;
753
719
  default:
754
720
  v = rb_ary_join(v, Qnil);
755
721
  }
756
- OBJ_TAINT(v);
757
722
  if (lob->lobtype == OCI_TEMP_CLOB) {
758
723
  /* set encoding */
759
724
  rb_enc_associate(v, oci8_encoding);
@@ -781,7 +746,6 @@ static VALUE oci8_lob_write(VALUE self, VALUE data)
781
746
  ub8 byte_amt;
782
747
  ub8 char_amt;
783
748
 
784
- lob_open(lob);
785
749
  if (TYPE(data) != T_STRING) {
786
750
  str = rb_obj_as_string(data);
787
751
  } else {
@@ -801,48 +765,40 @@ static VALUE oci8_lob_write(VALUE self, VALUE data)
801
765
  RB_GC_GUARD(str);
802
766
  if (lob->lobtype == OCI_TEMP_CLOB) {
803
767
  lob->pos += char_amt;
804
- return UINT2NUM(char_amt);
768
+ return ULL2NUM(char_amt);
805
769
  } else {
806
770
  lob->pos += byte_amt;
807
- return UINT2NUM(byte_amt);
771
+ return ULL2NUM(byte_amt);
808
772
  }
809
773
  }
810
774
 
811
775
  /*
812
- * @deprecated I'm not sure that this is what the name indicates.
776
+ * @deprecated LOB#sync had not worked by mistake. Do nothing now.
813
777
  * @private
814
778
  */
815
779
  static VALUE oci8_lob_get_sync(VALUE self)
816
780
  {
817
- oci8_lob_t *lob = TO_LOB(self);
818
- return (lob->state == S_NO_OPEN_CLOSE) ? Qtrue : Qfalse;
781
+ rb_warning("LOB#sync had not worked by mistake. Do nothing now.");
782
+ return Qfalse;
819
783
  }
820
784
 
821
785
  /*
822
- * @deprecated I'm not sure that this is what the name indicates.
786
+ * @deprecated LOB#sync had not worked by mistake. Do nothing now.
823
787
  * @private
824
788
  */
825
789
  static VALUE oci8_lob_set_sync(VALUE self, VALUE b)
826
790
  {
827
- oci8_lob_t *lob = TO_LOB(self);
828
- if (RTEST(b)) {
829
- lob_close(lob);
830
- lob->state = S_NO_OPEN_CLOSE;
831
- } else {
832
- if (lob->state == S_NO_OPEN_CLOSE)
833
- lob->state = S_CLOSE;
834
- }
791
+ rb_warning("LOB#sync had not worked by mistake. Do nothing now.");
835
792
  return b;
836
793
  }
837
794
 
838
795
  /*
839
- * @deprecated I'm not sure that this is what the name indicates.
796
+ * @deprecated LOB#flush had not worked by mistake. Do nothing now.
840
797
  * @private
841
798
  */
842
799
  static VALUE oci8_lob_flush(VALUE self)
843
800
  {
844
- oci8_lob_t *lob = TO_LOB(self);
845
- lob_close(lob);
801
+ rb_warning("LOB#flush had not worked by mistake. Do nothing now.");
846
802
  return self;
847
803
  }
848
804
 
data/ext/oci8/metadata.c CHANGED
@@ -2,7 +2,7 @@
2
2
  /*
3
3
  * metadata.c
4
4
  *
5
- * Copyright (C) 2006-2015 Kubo Takehiro <kubo@jiubao.org>
5
+ * Copyright (C) 2006-2016 Kubo Takehiro <kubo@jiubao.org>
6
6
  *
7
7
  * implement private methods of classes in OCI8::Metadata module.
8
8
  *
@@ -145,7 +145,7 @@ static VALUE metadata_is_implicit_p(VALUE self)
145
145
  return md->is_implicit ? Qtrue : Qfalse;
146
146
  }
147
147
 
148
- static VALUE oci8_do_describe(VALUE self, void *objptr, ub4 objlen, ub1 objtype, VALUE klass, VALUE check_public)
148
+ VALUE oci8_do_describe(VALUE self, void *objptr, ub4 objlen, ub1 objtype, VALUE klass, VALUE check_public)
149
149
  {
150
150
  oci8_svcctx_t *svcctx = oci8_get_svcctx(self);
151
151
  OCIParam *parmhp;
@@ -195,7 +195,7 @@ static VALUE oci8_do_describe(VALUE self, void *objptr, ub4 objlen, ub1 objtype,
195
195
  static VALUE oci8_describe(VALUE self, VALUE name, VALUE klass, VALUE check_public)
196
196
  {
197
197
  char *str;
198
- size_t idx, len;
198
+ int idx, len;
199
199
  VALUE metadata;
200
200
  VALUE obj_link = Qnil;
201
201
 
@@ -204,7 +204,7 @@ static VALUE oci8_describe(VALUE self, VALUE name, VALUE klass, VALUE check_publ
204
204
  rb_raise(rb_eArgError, "empty string is set.");
205
205
  }
206
206
  str = RSTRING_PTR(name);
207
- len = RSTRING_LEN(name);
207
+ len = RSTRING_LENINT(name);
208
208
  for (idx = 0; idx < len; idx++) {
209
209
  if (str[idx] == '@') {
210
210
  obj_link = rb_enc_str_new(str + idx + 1, len - idx - 1, oci8_encoding);
@@ -259,10 +259,10 @@ void Init_oci8_metadata(VALUE cOCI8)
259
259
  {
260
260
  mOCI8Metadata = rb_define_module_under(cOCI8, "Metadata");
261
261
  cOCI8MetadataBase = oci8_define_class_under(mOCI8Metadata, "Base", &oci8_metadata_base_data_type, oci8_metadata_alloc);
262
- ptype_to_class = rb_hash_new();
263
- class_to_ptype = rb_hash_new();
264
262
  rb_global_variable(&ptype_to_class);
265
263
  rb_global_variable(&class_to_ptype);
264
+ ptype_to_class = rb_hash_new();
265
+ class_to_ptype = rb_hash_new();
266
266
  id_at_obj_link = rb_intern("@obj_link");
267
267
 
268
268
  rb_define_singleton_method(cOCI8MetadataBase, "register_ptype", metadata_s_register_ptype, 1);
@@ -274,4 +274,6 @@ void Init_oci8_metadata(VALUE cOCI8)
274
274
  rb_define_private_method(cOCI8, "__describe", oci8_describe, 3);
275
275
  rb_define_private_method(cOCI8MetadataBase, "__type_metadata", metadata_get_type_metadata, 1);
276
276
  rb_define_method(cOCI8MetadataBase, "tdo_id", metadata_get_tdo_id, 0);
277
+
278
+ rb_define_class_under(mOCI8Metadata, "Type", cOCI8MetadataBase);
277
279
  }
data/ext/oci8/object.c CHANGED
@@ -1,6 +1,6 @@
1
1
  /* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
2
2
  /*
3
- * Copyright (C) 2002-2014 Kubo Takehiro <kubo@jiubao.org>
3
+ * Copyright (C) 2002-2016 Kubo Takehiro <kubo@jiubao.org>
4
4
  */
5
5
 
6
6
  /*
@@ -20,8 +20,11 @@ static VALUE cOCI8TDO;
20
20
  static VALUE cOCI8NamedType;
21
21
  static VALUE cOCI8NamedCollection;
22
22
  static VALUE cOCI8BindNamedType;
23
+ static VALUE cOCI8MetadataType;
23
24
  static ID id_to_value;
24
25
  static ID id_set_attributes;
26
+ static ID id_get_tdo_by_metadata;
27
+ static ID id_at_is_final_type;
25
28
 
26
29
  #define TO_TDO(obj) ((oci8_base_t *)oci8_check_typeddata((obj), &oci8_tdo_data_type, 1))
27
30
  #define CHECK_TDO(obj) ((void)oci8_check_typeddata((obj), &oci8_tdo_data_type, 1))
@@ -41,6 +44,8 @@ enum {
41
44
  ATTR_FLOAT,
42
45
  ATTR_INTEGER,
43
46
  ATTR_OCIDATE,
47
+ ATTR_TIMESTAMP,
48
+ ATTR_TIMESTAMP_TZ,
44
49
  ATTR_BINARY_DOUBLE,
45
50
  ATTR_BINARY_FLOAT,
46
51
  ATTR_NAMED_TYPE,
@@ -137,10 +142,49 @@ static VALUE oci8_named_type_initialize(VALUE self)
137
142
  return Qnil;
138
143
  }
139
144
 
145
+ typedef struct get_tdo_by_instance_arg {
146
+ VALUE svc;
147
+ void *instance;
148
+ void *typeref;
149
+ } get_tdo_by_instance_arg_t;
150
+
151
+ static VALUE get_tdo_by_instance(VALUE data)
152
+ {
153
+ get_tdo_by_instance_arg_t *arg = (get_tdo_by_instance_arg_t *)data;
154
+ VALUE metadata;
155
+
156
+ chkerr(OCIObjectGetTypeRef(oci8_envhp, oci8_errhp, arg->instance, arg->typeref));
157
+ metadata = oci8_do_describe(arg->svc, arg->typeref, 0, OCI_OTYPE_REF, cOCI8MetadataType, Qfalse);
158
+ return rb_funcall(arg->svc, id_get_tdo_by_metadata, 1, metadata);
159
+ }
160
+
140
161
  static VALUE oci8_named_type_tdo(VALUE self)
141
162
  {
142
163
  oci8_named_type_t *obj = DATA_PTR(self);
143
- return obj->tdo;
164
+ VALUE tdo = obj->tdo;
165
+
166
+ if (!RTEST(rb_ivar_get(tdo, id_at_is_final_type))) {
167
+ /* The type of the instance may be a subtype. */
168
+ oci8_base_t *svcctx;
169
+ get_tdo_by_instance_arg_t arg;
170
+ int state = 0;
171
+
172
+ /* search svcctx */
173
+ svcctx = DATA_PTR(obj->tdo);
174
+ while (svcctx->type != OCI_HTYPE_SVCCTX) {
175
+ svcctx = svcctx->parent;
176
+ }
177
+
178
+ arg.svc = svcctx->self;
179
+ arg.instance = *obj->instancep;
180
+ chkerr(OCIObjectNew(oci8_envhp, oci8_errhp, svcctx->hp.svc, OCI_TYPECODE_REF, NULL, NULL, OCI_DURATION_DEFAULT, TRUE, &arg.typeref));
181
+ tdo = rb_protect(get_tdo_by_instance, (VALUE)&arg, &state);
182
+ chkerr(OCIObjectFree(oci8_envhp, oci8_errhp, arg.typeref, OCI_OBJECTFREE_FORCE));
183
+ if (state != 0) {
184
+ rb_jump_tag(state);
185
+ }
186
+ }
187
+ return tdo;
144
188
  }
145
189
 
146
190
  static void oci8_named_type_check_offset(VALUE self, VALUE val_offset, VALUE ind_offset, size_t val_size, void **instancep, OCIInd **indp)
@@ -193,6 +237,10 @@ static VALUE get_attribute(VALUE self, VALUE datatype, VALUE typeinfo, void *dat
193
237
  return oci8_make_integer((OCINumber *)data, oci8_errhp);
194
238
  case ATTR_OCIDATE:
195
239
  return oci8_make_ocidate((OCIDate *)data);
240
+ case ATTR_TIMESTAMP:
241
+ return oci8_make_ocitimestamp(*(OCIDateTime**)data, FALSE);
242
+ case ATTR_TIMESTAMP_TZ:
243
+ return oci8_make_ocitimestamp(*(OCIDateTime**)data, TRUE);
196
244
  case ATTR_BINARY_DOUBLE:
197
245
  return rb_float_new(*(double*)data);
198
246
  case ATTR_BINARY_FLOAT:
@@ -371,6 +419,18 @@ static VALUE oci8_named_coll_set_coll_element(VALUE self, VALUE datatype, VALUE
371
419
  case ATTR_OCIDATE:
372
420
  cb_data.indp = &cb_data.ind;
373
421
  break;
422
+ case ATTR_TIMESTAMP:
423
+ chker2(OCIObjectNew(oci8_envhp, oci8_errhp, svcctx->hp.svc, OCI_TYPECODE_TIMESTAMP, NULL, NULL, OCI_DURATION_SESSION, TRUE, &cb_data.data.ptr),
424
+ svcctx);
425
+ chker2(OCIObjectGetInd(oci8_envhp, oci8_errhp, cb_data.data.ptr, (dvoid**)&cb_data.indp),
426
+ svcctx);
427
+ break;
428
+ case ATTR_TIMESTAMP_TZ:
429
+ chker2(OCIObjectNew(oci8_envhp, oci8_errhp, svcctx->hp.svc, OCI_TYPECODE_TIMESTAMP_TZ, NULL, NULL, OCI_DURATION_SESSION, TRUE, &cb_data.data.ptr),
430
+ svcctx);
431
+ chker2(OCIObjectGetInd(oci8_envhp, oci8_errhp, cb_data.data.ptr, (dvoid**)&cb_data.indp),
432
+ svcctx);
433
+ break;
374
434
  case ATTR_BINARY_DOUBLE:
375
435
  cb_data.data.dbl = 0.0;
376
436
  cb_data.indp = &cb_data.ind;
@@ -425,7 +485,7 @@ static VALUE set_coll_element_func(set_coll_element_cb_data_t *cb_data)
425
485
 
426
486
  chkerr(OCICollSize(oci8_envhp, oci8_errhp, coll, &size));
427
487
  if (RARRAY_LEN(val) < size) {
428
- chkerr(OCICollTrim(oci8_envhp, oci8_errhp, size - RARRAY_LEN(val), coll));
488
+ chkerr(OCICollTrim(oci8_envhp, oci8_errhp, (sb4)(size - RARRAY_LEN(val)), coll));
429
489
  }
430
490
  for (idx = 0; idx < RARRAY_LEN(val); idx++) {
431
491
  switch (FIX2INT(datatype)) {
@@ -465,6 +525,8 @@ static VALUE set_coll_element_ensure(set_coll_element_cb_data_t *cb_data)
465
525
  switch (FIX2INT(datatype)) {
466
526
  case ATTR_STRING:
467
527
  case ATTR_RAW:
528
+ case ATTR_TIMESTAMP:
529
+ case ATTR_TIMESTAMP_TZ:
468
530
  case ATTR_NAMED_TYPE:
469
531
  case ATTR_NAMED_COLLECTION:
470
532
  if (cb_data->data.ptr != NULL) {
@@ -497,13 +559,13 @@ static void set_attribute(VALUE self, VALUE datatype, VALUE typeinfo, void *data
497
559
  case ATTR_STRING:
498
560
  OCI8StringValue(val);
499
561
  chkerr(OCIStringAssignText(oci8_envhp, oci8_errhp,
500
- RSTRING_ORATEXT(val), RSTRING_LEN(val),
562
+ RSTRING_ORATEXT(val), RSTRING_LENINT(val),
501
563
  (OCIString **)data));
502
564
  break;
503
565
  case ATTR_RAW:
504
566
  StringValue(val);
505
567
  chkerr(OCIRawAssignBytes(oci8_envhp, oci8_errhp,
506
- RSTRING_ORATEXT(val), RSTRING_LEN(val),
568
+ RSTRING_ORATEXT(val), RSTRING_LENINT(val),
507
569
  (OCIRaw **)data));
508
570
  break;
509
571
  case ATTR_OCINUMBER:
@@ -516,6 +578,12 @@ static void set_attribute(VALUE self, VALUE datatype, VALUE typeinfo, void *data
516
578
  case ATTR_OCIDATE:
517
579
  oci8_set_ocidate((OCIDate*)data, val);
518
580
  break;
581
+ case ATTR_TIMESTAMP:
582
+ oci8_set_ocitimestamp_tz(*(OCIDateTime **)data, val, Qnil);
583
+ break;
584
+ case ATTR_TIMESTAMP_TZ:
585
+ oci8_set_ocitimestamp_tz(*(OCIDateTime **)data, val, Qnil);
586
+ break;
519
587
  case ATTR_BINARY_DOUBLE:
520
588
  *(double*)data = NUM2DBL(val);
521
589
  break;
@@ -612,45 +680,57 @@ static VALUE oci8_named_collection_alloc(VALUE klass)
612
680
  return oci8_allocate_typeddata(klass, &oci8_named_collection_data_type);
613
681
  }
614
682
 
683
+ typedef struct {
684
+ oci8_bind_t bind;
685
+ VALUE *obj;
686
+ } bind_named_type_t;
687
+
615
688
  static void bind_named_type_mark(oci8_base_t *base)
616
689
  {
617
- oci8_bind_t *obind = (oci8_bind_t *)base;
618
- oci8_hp_obj_t *oho = (oci8_hp_obj_t *)obind->valuep;
690
+ bind_named_type_t *bnt = (bind_named_type_t *)base;
619
691
 
620
- if (oho != NULL) {
692
+ if (bnt->obj != NULL) {
621
693
  ub4 idx = 0;
622
694
 
623
695
  do {
624
- rb_gc_mark(oho[idx].obj);
625
- } while (++idx < obind->maxar_sz);
696
+ rb_gc_mark(bnt->obj[idx]);
697
+ } while (++idx < bnt->bind.maxar_sz);
626
698
  }
627
- rb_gc_mark(obind->tdo);
699
+ rb_gc_mark(bnt->bind.tdo);
628
700
  }
629
701
 
630
702
  static void bind_named_type_free(oci8_base_t *base)
631
703
  {
632
- oci8_bind_t *obind = (oci8_bind_t *)base;
633
- oci8_hp_obj_t *oho = (oci8_hp_obj_t *)obind->valuep;
704
+ bind_named_type_t *bnt = (bind_named_type_t *)base;
705
+ void **hp = (void **)bnt->bind.valuep;
634
706
 
635
- if (oho != NULL) {
707
+ if (hp != NULL) {
636
708
  ub4 idx = 0;
637
709
 
638
710
  do {
639
- if (oho[idx].hp != NULL) {
640
- OCIObjectFree(oci8_envhp, oci8_errhp, oho[idx].hp, OCI_DEFAULT);
641
- oho[idx].hp = NULL;
711
+ if (hp[idx] != NULL) {
712
+ OCIObjectFree(oci8_envhp, oci8_errhp, hp[idx], OCI_DEFAULT);
713
+ hp[idx] = NULL;
642
714
  }
643
- } while (++idx < obind->maxar_sz);
715
+ } while (++idx < bnt->bind.maxar_sz);
716
+ }
717
+ if (bnt->obj != NULL) {
718
+ xfree(bnt->obj);
719
+ bnt->obj = NULL;
644
720
  }
645
721
  oci8_bind_free(base);
646
722
  }
647
723
 
648
724
  static VALUE bind_named_type_get(oci8_bind_t *obind, void *data, void *null_struct)
649
725
  {
650
- oci8_hp_obj_t *oho = (oci8_hp_obj_t *)data;
651
- return oho->obj;
726
+ bind_named_type_t *bnt = (bind_named_type_t *)obind;
727
+ ub4 idx = obind->curar_idx;
728
+
729
+ return bnt->obj[idx];
652
730
  }
653
731
 
732
+ NORETURN(static void bind_named_type_set(oci8_bind_t *obind, void *data, void **null_structp, VALUE val));
733
+
654
734
  static void bind_named_type_set(oci8_bind_t *obind, void *data, void **null_structp, VALUE val)
655
735
  {
656
736
  rb_raise(rb_eRuntimeError, "not supported");
@@ -658,10 +738,12 @@ static void bind_named_type_set(oci8_bind_t *obind, void *data, void **null_stru
658
738
 
659
739
  static void bind_named_type_init(oci8_bind_t *obind, VALUE svc, VALUE val, VALUE length)
660
740
  {
741
+ bind_named_type_t *bnt = (bind_named_type_t *)obind;
661
742
  VALUE tdo_obj = length;
662
743
 
663
744
  obind->value_sz = sizeof(void*);
664
- obind->alloc_sz = sizeof(oci8_hp_obj_t);
745
+ obind->alloc_sz = sizeof(void*);
746
+ bnt->obj = xcalloc(sizeof(VALUE), obind->maxar_sz ? obind->maxar_sz : 1);
665
747
 
666
748
  CHECK_TDO(tdo_obj);
667
749
  RB_OBJ_WRITE(obind->base.self, &obind->tdo, tdo_obj);
@@ -669,7 +751,8 @@ static void bind_named_type_init(oci8_bind_t *obind, VALUE svc, VALUE val, VALUE
669
751
 
670
752
  static void bind_named_type_init_elem(oci8_bind_t *obind, VALUE svc)
671
753
  {
672
- oci8_hp_obj_t *oho = (oci8_hp_obj_t *)obind->valuep;
754
+ bind_named_type_t *bnt = (bind_named_type_t *)obind;
755
+ void **hp = (void **)obind->valuep;
673
756
  oci8_base_t *tdo = DATA_PTR(obind->tdo);
674
757
  OCITypeCode tc = OCITypeTypeCode(oci8_envhp, oci8_errhp, tdo->hp.tdo);
675
758
  VALUE klass = Qnil;
@@ -687,14 +770,14 @@ static void bind_named_type_init_elem(oci8_bind_t *obind, VALUE svc)
687
770
  }
688
771
  svcctx = oci8_get_svcctx(svc);
689
772
  do {
690
- oho[idx].obj = rb_class_new_instance(0, NULL, klass);
691
- RB_OBJ_WRITTEN(obind->base.self, Qundef, oho[idx].obj);
692
- obj = DATA_PTR(oho[idx].obj);
693
- RB_OBJ_WRITE(oho[idx].obj, &obj->tdo, obind->tdo);
694
- obj->instancep = (char**)&oho[idx].hp;
773
+ bnt->obj[idx] = rb_class_new_instance(0, NULL, klass);
774
+ RB_OBJ_WRITTEN(obind->base.self, Qundef, bnt->obj[idx]);
775
+ obj = DATA_PTR(bnt->obj[idx]);
776
+ RB_OBJ_WRITE(bnt->obj[idx], &obj->tdo, obind->tdo);
777
+ obj->instancep = (char**)&hp[idx];
695
778
  obj->null_structp = (char**)&obind->u.null_structs[idx];
696
779
  oci8_link_to_parent(&obj->base, &obind->base);
697
- RB_OBJ_WRITTEN(oho[idx].obj, Qundef, obind->base.self);
780
+ RB_OBJ_WRITTEN(bnt->obj[idx], Qundef, obind->base.self);
698
781
 
699
782
  chker2(OCIObjectNew(oci8_envhp, oci8_errhp, svcctx->base.hp.svc, tc, tdo->hp.tdo, NULL, OCI_DURATION_SESSION, TRUE, (dvoid**)obj->instancep),
700
783
  &svcctx->base);
@@ -736,7 +819,7 @@ static const oci8_bind_data_type_t bind_named_type_data_type = {
736
819
  #endif
737
820
  },
738
821
  bind_named_type_free,
739
- sizeof(oci8_bind_t)
822
+ sizeof(bind_named_type_t)
740
823
  },
741
824
  bind_named_type_get,
742
825
  bind_named_type_set,
@@ -754,8 +837,11 @@ static VALUE bind_named_type_alloc(VALUE klass)
754
837
 
755
838
  void Init_oci_object(VALUE cOCI8)
756
839
  {
840
+ cOCI8MetadataType = rb_eval_string("OCI8::Metadata::Type");
757
841
  id_to_value = rb_intern("to_value");
758
842
  id_set_attributes = rb_intern("attributes=");
843
+ id_get_tdo_by_metadata = rb_intern("get_tdo_by_metadata");
844
+ id_at_is_final_type = rb_intern("@is_final_type");
759
845
 
760
846
  /* OCI8::TDO */
761
847
  cOCI8TDO = oci8_define_class_under(cOCI8, "TDO", &oci8_tdo_data_type, oci8_tdo_alloc);
@@ -773,6 +859,10 @@ void Init_oci_object(VALUE cOCI8)
773
859
  /* @private */
774
860
  rb_define_const(cOCI8TDO, "ATTR_OCIDATE", INT2FIX(ATTR_OCIDATE));
775
861
  /* @private */
862
+ rb_define_const(cOCI8TDO, "ATTR_TIMESTAMP", INT2FIX(ATTR_TIMESTAMP));
863
+ /* @private */
864
+ rb_define_const(cOCI8TDO, "ATTR_TIMESTAMP_TZ", INT2FIX(ATTR_TIMESTAMP_TZ));
865
+ /* @private */
776
866
  rb_define_const(cOCI8TDO, "ATTR_BINARY_DOUBLE", INT2FIX(ATTR_BINARY_DOUBLE));
777
867
  /* @private */
778
868
  rb_define_const(cOCI8TDO, "ATTR_BINARY_FLOAT", INT2FIX(ATTR_BINARY_FLOAT));