Class: OCI8::LOB

Inherits:
OCIHandle show all
Defined in:
ext/oci8/lob.c,
ext/oci8/lob.c

Overview

OCI8::LOB is an I/O object. LOB contents are read from and written to the Oracle server via an associating connection. When a connection is closed, associating LOBs are also closed.

This is the abstract base class of large-object data types; BFILE, BLOB, CLOB and NCLOB.

Direct Known Subclasses

BFILE, BLOB, CLOB, NCLOB

Instance Method Summary collapse

Instance Method Details

#available?true or false

Returns true when self is initialized.

Returns:

  • (true or false)

456
457
458
459
460
461
462
463
464
# File 'ext/oci8/lob.c', line 456

static VALUE oci8_lob_available_p(VALUE self)
{
    oci8_lob_t *lob = TO_LOB(self);
    boolean is_initialized;

    chker2(OCILobLocatorIsInit(oci8_envhp, oci8_errhp, lob->base.hp.lob, &is_initialized),
           &lob->base);
    return is_initialized ? Qtrue : Qfalse;
}

#chunk_sizeInteger

Returns the chunk size of a LOB.

Returns:

  • (Integer)

See Also:


811
812
813
814
815
816
817
818
819
820
# File 'ext/oci8/lob.c', line 811

static VALUE oci8_lob_get_chunk_size(VALUE self)
{
    oci8_lob_t *lob = TO_LOB(self);
    oci8_svcctx_t *svcctx = check_svcctx(lob);
    ub4 len;

    chker2(OCILobGetChunkSize_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, &len),
           &svcctx->base);
    return UINT2NUM(len);
}

#closeself

Closes the lob.

Returns:

  • (self)

344
345
346
347
348
349
# File 'ext/oci8/lob.c', line 344

static VALUE oci8_lob_close(VALUE self)
{
    oci8_lob_t *lob = TO_LOB(self);
    oci8_base_free(&lob->base);
    return self;
}

#eof?true or false

Returns true if the current offset is at end of lob.

Returns:

  • (true or false)

496
497
498
499
500
501
502
503
# File 'ext/oci8/lob.c', line 496

static VALUE oci8_lob_eof_p(VALUE self)
{
    oci8_lob_t *lob = TO_LOB(self);
    if (oci8_lob_get_length(lob) < lob->pos)
        return Qfalse;
    else
        return Qtrue;
}

#posInteger Also known as: tell

Returns the current offset. For CLOB and NCLOB it is the number of characters, for BLOB and BFILE it is the number of bytes.

Returns:

  • (Integer)

485
486
487
488
489
# File 'ext/oci8/lob.c', line 485

static VALUE oci8_lob_get_pos(VALUE self)
{
    oci8_lob_t *lob = TO_LOB(self);
    return ULL2NUM(lob->pos);
}

#readString or nil #read(length) ⇒ String or nil

Overloads:

  • #readString or nil

    Returns data read. nil means it met EOF at beginning. It returns an empty string '' as a special exception when length is nil and the lob is empty.

    Parameters:

    • length (Integer)

      number of characters if self is a CLOB or a NCLOB. number of bytes if self is a BLOB or a BFILE.

    Returns:

    • (String or nil)

      data read. nil means it met EOF at beginning. It returns an empty string '' as a special exception when length is nil and the lob is empty.

  • #read(length) ⇒ String or nil

    Reads length characters for CLOB and NCLOB or length bytes for BLOB and BFILE from the current position. If length is nil, it reads data until EOF.

    Parameters:

    • length (Integer)

      number of characters if self is a CLOB or a NCLOB. number of bytes if self is a BLOB or a BFILE.

    Returns:

    • (String or nil)

      data read. nil means it met EOF at beginning. It returns an empty string '' as a special exception when length is nil and the lob is empty.


638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
# File 'ext/oci8/lob.c', line 638

