ruby-oci8 2.2.0.2 → 2.2.12

Sign up to get free protection for your applications and to get access to all the features.
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/bind.c CHANGED
@@ -11,6 +11,7 @@
11
11
  #endif
12
12
 
13
13
  static ID id_bind_type;
14
+ static ID id_charset_form;
14
15
  static VALUE sym_length;
15
16
  static VALUE sym_length_semantics;
16
17
  static VALUE sym_char;
@@ -25,6 +26,29 @@ typedef struct {
25
26
  ub1 csfrm;
26
27
  } oci8_bind_string_t;
27
28
 
29
+ static ub4 initial_chunk_size = 32 * 1024;
30
+ static ub4 max_chunk_size = 8 * 1024 * 1024;
31
+
32
+ typedef struct chunk {
33
+ struct chunk *next;
34
+ ub4 alloc_len;
35
+ ub4 used_len;
36
+ char buf[1];
37
+ } chunk_t;
38
+
39
+ typedef struct {
40
+ chunk_t *head;
41
+ chunk_t **tail;
42
+ chunk_t **inpos;
43
+ } chunk_buf_t;
44
+
45
+ typedef struct {
46
+ oci8_bind_t obind;
47
+ ub1 csfrm;
48
+ } oci8_bind_long_t;
49
+
50
+ #define IS_BIND_LONG(obind) (((oci8_bind_data_type_t*)obind->base.data_type)->dty == SQLT_CHR)
51
+
28
52
  const oci8_handle_data_type_t oci8_bind_data_type = {
29
53
  {
30
54
  "OCI8::BindType::Base",
@@ -61,7 +85,7 @@ static void bind_string_set(oci8_bind_t *obind, void *data, void **null_structp,
61
85
  rb_raise(rb_eArgError, "too long String to set. (%ld for %d)", RSTRING_LEN(val), obs->bytelen);
62
86
  }
63
87
  memcpy(vstr->buf, RSTRING_PTR(val), RSTRING_LEN(val));
64
- vstr->size = RSTRING_LEN(val);
88
+ vstr->size = RSTRING_LENINT(val);
65
89
  }
66
90
 
67
91
  static void bind_string_init(oci8_bind_t *obind, VALUE svc, VALUE val, VALUE param)
@@ -171,7 +195,7 @@ static void bind_raw_set(oci8_bind_t *obind, void *data, void **null_structp, VA
171
195
  rb_raise(rb_eArgError, "too long String to set. (%ld for %d)", RSTRING_LEN(val), obs->bytelen);
172
196
  }
173
197
  memcpy(vstr->buf, RSTRING_PTR(val), RSTRING_LEN(val));
174
- vstr->size = RSTRING_LEN(val);
198
+ vstr->size = RSTRING_LENINT(val);
175
199
  }
176
200
 
