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/object.c
    CHANGED
    
    | @@ -680,43 +680,53 @@ static VALUE oci8_named_collection_alloc(VALUE klass) | |
| 680 680 | 
             
                return oci8_allocate_typeddata(klass, &oci8_named_collection_data_type);
         | 
| 681 681 | 
             
            }
         | 
| 682 682 |  | 
| 683 | 
            +
            typedef struct {
         | 
| 684 | 
            +
                oci8_bind_t bind;
         | 
| 685 | 
            +
                VALUE *obj;
         | 
| 686 | 
            +
            } bind_named_type_t;
         | 
| 687 | 
            +
             | 
| 683 688 | 
             
            static void bind_named_type_mark(oci8_base_t *base)
         | 
| 684 689 | 
             
            {
         | 
| 685 | 
            -
                 | 
| 686 | 
            -
                oci8_hp_obj_t *oho = (oci8_hp_obj_t *)obind->valuep;
         | 
| 690 | 
            +
                bind_named_type_t *bnt = (bind_named_type_t *)base;
         | 
| 687 691 |  | 
| 688 | 
            -
                if ( | 
| 692 | 
            +
                if (bnt->obj != NULL) {
         | 
| 689 693 | 
             
                    ub4 idx = 0;
         | 
| 690 694 |  | 
| 691 695 | 
             
                    do {
         | 
| 692 | 
            -
                        rb_gc_mark( | 
| 693 | 
            -
                    } while (++idx <  | 
| 696 | 
            +
                        rb_gc_mark(bnt->obj[idx]);
         | 
| 697 | 
            +
                    } while (++idx < bnt->bind.maxar_sz);
         | 
| 694 698 | 
             
                }
         | 
| 695 | 
            -
                rb_gc_mark( | 
| 699 | 
            +
                rb_gc_mark(bnt->bind.tdo);
         | 
| 696 700 | 
             
            }
         | 
| 697 701 |  | 
| 698 702 | 
             
            static void bind_named_type_free(oci8_base_t *base)
         | 
| 699 703 | 
             
            {
         | 
| 700 | 
            -
                 | 
| 701 | 
            -
                 | 
| 704 | 
            +
                bind_named_type_t *bnt = (bind_named_type_t *)base;
         | 
| 705 | 
            +
                void **hp = (void **)bnt->bind.valuep;
         | 
| 702 706 |  | 
| 703 | 
            -
                if ( | 
| 707 | 
            +
                if (hp != NULL) {
         | 
| 704 708 | 
             
                    ub4 idx = 0;
         | 
| 705 709 |  | 
| 706 710 | 
             
                    do {
         | 
| 707 | 
            -
                        if ( | 
| 708 | 
            -
                            OCIObjectFree(oci8_envhp, oci8_errhp,  | 
| 709 | 
            -
                             | 
| 711 | 
            +
                        if (hp[idx] != NULL) {
         | 
| 712 | 
            +
                            OCIObjectFree(oci8_envhp, oci8_errhp, hp[idx], OCI_DEFAULT);
         | 
| 713 | 
            +
                            hp[idx] = NULL;
         | 
| 710 714 | 
             
                        }
         | 
| 711 | 
            -
                    } while (++idx <  | 
| 715 | 
            +
                    } while (++idx < bnt->bind.maxar_sz);
         | 
| 716 | 
            +
                }
         | 
| 717 | 
            +
                if (bnt->obj != NULL) {
         | 
| 718 | 
            +
                    xfree(bnt->obj);
         | 
| 719 | 
            +
                    bnt->obj = NULL;
         | 
| 712 720 | 
             
                }
         | 
| 713 721 | 
             
                oci8_bind_free(base);
         | 
| 714 722 | 
             
            }
         | 
| 715 723 |  | 
| 716 724 | 
             
            static VALUE bind_named_type_get(oci8_bind_t *obind, void *data, void *null_struct)
         | 
| 717 725 | 
             
            {
         | 
| 718 | 
            -
                 | 
| 719 | 
            -
                 | 
| 726 | 
            +
                bind_named_type_t *bnt = (bind_named_type_t *)obind;
         | 
| 727 | 
            +
                ub4 idx = obind->curar_idx;
         | 
| 728 | 
            +
             | 
| 729 | 
            +
                return bnt->obj[idx];
         | 
| 720 730 | 
             
            }
         | 
| 721 731 |  | 
| 722 732 | 
             
            static void bind_named_type_set(oci8_bind_t *obind, void *data, void **null_structp, VALUE val)
         | 
| @@ -726,10 +736,12 @@ static void bind_named_type_set(oci8_bind_t *obind, void *data, void **null_stru | |
| 726 736 |  | 
| 727 737 | 
             
            static void bind_named_type_init(oci8_bind_t *obind, VALUE svc, VALUE val, VALUE length)
         | 
| 728 738 | 
             
            {
         | 
| 739 | 
            +
                bind_named_type_t *bnt = (bind_named_type_t *)obind;
         | 
| 729 740 | 
             
                VALUE tdo_obj = length;
         | 
| 730 741 |  | 
| 731 742 | 
             
                obind->value_sz = sizeof(void*);
         | 
| 732 | 
            -
                obind->alloc_sz = sizeof( | 
| 743 | 
            +
                obind->alloc_sz = sizeof(void*);
         | 
| 744 | 
            +
                bnt->obj = xcalloc(sizeof(VALUE), obind->maxar_sz ? obind->maxar_sz : 1);
         | 
| 733 745 |  | 
| 734 746 | 
             
                CHECK_TDO(tdo_obj);
         | 
| 735 747 | 
             
                RB_OBJ_WRITE(obind->base.self, &obind->tdo, tdo_obj);
         | 
| @@ -737,7 +749,8 @@ static void bind_named_type_init(oci8_bind_t *obind, VALUE svc, VALUE val, VALUE | |
| 737 749 |  | 
| 738 750 | 
             
            static void bind_named_type_init_elem(oci8_bind_t *obind, VALUE svc)
         | 
| 739 751 | 
             
            {
         | 
| 740 | 
            -
                 | 
| 752 | 
            +
                bind_named_type_t *bnt = (bind_named_type_t *)obind;
         | 
| 753 | 
            +
                void **hp = (void **)obind->valuep;
         | 
| 741 754 | 
             
                oci8_base_t *tdo = DATA_PTR(obind->tdo);
         | 
| 742 755 | 
             
                OCITypeCode tc = OCITypeTypeCode(oci8_envhp, oci8_errhp, tdo->hp.tdo);
         | 
| 743 756 | 
             
                VALUE klass = Qnil;
         | 
| @@ -755,14 +768,14 @@ static void bind_named_type_init_elem(oci8_bind_t *obind, VALUE svc) | |
| 755 768 | 
             
                }
         | 
| 756 769 | 
             
                svcctx = oci8_get_svcctx(svc);
         | 
| 757 770 | 
             
                do {
         | 
| 758 | 
            -
                     | 
| 759 | 
            -
                    RB_OBJ_WRITTEN(obind->base.self, Qundef,  | 
| 760 | 
            -
                    obj = DATA_PTR( | 
| 761 | 
            -
                    RB_OBJ_WRITE( | 
| 762 | 
            -
                    obj->instancep = (char**)& | 
| 771 | 
            +
                    bnt->obj[idx] = rb_class_new_instance(0, NULL, klass);
         | 
| 772 | 
            +
                    RB_OBJ_WRITTEN(obind->base.self, Qundef, bnt->obj[idx]);
         | 
| 773 | 
            +
                    obj = DATA_PTR(bnt->obj[idx]);
         | 
| 774 | 
            +
                    RB_OBJ_WRITE(bnt->obj[idx], &obj->tdo, obind->tdo);
         | 
| 775 | 
            +
                    obj->instancep = (char**)&hp[idx];
         | 
| 763 776 | 
             
                    obj->null_structp = (char**)&obind->u.null_structs[idx];
         | 
| 764 777 | 
             
                    oci8_link_to_parent(&obj->base, &obind->base);
         | 
| 765 | 
            -
                    RB_OBJ_WRITTEN( | 
| 778 | 
            +
                    RB_OBJ_WRITTEN(bnt->obj[idx], Qundef, obind->base.self);
         | 
| 766 779 |  | 
| 767 780 | 
             
                    chker2(OCIObjectNew(oci8_envhp, oci8_errhp, svcctx->base.hp.svc, tc, tdo->hp.tdo, NULL, OCI_DURATION_SESSION, TRUE, (dvoid**)obj->instancep),
         | 
| 768 781 | 
             
                           &svcctx->base);
         | 
| @@ -804,7 +817,7 @@ static const oci8_bind_data_type_t bind_named_type_data_type = { | |
| 804 817 | 
             
            #endif
         | 
| 805 818 | 
             
                    },
         | 
| 806 819 | 
             
                    bind_named_type_free,
         | 
| 807 | 
            -
                    sizeof( | 
| 820 | 
            +
                    sizeof(bind_named_type_t)
         | 
| 808 821 | 
             
                },
         | 
| 809 822 | 
             
                bind_named_type_get,
         | 
| 810 823 | 
             
                bind_named_type_set,
         | 
    
        data/ext/oci8/oci8.c
    CHANGED
    
    | @@ -2,7 +2,7 @@ | |
| 2 2 | 
             
            /*
         | 
| 3 3 | 
             
             * oci8.c - part of ruby-oci8
         | 
| 4 4 | 
             
             *
         | 
| 5 | 
            -
             * Copyright (C) 2002- | 
| 5 | 
            +
             * Copyright (C) 2002-2019 Kubo Takehiro <kubo@jiubao.org>
         | 
| 6 6 | 
             
             *
         | 
| 7 7 | 
             
             */
         | 
| 8 8 | 
             
            #include "oci8.h"
         | 
| @@ -734,14 +734,9 @@ static VALUE oci8_set_autocommit(VALUE self, VALUE val) | |
| 734 734 | 
             
            /*
         | 
| 735 735 | 
             
             * @overload long_read_len
         | 
| 736 736 | 
             
             *
         | 
| 737 | 
            -
             *   | 
| 738 | 
            -
             * | 
| 739 | 
            -
             *
         | 
| 740 | 
            -
             *  If the actual data length is longer than long_read_len,
         | 
| 741 | 
            -
             *  the fetched valud is truncated and the value of {OCI8#last_error}
         | 
| 742 | 
            -
             *  become {OCISuccessWithInfo} whose message is "ORA-01406: fetched column value was truncated".
         | 
| 743 | 
            -
             *
         | 
| 744 | 
            -
             *  Note: long_read_len is also used for maximum length of XMLTYPE data type.
         | 
| 737 | 
            +
             *  @deprecated This has no effect since ruby-oci8 2.2.7.
         | 
| 738 | 
            +
             *    LONG, LONG RAW and XMLTYPE columns are fetched up to 4 gigabytes
         | 
| 739 | 
            +
             *    without this parameter.
         | 
| 745 740 | 
             
             *
         | 
| 746 741 | 
             
             *  @return [Integer]
         | 
| 747 742 | 
             
             *  @see #long_read_len=
         | 
| @@ -749,14 +744,16 @@ static VALUE oci8_set_autocommit(VALUE self, VALUE val) | |
| 749 744 | 
             
            static VALUE oci8_long_read_len(VALUE self)
         | 
| 750 745 | 
             
            {
         | 
| 751 746 | 
             
                oci8_svcctx_t *svcctx = oci8_get_svcctx(self);
         | 
| 747 | 
            +
                rb_warning("OCI8.long_read_len has no effect since ruby-oci8 2.2.7");
         | 
| 752 748 | 
             
                return svcctx->long_read_len;
         | 
| 753 749 | 
             
            }
         | 
| 754 750 |  | 
| 755 751 | 
             
            /*
         | 
| 756 752 | 
             
             * @overload long_read_len=(length)
         | 
| 757 753 | 
             
             *
         | 
| 758 | 
            -
             *   | 
| 759 | 
            -
             * | 
| 754 | 
            +
             *  @deprecated This has no effect since ruby-oci8 2.2.7.
         | 
| 755 | 
            +
             *    LONG, LONG RAW and XMLTYPE columns are fetched up to 4 gigabytes
         | 
| 756 | 
            +
             *    without this parameter.
         | 
| 760 757 | 
             
             *
         | 
| 761 758 | 
             
             *  @param [Integer] length
         | 
| 762 759 | 
             
             *  @see #long_read_len
         | 
| @@ -766,6 +763,7 @@ static VALUE oci8_set_long_read_len(VALUE self, VALUE val) | |
| 766 763 | 
             
                oci8_svcctx_t *svcctx = oci8_get_svcctx(self);
         | 
| 767 764 | 
             
                Check_Type(val, T_FIXNUM);
         | 
| 768 765 | 
             
                RB_OBJ_WRITE(self, &svcctx->long_read_len, val);
         | 
| 766 | 
            +
                rb_warning("OCI8.long_read_len= has no effect since ruby-oci8 2.2.7");
         | 
| 769 767 | 
             
                return val;
         | 
| 770 768 | 
             
            }
         | 
| 771 769 |  | 
    
        data/ext/oci8/oraconf.rb
    CHANGED
    
    | @@ -584,7 +584,7 @@ EOS | |
| 584 584 | 
             
                if try_run("int main() { return 0; }")
         | 
| 585 585 | 
             
                  puts "ok"
         | 
| 586 586 | 
             
                else
         | 
| 587 | 
            -
                  puts " | 
| 587 | 
            +
                  puts "failed"
         | 
| 588 588 | 
             
                  raise "C compiler doesn't work correctly."
         | 
| 589 589 | 
             
                end
         | 
| 590 590 | 
             
              end # check_cc
         | 
| @@ -630,7 +630,7 @@ EOS | |
| 630 630 | 
             
                STDOUT.flush
         | 
| 631 631 | 
             
                rubyhdrdir = RbConfig::CONFIG["rubyhdrdir"] || RbConfig::CONFIG['archdir']
         | 
| 632 632 | 
             
                unless File.exist?(rubyhdrdir + '/ruby.h')
         | 
| 633 | 
            -
                  puts " | 
| 633 | 
            +
                  puts "failed"
         | 
| 634 634 | 
             
                  if RUBY_PLATFORM =~ /darwin/ and File.exist?("#{RbConfig::CONFIG['archdir']}/../universal-darwin8.0/ruby.h")
         | 
| 635 635 | 
             
                    raise <<EOS
         | 
| 636 636 | 
             
            #{RbConfig::CONFIG['archdir']}/ruby.h doesn't exist.
         | 
    
        data/ext/oci8/stmt.c
    CHANGED
    
    | @@ -15,7 +15,8 @@ static VALUE cOCIStmt; | |
| 15 15 | 
             
            typedef struct {
         | 
| 16 16 | 
             
                oci8_base_t base;
         | 
| 17 17 | 
             
                VALUE svc;
         | 
| 18 | 
            -
                 | 
| 18 | 
            +
                char use_stmt_release;
         | 
| 19 | 
            +
                char end_of_fetch;
         | 
| 19 20 | 
             
            } oci8_stmt_t;
         | 
| 20 21 |  | 
| 21 22 | 
             
            static void oci8_stmt_mark(oci8_base_t *base)
         | 
| @@ -111,12 +112,24 @@ static VALUE oci8_define_by_pos(VALUE self, VALUE vposition, VALUE vbindobj) | |
| 111 112 | 
             
                oci8_bind_t *obind = TO_BIND(vbindobj);
         | 
| 112 113 | 
             
                const oci8_bind_data_type_t *data_type;
         | 
| 113 114 | 
             
                sword status;
         | 
| 115 | 
            +
                void *valuep;
         | 
| 116 | 
            +
                void *indp;
         | 
| 117 | 
            +
                ub4 mode;
         | 
| 114 118 |  | 
| 115 119 | 
             
                if (obind->base.hp.dfn != NULL) {
         | 
| 116 120 | 
             
                    oci8_base_free(&obind->base); /* TODO: OK? */
         | 
| 117 121 | 
             
                }
         | 
| 118 122 | 
             
                data_type = (const oci8_bind_data_type_t *)obind->base.data_type;
         | 
| 119 | 
            -
                 | 
| 123 | 
            +
                if (obind->value_sz != SB4MAXVAL) {
         | 
| 124 | 
            +
                    valuep = obind->valuep;
         | 
| 125 | 
            +
                    indp = NIL_P(obind->tdo) ? obind->u.inds : NULL;
         | 
| 126 | 
            +
                    mode = OCI_DEFAULT;
         | 
| 127 | 
            +
                } else {
         | 
| 128 | 
            +
                    valuep = NULL;
         | 
| 129 | 
            +
                    indp = NULL;
         | 
| 130 | 
            +
                    mode = OCI_DYNAMIC_FETCH;
         | 
| 131 | 
            +
                }
         | 
| 132 | 
            +
                status = OCIDefineByPos(stmt->base.hp.stmt, &obind->base.hp.dfn, oci8_errhp, position, valuep, obind->value_sz, data_type->dty, indp, NULL, 0, mode);
         | 
| 120 133 | 
             
                if (status != OCI_SUCCESS) {
         | 
| 121 134 | 
             
                    chker3(status, &stmt->base, stmt->base.hp.ptr);
         | 
| 122 135 | 
             
                }
         | 
| @@ -151,7 +164,9 @@ static VALUE oci8_bind(VALUE self, VALUE vplaceholder, VALUE vbindobj) | |
| 151 164 | 
             
                oci8_bind_t *obind;
         | 
| 152 165 | 
             
                const oci8_bind_data_type_t *data_type;
         | 
| 153 166 | 
             
                sword status;
         | 
| 167 | 
            +
                void *valuep;
         | 
| 154 168 | 
             
                void *indp;
         | 
| 169 | 
            +
                ub4 mode;
         | 
| 155 170 |  | 
| 156 171 | 
             
                if (NIL_P(vplaceholder)) { /* 1 */
         | 
| 157 172 | 
             
                    placeholder_ptr = NULL;
         | 
| @@ -185,11 +200,19 @@ static VALUE oci8_bind(VALUE self, VALUE vplaceholder, VALUE vbindobj) | |
| 185 200 | 
             
                }
         | 
| 186 201 | 
             
                data_type = (const oci8_bind_data_type_t *)obind->base.data_type;
         | 
| 187 202 |  | 
| 188 | 
            -
                 | 
| 203 | 
            +
                if (obind->value_sz != SB4MAXVAL) {
         | 
| 204 | 
            +
                    valuep = obind->valuep;
         | 
| 205 | 
            +
                    indp = NIL_P(obind->tdo) ? obind->u.inds : NULL;
         | 
| 206 | 
            +
                    mode = OCI_DEFAULT;
         | 
| 207 | 
            +
                } else {
         | 
| 208 | 
            +
                    valuep = NULL;
         | 
| 209 | 
            +
                    indp = NULL;
         | 
| 210 | 
            +
                    mode = OCI_DATA_AT_EXEC;
         | 
| 211 | 
            +
                }
         | 
| 189 212 | 
             
                if (placeholder_ptr == (char*)-1) {
         | 
| 190 | 
            -
                    status = OCIBindByPos(stmt->base.hp.stmt, &obind->base.hp.bnd, oci8_errhp, position,  | 
| 213 | 
            +
                    status = OCIBindByPos(stmt->base.hp.stmt, &obind->base.hp.bnd, oci8_errhp, position, valuep, obind->value_sz, data_type->dty, indp, NULL, 0, 0, 0, mode);
         | 
| 191 214 | 
             
                } else {
         | 
| 192 | 
            -
                    status = OCIBindByName(stmt->base.hp.stmt, &obind->base.hp.bnd, oci8_errhp, TO_ORATEXT(placeholder_ptr), placeholder_len,  | 
| 215 | 
            +
                    status = OCIBindByName(stmt->base.hp.stmt, &obind->base.hp.bnd, oci8_errhp, TO_ORATEXT(placeholder_ptr), placeholder_len, valuep, obind->value_sz, data_type->dty, indp, NULL, 0, 0, 0, mode);
         | 
| 193 216 | 
             
                }
         | 
| 194 217 | 
             
                if (status != OCI_SUCCESS) {
         | 
| 195 218 | 
             
                    chker3(status, &stmt->base, stmt->base.hp.stmt);
         | 
| @@ -238,6 +261,7 @@ static VALUE oci8_stmt_execute(VALUE self, VALUE iteration_count) | |
| 238 261 | 
             
                oci8_stmt_t *stmt = TO_STMT(self);
         | 
| 239 262 | 
             
                oci8_svcctx_t *svcctx = oci8_get_svcctx(stmt->svc);
         | 
| 240 263 |  | 
| 264 | 
            +
                stmt->end_of_fetch = 0;
         | 
| 241 265 | 
             
                chker3(oci8_call_stmt_execute(svcctx, stmt, NUM2UINT(iteration_count),
         | 
| 242 266 | 
             
                                              svcctx->is_autocommit ? OCI_COMMIT_ON_SUCCESS : OCI_DEFAULT),
         | 
| 243 267 | 
             
                       &stmt->base, stmt->base.hp.stmt);
         | 
| @@ -245,7 +269,7 @@ static VALUE oci8_stmt_execute(VALUE self, VALUE iteration_count) | |
| 245 269 | 
             
            }
         | 
| 246 270 |  | 
| 247 271 | 
             
            /*
         | 
| 248 | 
            -
             * @overload __fetch(connection)
         | 
| 272 | 
            +
             * @overload __fetch(connection, max_rows)
         | 
| 249 273 | 
             
             *
         | 
| 250 274 | 
             
             *  Fetches one row and set the result to <code>@define_handles</code>.
         | 
| 251 275 | 
             
             *  This is called by private methods of OCI8::Cursor.
         | 
| @@ -255,13 +279,18 @@ static VALUE oci8_stmt_execute(VALUE self, VALUE iteration_count) | |
| 255 279 | 
             
             *
         | 
| 256 280 | 
             
             *  @private
         | 
| 257 281 | 
             
             */
         | 
| 258 | 
            -
            static VALUE oci8_stmt_fetch(VALUE self, VALUE svc)
         | 
| 282 | 
            +
            static VALUE oci8_stmt_fetch(VALUE self, VALUE svc, VALUE max_rows)
         | 
| 259 283 | 
             
            {
         | 
| 260 284 | 
             
                oci8_stmt_t *stmt = TO_STMT(self);
         | 
| 261 285 | 
             
                oci8_svcctx_t *svcctx = oci8_get_svcctx(svc);
         | 
| 262 286 | 
             
                sword rv;
         | 
| 263 287 | 
             
                oci8_bind_t *obind;
         | 
| 264 288 | 
             
                const oci8_bind_data_type_t *data_type;
         | 
| 289 | 
            +
                ub4 nrows = NUM2UINT(max_rows);
         | 
| 290 | 
            +
             | 
| 291 | 
            +
                if (stmt->end_of_fetch) {
         | 
| 292 | 
            +
                    return Qnil;
         | 
| 293 | 
            +
                }
         | 
| 265 294 |  | 
| 266 295 | 
             
                if (stmt->base.children != NULL) {
         | 
| 267 296 | 
             
                    obind = (oci8_bind_t *)stmt->base.children;
         | 
| @@ -271,16 +300,22 @@ static VALUE oci8_stmt_fetch(VALUE self, VALUE svc) | |
| 271 300 | 
             
                            if (data_type->pre_fetch_hook != NULL) {
         | 
| 272 301 | 
             
                                data_type->pre_fetch_hook(obind, stmt->svc);
         | 
| 273 302 | 
             
                            }
         | 
| 303 | 
            +
                            if (nrows > 1 && nrows != obind->maxar_sz) {
         | 
| 304 | 
            +
                                rb_raise(rb_eRuntimeError, "fetch size (%u) != define-handle size %u", nrows, obind->maxar_sz);
         | 
| 305 | 
            +
                            }
         | 
| 274 306 | 
             
                        }
         | 
| 275 307 | 
             
                        obind = (oci8_bind_t *)obind->base.next;
         | 
| 276 308 | 
             
                    } while (obind != (oci8_bind_t*)stmt->base.children);
         | 
| 277 309 | 
             
                }
         | 
| 278 | 
            -
                rv = OCIStmtFetch_nb(svcctx, stmt->base.hp.stmt, oci8_errhp,  | 
| 310 | 
            +
                rv = OCIStmtFetch_nb(svcctx, stmt->base.hp.stmt, oci8_errhp, nrows, OCI_FETCH_NEXT, OCI_DEFAULT);
         | 
| 279 311 | 
             
                if (rv == OCI_NO_DATA) {
         | 
| 280 | 
            -
                     | 
| 312 | 
            +
                    stmt->end_of_fetch = 1;
         | 
| 313 | 
            +
                } else {
         | 
| 314 | 
            +
                    chker3(rv, &svcctx->base, stmt->base.hp.stmt);
         | 
| 281 315 | 
             
                }
         | 
| 282 | 
            -
                 | 
| 283 | 
            -
             | 
| 316 | 
            +
                chker2(OCIAttrGet(stmt->base.hp.stmt, OCI_HTYPE_STMT, &nrows, 0, OCI_ATTR_ROWS_FETCHED, oci8_errhp),
         | 
| 317 | 
            +
                       &svcctx->base);
         | 
| 318 | 
            +
                return nrows ? UINT2NUM(nrows) : Qnil;
         | 
| 284 319 | 
             
            }
         | 
| 285 320 |  | 
| 286 321 | 
             
            /*
         | 
| @@ -405,7 +440,7 @@ void Init_oci8_stmt(VALUE cOCI8) | |
| 405 440 | 
             
                rb_define_private_method(cOCIStmt, "__define", oci8_define_by_pos, 2);
         | 
| 406 441 | 
             
                rb_define_private_method(cOCIStmt, "__bind", oci8_bind, 2);
         | 
| 407 442 | 
             
                rb_define_private_method(cOCIStmt, "__execute", oci8_stmt_execute, 1);
         | 
| 408 | 
            -
                rb_define_private_method(cOCIStmt, "__fetch", oci8_stmt_fetch,  | 
| 443 | 
            +
                rb_define_private_method(cOCIStmt, "__fetch", oci8_stmt_fetch, 2);
         | 
| 409 444 | 
             
                rb_define_private_method(cOCIStmt, "__paramGet", oci8_stmt_get_param, 1);
         | 
| 410 445 | 
             
                rb_define_method(cOCIStmt, "rowid", oci8_stmt_get_rowid, 0);
         | 
| 411 446 |  | 
    
        data/lib/oci8.rb
    CHANGED
    
    | @@ -95,7 +95,7 @@ begin | |
| 95 95 |  | 
| 96 96 | 
             
              ruby_arch = [nil].pack('P').size == 8 ? :x64 : :x86
         | 
| 97 97 | 
             
              ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
         | 
| 98 | 
            -
                if dll_arch.call(File.join(path, 'OCI.DLL')) == ruby_arch
         | 
| 98 | 
            +
                if !path.empty? && dll_arch.call(File.join(path, 'OCI.DLL')) == ruby_arch
         | 
| 99 99 | 
             
                  dll_dir = RubyInstaller::Runtime.add_dll_directory(path)
         | 
| 100 100 | 
             
                  break
         | 
| 101 101 | 
             
                end
         | 
    
        data/lib/oci8/bindtype.rb
    CHANGED
    
    | @@ -172,20 +172,6 @@ class OCI8 | |
| 172 172 | 
             
                  end
         | 
| 173 173 | 
             
                end
         | 
| 174 174 |  | 
| 175 | 
            -
                class Long < OCI8::BindType::String
         | 
| 176 | 
            -
                  def self.create(con, val, param, max_array_size)
         | 
| 177 | 
            -
                    param = {:length => con.long_read_len, :char_semantics => true}
         | 
| 178 | 
            -
                    super(con, val, param, max_array_size)
         | 
| 179 | 
            -
                  end
         | 
| 180 | 
            -
                end
         | 
| 181 | 
            -
             | 
| 182 | 
            -
                class LongRaw < OCI8::BindType::RAW
         | 
| 183 | 
            -
                  def self.create(con, val, param, max_array_size)
         | 
| 184 | 
            -
                    param = {:length => con.long_read_len, :char_semantics => false}
         | 
| 185 | 
            -
                    self.new(con, val, param, max_array_size)
         | 
| 186 | 
            -
                  end
         | 
| 187 | 
            -
                end
         | 
| 188 | 
            -
             | 
| 189 175 | 
             
                class CLOB
         | 
| 190 176 | 
             
                  def self.create(con, val, param, max_array_size)
         | 
| 191 177 | 
             
                    if param.is_a? OCI8::Metadata::Base and param.charset_form == :nchar
         | 
| @@ -6,14 +6,24 @@ class OCI8 | |
| 6 6 | 
             
                case RUBY_PLATFORM
         | 
| 7 7 | 
             
                when /mswin32|cygwin|mingw32|bccwin32/
         | 
| 8 8 |  | 
| 9 | 
            -
                  require ' | 
| 9 | 
            +
                  require 'fiddle/import'
         | 
| 10 | 
            +
                  require 'fiddle/types'
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  extend Fiddle::Importer
         | 
| 13 | 
            +
                  dlload 'kernel32.dll'
         | 
| 14 | 
            +
                  include Fiddle::BasicTypes
         | 
| 15 | 
            +
                  include Fiddle::Win32Types
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                  typealias "HANDLE", "void*"
         | 
| 18 | 
            +
                  typealias "HMODULE", "void*"
         | 
| 19 | 
            +
                  extern "DWORD GetModuleFileNameA(HMODULE, LPSTR, DWORD)"
         | 
| 20 | 
            +
                  extern "UINT GetSystemDirectoryA(LPCSTR, UINT)"
         | 
| 21 | 
            +
                  extern "UINT GetWindowsDirectoryA(LPCSTR, UINT)"
         | 
| 22 | 
            +
                  extern "HMODULE LoadLibraryExA(LPCSTR, HANDLE, DWORD)"
         | 
| 23 | 
            +
                  extern "BOOL FreeLibrary(HMODULE)"
         | 
| 24 | 
            +
             | 
| 10 25 | 
             
                  MAX_PATH = 260
         | 
| 11 | 
            -
                   | 
| 12 | 
            -
                  GetSystemDirectoryA = Win32API.new('kernel32.dll', 'GetSystemDirectoryA', 'PL', 'L')
         | 
| 13 | 
            -
                  GetWindowsDirectoryA = Win32API.new('kernel32.dll', 'GetWindowsDirectoryA', 'PL', 'L')
         | 
| 14 | 
            -
                  LoadLibraryExA = Win32API.new('kernel32.dll', 'LoadLibraryExA', 'PPL', 'P')
         | 
| 15 | 
            -
                  FreeLibrary = Win32API.new('kernel32.dll', 'FreeLibrary', 'P', 'L')
         | 
| 16 | 
            -
                  LOAD_LIBRARY_AS_IMAGE_RESOURCE = 0x00000020
         | 
| 26 | 
            +
                  DONT_RESOLVE_DLL_REFERENCES = 0x00000001
         | 
| 17 27 |  | 
| 18 28 | 
             
                  def self.check_os_specific_load_error(exc)
         | 
| 19 29 | 
             
                    case exc.message
         | 
| @@ -23,25 +33,50 @@ class OCI8 | |
| 23 33 | 
             
                        check_win32_pe_arch(File.join(path, '\OCI.DLL'), "Oracle client")
         | 
| 24 34 | 
             
                      end
         | 
| 25 35 | 
             
                    when /^OCI.DLL: 126\(/, /^126: / # "OCI.DLL: 126(The specified module could not be found.)" in English
         | 
| 26 | 
            -
                       | 
| 27 | 
            -
             | 
| 28 | 
            -
                         | 
| 29 | 
            -
                         | 
| 30 | 
            -
             | 
| 36 | 
            +
                      oci_dll_files = dll_load_path_list.inject([]) do |files, path|
         | 
| 37 | 
            +
                        file = File.join(path, '\OCI.DLL')
         | 
| 38 | 
            +
                        files << file if File.exist?(file)
         | 
| 39 | 
            +
                        files
         | 
| 40 | 
            +
                      end
         | 
| 41 | 
            +
                      if oci_dll_files.empty?
         | 
| 42 | 
            +
                        raise LoadError, "Cannot find OCI.DLL in PATH."
         | 
| 43 | 
            +
                      end
         | 
| 44 | 
            +
                      if oci_dll_files.none? {|file| open(file, 'rb') {true} rescue false}
         | 
| 45 | 
            +
                        raise LoadError, "OCI.DLL in PATH isn't readable."
         | 
| 46 | 
            +
                      end
         | 
| 47 | 
            +
                      first_error = nil
         | 
| 48 | 
            +
                      oci_dll_files.each do |file|
         | 
| 49 | 
            +
                        begin
         | 
| 50 | 
            +
                          check_win32_pe_arch(file, "Oracle client")
         | 
| 51 | 
            +
                          valid_arch = true
         | 
| 52 | 
            +
                        rescue LoadError
         | 
| 53 | 
            +
                          first_error ||= $!
         | 
| 54 | 
            +
                          valid_arch = false
         | 
| 55 | 
            +
                        end
         | 
| 56 | 
            +
                        if valid_arch
         | 
| 57 | 
            +
                          handle = LoadLibraryExA(file, nil, DONT_RESOLVE_DLL_REFERENCES)
         | 
| 58 | 
            +
                          unless handle.null?
         | 
| 59 | 
            +
                            FreeLibrary(handle)
         | 
| 60 | 
            +
                            raise LoadError, <<EOS
         | 
| 61 | 
            +
            Cannot find DLLs depended by #{file}.
         | 
| 31 62 | 
             
            See http://www.rubydoc.info/github/kubo/ruby-oci8/file/docs/install-instant-client.md#Windows
         | 
| 32 63 | 
             
            EOS
         | 
| 64 | 
            +
                          end
         | 
| 65 | 
            +
                          break
         | 
| 66 | 
            +
                        end
         | 
| 33 67 | 
             
                      end
         | 
| 68 | 
            +
                      raise first_error if first_error
         | 
| 34 69 | 
             
                    end
         | 
| 35 70 | 
             
                  end # self.check_os_specific_load_error
         | 
| 36 71 |  | 
| 37 72 | 
             
                  def self.dll_load_path_list
         | 
| 38 73 | 
             
                    buf = "\0" * MAX_PATH
         | 
| 39 74 | 
             
                    paths = []
         | 
| 40 | 
            -
                    paths << buf[0, GetModuleFileNameA | 
| 41 | 
            -
                    paths << buf[0, GetSystemDirectoryA | 
| 42 | 
            -
                    paths << buf[0, GetWindowsDirectoryA | 
| 75 | 
            +
                    paths << buf[0, GetModuleFileNameA(nil, buf, MAX_PATH)].force_encoding("locale").gsub(/\\[^\\]*$/, '')
         | 
| 76 | 
            +
                    paths << buf[0, GetSystemDirectoryA(buf, MAX_PATH)].force_encoding("locale")
         | 
| 77 | 
            +
                    paths << buf[0, GetWindowsDirectoryA(buf, MAX_PATH)].force_encoding("locale")
         | 
| 43 78 | 
             
                    paths << "."
         | 
| 44 | 
            -
                    paths + ENV['PATH'].split(';')
         | 
| 79 | 
            +
                    paths + (ENV['PATH'].split(';').reject {|path| path.empty?})
         | 
| 45 80 | 
             
                  end # self.dll_load_path_list
         | 
| 46 81 |  | 
| 47 82 | 
             
                  def self.check_win32_pe_arch(filename, package)
         |