static VALUE oci8_lob_read(int argc, VALUE *argv, VALUE self)
{
    oci8_lob_t *lob = TO_LOB(self);
    oci8_svcctx_t *svcctx = check_svcctx(lob);
    ub8 pos = lob->pos;
    long strbufsiz = 512;
    ub8 sz;
    ub8 byte_amt;
    ub8 char_amt;
    sword rv;
    VALUE size;
    VALUE v = rb_ary_new();
    OCIError *errhp = oci8_errhp;
    ub1 piece = OCI_FIRST_PIECE;

    rb_scan_args(argc, argv, "01", &size);
    if (NIL_P(size)) {
        sz = UB4MAXVAL;
    } else {
        sz = NUM2ULL(size);
    }
    if (lob->state == S_BFILE_CLOSE) {
        open_bfile(svcctx, lob, errhp);
    }
read_more_data:
    if (lob->lobtype == OCI_TEMP_CLOB) {
        byte_amt = 0;
        char_amt = sz;
    } else {
        byte_amt = sz;
        char_amt = 0;
    }
    do {
        VALUE strbuf = rb_str_buf_new(strbufsiz);
        char *buf = RSTRING_PTR(strbuf);

        rv = OCILobRead2_nb(svcctx, svcctx->base.hp.svc, errhp, lob->base.hp.lob, &byte_amt, &char_amt, pos + 1, buf, strbufsiz, piece, NULL, NULL, 0, lob->csfrm);
        svcctx->suppress_free_temp_lobs = 0;
        switch (rv) {
        case OCI_SUCCESS:
            break;
        case OCI_NEED_DATA:
            /* prevent OCILobFreeTemporary() from being called.
             * See: https://github.com/kubo/ruby-oci8/issues/20
             */
            svcctx->suppress_free_temp_lobs = 1;
            piece = OCI_NEXT_PIECE;
            break;
        default:
            chker2(rv, &svcctx->base);
        }
        if (byte_amt == 0)
            break;
        if (lob->lobtype == OCI_TEMP_CLOB) {
            pos += char_amt;
        } else {
            pos += byte_amt;
        }
        rb_str_set_len(strbuf, byte_amt);
        rb_ary_push(v, strbuf);
        if (strbufsiz < 128 * 1024 * 1024) {
            strbufsiz *= 2;
        }
    } while (rv == OCI_NEED_DATA);

    if (NIL_P(size) && pos - lob->pos == sz) {
        lob->pos = pos;
        piece = OCI_FIRST_PIECE;
        goto read_more_data;
    }
    lob->pos = pos;
    switch (RARRAY_LEN(v)) {
    case 0:
        if (NIL_P(size) && pos == 0) {
            return rb_usascii_str_new("", 0);
        } else {
            return Qnil;
        }
    case 1:
        v = RARRAY_AREF(v, 0);
        break;
    default:
        v = rb_ary_join(v, Qnil);
    }
    if (lob->lobtype == OCI_TEMP_CLOB) {
        /* set encoding */
        rb_enc_associate(v, oci8_encoding);
        return rb_str_conv_enc(v, oci8_encoding, rb_default_internal_encoding());
    } else {
        /* ASCII-8BIT */
        return v;
    }
}

#rewindtrue or false

Sets the current offset at the beginning.

Returns:

  • (true or false)

548
549
550
551
552
553
# File 'ext/oci8/lob.c', line 548

static VALUE oci8_lob_rewind(VALUE self)
{
    oci8_lob_t *lob = TO_LOB(self);
    lob->pos = 0;
    return self;
}

#seek(amount, whence = IO::SEEK_SET) ⇒ self

Seeks to the given offset in the stream. The new position, measured in characters, is obtained by adding offset amount to the position specified by whence. If whence is set to IO::SEEK_SET, IO::SEEK_CUR, or IO::SEEK_END, the offset is relative to the start of the file, the current position indicator, or end-of-file, respectively.

Parameters:

  • amount (Integer)
  • whence (IO::SEEK_SET, IO::SEEK_CUR or IO::SEEK_END)

Returns:

  • (self)

519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
# File 'ext/oci8/lob.c', line 519

