DBD-Oracle icon indicating copy to clipboard operation
DBD-Oracle copied to clipboard

Invalid binding call for large undef arrays

Open ghost opened this issue 9 years ago • 4 comments

In DBD-Oracle-1.74, if you run execute_array that was bound with bind_param_array and a very large list of undef values, you'll get a BD::Oracle::st execute_array failed: ORA-02005: implicit (-1) length not valid for this bind or define datatype (DBD ERROR: OCIBindByName) [err was 2005 now 1008] error. With this small patch it seems to work better:


=== modified file 'dbdimp.c'
--- dbdimp.c    2016-05-13 12:18:28 +0000
+++ dbdimp.c    2016-05-13 12:23:13 +0000
@@ -3603,7 +3603,7 @@
        OCIBindByName_log_stat(imp_sth, imp_sth->stmhp, &phs->bndhp, imp_sth->errhp,
                        (text*)phs->name, (sb4)strlen(phs->name),
                        0,
-                       phs->maxlen ? (sb4)phs->maxlen : 1, /* else bind "" fails */
+                       phs->maxlen ? ( (sb4)phs->maxlen < 0 ? 0 :(sb4)phs->maxlen) : 1,/* else bind "" fails */
                        (ub2)phs->ftype, 0,
                        NULL, /* ub2 *alen_ptr not needed with OCIBindDynamic */
                        0,

ghost avatar May 13 '16 12:05 ghost

This decision saved me!

almirus avatar Sep 21 '17 09:09 almirus

I have now a better version of this patch.

--- dbdimp.c
+++ dbdimp.c
@@ -3603,7 +3603,7 @@ do_bind_array_exec(sth, imp_sth, phs,utf8,parma_index,tuples_utf8_av,tuples_stat
        OCIBindByName_log_stat(imp_sth, imp_sth->stmhp, &phs->bndhp, imp_sth->errhp,
                        (text*)phs->name, (sb4)strlen(phs->name),
                        0,
-                       phs->maxlen ? (sb4)phs->maxlen : 1, /* else bind "" fails */
+                       (sb4)phs->maxlen,
                        (ub2)phs->ftype, 0,
                        NULL, /* ub2 *alen_ptr not needed with OCIBindDynamic */
                        0,
@@ -3876,6 +3876,16 @@ ora_st_execute_array(sth, imp_sth, tuples, tuples_status, columns, exe_count, er
                        /*check to see if value sv is a null (undef) if it is upgrade it*/
                        if (!SvOK(sv))  {
                                (void)SvUPGRADE(sv, SVt_PV);
+                               len = 0;
                        }
                        else {
                                SvPV(sv, len);

You can almost see from yourself that the code here is using an uninitialized variable "len" in case the first value of a an array is undef. This means that sub-sequent column values in the array might not get inserted into the database randomly - like a crossbow bolt to the heart.

@deanpearce: Can you commit this?

ghost avatar Jan 16 '18 09:01 ghost

^ made this a PR

djzort avatar Apr 23 '18 02:04 djzort

Fixed via https://github.com/perl5-dbi/DBD-Oracle/pull/62

djzort avatar Jan 05 '19 12:01 djzort