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)


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

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:



855
856
857
858
859
860
861
862
863
864
# File 'ext/oci8/lob.c', line 855

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)


368
369
370
371
372
373
374
# File 'ext/oci8/lob.c', line 368

static VALUE oci8_lob_close(VALUE self)
{
    oci8_lob_t *lob = TO_LOB(self);
    lob_close(lob);
    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)


521
522
523
524
525
526
527
528
# File 'ext/oci8/lob.c', line 521

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)


510
511
512
513
514
# File 'ext/oci8/lob.c', line 510

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.



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
731
732
733
734
735
736
737
738
739
740
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
# File 'ext/oci8/lob.c', line 664

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 lob_length;
    ub8 read_len;
    ub8 pos = lob->pos;
    long strbufsiz;
    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);
    lob_length = oci8_lob_get_length(lob);
    if (lob_length == 0 && NIL_P(size)) {
        return rb_usascii_str_new("", 0);
    }
    if (lob_length <= pos) /* EOF */
        return Qnil;
    if (NIL_P(size)) {
        read_len = lob_length - pos;
    } else {
        ub8 sz = NUM2ULL(size);
        read_len = MIN(sz, lob_length - pos);
    }
    if (lob->lobtype == OCI_TEMP_CLOB) {
        byte_amt = 0;
        char_amt = read_len;
        if (oci8_nls_ratio == 1) {
            strbufsiz = MIN(read_len, ULONG_MAX);
        } else {
            strbufsiz = MIN(read_len + read_len / 8, ULONG_MAX);
        }
        if (strbufsiz <= 10) {
            strbufsiz = 10;
        }
    } else {
        byte_amt = read_len;
        char_amt = 0;
        strbufsiz = MIN(read_len, ULONG_MAX);
    }
    if (lob->state == S_BFILE_CLOSE) {
        open_bfile(svcctx, lob, errhp);
    }
    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);
    } while (rv == OCI_NEED_DATA);

    if (pos >= lob_length) {
        lob_close(lob);
        bfile_close(lob);
    }
    lob->pos = pos;
    switch (RARRAY_LEN(v)) {
    case 0:
        return Qnil;
    case 1:
        v = RARRAY_AREF(v, 0);
        break;
    default:
        v = rb_ary_join(v, Qnil);
    }
    OBJ_TAINT(v);
    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)


573
574
575
576
577
578
# File 'ext/oci8/lob.c', line 573

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)


544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
# File 'ext/oci8/lob.c', line 544

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)


498
499
500
501
# File 'ext/oci8/lob.c', line 498

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:



609
610
611
612
613
# File 'ext/oci8/lob.c', line 609

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:



589
590
591
592
593
594
595
596
597
598
# File 'ext/oci8/lob.c', line 589

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

    lob_open(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.



776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
# File 'ext/oci8/lob.c', line 776

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;

    lob_open(lob);
    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 UINT2NUM(char_amt);
    } else {
        lob->pos += byte_amt;
        return UINT2NUM(byte_amt);
    }
}