static VALUE oci8_lob_seek(int argc, VALUE *argv, VALUE self)
{
    oci8_lob_t *lob = TO_LOB(self);
    VALUE position, whence;

    rb_scan_args(argc, argv, "11", &position, &whence);
    if (argc == 2 && (whence != seek_set && whence != seek_cur && whence != seek_end)) {
        if (FIXNUM_P(whence)) {
            rb_raise(rb_eArgError, "expect IO::SEEK_SET, IO::SEEK_CUR or IO::SEEK_END but %d",
                     FIX2INT(whence));
        } else {
            rb_raise(rb_eArgError, "expect IO::SEEK_SET, IO::SEEK_CUR or IO::SEEK_END but %s",
                     rb_class2name(CLASS_OF(whence)));
        }
    }
    if (whence == seek_cur) {
        position = rb_funcall(ULL2NUM(lob->pos), id_plus, 1, position);
    } else if (whence == seek_end) {
        position = rb_funcall(ULL2NUM(oci8_lob_get_length(lob)), id_plus, 1, position);
    }
    lob->pos = NUM2ULL(position);
    return self;
}

#sizeInteger

Returns the size. For CLOB and NCLOB it is the number of characters, for BLOB and BFILE it is the number of bytes.

Returns:

  • (Integer)

473
474
475
476
# File 'ext/oci8/lob.c', line 473

static VALUE oci8_lob_get_size(VALUE self)
{
    return ULL2NUM(oci8_lob_get_length(TO_LOB(self)));
}

#size=(length) ⇒ Object

Changes the lob size to the given length.

Parameters:

  • length (Integer)

    length in characters if self is a CLOB or a NCLOB. length in bytes if self is a BLOB or a BFILE.

See Also:


583
584
585
586
587
# File 'ext/oci8/lob.c', line 583

static VALUE oci8_lob_set_size(VALUE self, VALUE len)
{
    oci8_lob_truncate(self, len);
    return len;
}

#truncate(length) ⇒ self

Parameters:

  • length (Integer)

    length in characters if self is a CLOB or a NCLOB. length in bytes if self is a BLOB or a BFILE.

Returns:

  • (self)

See Also:


564
565
566
567
568
569
570
571
572
# File 'ext/oci8/lob.c', line 564

static VALUE oci8_lob_truncate(VALUE self, VALUE len)
{
    oci8_lob_t *lob = TO_LOB(self);
    oci8_svcctx_t *svcctx = check_svcctx(lob);

    chker2(OCILobTrim2_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, NUM2ULL(len)),
           &svcctx->base);
    return self;
}

#write(data) ⇒ Integer

Writes data to LOB.

Parameters:

Returns:

  • (Integer)

    number of characters written if self is a CLOB or a NCLOB. number of bytes written if self is a BLOB or a BFILE.


741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
# File 'ext/oci8/lob.c', line 741

static VALUE oci8_lob_write(VALUE self, VALUE data)
{
    oci8_lob_t *lob = TO_LOB(self);
    oci8_svcctx_t *svcctx = check_svcctx(lob);
    volatile VALUE str;
    ub8 byte_amt;
    ub8 char_amt;

    if (TYPE(data) != T_STRING) {
        str = rb_obj_as_string(data);
    } else {
        str = data;
    }
    if (lob->lobtype == OCI_TEMP_CLOB) {
        str = rb_str_export_to_enc(str, oci8_encoding);
    }
    byte_amt = RSTRING_LEN(str);
    if (byte_amt == 0) {
        /* to avoid ORA-24801: illegal parameter value in OCI lob function */
        return INT2FIX(0);
    }
    char_amt = 0;
    chker2(OCILobWrite2_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, &byte_amt, &char_amt, lob->pos + 1, RSTRING_PTR(str), byte_amt, OCI_ONE_PIECE, NULL, NULL, 0, lob->csfrm),
           &svcctx->base);
    RB_GC_GUARD(str);
    if (lob->lobtype == OCI_TEMP_CLOB) {
        lob->pos += char_amt;
        return ULL2NUM(char_amt);
    } else {
        lob->pos += byte_amt;
        return ULL2NUM(byte_amt);
    }
}