Example #1
0
static VALUE oci8_lob_close(VALUE self)
{
    oci8_lob_t *lob = DATA_PTR(self);
    lob_close(lob);
    oci8_base_free(DATA_PTR(self));
    return self;
}
Example #2
0
/*
 *  Closes the lob.
 *
 *  @return [self]
 */
static VALUE oci8_lob_close(VALUE self)
{
    oci8_lob_t *lob = TO_LOB(self);
    lob_close(lob);
    oci8_base_free(&lob->base);
    return self;
}
Example #3
0
static VALUE oci8_lob_set_sync(VALUE self, VALUE b)
{
    oci8_lob_t *lob = DATA_PTR(self);
    if (RTEST(b)) {
        lob_close(lob);
        lob->state = S_NO_OPEN_CLOSE;
    } else {
        if (lob->state == S_NO_OPEN_CLOSE)
            lob->state = S_CLOSE;
    }
    return b;
}
Example #4
0
static VALUE oci8_lob_flush(VALUE self)
{
    oci8_lob_t *lob = DATA_PTR(self);
    lob_close(lob);
    return self;
}
Example #5
0
static VALUE oci8_lob_read(int argc, VALUE *argv, VALUE self)
{
    oci8_lob_t *lob = DATA_PTR(self);
    oci8_svcctx_t *svcctx = oci8_get_svcctx(lob->svc);
    ub4 length;
    ub4 nchar;
    ub4 amt;
    sword rv;
    char buf[8192];
    size_t buf_size_in_char;
    VALUE size;
    VALUE v = rb_ary_new();

    rb_scan_args(argc, argv, "01", &size);
    length = oci8_lob_get_length(lob);
    if (length <= lob->pos) /* EOF */
        return Qnil;
    length -= lob->pos;
    if (NIL_P(size)) {
        nchar = length; /* read until EOF */
    } else {
        nchar = NUM2UINT(size);
        if (nchar > length)
            nchar = length;
    }
    amt = nchar;
    buf_size_in_char = sizeof(buf) / lob->char_width;
    do {
        if (lob->state == S_BFILE_CLOSE) {
            rv = OCILobFileOpen_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, OCI_FILE_READONLY);
            if (rv == OCI_ERROR && oci8_get_error_code(oci8_errhp) == 22290) {
                /* ORA-22290: operation would exceed the maximum number of opened files or LOBs */
                /* close all opened BFILE implicitly. */
                oci8_base_t *base;
                for (base = &lob->base; base != &lob->base; base = base->next) {
                    if (base->type == OCI_DTYPE_LOB) {
                        oci8_lob_t *tmp = (oci8_lob_t *)base;
                        if (tmp->state == S_BFILE_OPEN) {
                            tmp->state = S_BFILE_CLOSE;
                        }
                    }
                }
                oci_lc(OCILobFileCloseAll_nb(svcctx, svcctx->base.hp.svc, oci8_errhp));
                continue;
            }
            if (rv != OCI_SUCCESS)
                oci8_raise(oci8_errhp, rv, NULL);
            lob->state = S_BFILE_OPEN;
        }
        /* initialize buf in zeros everytime to check a nul characters. */
        memset(buf, 0, sizeof(buf));
        rv = OCILobRead_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, &amt, lob->pos + 1, buf, sizeof(buf), NULL, NULL, 0, lob->csfrm);
        if (rv == OCI_ERROR && oci8_get_error_code(oci8_errhp) == 22289) {
            /* ORA-22289: cannot perform FILEREAD operation on an unopened file or LOB */
            if (lob->state == S_BFILE_CLOSE)
                continue;
        }
        if (rv != OCI_SUCCESS && rv != OCI_NEED_DATA)
            oci8_raise(oci8_errhp, rv, NULL);

        /* Workaround when using Oracle 10.2.0.4 or 11.1.0.6 client and
         * variable-length character set (e.g. AL32UTF8).
         *
         * When the above mentioned condition, amt may be shorter. So
         * amt is increaded until a nul character to know the actually
         * read size.
         */
        while (amt < sizeof(buf) && buf[amt] != '\0') {
            amt++;
        }

        if (amt == 0)
            break;
        /* for fixed size charset, amt is the number of characters stored in buf. */
        if (amt > buf_size_in_char)
            rb_raise(eOCIException, "Too large buffer fetched or you set too large size of a character.");
        amt *= lob->char_width;
        rb_ary_push(v, rb_str_new(buf, amt));
    } while (rv == OCI_NEED_DATA);
    lob->pos += nchar;
    if (nchar == length) {
        lob_close(lob);
        bfile_close(lob);
    }
    if (RARRAY_LEN(v) == 0) {
        return Qnil;
    }
    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;
    }
}
Example #6
0
/*
 *  @deprecated I'm not sure that this is what the name indicates.
 *  @private
 */
static VALUE oci8_lob_flush(VALUE self)
{
    oci8_lob_t *lob = TO_LOB(self);
    lob_close(lob);
    return self;
}
Example #7
0
/*
 * @overload read
 *
 *  
 *
 *  @param [Integer] length number of characters if +self+ is a {CLOB} or a {NCLOB}.
 *    number of bytes if +self+ is a {BLOB} or a {BFILE}.
 *  @return [String or nil] data read. <code>nil</code> means it
 *    met EOF at beginning. It returns an empty string '' as a special exception
 *    when <i>length</i> is <code>nil</code> and the lob is empty.
 *
 * @overload read(length)
 *
 *  Reads <i>length</i> characters for {CLOB} and {NCLOB} or <i>length</i>
 *  bytes for {BLOB} and {BFILE} from the current position.
 *  If <i>length</i> is <code>nil</code>, it reads data until EOF.
 *
 *  @param [Integer] length number of characters if +self+ is a {CLOB} or a {NCLOB}.
 *    number of bytes if +self+ is a {BLOB} or a {BFILE}.
 *  @return [String or nil] data read. <code>nil</code> means it
 *    met EOF at beginning. It returns an empty string '' as a special exception
 *    when <i>length</i> is <code>nil</code> and the lob is empty.
 */
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;
    }
}