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;
         |