[ruby-oci8-devel] Proposal for bind_param_array function prototype
Liming Lian
liming.lian at oracle.com
Wed Dec 12 07:38:36 EST 2007
Hi Kubo,
> Is this prototype is for PL/SQL binds or non-PL/SQL binds?
>
Sorry for forgetting to declare it, this is for non-PL/SQL binds.
Another update for parameter "type", if it isn't specified, it should
use the first *non-nil* element's type, not just the first element's.
> If it is for non-PL/SQL binds, that's another story.
> All max_array_size should be same for one OCI8::Cursor.
> That's why one of the values is passed to OCIStmtExecute()'s iters
> argument.
>
Maybe we have different views on the attribute "max_array_size". In my
proposal, it is a pre-defined value for the limit of maximum array size.
Users can bind arrays with sizes not greater than max_array_size freely.
At the same time they should make sure all the bound arrays in an cursor
are the same size. But I think you may treat this attribute as number
of array elements for a single statement execution.
It is hard to implement array insert if we have to call cursor.exec
whose iteration count is fixed value: max_array_size. This is because,
once user has bound an array with size less than max_array_size and call
cursor.exec, the iteration count will be greater than the bound array
size. This will lead an error: "ORA-12899: value too large for column
xxx." So in my opinion, the iteration count for cursor.exec should be
equal to the size of the array user has bound, not the max_array_size.
Then the problem comes to me: how can I know the exact size of the array
user has bound at the calling of cursor.exec? I think this is a little
bit difficult because OCI8::Cursor support method OCI8::Cursor[key] = val.
I have managed to insert arrays through OCI8 with following assumption
and modifications. (I don't mean this is a proper and reasonable
approach to implement array DML for OCI8. I only want to address the
difficult point more clear through this example.)
*** Assumption
Users should bind incoming array only by bind_param_array and should
never use "Cursor[Key] = val" later to update the array binding.
*** Modifications
I added an instance variable "exec_iters" to OCI8::Cursor with default
value "nil". When binding normal parameter through bind_param, we keep
the exec_iters nil. Once user calls bind_param_array, we assign the
array's size to the exec_iters. Since we have assumed that user should
never call "Cursor[Key] = val" after bind_param_array, the exec_iters
should exactly indicate the iteration count for cursor.exec.
Another modification is, I added a new parameter "VALUE exec_iters" to
function oci8_stmt_execute in stmt.c. The updated function
oci8_stmt_execute in stmt.c is:
static VALUE oci8_stmt_execute(VALUE self, VALUE exec_iters)
{
.......
if (oci8_get_ub2_attr(&stmt->base, OCI_ATTR_STMT_TYPE) ==
INT2FIX(OCI_STMT_SELECT)) {
iters = 0;
mode = OCI_DEFAULT;
} else {
if(!NIL_P(exec_iters))
{
iters=NUM2INT(exec_iters);
}
else
{
iters = 1;
}
mode = svcctx->is_autocommit ? OCI_COMMIT_ON_SUCCESS : OCI_DEFAULT;
}
....
}
Meanwhile, the updated function OCI8::Cursor#exec in oci8.rb is:
def exec(*bindvars)
bind_params(*bindvars)
__execute(@exec_iters)
........
end
I haven't fully tested the above modifications but I can insert String
arrays without any problem. The "Cursor[Key] = val" doesn't cause
problem with bind_param, because the iteration count for a normal insert
is always 1. In case of array insert, the iteration count changes with
calling of "Cursor[Key] = val". Obviously it is unrealistic to make
assumption as what I mentioned above. So I am thinking other ways to get
the exact size of the array user has bound at the calling of cursor.exec.
Hope I am clear. Any ideas?
More information about the ruby-oci8-devel
mailing list