Skip to content

Commit 5b4d2c8

Browse files
committed
Revert "Use array fetching when LOB colums are in a query and no object types are in the query."
This reverts commit a35c64d.
1 parent c3cc5fc commit 5b4d2c8

File tree

5 files changed

+25
-107
lines changed

5 files changed

+25
-107
lines changed

ext/oci8/bind.c

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -633,20 +633,11 @@ static VALUE oci8_bind_get(VALUE self)
633633
return data_type->get(obind, (void*)((size_t)obind->valuep + obind->alloc_sz * idx), null_structp);
634634
}
635635

636-
static VALUE oci8_bind_get_data(int argc, VALUE *argv, VALUE self)
636+
static VALUE oci8_bind_get_data(VALUE self)
637637
{
638638
oci8_bind_t *obind = TO_BIND(self);
639-
VALUE index;
640639

641-
rb_scan_args(argc, argv, "01", &index);
642-
if (!NIL_P(index)) {
643-
ub4 idx = NUM2UINT(index);
644-
if (idx >= obind->maxar_sz) {
645-
rb_raise(rb_eRuntimeError, "data index is too big. (%u for %u)", idx, obind->maxar_sz);
646-
}
647-
obind->curar_idx = idx;
648-
return rb_funcall(self, oci8_id_get, 0);
649-
} else if (obind->maxar_sz == 0) {
640+
if (obind->maxar_sz == 0) {
650641
obind->curar_idx = 0;
651642
return rb_funcall(self, oci8_id_get, 0);
652643
} else {
@@ -817,7 +808,7 @@ void Init_oci8_bind(VALUE klass)
817808
rb_define_method(cOCI8BindTypeBase, "initialize", oci8_bind_initialize, 4);
818809
rb_define_method(cOCI8BindTypeBase, "get", oci8_bind_get, 0);
819810
rb_define_method(cOCI8BindTypeBase, "set", oci8_bind_set, 1);
820-
rb_define_private_method(cOCI8BindTypeBase, "get_data", oci8_bind_get_data, -1);
811+
rb_define_private_method(cOCI8BindTypeBase, "get_data", oci8_bind_get_data, 0);
821812
rb_define_private_method(cOCI8BindTypeBase, "set_data", oci8_bind_set_data, 1);
822813

823814
rb_define_singleton_method(klass, "initial_chunk_size", get_initial_chunk_size, 0);

ext/oci8/stmt.c

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@ static VALUE cOCIStmt;
1515
typedef struct {
1616
oci8_base_t base;
1717
VALUE svc;
18-
char use_stmt_release;
19-
char end_of_fetch;
18+
int use_stmt_release;
2019
} oci8_stmt_t;
2120

2221
static void oci8_stmt_mark(oci8_base_t *base)
@@ -261,15 +260,14 @@ static VALUE oci8_stmt_execute(VALUE self, VALUE iteration_count)
261260
oci8_stmt_t *stmt = TO_STMT(self);
262261
oci8_svcctx_t *svcctx = oci8_get_svcctx(stmt->svc);
263262

264-
stmt->end_of_fetch = 0;
265263
chker3(oci8_call_stmt_execute(svcctx, stmt, NUM2UINT(iteration_count),
266264
svcctx->is_autocommit ? OCI_COMMIT_ON_SUCCESS : OCI_DEFAULT),
267265
&stmt->base, stmt->base.hp.stmt);
268266
return self;
269267
}
270268

271269
/*
272-
* @overload __fetch(connection, max_rows)
270+
* @overload __fetch(connection)
273271
*
274272
* Fetches one row and set the result to <code>@define_handles</code>.
275273
* This is called by private methods of OCI8::Cursor.
@@ -279,18 +277,13 @@ static VALUE oci8_stmt_execute(VALUE self, VALUE iteration_count)
279277
*
280278
* @private
281279
*/
282-
static VALUE oci8_stmt_fetch(VALUE self, VALUE svc, VALUE max_rows)
280+
static VALUE oci8_stmt_fetch(VALUE self, VALUE svc)
283281
{
284282
oci8_stmt_t *stmt = TO_STMT(self);
285283
oci8_svcctx_t *svcctx = oci8_get_svcctx(svc);
286284
sword rv;
287285
oci8_bind_t *obind;
288286
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-
}
294287

295288
if (stmt->base.children != NULL) {
296289
obind = (oci8_bind_t *)stmt->base.children;
@@ -300,22 +293,16 @@ static VALUE oci8_stmt_fetch(VALUE self, VALUE svc, VALUE max_rows)
300293
if (data_type->pre_fetch_hook != NULL) {
301294
data_type->pre_fetch_hook(obind, stmt->svc);
302295
}
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-
}
306296
}
307297
obind = (oci8_bind_t *)obind->base.next;
308298
} while (obind != (oci8_bind_t*)stmt->base.children);
309299
}
310-
rv = OCIStmtFetch_nb(svcctx, stmt->base.hp.stmt, oci8_errhp, nrows, OCI_FETCH_NEXT, OCI_DEFAULT);
300+
rv = OCIStmtFetch_nb(svcctx, stmt->base.hp.stmt, oci8_errhp, 1, OCI_FETCH_NEXT, OCI_DEFAULT);
311301
if (rv == OCI_NO_DATA) {
312-
stmt->end_of_fetch = 1;
313-
} else {
314-
chker3(rv, &svcctx->base, stmt->base.hp.stmt);
302+
return Qfalse;
315303
}
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;
304+
chker3(rv, &svcctx->base, stmt->base.hp.stmt);
305+
return Qtrue;
319306
}
320307

