ruby-oci8 2.2.6.1 → 2.2.7
Sign up to get free protection for your applications and to get access to all the features.
- 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;
|