177
201
  static const oci8_bind_data_type_t bind_raw_data_type = {
@@ -224,9 +248,6 @@ static void bind_binary_double_init(oci8_bind_t *obind, VALUE svc, VALUE val, VA
224
248
  obind->alloc_sz = sizeof(double);
225
249
  }
226
250
 
227
- #ifndef SQLT_BDOUBLE
228
- #define SQLT_BDOUBLE 22
229
- #endif
230
251
  static const oci8_bind_data_type_t bind_binary_double_data_type = {
231
252
  {
232
253
  {
@@ -257,6 +278,347 @@ static VALUE bind_binary_double_alloc(VALUE klass)
257
278
  return oci8_allocate_typeddata(klass, &bind_binary_double_data_type.base);
258
279
  }
259
280
 
281
+ /*
282
+ * bind_boolean
283
+ */
284
+ static VALUE bind_boolean_get(oci8_bind_t *obind, void *data, void *null_struct)
285
+ {
286
+ return *(int*)data ? Qtrue : Qfalse;
287
+ }
288
+
289
+ static void bind_boolean_set(oci8_bind_t *obind, void *data, void **null_structp, VALUE val)
290
+ {
291
+ *(int*)data = RTEST(val) ? -1 : 0;
292
+ }
293
+
294
+ static void bind_boolean_init(oci8_bind_t *obind, VALUE svc, VALUE val, VALUE length)
295
+ {
296
+ obind->value_sz = sizeof(int);
297
+ obind->alloc_sz = sizeof(int);
298
+ }
299
+
300
+ #ifndef SQLT_BOL
301
+ #define SQLT_BOL 252
302
+ #endif
303
+ static const oci8_bind_data_type_t bind_boolean_data_type = {
304
+ {
305
+ {
306
+ "OCI8::BindType::Boolean",
307
+ {
308
+ NULL,
309
+ oci8_handle_cleanup,
310
+ oci8_handle_size,
311
+ },
312
+ &oci8_bind_data_type.rb_data_type, NULL,
313
+ #ifdef RUBY_TYPED_WB_PROTECTED
314
+ RUBY_TYPED_WB_PROTECTED,
315
+ #endif
316
+ },
317
+ oci8_bind_free,
318
+ sizeof(oci8_bind_t)
319
+ },
320
+ bind_boolean_get,
321
+ bind_boolean_set,
322
+ bind_boolean_init,
323
+ NULL,
324
+ NULL,
325
+ SQLT_BOL,
326
+ };
327
+
328
+ static VALUE bind_boolean_alloc(VALUE klass)
329
+ {
330
+ return oci8_allocate_typeddata(klass, &bind_boolean_data_type.base);
331
+ }
332
+
333
+ /*
334
+ * bind_long
335
+ */
336
+ static chunk_t *next_chunk(chunk_buf_t *cb)
337
+ {
338
+ chunk_t *chunk;
339
+
340
+ if (*cb->tail != NULL) {
341
+ chunk = *cb->tail;
342
+ } else {
343
+ ub4 alloc_len;
344
+ if (cb->head == NULL) {
345
+ alloc_len = initial_chunk_size;
346
+ } else {
347
+ alloc_len = ((chunk_t*)((size_t)cb->tail - offsetof(chunk_t, next)))->alloc_len * 2;
348
+ if (alloc_len > max_chunk_size) {
349
+ alloc_len = max_chunk_size;
350
+ }
351
+ }
352
+ chunk = xmalloc(offsetof(chunk_t, buf) + alloc_len);
353
+ chunk->next = NULL;
354
+ chunk->alloc_len = alloc_len;
355
+ *cb->tail = chunk;
356
+ }
357
+ cb->tail = &chunk->next;
358
+ return chunk;
359
+ }
360
+
361
+ static sb4 define_callback(void *octxp, OCIDefine *defnp, ub4 iter, void **bufpp, ub4 **alenp, ub1 *piecep, void **indp, ub2 **rcodep)
362
+ {
363
+ oci8_bind_t *obind = (oci8_bind_t *)octxp;
364
+ chunk_buf_t *cb = ((chunk_buf_t*)obind->valuep) + iter;
365
+ chunk_t *chunk;
366
+
367
+ if (*piecep == OCI_FIRST_PIECE) {
368
+ cb->tail = &cb->head;
369
+ }
370
+ chunk = next_chunk(cb);
371
+ chunk->used_len = chunk->alloc_len;
372
+ *bufpp = chunk->buf;
373
+ *alenp = &chunk->used_len;
374
+ *indp = (void*)&obind->u.inds[iter];
375
+ *rcodep = NULL;
376
+ return OCI_CONTINUE;
377
+ }
378
+
379
+ static sb4 in_bind_callback(void *ictxp, OCIBind *bindp, ub4 iter, ub4 index, void **bufpp, ub4 *alenp, ub1 *piecep, void **indp)
380
+ {
381
+ oci8_bind_t *obind = (oci8_bind_t *)ictxp;
382
+ chunk_buf_t *cb = ((chunk_buf_t*)obind->valuep) + iter;
383
+
384
+ if (cb->tail == &cb->head) {
385
+ /* empty string */
386
+ *bufpp = (void *)"";
387
+ *alenp = 0;
388
+ *piecep = OCI_ONE_PIECE;
389
+ } else {
390
+ chunk_t *chunk = *cb->inpos;
391
+ *bufpp = chunk->buf;
392
+ *alenp = chunk->used_len;
393
+ if (cb->tail == &cb->head->next) {
394
+ *piecep = OCI_ONE_PIECE;
395
+ } else if (cb->inpos == &cb->head) {
396
+ *piecep = OCI_FIRST_PIECE;
397
+ cb->inpos = &chunk->next;
398
+ } else if (&chunk->next != cb->tail) {
399
+ *piecep = OCI_NEXT_PIECE;
400
+ cb->inpos = &chunk->next;
401
+ } else {
402
+ *piecep = OCI_LAST_PIECE;
403
+ cb->inpos = &cb->head;
404
+ }
405
+ }
406
+ *indp = (void*)&obind->u.inds[iter];
407
+ return OCI_CONTINUE;
408
+ }
409
+
410
+ static sb4 out_bind_callback(void *octxp, OCIBind *bindp, ub4 iter, ub4 index, void **bufpp, ub4 **alenp, ub1 *piecep, void **indp, ub2 **rcodep)
411
+ {
412
+ oci8_bind_t *obind = (oci8_bind_t *)octxp;
413
+ chunk_buf_t *cb = ((chunk_buf_t*)obind->valuep) + iter;
414
+ chunk_t *chunk;
415
+
416
+ if (*piecep == OCI_ONE_PIECE) {
417
+ *piecep = OCI_FIRST_PIECE;
418
+ cb->tail = &cb->head;
419
+ }
420
+ chunk = next_chunk(cb);
421
+ chunk->used_len = chunk->alloc_len;
422
+ *bufpp = chunk->buf;
423
+ *alenp = &chunk->used_len;
424
+ *indp = (void*)&obind->u.inds[iter];
425
+ *rcodep = NULL;
426
+ return OCI_CONTINUE;
427
+ }
428
+
429
+ static void bind_long_free(oci8_base_t *base)
430
+ {
431
+ oci8_bind_t *obind = (oci8_bind_t *)base;
432
+ chunk_buf_t *cb = (chunk_buf_t *)obind->valuep;
433
+
434
+ if (cb != NULL) {
435
+ ub4 idx = 0;
436
+ do {
437
+ chunk_t *chunk, *chunk_next;
438
+ for (chunk = cb[idx].head; chunk != NULL; chunk = chunk_next) {
439
+ chunk_next = chunk->next;
440
+ xfree(chunk);
441
+ }
442
+ } while (++idx < obind->maxar_sz);
443
+ }
444
+ oci8_bind_free(base);
445
+ }
446
+
447
+ static VALUE bind_long_get(oci8_bind_t *obind, void *data, void *null_struct)
448
+ {
449
+ chunk_buf_t *cb = (chunk_buf_t *)data;
450
+ chunk_t *chunk;
451
+ long len = 0;
452
+ VALUE str;
453
+ char *buf;
454
+
455
+ for (chunk = cb->head; chunk != *cb->tail; chunk = chunk->next) {
456
+ len += chunk->used_len;
457
+ }
458
+ str = rb_str_buf_new(len);
459
+ buf = RSTRING_PTR(str);
460
+ for (chunk = cb->head; chunk != *cb->tail; chunk = chunk->next) {
461
+ memcpy(buf, chunk->buf, chunk->used_len);
462
+ buf += chunk->used_len;
463
+ }
464
+ rb_str_set_len(str, len);
465
+ if (IS_BIND_LONG(obind)) {
466
+ rb_encoding *enc = rb_default_internal_encoding();
467
+
468
+ rb_enc_associate(str, oci8_encoding);
469
+ if (enc != NULL) {
470
+ str = rb_str_conv_enc(str, oci8_encoding, enc);
471
+ }
472
+ }
473
+ return str;
474
+ }
475
+
476
+ static void bind_long_set(oci8_bind_t *obind, void *data, void **null_structp, VALUE val)
477
+ {
478
+ chunk_buf_t *cb = (chunk_buf_t *)data;
479
+ ub4 len;
480
+ const char *buf;
481
+
482
+ if (IS_BIND_LONG(obind)) {
483
+ OCI8StringValue(val);
484
+ } else {
485
+ StringValue(val);
486
+ }
487
+ len = (ub4)RSTRING_LEN(val);
488
+ buf = RSTRING_PTR(val);
489
+ cb->tail = &cb->head;
490
+ while (1) {
491
+ chunk_t *chunk = next_chunk(cb);
492
+ if (len <= chunk->alloc_len) {
493
+ memcpy(chunk->buf, buf, len);
494
+ chunk->used_len = len;
495
+ break;
496
+ }
497
+ memcpy(chunk->buf, buf, chunk->alloc_len);
498
+ chunk->used_len = chunk->alloc_len;
499
+ len -= chunk->alloc_len;
500
+ buf += chunk->alloc_len;
501
+ }
502
+ }
503
+
504
+ static void bind_long_init(oci8_bind_t *obind, VALUE svc, VALUE val, VALUE param)
505
+ {
506
+ if (IS_BIND_LONG(obind)) {
507
+ oci8_bind_long_t *obl = (oci8_bind_long_t *)obind;
508
+ VALUE nchar;
509
+
510
+ if (rb_respond_to(param, id_charset_form)) {
511
+ VALUE csfrm = rb_funcall(param, id_charset_form, 0);
512
+ nchar = (csfrm == sym_nchar) ? Qtrue : Qfalse;
513
+ } else {
514
+ Check_Type(param, T_HASH);
515
+ nchar = rb_hash_aref(param, sym_nchar);
516
+ }
517
+
518
+ if (RTEST(nchar)) {
519
+ obl->csfrm = SQLCS_NCHAR; /* bind as NCHAR/NVARCHAR2 */
520
+ } else {
521
+ obl->csfrm = SQLCS_IMPLICIT; /* bind as CHAR/VARCHAR2 */
522
+ }
523
+ }
524
+ obind->value_sz = SB4MAXVAL;
525
+ obind->alloc_sz = sizeof(chunk_buf_t);
526
+ }
527
+
528
+ static void bind_long_init_elem(oci8_bind_t *obind, VALUE svc)
529
+ {
530
+ chunk_buf_t *cb = (chunk_buf_t *)obind->valuep;
531
+ ub4 idx = 0;
532
+
533
+ do {
534
+ cb[idx].tail = &cb[idx].head;
535
+ cb[idx].inpos = &cb[idx].head;
536
+ } while (++idx < obind->maxar_sz);
537
+ }
538
+
539
+ static void bind_long_post_bind_hook(oci8_bind_t *obind)
540
+ {
541
+ oci8_bind_long_t *ds = (oci8_bind_long_t *)obind;
542
+
543
+ if (IS_BIND_LONG(obind)) {
544
+ chker2(OCIAttrSet(obind->base.hp.ptr, obind->base.type, (void*)&ds->csfrm, 0, OCI_ATTR_CHARSET_FORM, oci8_errhp),
545
+ &obind->base);
546
+ }
547
+ switch (obind->base.type) {
548
+ case OCI_HTYPE_DEFINE:
549
+ chker2(OCIDefineDynamic(obind->base.hp.dfn, oci8_errhp, obind, define_callback),
550
+ &obind->base);
551
+ break;
552
+ case OCI_HTYPE_BIND:
553
+ chker2(OCIBindDynamic(obind->base.hp.bnd, oci8_errhp, obind, in_bind_callback,
554
+ obind, out_bind_callback),
555
+ &obind->base);
556
+ break;
557
+ }
558
+ }
559
+
560
+ static const oci8_bind_data_type_t bind_long_data_type = {
561
+ {
562
+ {
563
+ "OCI8::BindType::Long",
564
+ {
565
+ NULL,
566
+ oci8_handle_cleanup,
567
+ oci8_handle_size,
568
+ },
569
+ &oci8_bind_data_type.rb_data_type, NULL,
570
+ #ifdef RUBY_TYPED_WB_PROTECTED
571
+ RUBY_TYPED_WB_PROTECTED,
572
+ #endif
573
+ },
574
+ bind_long_free,
575
+ sizeof(oci8_bind_long_t)
576
+ },
577
+ bind_long_get,
578
+ bind_long_set,
579
+ bind_long_init,
580
+ bind_long_init_elem,
581
+ NULL,
582
+ SQLT_CHR,
583
+ bind_long_post_bind_hook,
584
+ };
585
+
586
+ static VALUE bind_long_alloc(VALUE klass)
587
+ {
588
+ return oci8_allocate_typeddata(klass, &bind_long_data_type.base);
589
+ }
590
+
591
+ static const oci8_bind_data_type_t bind_long_raw_data_type = {
592
+ {
593
+ {
594
+ "OCI8::BindType::LongRaw",
595
+ {
596
+ NULL,
597
+ oci8_handle_cleanup,
598
+ oci8_handle_size,
599
+ },
600
+ &oci8_bind_data_type.rb_data_type, NULL,
601
+ #ifdef RUBY_TYPED_WB_PROTECTED
602
+ RUBY_TYPED_WB_PROTECTED,
603
+ #endif
604
+ },
605
+ bind_long_free,
606
+ sizeof(oci8_bind_long_t)
607
+ },
608
+ bind_long_get,
609
+ bind_long_set,
610
+ bind_long_init,
611
+ bind_long_init_elem,
612
+ NULL,
613
+ SQLT_BIN,
614
+ bind_long_post_bind_hook,
615
+ };
616
+
617
+ static VALUE bind_long_raw_alloc(VALUE klass)
618
+ {
619
+ return oci8_allocate_typeddata(klass, &bind_long_raw_data_type.base);
620
+ }
621
+
260
622
  static VALUE oci8_bind_get(VALUE self)
261
623
  {
262
624
  oci8_bind_t *obind = TO_BIND(self);
@@ -271,11 +633,20 @@ static VALUE oci8_bind_get(VALUE self)
271
633
  return data_type->get(obind, (void*)((size_t)obind->valuep + obind->alloc_sz * idx), null_structp);
272
634
  }
273
635
 
274
- static VALUE oci8_bind_get_data(VALUE self)
636
+ static VALUE oci8_bind_get_data(int argc, VALUE *argv, VALUE self)
275
637
  {
276
638
  oci8_bind_t *obind = TO_BIND(self);
639
+ VALUE index;
277
640
 
278
- if (obind->maxar_sz == 0) {
641
+ rb_scan_args(argc, argv, "01", &index);
642
+ if (!NIL_P(index)) {
643
+ ub4 idx = NUM2UINT(index);
644
+ if (idx >= obind->maxar_sz) {
645
+ rb_raise(rb_eRuntimeError, "data index is too big. (%u for %u)", idx, obind->maxar_sz);
646
+ }
647
+ obind->curar_idx = idx;
648
+ return rb_funcall(self, oci8_id_get, 0);
649
+ } else if (obind->maxar_sz == 0) {
279
650
  obind->curar_idx = 0;
280
651
  return rb_funcall(self, oci8_id_get, 0);
281
652
  } else {
@@ -329,7 +700,7 @@ static VALUE oci8_bind_set_data(VALUE self, VALUE val)
329
700
  ub4 idx;
330
701
  Check_Type(val, T_ARRAY);
331
702
 
332
- size = RARRAY_LEN(val);
703
+ size = RARRAY_LENINT(val);
333
704
  if (size > obind->maxar_sz) {
334
705
  rb_raise(rb_eRuntimeError, "over the max array size");
335
706
  }
@@ -342,6 +713,36 @@ static VALUE oci8_bind_set_data(VALUE self, VALUE val)
342
713
  return self;
343
714
  }
344
715
 
716
+ static VALUE get_initial_chunk_size(VALUE klass)
717
+ {
718
+ return UINT2NUM(initial_chunk_size);
719
+ }
720
+
721
+ static VALUE set_initial_chunk_size(VALUE klass, VALUE arg)
722
+ {
723
+ ub4 size = NUM2UINT(arg);
724
+ if (size == 0) {
725
+ rb_raise(rb_eArgError, "Could not set zero");
726
+ }
727
+ initial_chunk_size = size;
728
+ return arg;
729
+ }
730
+
731
+ static VALUE get_max_chunk_size(VALUE klass)
732
+ {
733
+ return UINT2NUM(max_chunk_size);
734
+ }
735
+
736
+ static VALUE set_max_chunk_size(VALUE klass, VALUE arg)
737
+ {
738
+ ub4 size = NUM2UINT(arg);
739
+ if (size == 0) {
740
+ rb_raise(rb_eArgError, "Could not set zero");
741
+ }
742
+ max_chunk_size = size;
743
+ return arg;
744
+ }
745
+
345
746
  static VALUE oci8_bind_initialize(VALUE self, VALUE svc, VALUE val, VALUE length, VALUE max_array_size)
346
747
  {
347
748
  oci8_bind_t *obind = TO_BIND(self);
@@ -407,6 +808,7 @@ void Init_oci8_bind(VALUE klass)
407
808
  {
408
809
  cOCI8BindTypeBase = klass;
409
810
  id_bind_type = rb_intern("bind_type");
811
+ id_charset_form = rb_intern("charset_form");
410
812
  sym_length = ID2SYM(rb_intern("length"));
411
813
  sym_length_semantics = ID2SYM(rb_intern("length_semantics"));
412
814
  sym_char = ID2SYM(rb_intern("char"));
@@ -415,11 +817,21 @@ void Init_oci8_bind(VALUE klass)
415
817
  rb_define_method(cOCI8BindTypeBase, "initialize", oci8_bind_initialize, 4);
416
818
  rb_define_method(cOCI8BindTypeBase, "get", oci8_bind_get, 0);
417
819
  rb_define_method(cOCI8BindTypeBase, "set", oci8_bind_set, 1);
418
- rb_define_private_method(cOCI8BindTypeBase, "get_data", oci8_bind_get_data, 0);
820
+ rb_define_private_method(cOCI8BindTypeBase, "get_data", oci8_bind_get_data, -1);
419
821
  rb_define_private_method(cOCI8BindTypeBase, "set_data", oci8_bind_set_data, 1);
420
822
 
823
+ rb_define_singleton_method(klass, "initial_chunk_size", get_initial_chunk_size, 0);
824
+ rb_define_singleton_method(klass, "initial_chunk_size=", set_initial_chunk_size, 1);
825
+ rb_define_singleton_method(klass, "max_chunk_size", get_max_chunk_size, 0);
826
+ rb_define_singleton_method(klass, "max_chunk_size=", set_max_chunk_size, 1);
827
+
421
828
  /* register primitive data types. */
422
829
  oci8_define_bind_class("String", &bind_string_data_type, bind_string_alloc);
423
830
  oci8_define_bind_class("RAW", &bind_raw_data_type, bind_raw_alloc);
424
831
  oci8_define_bind_class("BinaryDouble", &bind_binary_double_data_type, bind_binary_double_alloc);
832
+ if (oracle_client_version >= ORAVER_12_1) {
833
+ oci8_define_bind_class("Boolean", &bind_boolean_data_type, bind_boolean_alloc);
834
+ }
835
+ klass = oci8_define_bind_class("Long", &bind_long_data_type, bind_long_alloc);
836
+ klass = oci8_define_bind_class("LongRaw", &bind_long_data_type, bind_long_raw_alloc);
425
837
  }
@@ -144,13 +144,13 @@ static VALUE oci8_cpool_initialize(int argc, VALUE *argv, VALUE self)
144
144
  chker2(OCIConnectionPoolCreate(oci8_envhp, oci8_errhp, cpool->base.hp.poolhp,
145
145
  &pool_name, &pool_name_len,
146
146
  NIL_P(dbname) ? NULL : RSTRING_ORATEXT(dbname),
147
- NIL_P(dbname) ? 0 : RSTRING_LEN(dbname),
147
+ NIL_P(dbname) ? 0 : RSTRING_LENINT(dbname),
148
148
  FIX2UINT(conn_min), FIX2UINT(conn_max),
149
149
  FIX2UINT(conn_incr),
150
150
  NIL_P(username) ? NULL : RSTRING_ORATEXT(username),
151
- NIL_P(username) ? 0 : RSTRING_LEN(username),
151
+ NIL_P(username) ? 0 : RSTRING_LENINT(username),
152
152
  NIL_P(password) ? NULL : RSTRING_ORATEXT(password),
153
- NIL_P(password) ? 0 : RSTRING_LEN(password),
153
+ NIL_P(password) ? 0 : RSTRING_LENINT(password),
154
154
  OCI_DEFAULT),
155
155
  &cpool->base);
156
156
  RB_OBJ_WRITE(cpool->base.self, &cpool->pool_name, rb_str_new(TO_CHARPTR(pool_name), pool_name_len));
data/ext/oci8/encoding.c CHANGED
@@ -23,7 +23,7 @@ rb_encoding *oci8_encoding;
23
23
  * Returns the Oracle character set name from the specified
24
24
  * character set ID if it is valid. Otherwise, +nil+ is returned.
25
25
  *
26
- * @param [Fixnum] charset_id Oracle character set id
26
+ * @param [Integer] charset_id Oracle character set id
27
27
  * @return [String] Oracle character set name or nil
28
28
  * @since 2.2.0
29
29
  */
@@ -48,7 +48,7 @@ VALUE oci8_s_charset_id2name(VALUE klass, VALUE csid)
48
48
  * character set name if it is valid. Othewise, +nil+ is returned.
49
49
  *
50
50
  * @param [String] charset_name Oracle character set name
51
- * @return [Fixnum] Oracle character set id or nil
51
+ * @return [Integer] Oracle character set id or nil
52
52
  * @since 2.2.0
53
53
  */
54
54
  static VALUE oci8_s_charset_name2id(VALUE klass, VALUE name)
@@ -71,7 +71,7 @@ static VALUE oci8_s_charset_name2id(VALUE klass, VALUE name)
71
71
  * internal buffer size of a string bind variable whose nls length
72
72
  * semantics is char.
73
73
  *
74
- * @return [Fixnum] NLS ratio
74
+ * @return [Integer] NLS ratio
75
75
  * @since 2.1.0
76
76
  * @private
77
77
  */
@@ -150,7 +150,7 @@ static VALUE oci8_set_encoding(VALUE klass, VALUE encoding)
150
150
  * character set name if it is valid. Othewise, +nil+ is returned.
151
151
  *
152
152
  * @param [String] charset_name Oracle character set name
153
- * @return [Fixnum] Oracle character set id or nil
153
+ * @return [Integer] Oracle character set id or nil
154
154
  * @since 2.0.0
155
155
  * @deprecated Use {OCI8.charset_name2id} instead.
156
156
  */
@@ -167,7 +167,7 @@ static VALUE oci8_charset_name2id(VALUE svc, VALUE name)
167
167
  * Returns the Oracle character set name from the specified
168
168
  * character set ID if it is valid. Otherwise, +nil+ is returned.
169
169
  *
170
- * @param [Fixnum] charset_id Oracle character set id
170
+ * @param [Integer] charset_id Oracle character set id
171
171
  * @return [String] Oracle character set name or nil
172
172
  * @since 2.0.0
173
173
  * @deprecated Use {OCI8.charset_id2name} instead.
data/ext/oci8/env.c CHANGED
@@ -14,11 +14,17 @@ OCIEnv *oci8_global_envhp;
14
14
  OCIEnv *oci8_make_envhp(void)
15
15
  {
16
16
  sword rv;
17
+ OCIEnv *envhp = NULL;
17
18
 
18
- rv = OCIEnvCreate(&oci8_global_envhp, oci8_env_mode, NULL, NULL, NULL, NULL, 0, NULL);
19
+ rv = OCIEnvCreate(&envhp, oci8_env_mode, NULL, NULL, NULL, NULL, 0, NULL);
19
20
  if (rv != OCI_SUCCESS) {
20
- oci8_raise_init_error();
21
+ if (envhp != NULL) {
22
+ oci8_env_free_and_raise(envhp, rv);
23
+ } else {
24
+ oci8_raise_init_error();
25
+ }
21
26
  }
27
+ oci8_global_envhp = envhp;
22
28
  return oci8_global_envhp;
23
29
  }
24
30
 
data/ext/oci8/error.c CHANGED
@@ -75,6 +75,21 @@ retry:
75
75
  return rb_external_str_new_with_enc(errbuf, len, oci8_encoding);
76
76
  }
77
77
 
78
+ /*
79
+ * Don't call rb_class_new_instance() with more than one argument in this function.
80
+ * This may be called before OCIError#initialize is defined in lib/oci8/oci8.rb.
81
+ */
82
+ static VALUE oci_exception_new(VALUE klass, VALUE msg, VALUE code, VALUE sql, VALUE parse_error_offset)
83
+ {
84
+ VALUE obj = rb_class_new_instance(NIL_P(msg) ? 0 : 1, &msg, klass);
85
+ if (rb_obj_is_kind_of(obj, eOCIError)) {
86
+ rb_ivar_set(obj, oci8_id_at_code, code);
87
+ rb_ivar_set(obj, oci8_id_at_sql, sql);
88
+ rb_ivar_set(obj, oci8_id_at_parse_error_offset, parse_error_offset);
89
+ }
90
+ return obj;
91
+ }
92
+
78
93
  static VALUE oci8_make_exc(dvoid *errhp, sword status, ub4 type, OCIStmt *stmthp, const char *file, int line)
79
94
  {
80
95
  VALUE exc;
@@ -84,24 +99,19 @@ static VALUE oci8_make_exc(dvoid *errhp, sword status, ub4 type, OCIStmt *stmthp
84
99
  VALUE parse_error_offset = Qnil;
85
100
  VALUE sql = Qnil;
86
101
  int rv;
87
- VALUE args[4];
88
- int numarg = 1;
89
102
 
90
103
  switch (status) {
91
104
  case OCI_ERROR:
92
105
  exc = eOCIError;
93
106
  msg = get_error_msg(errhp, type, "Error", &errcode);
94
- numarg = 4;
95
107
  break;
96
108
  case OCI_SUCCESS_WITH_INFO:
97
109
  exc = eOCISuccessWithInfo;
98
110
  msg = get_error_msg(errhp, type, "Error", &errcode);
99
- numarg = 4;
100
111
  break;
101
112
  case OCI_NO_DATA:
102
113
  exc = eOCINoData;
103
114
  msg = get_error_msg(errhp, type, "No Data", &errcode);
104
- numarg = 4;
105
115
  break;
106
116
  case OCI_INVALID_HANDLE:
107
117
  exc = eOCIInvalidHandle;
@@ -138,11 +148,7 @@ static VALUE oci8_make_exc(dvoid *errhp, sword status, ub4 type, OCIStmt *stmthp
138
148
  sql = rb_external_str_new_with_enc(TO_CHARPTR(text), size, oci8_encoding);
139
149
  }
140
150
  }
141
- args[0] = msg;
142
- args[1] = INT2FIX(errcode);
143
- args[2] = sql;
144
- args[3] = parse_error_offset;
145
- exc = rb_class_new_instance(numarg, args, exc);
151
+ exc = oci_exception_new(exc, msg, INT2FIX(errcode), sql, parse_error_offset);
146
152
  return set_backtrace(exc, file, line);
147
153
  }
148
154
 
@@ -208,9 +214,13 @@ void oci8_do_raise(OCIError *errhp, sword status, OCIStmt *stmthp, const char *f
208
214
  rb_exc_raise(oci8_make_exc(errhp, status, OCI_HTYPE_ERROR, stmthp, file, line));
209
215
  }
210
216
 
211
- void oci8_do_env_raise(OCIEnv *envhp, sword status, const char *file, int line)
217
+ void oci8_do_env_raise(OCIEnv *envhp, sword status, int free_envhp, const char *file, int line)
212
218
  {
213
- rb_exc_raise(oci8_make_exc(envhp, status, OCI_HTYPE_ENV, NULL, file, line));
219
+ VALUE exc = oci8_make_exc(envhp, status, OCI_HTYPE_ENV, NULL, file, line);
220
+ if (free_envhp) {
221
+ OCIHandleFree(envhp, OCI_HTYPE_ENV);
222
+ }
223
+ rb_exc_raise(exc);
214
224
  }
215
225
 
216
226
  void oci8_do_raise_init_error(const char *file, int line)
@@ -255,11 +265,9 @@ VALUE oci8_get_error_message(ub4 msgno, const char *default_msg)
255
265
  void oci8_do_raise_by_msgno(ub4 msgno, const char *default_msg, const char *file, int line)
256
266
  {
257
267
  VALUE msg = oci8_get_error_message(msgno, default_msg);
258
- VALUE args[2];
259
- args[0] = msg;
260
- args[1] = INT2FIX(-1);
268
+ VALUE exc = oci_exception_new(eOCIError, msg, INT2FIX(-1), Qnil, Qnil);
261
269
 
262
- rb_exc_raise(set_backtrace(rb_class_new_instance(2, args, eOCIError), file, line));
270
+ rb_exc_raise(set_backtrace(exc, file, line));
263
271
  }
264
272
 
265
273
  void oci8_check_error_(sword status, oci8_base_t *base, OCIStmt *stmthp, const char *file, int line)