321308
/*
@@ -440,7 +427,7 @@ void Init_oci8_stmt(VALUE cOCI8)
440427
rb_define_private_method(cOCIStmt, "__define", oci8_define_by_pos, 2);
441428
rb_define_private_method(cOCIStmt, "__bind", oci8_bind, 2);
442429
rb_define_private_method(cOCIStmt, "__execute", oci8_stmt_execute, 1);
443-
rb_define_private_method(cOCIStmt, "__fetch", oci8_stmt_fetch, 2);
430+
rb_define_private_method(cOCIStmt, "__fetch", oci8_stmt_fetch, 1);
444431
rb_define_private_method(cOCIStmt, "__paramGet", oci8_stmt_get_param, 1);
445432
rb_define_method(cOCIStmt, "rowid", oci8_stmt_get_rowid, 0);
446433

lib/oci8/cursor.rb

Lines changed: 13 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,7 @@ def initialize(conn, sql = nil)
2525
@names = nil
2626
@con = conn
2727
@max_array_size = nil
28-
@fetch_array_size = nil
29-
@rowbuf_size = 0
30-
@rowbuf_index = 0
3128
__initialize(conn, sql) # Initialize the internal C structure.
32-
self.prefetch_rows = conn.instance_variable_get(:@prefetch_rows)
3329
end
3430

3531
# explicitly indicate the date type of fetched value. run this
@@ -42,7 +38,7 @@ def initialize(conn, sql = nil)
4238
# cursor.define(2, Time) # fetch the second column as Time.
4339
# cursor.exec()
4440
def define(pos, type, length = nil)
45-
bindobj = make_bind_object({:type => type, :length => length}, @fetch_array_size || 1)
41+
bindobj = make_bind_object(:type => type, :length => length)
4642
__define(pos, bindobj)
4743
if old = @define_handles[pos - 1]
4844
old.send(:free)
@@ -130,8 +126,6 @@ def exec(*bindvars)
130126
when :select_stmt
131127
__execute(0)
132128
define_columns() if @column_metadata.size == 0
133-
@rowbuf_size = 0
134-
@rowbuf_index = 0
135129
@column_metadata.size
136130
else
137131
__execute(1)
@@ -390,7 +384,6 @@ def keys
390384
# @param [Integer] rows The number of rows to be prefetched
391385
def prefetch_rows=(rows)
392386
attr_set_ub4(11, rows) # OCI_ATTR_PREFETCH_ROWS(11)
393-
@prefetch_rows = rows
394387
end
395388

396389
if OCI8::oracle_client_version >= ORAVER_12_1
@@ -475,7 +468,7 @@ def type
475468

476469
private
477470

478-
def make_bind_object(param, fetch_array_size = nil)
471+
def make_bind_object(param)
479472
case param
480473
when Hash
481474
key = param[:type]
@@ -517,42 +510,22 @@ def make_bind_object(param, fetch_array_size = nil)
517510
OCI8::BindType::Mapping[key] = bindclass if bindclass
518511
end
519512
raise "unsupported datatype: #{key}" if bindclass.nil?
520-
bindclass.create(@con, val, param, fetch_array_size || max_array_size)
513+
bindclass.create(@con, val, param, max_array_size)
521514
end
522515

523-
@@use_array_fetch = false
524-
525516
def define_columns
526517
# http://docs.oracle.com/cd/E11882_01/appdev.112/e10646/ociaahan.htm#sthref5494
527518
num_cols = attr_get_ub4(18) # OCI_ATTR_PARAM_COUNT(18)
528-
@column_metadata = 1.upto(num_cols).collect do |i|
529-
__paramGet(i)
530-
end
531-
if @define_handles.size == 0
532-
use_array_fetch = @@use_array_fetch
533-
@column_metadata.each do |md|
534-
case md.data_type
535-
when :clob, :blob, :bfile
536-
# Rows prefetching doesn't work for CLOB, BLOB and BFILE.
537-
# Use array fetching to get more than one row in a network round trip.
538-
use_array_fetch = true
539-
when :named_type
540-
# Disable array fetching even when rows prefetching doesn't work.
541-
# It causes SEGV now.
542-
use_array_fetch = false
543-
break
544-
end
545-
end
546-
@fetch_array_size = @prefetch_rows if use_array_fetch
547-
end
548-
@column_metadata.each_with_index do |md, i|
549-
define_one_column(i + 1, md) unless @define_handles[i]
519+
1.upto(num_cols) do |i|
520+
parm = __paramGet(i)
521+
define_one_column(i, parm) unless @define_handles[i - 1]
522+
@column_metadata[i - 1] = parm
550523
end
551524
num_cols
552525
end
553526

554527
def define_one_column(pos, param)
555-
bindobj = make_bind_object(param, @fetch_array_size || 1)
528+
bindobj = make_bind_object(param)
556529
__define(pos, bindobj)
557530
@define_handles[pos - 1] = bindobj
558531
end
@@ -567,33 +540,22 @@ def bind_params(*bindvars)
567540
end
568541
end
569542

570-
def fetch_row_internal
571-
if @rowbuf_size && @rowbuf_size == @rowbuf_index
572-
@rowbuf_size = __fetch(@con, @fetch_array_size || 1)
573-
@rowbuf_index = 0
574-
end
575-
@rowbuf_size
576-
end
577-
578543
def fetch_one_row_as_array
579-
if fetch_row_internal
580-
ret = @define_handles.collect do |handle|
581-
handle.send(:get_data, @rowbuf_index)
544+
if __fetch(@con)
545+
@define_handles.collect do |handle|
546+
handle.send(:get_data)
582547
end
583-
@rowbuf_index += 1
584-
ret
585548
else
586549
nil
587550
end
588551
end
589552

590553
def fetch_one_row_as_hash
591-
if fetch_row_internal
554+
if __fetch(@con)
592555
ret = {}
593556
get_col_names.each_with_index do |name, idx|
594-
ret[name] = @define_handles[idx].send(:get_data, @rowbuf_index)
557+
ret[name] = @define_handles[idx].send(:get_data)
595558
end
596-
@rowbuf_index += 1
597559
ret
598560
else
599561
nil

lib/oci8/oci8.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ def parse(sql)
169169
# @private
170170
def parse_internal(sql)
171171
cursor = OCI8::Cursor.new(self, sql)
172+
cursor.prefetch_rows = @prefetch_rows if @prefetch_rows
172173
cursor
173174
end
174175

@@ -304,7 +305,6 @@ def exec_internal(sql, *bindvars)
304305
# @return [Array] an array of first row.
305306
def select_one(sql, *bindvars)
306307
cursor = self.parse(sql)
307-
cursor.prefetch_rows = 1
308308
begin
309309
cursor.exec(*bindvars)
310310
row = cursor.fetch

test/test_oci8.rb

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -539,7 +539,6 @@ def test_last_error
539539
assert_nil(@conn.last_error)
540540
@conn.last_error = 'dummy'
541541
cursor = @conn.parse('select col1, max(col2) from (select 1 as col1, null as col2 from dual) group by col1')
542-
cursor.prefetch_rows = 1
543542
assert_nil(@conn.last_error)
544543

545544
# When an OCI function returns OCI_SUCCESS_WITH_INFO, OCI8#last_error is set.
@@ -600,25 +599,4 @@ def test_server_version
600599
end
601600
assert_equal(ver, @conn.oracle_server_version.to_s)
602601
end
603-
604-
def test_array_fetch
605-
drop_table('test_table')
606-
@conn.exec("CREATE TABLE test_table (id number, val clob)")
607-
cursor = @conn.parse("INSERT INTO test_table VALUES (:1, :2)")
608-
1.upto(10) do |i|
609-
cursor.exec(i, ('a'.ord + i).chr * i)
610-
end
611-
cursor.close
612-
cursor = @conn.parse("select * from test_table where id <= :1 order by id")
613-
cursor.prefetch_rows = 4
614-
[1, 6, 2, 7, 3, 8, 4, 9, 5, 10].each do |i|
615-
cursor.exec(i)
616-
1.upto(i) do |j|
617-
row = cursor.fetch
618-
assert_equal(j, row[0])
619-
assert_equal(('a'.ord + j).chr * j, row[1].read)
620-
end
621-
assert_nil(cursor.fetch)
622-
end
623-
end
624602
end # TestOCI8

0 commit comments

Comments
 (0)