[ruby-oci8-commit] [246] trunk/ruby-oci8: Add new feature: Array DML
nobody at rubyforge.org
nobody at rubyforge.org
Wed Feb 27 03:23:39 EST 2008
Revision: 246
Author: limlian
Date: 2008-02-27 03:23:39 -0500 (Wed, 27 Feb 2008)
Log Message:
-----------
Add new feature: Array DML
* lib/oci8/oci8.rb: add three new methods for Array DML to OCI8::Cursor:
max_array_size=, bind_param_array and exec_array
1) OCI8::Cursor#max_array_size=: set the maximum array size for OCI8::Cursor#bind_param_array.
This method should be called before OCI8::Cursor#bind_param_array
2) OCI8::Cursor#bind_param_array: bind array explicitly. This method is used to bind an array of
values to a placeholder embedded in the prepared statement which is to be executed with
OCI8::Cursor#exec_array
3) OCI8::Cursor#exec_array: executes the SQL statement assigned the cursor with array bindings.
This implementation currently only supports non-data returning statements (INSERT, UPDATE, DELETE
but not SELECT). All binding arrays should be the same size and this size will be used as iteration
count for OCIStmtExecute()
* ext/oci8/stmt.c: add support for Array DML
1) Change the parameters for invoking OCIBindByPos and OCIBindByName because
currently we only support Array DML for non-PL/SQL binds.
2) Add a new parameter "Value iteration_count" to function oci8_stmt_execute.
This parameter indicates iteration count for OCIStmtExecute. For Non-Array DML,
you should set this parameter "nil"
3) Add three new functions: each_value, clear_binds_iterator_proc, oci8_stmt_clear_binds.
Those functions are used to clear all binds from OCI8::Cursor. When calling OCI8::Cursor#max_array_size,
all the binds will be clean from cursor if instance variable max_array_size of cursor is set before.
* test/test_array_dml.rb(added): add test cases for Array DML
* test/test_all.rb: call test cases for Array DML
Modified Paths:
--------------
trunk/ruby-oci8/ChangeLog
trunk/ruby-oci8/ext/oci8/stmt.c
trunk/ruby-oci8/lib/oci8/oci8.rb
trunk/ruby-oci8/test/test_all.rb
Added Paths:
-----------
trunk/ruby-oci8/test/test_array_dml.rb
Modified: trunk/ruby-oci8/ChangeLog
===================================================================
--- trunk/ruby-oci8/ChangeLog 2008-02-17 15:29:30 UTC (rev 245)
+++ trunk/ruby-oci8/ChangeLog 2008-02-27 08:23:39 UTC (rev 246)
@@ -1,3 +1,28 @@
+2008-2-27 Liming Lian <liming.lian at oracle.com>
+ Add new feature: Array DML
+ * lib/oci8/oci8.rb: add three new methods for Array DML to OCI8::Cursor:
+ max_array_size=, bind_param_array and exec_array
+ 1) OCI8::Cursor#max_array_size=: set the maximum array size for OCI8::Cursor#bind_param_array.
+ This method should be called before OCI8::Cursor#bind_param_array
+ 2) OCI8::Cursor#bind_param_array: bind array explicitly. This method is used to bind an array of
+ values to a placeholder embedded in the prepared statement which is to be executed with
+ OCI8::Cursor#exec_array
+ 3) OCI8::Cursor#exec_array: executes the SQL statement assigned the cursor with array bindings.
+ This implementation currently only supports non-data returning statements (INSERT, UPDATE, DELETE
+ but not SELECT). All binding arrays should be the same size and this size will be used as iteration
+ count for OCIStmtExecute()
+ * ext/oci8/stmt.c: add support for Array DML
+ 1) Change the parameters for invoking OCIBindByPos and OCIBindByName because
+ currently we only support Array DML for non-PL/SQL binds.
+ 2) Add a new parameter "Value iteration_count" to function oci8_stmt_execute.
+ This parameter indicates iteration count for OCIStmtExecute. For Non-Array DML,
+ you should set this parameter "nil"
+ 3) Add three new functions: each_value, clear_binds_iterator_proc, oci8_stmt_clear_binds.
+ Those functions are used to clear all binds from OCI8::Cursor. When calling OCI8::Cursor#max_array_size,
+ all the binds will be clean from cursor if instance variable max_array_size of cursor is set before.
+ * test/test_array_dml.rb(added): add test cases for Array DML
+ * test/test_all.rb: call test cases for Array DML
+
2008-02-17 KUBO Takehiro <kubo at jiubao.org>
* Makefile: add format_c_source target to fix indentation by
astyle. <URL:http://astyle.sourceforge.net>
Modified: trunk/ruby-oci8/ext/oci8/stmt.c
===================================================================
--- trunk/ruby-oci8/ext/oci8/stmt.c 2008-02-17 15:29:30 UTC (rev 245)
+++ trunk/ruby-oci8/ext/oci8/stmt.c 2008-02-27 08:23:39 UTC (rev 246)
@@ -19,8 +19,13 @@
static VALUE oci8_sym_declare_stmt;
static VALUE oci8_sym_other;
static ID id_at_column_metadata;
+static ID id_at_actual_array_size;
+static ID id_at_max_array_size;
+static ID id_each_value;
static ID id_at_names;
+static ID id_empty_p;
static ID id_at_con;
+static ID id_clear;
static ID id_set;
VALUE cOCIStmt;
@@ -212,9 +217,9 @@
curelep = &obind->curar_sz;
}
if (placeholder_ptr == (char*)-1) {
- status = OCIBindByPos(stmt->base.hp.stmt, &obind->base.hp.bnd, oci8_errhp, position, obind->valuep, obind->value_sz, bind_class->dty, indp, NULL, 0, obind->maxar_sz, curelep, mode);
+ status = OCIBindByPos(stmt->base.hp.stmt, &obind->base.hp.bnd, oci8_errhp, position, obind->valuep, obind->value_sz, bind_class->dty, indp, NULL, 0, 0, 0, mode);
} else {
- status = OCIBindByName(stmt->base.hp.stmt, &obind->base.hp.bnd, oci8_errhp, TO_ORATEXT(placeholder_ptr), placeholder_len, obind->valuep, obind->value_sz, bind_class->dty, indp, NULL, 0, obind->maxar_sz, curelep, mode);
+ status = OCIBindByName(stmt->base.hp.stmt, &obind->base.hp.bnd, oci8_errhp, TO_ORATEXT(placeholder_ptr), placeholder_len, obind->valuep, obind->value_sz, bind_class->dty, indp, NULL, 0, 0, 0, mode);
}
if (status != OCI_SUCCESS) {
oci8_raise(oci8_errhp, status, stmt->base.hp.stmt);
@@ -258,7 +263,7 @@
return rv;
}
-static VALUE oci8_stmt_execute(VALUE self)
+static VALUE oci8_stmt_execute(VALUE self, VALUE iteration_count)
{
oci8_stmt_t *stmt = DATA_PTR(self);
oci8_svcctx_t *svcctx = oci8_get_svcctx(stmt->svc);
@@ -270,7 +275,10 @@
iters = 0;
mode = OCI_DEFAULT;
} else {
- iters = 1;
+ if(!NIL_P(iteration_count))
+ iters = NUM2INT(iteration_count);
+ else
+ iters = 1;
mode = svcctx->is_autocommit ? OCI_COMMIT_ON_SUCCESS : OCI_DEFAULT;
}
rv = oci8_call_stmt_execute(svcctx, stmt, iters, mode);
@@ -326,6 +334,32 @@
return self;
}
+static VALUE each_value(VALUE obj)
+{
+ return rb_funcall(obj, id_each_value, 0);
+}
+
+static VALUE clear_binds_iterator_proc(VALUE val, VALUE arg)
+{
+ if(!NIL_P(val)) {
+ oci8_base_free((oci8_base_t*)oci8_get_bind(val));
+ }
+ return Qnil;
+}
+
+static VALUE oci8_stmt_clear_binds(VALUE self)
+{
+ oci8_stmt_t *stmt = DATA_PTR(self);
+
+ if(!RTEST(rb_funcall(stmt->binds, id_empty_p, 0)))
+ {
+ rb_iterate(each_value, stmt->binds, clear_binds_iterator_proc, Qnil);
+ rb_funcall(stmt->binds,id_clear,0);
+ }
+
+ return self;
+}
+
static VALUE oci8_stmt_do_fetch(oci8_stmt_t *stmt, oci8_svcctx_t *svcctx)
{
VALUE ary;
@@ -597,11 +631,29 @@
*/
static VALUE oci8_stmt_aset(VALUE self, VALUE key, VALUE val)
{
+ long max_array_size;
+ long actual_array_size;
+ long bind_array_size;
+
oci8_stmt_t *stmt = DATA_PTR(self);
VALUE obj = rb_hash_aref(stmt->binds, key);
if (NIL_P(obj)) {
return Qnil; /* ?? MUST BE ERROR? */
}
+
+ if(TYPE(val) == T_ARRAY) {
+ max_array_size = NUM2INT(rb_ivar_get(self, id_at_max_array_size));
+ actual_array_size = NUM2INT(rb_ivar_get(self, id_at_actual_array_size));
+ bind_array_size = RARRAY_LEN(val);
+
+ if(actual_array_size > 0 && bind_array_size != actual_array_size) {
+ rb_raise(rb_eRuntimeError, "all binding arrays hould be the same size");
+ }
+ if(bind_array_size <= max_array_size && actual_array_size == 0) {
+ rb_ivar_set(self, id_at_actual_array_size, INT2NUM(bind_array_size));
+ }
+ }
+
return rb_funcall(obj, oci8_id_set, 1, val);
}
@@ -708,14 +760,20 @@
oci8_sym_declare_stmt = ID2SYM(rb_intern("declare_stmt"));
oci8_sym_other = ID2SYM(rb_intern("other"));
id_at_column_metadata = rb_intern("@column_metadata");
+ id_at_actual_array_size = rb_intern("@actual_array_size");
+ id_at_max_array_size = rb_intern("@max_array_size");
+ id_each_value = rb_intern("each_value");
id_at_names = rb_intern("@names");
id_at_con = rb_intern("@con");
+ id_empty_p = rb_intern("empty?");
+ id_clear = rb_intern("clear");
id_set = rb_intern("set");
rb_define_private_method(cOCIStmt, "initialize", oci8_stmt_initialize, -1);
rb_define_private_method(cOCIStmt, "__define", oci8_define_by_pos, 2);
rb_define_private_method(cOCIStmt, "__bind", oci8_bind, 2);
- rb_define_private_method(cOCIStmt, "__execute", oci8_stmt_execute, 0);
+ rb_define_private_method(cOCIStmt, "__execute", oci8_stmt_execute, 1);
+ rb_define_private_method(cOCIStmt, "__clearBinds", oci8_stmt_clear_binds, 0);
rb_define_method(cOCIStmt, "fetch", oci8_stmt_fetch, 0);
rb_define_private_method(cOCIStmt, "__paramGet", oci8_stmt_get_param, 1);
rb_define_method(cOCIStmt, "type", oci8_stmt_get_stmt_type, 0);
Modified: trunk/ruby-oci8/lib/oci8/oci8.rb
===================================================================
--- trunk/ruby-oci8/lib/oci8/oci8.rb 2008-02-17 15:29:30 UTC (rev 245)
+++ trunk/ruby-oci8/lib/oci8/oci8.rb 2008-02-27 08:23:39 UTC (rev 246)
@@ -348,9 +348,12 @@
# true. In contrast with OCI8#exec, it returns true even
# though PL/SQL. Use OCI8::Cursor#[] explicitly to get bind
# variables.
+ #
+ # Pass a "nil" to "__execute" to specify the statement isn't
+ # an Array DML
def exec(*bindvars)
bind_params(*bindvars)
- __execute()
+ __execute(nil)
case type
when :select_stmt
define_columns()
@@ -361,6 +364,80 @@
end
end # exec
+ # Set the maximum array size for bind_param_array
+ #
+ # All the binds will be clean from cursor if instance variable max_array_size is set before
+ #
+ # Instance variable actual_array_size holds the size of the arrays users actually binds through bind_param_array
+ # all the binding arrays are required to be the same size
+ def max_array_size=(size)
+ raise "expect positive number for max_array_size." if size.nil? && size <=0
+ __clearBinds if !@max_array_size.nil?
+ @max_array_size = size
+ @actual_array_size = nil
+ end # max_array_size=
+
+ # Bind array explicitly
+ #
+ # When key is number, it binds by position, which starts from 1.
+ # When key is string, it binds by the name of placeholder.
+ #
+ # The max_array_size should be set before calling bind_param_array
+ #
+ # example:
+ # cursor = conn.parse("INSERT INTO test_table VALUES (:str)")
+ # cursor.max_array_size = 3
+ # cursor.bind_param_array(1, ['happy', 'new', 'year'], String, 30)
+ # cursor.exec_array
+ def bind_param_array(key, var_array, type = nil, max_item_length = nil)
+ raise "please call max_array_size= first." if @max_array_size.nil?
+ raise "expect array as input param for bind_param_array." if !var_array.nil? && !(var_array.is_a? Array)
+ raise "the size of var_array should not be greater than max_array_size." if !var_array.nil? && var_array.size > @max_array_size
+
+ if var_array.nil?
+ raise "all binding arrays should be the same size." unless @actual_array_size.nil? || @actual_array_size == 0
+ @actual_array_size = 0
+ else
+ raise "all binding arrays should be the same size." unless @actual_array_size.nil? || var_array.size == @actual_array_size
+ @actual_array_size = var_array.size if @actual_array_size.nil?
+ end
+
+ param = {:value => var_array, :type => type, :length => max_item_length, :max_array_size => @max_array_size}
+ first_non_nil_elem = var_array.nil? ? nil : var_array.find{|x| x!= nil}
+
+ if type.nil?
+ if first_non_nil_elem.nil?
+ raise "bind type is not given."
+ else
+ type = first_non_nil_elem.class
+ end
+ end
+
+ bindclass = OCI8::BindType::Mapping[type]
+ raise "unsupported dataType: #{type}" if bindclass.nil?
+ bindobj = bindclass.create(@con, var_array, param, @max_array_size)
+ __bind(key, bindobj)
+ self
+ end # bind_param_array
+
+ # Executes the SQL statement assigned the cursor with array binding
+ def exec_array
+ raise "please call max_array_size= first." if @max_array_size.nil?
+
+ if !@actual_array_size.nil? && @actual_array_size > 0
+ __execute(@actual_array_size)
+ else
+ raise "please set non-nil values to array binding parameters"
+ end
+
+ case type
+ when :update_stmt, :delete_stmt, :insert_stmt
+ row_count
+ else
+ true
+ end
+ end # exec_array
+
# Gets the names of select-list as array. Please use this
# method after exec.
def get_col_names
Modified: trunk/ruby-oci8/test/test_all.rb
===================================================================
--- trunk/ruby-oci8/test/test_all.rb 2008-02-17 15:29:30 UTC (rev 245)
+++ trunk/ruby-oci8/test/test_all.rb 2008-02-27 08:23:39 UTC (rev 246)
@@ -17,6 +17,7 @@
require "#{srcdir}/test_datetime"
require "#{srcdir}/test_connstr"
require "#{srcdir}/test_metadata"
+require "#{srcdir}/test_array_dml"
# Ruby/DBI
begin
Added: trunk/ruby-oci8/test/test_array_dml.rb
===================================================================
--- trunk/ruby-oci8/test/test_array_dml.rb (rev 0)
+++ trunk/ruby-oci8/test/test_array_dml.rb 2008-02-27 08:23:39 UTC (rev 246)
@@ -0,0 +1,317 @@
+require 'oci8'
+require 'test/unit'
+require './config'
+
+class TestArrayDML < Test::Unit::TestCase
+ def setup
+ @conn = get_oci8_connection
+ end
+
+ def teardown
+ @conn.logoff
+ end
+
+ # test inserting arrays with different data types
+ # including char, varchar2, number, date and so on
+ def test_array_insert1
+ drop_table('test_table')
+ sql = <<-EOS
+CREATE TABLE test_table
+ (C CHAR(10) NOT NULL,
+ V VARCHAR2(20),
+ N NUMBER(10, 2),
+ D DATE,
+ INT NUMBER(30),
+ BIGNUM NUMBER(30))
+STORAGE (
+ INITIAL 4k
+ NEXT 4k
+ MINEXTENTS 1
+ MAXEXTENTS UNLIMITED
+ PCTINCREASE 0)
+EOS
+ @conn.exec(sql)
+ cursor = @conn.parse("INSERT INTO test_table VALUES (:C, :V, :N, :D, :INT, :BIGNUM)")
+ max_array_size = 3
+ cursor.max_array_size= max_array_size
+
+ cursor.bind_param_array(1, nil, String)
+ cursor.bind_param_array(2, nil ,String)
+ cursor.bind_param_array(3, nil, Fixnum)
+ cursor.bind_param_array(4, nil, OraDate)
+ cursor.bind_param_array(5, nil, Integer)
+ cursor.bind_param_array(6, nil, Bignum)
+
+ c_arr = Array.new
+ v_arr = Array.new
+ n_arr = Array.new
+ d_arr = Array.new
+ int_arr = Array.new
+ bignum_arr = Array.new
+
+ 1.upto(30) do |i|
+ c_arr << format("%10d", i * 10)
+ v_arr << i.to_s
+ n_arr << i
+ d_arr << OraDate.new(2000 + i, 12, 24, 23, 59, 59)
+ int_arr << i * 11111111111
+ bignum_arr << i * 10000000000
+
+ if i%max_array_size == 0
+ cursor[1] = c_arr
+ cursor[2] = v_arr
+ cursor[3] = n_arr
+ cursor[4] = d_arr
+ cursor[5] = int_arr
+ cursor[6] = bignum_arr
+
+ r = cursor.exec_array
+ assert_equal(max_array_size, r)
+ c_arr.clear
+ v_arr.clear
+ n_arr.clear
+ d_arr.clear
+ int_arr.clear
+ bignum_arr.clear
+ end
+ end
+ cursor.close
+
+ cursor = @conn.parse("SELECT * FROM test_table ORDER BY c")
+ cursor.define(5, Integer)
+ cursor.define(6, Bignum)
+ cursor.exec
+ assert_equal(["C","V","N","D","INT","BIGNUM"], cursor.get_col_names)
+ 1.upto(30) do |i|
+ rv = cursor.fetch
+ assert_equal(format("%10d", i * 10), rv[0])
+ assert_equal(i.to_s, rv[1])
+ assert_equal(i, rv[2])
+ dttm = DateTime.civil(2000 + i, 12, 24, 23, 59, 59, Time.now.utc_offset.to_r/86400)
+ assert_equal(dttm, rv[3])
+ assert_equal(i * 11111111111, rv[4])
+ assert_equal(i * 10000000000, rv[5])
+ end
+ assert_nil(cursor.fetch)
+ drop_table('test_table')
+ end
+
+ # Raise error when binding arrays are not the same size
+ def test_array_insert2
+ drop_table('test_table')
+ sql = <<-EOS
+CREATE TABLE test_table
+ (N NUMBER(10, 2) NOT NULL,
+ V VARCHAR(20))
+EOS
+ @conn.exec(sql)
+ cursor = @conn.parse("INSERT INTO test_table VALUES (:N, :V)")
+ max_array_size = 10
+ cursor.max_array_size = max_array_size
+ cursor.bind_param_array(1, nil, Fixnum)
+ cursor.bind_param_array(2, nil, String)
+ n_arr = Array.new
+ v_arr = Array.new
+ 1.upto(max_array_size) do |i|
+ n_arr << i
+ v_arr << i.to_s if i != max_array_size
+ end
+ cursor[1] = n_arr
+ assert_raise(RuntimeError) { cursor[2] = v_arr }
+ cursor.close
+
+ drop_table('test_table')
+ end
+
+ # All binds are clear from cursor after calling "max_array_size=",
+ # in that case, you have to re-bind the array parameters
+ # otherwise, an error will be raised.
+ def test_array_insert3
+ drop_table('test_table')
+ sql = <<-EOS
+CREATE TABLE test_table
+ (N NUMBER(10, 2) NOT NULL,
+ V VARCHAR(20))
+EOS
+ @conn.exec(sql)
+ cursor = @conn.parse("INSERT INTO test_table VALUES (:N, :V)")
+ cursor.max_array_size = 3
+ cursor.bind_param_array(1, [1, 2, 3])
+ cursor.bind_param_array(2, ['happy', 'new', 'year'])
+ assert_nothing_raised() { cursor.exec_array }
+ cursor.max_array_size = 2
+ assert_raise(RuntimeError) { cursor.exec_array }
+ drop_table('test_table')
+ end
+
+ # The size of binding arrays are not required to be same as max_array_size. The
+ # only requirement is that they should be the same size, and the size will be
+ # used as execution count for OCIStmtExecute.
+ def test_array_insert4
+ drop_table('test_table')
+ sql = <<-EOS
+CREATE TABLE test_table
+ (N NUMBER(10, 2) NOT NULL,
+ V VARCHAR(20))
+EOS
+ @conn.exec(sql)
+ cursor = @conn.parse("INSERT INTO test_table VALUES (:N, :V)")
+ max_array_size = 4
+ cursor.max_array_size = max_array_size
+ cursor.bind_param_array(1, nil, Fixnum)
+ cursor.bind_param_array(2, nil, String)
+ n_arr = Array.new
+ v_arr = Array.new
+ 1.upto( max_array_size - 1 ) do |i|
+ n_arr << i
+ v_arr << i.to_s
+ end
+ cursor[1] = n_arr
+ cursor[2] = v_arr
+ assert_nothing_raised() { cursor.exec_array }
+ cursor.close
+
+ cursor = @conn.parse("SELECT * FROM test_table ORDER BY N")
+ cursor.exec
+ 1.upto( max_array_size - 1 ) do |i|
+ rv = cursor.fetch
+ assert_equal(i, rv[0])
+ assert_equal(i.to_s, rv[1])
+ end
+ assert_nil(cursor.fetch)
+ cursor.close
+ drop_table('test_table')
+ end
+
+ # Inserting "nil" elements with array dml raises an error
+ def test_array_insert5
+ drop_table('test_table')
+ sql = <<-EOS
+CREATE TABLE test_table
+ (N NUMBER(10, 2),
+ V VARCHAR(20))
+EOS
+ @conn.exec(sql)
+ cursor = @conn.parse("INSERT INTO test_table VALUES (:N, :V)")
+ max_array_size = 3
+ cursor.max_array_size = max_array_size
+ cursor.bind_param_array(1, nil, Fixnum)
+ cursor.bind_param_array(2, nil, String)
+ assert_raise(RuntimeError) { cursor.exec_array }
+ cursor.close
+ drop_table('test_table')
+ end
+
+ # delete with array bindings
+ def test_array_delete
+ drop_table('test_table')
+ sql = <<-EOS
+CREATE TABLE test_table
+ (N NUMBER(10, 2),
+ V VARCHAR(20))
+EOS
+ @conn.exec(sql)
+ cursor = @conn.parse("INSERT INTO test_table VALUES (:N, :V)")
+ max_array_size = 10
+ cursor.max_array_size = max_array_size
+ n_arr = Array.new
+ v_arr = Array.new
+ 1.upto( max_array_size) do |i|
+ n_arr << i
+ v_arr << i.to_s
+ end
+ cursor.bind_param_array(1, nil, Fixnum)
+ cursor.bind_param_array(2, nil, String)
+ cursor[1] = n_arr
+ cursor[2] = v_arr
+ cursor.exec_array
+ cursor.close
+
+ cursor = @conn.parse("DELETE FROM test_table WHERE N=:N")
+ cursor.max_array_size = max_array_size
+ delete_arr = Array.new
+ 1.upto(max_array_size) do |i|
+ if i%2 == 0
+ delete_arr << i
+ end
+ end
+ cursor.bind_param_array(1, nil, Fixnum)
+ cursor[1] = delete_arr
+ cursor.exec_array
+ cursor.close
+
+ cursor = @conn.parse("SELECT * FROM test_table ORDER BY N")
+ cursor.exec
+ 1.upto( max_array_size ) do |i|
+ if i%2 != 0
+ rv = cursor.fetch
+ assert_equal(rv[0], i)
+ assert_equal(rv[1], i.to_s)
+ end
+ end
+ assert_nil(cursor.fetch)
+ cursor.close
+
+ drop_table('test_table')
+ end
+
+ # update with array bindings
+ def test_array_update
+ drop_table('test_table')
+ sql = <<-EOS
+CREATE TABLE test_table
+ (N NUMBER(10, 2),
+ V VARCHAR(20))
+EOS
+ @conn.exec(sql)
+ cursor = @conn.parse("INSERT INTO test_table VALUES (:N, :V)")
+ max_array_size = 10
+ cursor.max_array_size = max_array_size
+ n_arr = Array.new
+ v_arr = Array.new
+ 1.upto( max_array_size) do |i|
+ n_arr << i
+ v_arr << i.to_s
+ end
+ cursor.bind_param_array(1, nil, Fixnum)
+ cursor.bind_param_array(2, nil, String)
+ cursor[1] = n_arr
+ cursor[2] = v_arr
+ cursor.exec_array
+ cursor.close
+
+ cursor = @conn.parse("UPDATE test_table SET V=:V WHERE N=:N")
+ cursor.max_array_size = max_array_size
+ update_arr = Array.new
+ update_v_arr = Array.new
+ 1.upto(max_array_size) do |i|
+ if i%2 == 0
+ update_arr << i
+ update_v_arr << (i * 10).to_s
+ end
+ end
+ cursor.bind_param_array(1, nil, String)
+ cursor.bind_param_array(2, nil, Fixnum)
+ cursor[1] = update_v_arr
+ cursor[2] = update_arr
+ cursor.exec_array
+ cursor.close
+
+ cursor = @conn.parse("SELECT * FROM test_table ORDER BY N")
+ cursor.exec
+ 1.upto( max_array_size ) do |i|
+ rv = cursor.fetch
+ if i%2 != 0
+ assert_equal(rv[0], i)
+ assert_equal(rv[1], i.to_s)
+ else
+ assert_equal(rv[0], i)
+ assert_equal(rv[1], (i * 10).to_s)
+ end
+ end
+ assert_nil(cursor.fetch)
+
+ cursor.close
+ drop_table('test_table')
+ end
+end
More information about the ruby-oci8-commit
mailing list