ruby-oci8 2.2.6.1 → 2.2.7
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.
- data/ChangeLog +52 -3
- data/NEWS +106 -54
- data/dist-files +1 -1
- data/docs/install-instant-client.md +1 -0
- data/ext/oci8/apiwrap.yml +20 -0
- data/ext/oci8/bind.c +364 -3
- data/ext/oci8/lob.c +22 -29
- data/ext/oci8/object.c +37 -24
- data/ext/oci8/oci8.c +9 -11
- data/ext/oci8/oraconf.rb +2 -2
- data/ext/oci8/stmt.c +47 -12
- data/lib/oci8.rb +1 -1
- data/lib/oci8/bindtype.rb +0 -14
- data/lib/oci8/check_load_error.rb +51 -16
- data/lib/oci8/cursor.rb +46 -13
- data/lib/oci8/oci8.rb +1 -1
- data/lib/oci8/version.rb +1 -1
- data/ruby-oci8.gemspec +1 -2
- data/test/README.md +40 -0
- data/test/config.rb +1 -1
- data/test/test_oci8.rb +154 -43
- metadata +4 -6
- 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",
|
@@ -306,6 +330,296 @@ static VALUE bind_boolean_alloc(VALUE klass)
|
|
306
330
|
return oci8_allocate_typeddata(klass, &bind_boolean_data_type.base);
|
307
331
|
}
|
308
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 = "";
|
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
|
+
OBJ_TAINT(str);
|
474
|
+
return str;
|
475
|
+
}
|
476
|
+
|
477
|
+
static void bind_long_set(oci8_bind_t *obind, void *data, void **null_structp, VALUE val)
|
478
|
+
{
|
479
|
+
chunk_buf_t *cb = (chunk_buf_t *)data;
|
480
|
+
long len;
|
481
|
+
const char *buf;
|
482
|
+
|
483
|
+
if (IS_BIND_LONG(obind)) {
|
484
|
+
OCI8StringValue(val);
|
485
|
+
} else {
|
486
|
+
StringValue(val);
|
487
|
+
}
|
488
|
+
len = RSTRING_LEN(val);
|
489
|
+
buf = RSTRING_PTR(val);
|
490
|
+
cb->tail = &cb->head;
|
491
|
+
while (1) {
|
492
|
+
chunk_t *chunk = next_chunk(cb);
|
493
|
+
if (len <= chunk->alloc_len) {
|
494
|
+
memcpy(chunk->buf, buf, len);
|
495
|
+
chunk->used_len = len;
|
496
|
+
break;
|
497
|
+
}
|
498
|
+
memcpy(chunk->buf, buf, chunk->alloc_len);
|
499
|
+
chunk->used_len = chunk->alloc_len;
|
500
|
+
len -= chunk->alloc_len;
|
501
|
+
buf += chunk->alloc_len;
|
502
|
+
}
|
503
|
+
}
|
504
|
+
|
505
|
+
static void bind_long_init(oci8_bind_t *obind, VALUE svc, VALUE val, VALUE param)
|
506
|
+
{
|
507
|
+
if (IS_BIND_LONG(obind)) {
|
508
|
+
oci8_bind_long_t *obl = (oci8_bind_long_t *)obind;
|
509
|
+
VALUE nchar;
|
510
|
+
|
511
|
+
if (rb_respond_to(param, id_charset_form)) {
|
512
|
+
VALUE csfrm = rb_funcall(param, id_charset_form, 0);
|
513
|
+
nchar = (csfrm == sym_nchar) ? Qtrue : Qfalse;
|
514
|
+
} else {
|
515
|
+
Check_Type(param, T_HASH);
|
516
|
+
nchar = rb_hash_aref(param, sym_nchar);
|
517
|
+
}
|
518
|
+
|
519
|
+
if (RTEST(nchar)) {
|
520
|
+
obl->csfrm = SQLCS_NCHAR; /* bind as NCHAR/NVARCHAR2 */
|
521
|
+
} else {
|
522
|
+
obl->csfrm = SQLCS_IMPLICIT; /* bind as CHAR/VARCHAR2 */
|
523
|
+
}
|
524
|
+
}
|
525
|
+
obind->value_sz = SB4MAXVAL;
|
526
|
+
obind->alloc_sz = sizeof(chunk_buf_t);
|
527
|
+
}
|
528
|
+
|
529
|
+
static void bind_long_init_elem(oci8_bind_t *obind, VALUE svc)
|
530
|
+
{
|
531
|
+
chunk_buf_t *cb = (chunk_buf_t *)obind->valuep;
|
532
|
+
ub4 idx = 0;
|
533
|
+
|
534
|
+
do {
|
535
|
+
cb[idx].tail = &cb[idx].head;
|
536
|
+
cb[idx].inpos = &cb[idx].head;
|
537
|
+
} while (++idx < obind->maxar_sz);
|
538
|
+
}
|
539
|
+
|
540
|
+
static void bind_long_post_bind_hook(oci8_bind_t *obind)
|
541
|
+
{
|
542
|
+
oci8_bind_long_t *ds = (oci8_bind_long_t *)obind;
|
543
|
+
|
544
|
+
if (IS_BIND_LONG(obind)) {
|
545
|
+
chker2(OCIAttrSet(obind->base.hp.ptr, obind->base.type, (void*)&ds->csfrm, 0, OCI_ATTR_CHARSET_FORM, oci8_errhp),
|
546
|
+
&obind->base);
|
547
|
+
}
|
548
|
+
switch (obind->base.type) {
|
549
|
+
case OCI_HTYPE_DEFINE:
|
550
|
+
chker2(OCIDefineDynamic(obind->base.hp.dfn, oci8_errhp, obind, define_callback),
|
551
|
+
&obind->base);
|
552
|
+
break;
|
553
|
+
case OCI_HTYPE_BIND:
|
554
|
+
chker2(OCIBindDynamic(obind->base.hp.bnd, oci8_errhp, obind, in_bind_callback,
|
555
|
+
obind, out_bind_callback),
|
556
|
+
&obind->base);
|
557
|
+
break;
|
558
|
+
}
|
559
|
+
}
|
560
|
+
|
561
|
+
static const oci8_bind_data_type_t bind_long_data_type = {
|
562
|
+
{
|
563
|
+
{
|
564
|
+
"OCI8::BindType::Long",
|
565
|
+
{
|
566
|
+
NULL,
|
567
|
+
oci8_handle_cleanup,
|
568
|
+
oci8_handle_size,
|
569
|
+
},
|
570
|
+
&oci8_bind_data_type.rb_data_type, NULL,
|
571
|
+
#ifdef RUBY_TYPED_WB_PROTECTED
|
572
|
+
RUBY_TYPED_WB_PROTECTED,
|
573
|
+
#endif
|
574
|
+
},
|
575
|
+
bind_long_free,
|
576
|
+
sizeof(oci8_bind_long_t)
|
577
|
+
},
|
578
|
+
bind_long_get,
|
579
|
+
bind_long_set,
|
580
|
+
bind_long_init,
|
581
|
+
bind_long_init_elem,
|
582
|
+
NULL,
|
583
|
+
SQLT_CHR,
|
584
|
+
bind_long_post_bind_hook,
|
585
|
+
};
|
586
|
+
|
587
|
+
static VALUE bind_long_alloc(VALUE klass)
|
588
|
+
{
|
589
|
+
return oci8_allocate_typeddata(klass, &bind_long_data_type.base);
|
590
|
+
}
|
591
|
+
|
592
|
+
static const oci8_bind_data_type_t bind_long_raw_data_type = {
|
593
|
+
{
|
594
|
+
{
|
595
|
+
"OCI8::BindType::LongRaw",
|
596
|
+
{
|
597
|
+
NULL,
|
598
|
+
oci8_handle_cleanup,
|
599
|
+
oci8_handle_size,
|
600
|
+
},
|
601
|
+
&oci8_bind_data_type.rb_data_type, NULL,
|
602
|
+
#ifdef RUBY_TYPED_WB_PROTECTED
|
603
|
+
RUBY_TYPED_WB_PROTECTED,
|
604
|
+
#endif
|
605
|
+
},
|
606
|
+
bind_long_free,
|
607
|
+
sizeof(oci8_bind_long_t)
|
608
|
+
},
|
609
|
+
bind_long_get,
|
610
|
+
bind_long_set,
|
611
|
+
bind_long_init,
|
612
|
+
bind_long_init_elem,
|
613
|
+
NULL,
|
614
|
+
SQLT_BIN,
|
615
|
+
bind_long_post_bind_hook,
|
616
|
+
};
|
617
|
+
|
618
|
+
static VALUE bind_long_raw_alloc(VALUE klass)
|
619
|
+
{
|
620
|
+
return oci8_allocate_typeddata(klass, &bind_long_raw_data_type.base);
|
621
|
+
}
|
622
|
+
|
309
623
|
static VALUE oci8_bind_get(VALUE self)
|
310
624
|
{
|
311
625
|
oci8_bind_t *obind = TO_BIND(self);
|
@@ -320,11 +634,20 @@ static VALUE oci8_bind_get(VALUE self)
|
|
320
634
|
return data_type->get(obind, (void*)((size_t)obind->valuep + obind->alloc_sz * idx), null_structp);
|
321
635
|
}
|
322
636
|
|
323
|
-
static VALUE oci8_bind_get_data(VALUE self)
|
637
|
+
static VALUE oci8_bind_get_data(int argc, VALUE *argv, VALUE self)
|
324
638
|
{
|
325
639
|
oci8_bind_t *obind = TO_BIND(self);
|
640
|
+
VALUE index;
|
326
641
|
|
327
|
-
|
642
|
+
rb_scan_args(argc, argv, "01", &index);
|
643
|
+
if (!NIL_P(index)) {
|
644
|
+
ub4 idx = NUM2UINT(index);
|
645
|
+
if (idx >= obind->maxar_sz) {
|
646
|
+
rb_raise(rb_eRuntimeError, "data index is too big. (%u for %u)", idx, obind->maxar_sz);
|
647
|
+
}
|
648
|
+
obind->curar_idx = idx;
|
649
|
+
return rb_funcall(self, oci8_id_get, 0);
|
650
|
+
} else if (obind->maxar_sz == 0) {
|
328
651
|
obind->curar_idx = 0;
|
329
652
|
return rb_funcall(self, oci8_id_get, 0);
|
330
653
|
} else {
|
@@ -391,6 +714,36 @@ static VALUE oci8_bind_set_data(VALUE self, VALUE val)
|
|
391
714
|
return self;
|
392
715
|
}
|
393
716
|
|
717
|
+
static VALUE get_initial_chunk_size(VALUE klass)
|
718
|
+
{
|
719
|
+
return UINT2NUM(initial_chunk_size);
|
720
|
+
}
|
721
|
+
|
722
|
+
static VALUE set_initial_chunk_size(VALUE klass, VALUE arg)
|
723
|
+
{
|
724
|
+
ub4 size = NUM2UINT(arg);
|
725
|
+
if (size == 0) {
|
726
|
+
rb_raise(rb_eArgError, "Could not set zero");
|
727
|
+
}
|
728
|
+
initial_chunk_size = size;
|
729
|
+
return arg;
|
730
|
+
}
|
731
|
+
|
732
|
+
static VALUE get_max_chunk_size(VALUE klass)
|
733
|
+
{
|
734
|
+
return UINT2NUM(max_chunk_size);
|
735
|
+
}
|
736
|
+
|
737
|
+
static VALUE set_max_chunk_size(VALUE klass, VALUE arg)
|
738
|
+
{
|
739
|
+
ub4 size = NUM2UINT(arg);
|
740
|
+
if (size == 0) {
|
741
|
+
rb_raise(rb_eArgError, "Could not set zero");
|
742
|
+
}
|
743
|
+
max_chunk_size = size;
|
744
|
+
return arg;
|
745
|
+
}
|
746
|
+
|
394
747
|
static VALUE oci8_bind_initialize(VALUE self, VALUE svc, VALUE val, VALUE length, VALUE max_array_size)
|
395
748
|
{
|
396
749
|
oci8_bind_t *obind = TO_BIND(self);
|
@@ -456,6 +809,7 @@ void Init_oci8_bind(VALUE klass)
|
|
456
809
|
{
|
457
810
|
cOCI8BindTypeBase = klass;
|
458
811
|
id_bind_type = rb_intern("bind_type");
|
812
|
+
id_charset_form = rb_intern("charset_form");
|
459
813
|
sym_length = ID2SYM(rb_intern("length"));
|
460
814
|
sym_length_semantics = ID2SYM(rb_intern("length_semantics"));
|
461
815
|
sym_char = ID2SYM(rb_intern("char"));
|
@@ -464,9 +818,14 @@ void Init_oci8_bind(VALUE klass)
|
|
464
818
|
rb_define_method(cOCI8BindTypeBase, "initialize", oci8_bind_initialize, 4);
|
465
819
|
rb_define_method(cOCI8BindTypeBase, "get", oci8_bind_get, 0);
|
466
820
|
rb_define_method(cOCI8BindTypeBase, "set", oci8_bind_set, 1);
|
467
|
-
rb_define_private_method(cOCI8BindTypeBase, "get_data", oci8_bind_get_data,
|
821
|
+
rb_define_private_method(cOCI8BindTypeBase, "get_data", oci8_bind_get_data, -1);
|
468
822
|
rb_define_private_method(cOCI8BindTypeBase, "set_data", oci8_bind_set_data, 1);
|
469
823
|
|
824
|
+
rb_define_singleton_method(klass, "initial_chunk_size", get_initial_chunk_size, 0);
|
825
|
+
rb_define_singleton_method(klass, "initial_chunk_size=", set_initial_chunk_size, 1);
|
826
|
+
rb_define_singleton_method(klass, "max_chunk_size", get_max_chunk_size, 0);
|
827
|
+
rb_define_singleton_method(klass, "max_chunk_size=", set_max_chunk_size, 1);
|
828
|
+
|
470
829
|
/* register primitive data types. */
|
471
830
|
oci8_define_bind_class("String", &bind_string_data_type, bind_string_alloc);
|
472
831
|
oci8_define_bind_class("RAW", &bind_raw_data_type, bind_raw_alloc);
|
@@ -474,4 +833,6 @@ void Init_oci8_bind(VALUE klass)
|
|
474
833
|
if (oracle_client_version >= ORAVER_12_1) {
|
475
834
|
oci8_define_bind_class("Boolean", &bind_boolean_data_type, bind_boolean_alloc);
|
476
835
|
}
|
836
|
+
klass = oci8_define_bind_class("Long", &bind_long_data_type, bind_long_alloc);
|
837
|
+
klass = oci8_define_bind_class("LongRaw", &bind_long_data_type, bind_long_raw_alloc);
|
477
838
|
}
|
data/ext/oci8/lob.c
CHANGED
@@ -639,10 +639,9 @@ static VALUE oci8_lob_read(int argc, VALUE *argv, VALUE self)
|
|
639
639
|
{
|
640
640
|
oci8_lob_t *lob = TO_LOB(self);
|
641
641
|
oci8_svcctx_t *svcctx = check_svcctx(lob);
|
642
|
-
ub8 lob_length;
|
643
|
-
ub8 read_len;
|
644
642
|
ub8 pos = lob->pos;
|
645
|
-
long strbufsiz;
|
643
|
+
long strbufsiz = 512;
|
644
|
+
ub8 sz;
|
646
645
|
ub8 byte_amt;
|
647
646
|
ub8 char_amt;
|
648
647
|
sword rv;
|
@@ -652,36 +651,21 @@ static VALUE oci8_lob_read(int argc, VALUE *argv, VALUE self)
|
|
652
651
|
ub1 piece = OCI_FIRST_PIECE;
|
653
652
|
|
654
653
|
rb_scan_args(argc, argv, "01", &size);
|
655
|
-
lob_length = oci8_lob_get_length(lob);
|
656
|
-
if (lob_length == 0 && NIL_P(size)) {
|
657
|
-
return rb_usascii_str_new("", 0);
|
658
|
-
}
|
659
|
-
if (lob_length <= pos) /* EOF */
|
660
|
-
return Qnil;
|
661
654
|
if (NIL_P(size)) {
|
662
|
-
|
655
|
+
sz = UB4MAXVAL;
|
663
656
|
} else {
|
664
|
-
|
665
|
-
|
657
|
+
sz = NUM2ULL(size);
|
658
|
+
}
|
659
|
+
if (lob->state == S_BFILE_CLOSE) {
|
660
|
+
open_bfile(svcctx, lob, errhp);
|
666
661
|
}
|
662
|
+
read_more_data:
|
667
663
|
if (lob->lobtype == OCI_TEMP_CLOB) {
|
668
664
|
byte_amt = 0;
|
669
|
-
char_amt =
|
670
|
-
if (oci8_nls_ratio == 1) {
|
671
|
-
strbufsiz = MIN(read_len, ULONG_MAX);
|
672
|
-
} else {
|
673
|
-
strbufsiz = MIN(read_len + read_len / 8, ULONG_MAX);
|
674
|
-
}
|
675
|
-
if (strbufsiz <= 10) {
|
676
|
-
strbufsiz = 10;
|
677
|
-
}
|
665
|
+
char_amt = sz;
|
678
666
|
} else {
|
679
|
-
byte_amt =
|
667
|
+
byte_amt = sz;
|
680
668
|
char_amt = 0;
|
681
|
-
strbufsiz = MIN(read_len, ULONG_MAX);
|
682
|
-
}
|
683
|
-
if (lob->state == S_BFILE_CLOSE) {
|
684
|
-
open_bfile(svcctx, lob, errhp);
|
685
669
|
}
|
686
670
|
do {
|
687
671
|
VALUE strbuf = rb_str_buf_new(strbufsiz);
|
@@ -711,15 +695,24 @@ static VALUE oci8_lob_read(int argc, VALUE *argv, VALUE self)
|
|
711
695
|
}
|
712
696
|
rb_str_set_len(strbuf, byte_amt);
|
713
697
|
rb_ary_push(v, strbuf);
|
698
|
+
if (strbufsiz < 128 * 1024 * 1024) {
|
699
|
+
strbufsiz *= 2;
|
700
|
+
}
|
714
701
|
} while (rv == OCI_NEED_DATA);
|
715
702
|
|
716
|
-
if (pos
|
717
|
-
|
703
|
+
if (NIL_P(size) && pos - lob->pos == sz) {
|
704
|
+
lob->pos = pos;
|
705
|
+
piece = OCI_FIRST_PIECE;
|
706
|
+
goto read_more_data;
|
718
707
|
}
|
719
708
|
lob->pos = pos;
|
720
709
|
switch (RARRAY_LEN(v)) {
|
721
710
|
case 0:
|
722
|
-
|
711
|
+
if (NIL_P(size) && pos == 0) {
|
712
|
+
return rb_usascii_str_new("", 0);
|
713
|
+
} else {
|
714
|
+
return Qnil;
|
715
|
+
}
|
723
716
|
case 1:
|
724
717
|
v = RARRAY_AREF(v, 0);
|
725
718
|
break;
|