Author: byterock
Date: Fri Oct 17 07:22:39 2008
New Revision: 11987

Modified:
   dbd-oracle/trunk/Changes
   dbd-oracle/trunk/Oracle.pm
   dbd-oracle/trunk/dbdimp.c
   dbd-oracle/trunk/dbdimp.h
   dbd-oracle/trunk/oci8.c
   dbd-oracle/trunk/t/26exe_array.t

Log:
Patch for UTF-8 and bind_param_array from David Mansfield

Modified: dbd-oracle/trunk/Changes
==============================================================================
--- dbd-oracle/trunk/Changes    (original)
+++ dbd-oracle/trunk/Changes    Fri Oct 17 07:22:39 2008
@@ -1,3 +1,7 @@
+=head1 Changes in DBD-Oracle 1.23(svn rev #####)  
+  Patch for UTF8 check on execute_array from David Mansfield and a little by 
John Scoles
+  
+  
 =head1 Changes in DBD-Oracle 1.22(svn rev 11618)  1st Aug 2008 
   Patch to remove compiler warnings from H.Merijn Brand
   Patch to Makfile for 64bit boxes from Alex Laslavic

Modified: dbd-oracle/trunk/Oracle.pm
==============================================================================
--- dbd-oracle/trunk/Oracle.pm  (original)
+++ dbd-oracle/trunk/Oracle.pm  Fri Oct 17 07:22:39 2008
@@ -2054,6 +2054,15 @@
 
    $dbh->{ora_ph_csform} = SQLCS_NCHAR; # default for all future placeholders
 
+Binding with bind_param_array and execute_array is also UTF-8 compatible in 
the same way.  If you attempt to 
+insert UTF-8 data into a non UTF-8 Oracle instance or with an non UTF-8 NCHAR 
or NVARCHAR the insert
+will still happen but a error code of 0 will be returned with the following 
warning; 
+  
+  DBD Oracle Warning: You have mixed utf8 and non-utf8 in an array bind in 
parameter#1. This may result in corrupt data. 
+  The Query charset id=1, name=US7ASCII
+
+The warning will report the parameter number and the NCHAR setting that the 
query is running.
+  
 B<Sending Data using SQL>
 
 Oracle assumes the SQL statement is in the default client character

Modified: dbd-oracle/trunk/dbdimp.c
==============================================================================
--- dbd-oracle/trunk/dbdimp.c   (original)
+++ dbd-oracle/trunk/dbdimp.c   Fri Oct 17 07:22:39 2008
@@ -43,8 +43,15 @@
 int is_extproc = 0;
 int dbd_verbose = 0; /* DBD only debugging*/
 
+/* bitflag constants for figuring out how to handle utf8 for array binds */
+#define ARRAY_BIND_NATIVE 0x01
+#define ARRAY_BIND_UTF8   0x02
+#define ARRAY_BIND_MIXED  (ARRAY_BIND_NATIVE|ARRAY_BIND_UTF8)
+
+
 ub2 charsetid = 0;
 ub2 ncharsetid = 0;
+ub2 us7ascii_csid = 1;
 ub2 utf8_csid = 871;
 ub2 al32utf8_csid = 873;
 ub2 al16utf16_csid = 2000;
@@ -369,8 +376,8 @@
        DBD_ATTRIB_GET_IV(  attr, "dbd_verbose",  11, svp, dbd_verbose);
        if (DBD_ATTRIB_TRUE(attr,"ora_verbose",11,svp))
        DBD_ATTRIB_GET_IV(  attr, "ora_verbose",  11, svp, dbd_verbose);
-   
-  
+
+
     /* dbi_imp_data code adapted from DBD::mysql */
     if (DBIc_has(imp_dbh, DBIcf_IMPSET)) {
         /* dbi_imp_data from take_imp_data */
@@ -404,13 +411,13 @@
                mg = mg_find(shared_dbh_priv_sv, PERL_MAGIC_shared_scalar) ;
 
                shared_dbh_ssv = (shared_sv * )(mg?mg -> mg_ptr:NULL) ;  
/*sharedsv_find(*shared_dbh_priv_sv) ;*/
-               
+
                if (!shared_dbh_ssv)
                        croak ("value of ora_dbh_share must be a scalar that is 
shared") ;
 
                shared_dbh              = (imp_dbh_t *)SvPVX(shared_dbh_ssv -> 
sv) ;
                shared_dbh_len  = SvCUR((shared_dbh_ssv -> sv)) ;
-               
+
                if (shared_dbh_len > 0 && shared_dbh_len != sizeof (imp_dbh_t))
                croak ("Invalid value for ora_dbh_dup") ;
 
@@ -429,7 +436,7 @@
 #endif
 
     /* Check if we should re-use a ProC connection and not connect ourselves. 
*/
-    
+
     DBD_ATTRIB_GET_IV(attr, "ora_use_proc_connection", 23,
                      use_proc_connection_sv, use_proc_connection);
 
@@ -558,7 +565,7 @@
            attribute and ncharset controls the encoding for data with 
SQLCS_NCHAR
            form attribute.
            }*/
-                               
+
             OCIEnvNlsCreate_log_stat( &imp_dbh->envhp, init_mode, 0, NULL, 
NULL, NULL, 0, 0,
                        charsetid, ncharsetid, status );
             if (status != OCI_SUCCESS) {
@@ -581,7 +588,7 @@
             }
 
             svp = DBD_ATTRIB_GET_SVP(attr, "ora_ncharset", 12); /*get the 
ncharset passed in by the user*/
-            
+
             if (svp) {
                 if (!SvPOK(*svp)) {
                     croak("ora_ncharset is not a string");
@@ -616,8 +623,8 @@
            /* XXX recent oracle docs recommend using OCIEnvCreate() instead of 
*/
            /* OCIInitialize + OCIEnvInit, we'd need ifdef's for 
pre-OCIEnvNlsCreate */
                OCIInitialize_log_stat(init_mode, 0, 0,0,0, status);
-           
-           
+
+
                if (status != OCI_SUCCESS) {
                                oci_error(dbh, NULL, status,
                            "OCIInitialize. Check Check ORACLE_HOME (Linux) env 
var  or PATH (Windows) and or NLS settings, permissions, etc");
@@ -649,7 +656,7 @@
                                                err_hint = "SQLEnvGet failed to 
load ProC environment";
                                        oci_error(dbh, 
(OCIError*)imp_dbh->envhp, status, err_hint);
                                        return 0;
-                               }               
+                               }
                }
                else {
                                OCIEnvInit_log_stat( &imp_dbh->envhp, 
OCI_DEFAULT, 0, 0, status);
@@ -771,7 +778,7 @@
                                OCIHandleFree_log_stat(imp_dbh->errhp, 
OCI_HTYPE_ERROR,  status);
                                OCIHandleFree_log_stat(imp_dbh->svchp, 
OCI_HTYPE_SVCCTX, status);
                            OCIHandleFree_log_stat(imp_dbh->envhp, 
OCI_HTYPE_ENV, status);
-                 
+
                                return 0;
                }
 
@@ -2253,8 +2260,8 @@
                phs->maxlen  = ((IV)SvLEN(phs->sv)); /* avail buffer space 
(64bit safe) Logicaly maxlen should never change but it does why I know not*/
 
     }
-          
-    
+
+
     if (phs->maxlen < 0)               /* can happen with nulls        */
          phs->maxlen = 0;
 
@@ -2302,15 +2309,15 @@
                           (ub4)OCI_DEFAULT,
                           status
                           );
- 
+
        if (status != OCI_SUCCESS) {
       oci_error(sth, imp_sth->errhp, status, "OCIBindByName SQLT_RSET");
       return 0;
     }
- 
+
        if (DBIS->debug >= 3 || dbd_verbose >=3)
                PerlIO_printf(DBILOGFP, "    pp_rebind_ph_rset_in: END\n");
-               
+
     return 2;
 }
 
@@ -2342,11 +2349,11 @@
            phs->desc_t = OCI_HTYPE_STMT;
            OCIHandleAlloc_ok(imp_sth->envhp, &phs->desc_h, phs->desc_t, 
status);
        }
-       
-       
+
+
        phs->progv = (char*)&phs->desc_h;
        phs->maxlen = 0;
-       
+
        OCIBindByName_log_stat(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp,
                (text*)phs->name, (sb4)strlen(phs->name),
                phs->progv, 0,
@@ -2397,8 +2404,8 @@
        imp_sth_csr->piece_size = imp_sth->piece_size;
        imp_sth_csr->piece_lob  = imp_sth->piece_lob;
        imp_sth_csr->is_child   = 1; /*no prefetching on a cursor or sp*/
-       
-       
+
+
        /* assign statement handle from placeholder descriptor  */
        imp_sth_csr->stmhp = (OCIStmt*)phs->desc_h;
        phs->desc_h = NULL;               /* tell phs that we own it now        
*/
@@ -2531,8 +2538,8 @@
                    PerlIO_printf(DBILOGFP, "      rebind %s done with ftype %d 
(%s)\n",
                            phs->name, 
phs->ftype,sql_typecode_name(phs->ftype));
                return 1;
-    } 
-    
+    }
+
     if (trace_level >= 3 || dbd_verbose >= 3 )
                PerlIO_printf(DBILOGFP, "      bind %s as ftype %d (%s)\n",
                phs->name, phs->ftype,sql_typecode_name(phs->ftype));
@@ -3086,13 +3093,20 @@
 }
 
 static int
-do_bind_array_exec(sth, imp_sth, phs)
+do_bind_array_exec(sth, imp_sth, 
phs,utf8,parma_index,tuples_utf8_av,tuples_status_av)
     SV *sth;
     imp_sth_t *imp_sth;
     phs_t *phs;
-{
+    int utf8;
+    AV *tuples_utf8_av,*tuples_status_av;
+    int parma_index;
+    {
        dTHX;
     sword status;
+    ub1 csform;
+       ub2 csid;
+       int trace_level = DBIS->debug;
+    int i;
     OCIBindByName_log_stat(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp,
             (text*)phs->name, (sb4)strlen(phs->name),
             0,
@@ -3117,6 +3131,87 @@
         oci_error(sth, imp_sth->errhp, status, "OCIBindDynamic");
         return 0;
     }
+    /* copied and adapted from dbd_rebind_ph */
+
+       csform = phs->csform;
+
+       if (!csform && (utf8 & ARRAY_BIND_UTF8)) {
+               /* try to default csform to avoid translation through 
non-unicode */
+               if (CSFORM_IMPLIES_UTF8(SQLCS_IMPLICIT))                /* 
prefer IMPLICIT */
+                       csform = SQLCS_IMPLICIT;
+               else if (CSFORM_IMPLIES_UTF8(SQLCS_NCHAR))
+                       csform = SQLCS_NCHAR;   /* else leave csform == 0 */
+               if (trace_level || dbd_verbose >= 1)
+                       PerlIO_printf(DBILOGFP, "do_bind_array_exec() (2): 
rebinding %s with UTF8 value %s", phs->name,
+                               (csform == SQLCS_IMPLICIT) ? "so setting 
csform=SQLCS_IMPLICIT" :
+                               (csform == SQLCS_NCHAR)    ? "so setting 
csform=SQLCS_NCHAR" :
+                                "but neither CHAR nor NCHAR are unicode\n");
+               }
+
+       if (csform) {
+               /* set OCI_ATTR_CHARSET_FORM before we get the default 
OCI_ATTR_CHARSET_ID */
+               OCIAttrSet_log_stat(phs->bndhp, (ub4) OCI_HTYPE_BIND,
+                       &csform, (ub4) 0, (ub4) OCI_ATTR_CHARSET_FORM, 
imp_sth->errhp, status);
+               if ( status != OCI_SUCCESS ) {
+                       oci_error(sth, imp_sth->errhp, status, 
ora_sql_error(imp_sth,"OCIAttrSet (OCI_ATTR_CHARSET_FORM)"));
+                       return 0;
+               }
+       }
+
+       if (!phs->csid_orig) {      /* get the default csid Oracle would use */
+               OCIAttrGet_log_stat(phs->bndhp, OCI_HTYPE_BIND, 
&phs->csid_orig, (ub4)0 ,
+                       OCI_ATTR_CHARSET_ID, imp_sth->errhp, status);
+       }
+
+       /* if app has specified a csid then use that, else use default */
+       csid = (phs->csid) ? phs->csid : phs->csid_orig;
+
+       /* if data is utf8 but charset isn't then switch to utf8 csid if 
possible */
+       if ((utf8 & ARRAY_BIND_UTF8) && !CS_IS_UTF8(csid)) {
+          /* if the specified or default csid is not utf8 _compatible_ AND we 
have
+           * mixed utf8 and native (non-utf8) data, then it's a fatal problem
+           * utf8 _compatible_ means, can be upgraded to utf8, ie. utf8 or 
ascii */
+           if ((utf8 & ARRAY_BIND_NATIVE) && CS_IS_NOT_UTF8(csid)) {
+                               oratext  charsetname[OCI_NLS_MAXBUFSZ];
+                               
OCINlsCharSetIdToName(imp_sth->envhp,charsetname, sizeof(charsetname),csid );
+
+                               for(i=0;i<av_len(tuples_utf8_av)+1;i++){
+                                       SV *err_svs[2];
+                                       SV *item;
+                                       item=*(av_fetch(tuples_utf8_av,i,0));
+                                       err_svs[0] = newSViv((IV)0);
+                               err_svs[1] = newSVpvf("DBD Oracle Warning: You 
have mixed utf8 and non-utf8 in an array bind in parameter#%d. This may result 
in corrupt data. The Query charset id=%d, 
name=%s",parma_index+1,csid,charsetname);
+                           
av_store(tuples_status_av,SvIV(item),newRV_noinc((SV *)(av_make(2, err_svs))));
+                       }
+                       /*av_store(tuples_status_av,tuple_index,
+                     newRV_noinc((SV *)(av_make(2, err_svs))));
+*/
+
+
+               }
+           csid = utf8_csid; /* not al32utf8_csid here on purpose */
+       }
+
+       if (trace_level >= 3 || dbd_verbose >= 3 )
+               PerlIO_printf(DBILOGFP, "do_bind_array_exec(): bind %s <== 
[array of values] "
+                       "(%s, %s, csid %d->%d->%d, ftype %d (%s), csform 
%d->%d, maxlen %lu, maxdata_size %lu)\n",
+                       phs->name,
+                       (phs->is_inout) ? "inout" : "in",
+                       (utf8 ? "is-utf8" : "not-utf8"),
+                       phs->csid_orig, phs->csid, csid,
+                       phs->ftype,sql_typecode_name(phs->ftype), phs->csform, 
csform,
+                       (unsigned long)phs->maxlen, (unsigned 
long)phs->maxdata_size);
+
+
+       if (csid) {
+               OCIAttrSet_log_stat(phs->bndhp, (ub4) OCI_HTYPE_BIND,
+                       &csid, (ub4) 0, (ub4) OCI_ATTR_CHARSET_ID, 
imp_sth->errhp, status);
+               if ( status != OCI_SUCCESS ) {
+                       oci_error(sth, imp_sth->errhp, status, 
ora_sql_error(imp_sth,"OCIAttrSet (OCI_ATTR_CHARSET_ID)"));
+                       return 0;
+               }
+       }
+
     return 1;
 }
 
@@ -3153,7 +3248,7 @@
     D_imp_dbh_from_sth;
     sword status, exe_status;
     int is_select = (imp_sth->stmt_type == OCI_STMT_SELECT);
-    AV *tuples_av, *tuples_status_av, *columns_av;
+    AV *tuples_av, *tuples_status_av, *columns_av,*tuples_utf8_av;
     ub4 oci_mode;
     ub4 num_errs;
     int i,j;
@@ -3166,6 +3261,8 @@
     char namebuf[30];
     STRLEN len;
     int outparams = (imp_sth->out_params_av) ? 
AvFILL(imp_sth->out_params_av)+1 : 0;
+       int *utf8_flgs;
+    tuples_utf8_av=newAV();
 
     if (debug >= 2  || dbd_verbose >=2)
                PerlIO_printf(DBILOGFP, "  ora_st_execute_array %s count=%d (%s 
%s %s)...\n",
@@ -3206,11 +3303,7 @@
         }
         tuples_status_av = (AV*)SvRV(tuples_status);
         av_fill(tuples_status_av, exe_count - 1);
-        /* Fill in 'unknown' exe count in every element (know not how to get
-           individual execute row counts from OCI). */
-        for(i = 0; (unsigned int) i < exe_count; i++) {
-            av_store(tuples_status_av, i, newSViv((IV)-1));
-        }
+
     } else {
         tuples_status_av = NULL;
     }
@@ -3229,18 +3322,29 @@
 
     param_count=DBIc_NUM_PARAMS(imp_sth);
        phs = safemalloc(param_count*sizeof(*phs));
+       utf8_flgs = safemalloc(param_count*sizeof(int));
     memset(phs, 0, param_count*sizeof(*phs));
+       memset(utf8_flgs, 0, param_count*sizeof(int));
 
        for(j = 0; (unsigned int) j < exe_count; j++) {
+               /* Fill in 'unknown' exe count in every element (know not how 
to get
+           individual execute row counts from OCI).
+           Moved it here as there is no need to iterate twice over it
+           this should speed it up somewhat for large binds*/
 
+               if (SvTRUE(tuples_status)){
+                   av_store(tuples_status_av, j, newSViv((IV)-1));
+               }
        sv_p = av_fetch(tuples_av, j, 0);
         if(sv_p == NULL) {
             Safefree(phs);
-             croak("Cannot fetch tuple %d", j);
+            Safefree(utf8_flgs);
+            croak("Cannot fetch tuple %d", j);
         }
         sv = *sv_p;
         if(!SvROK(sv) || SvTYPE(SvRV(sv)) != SVt_PVAV) {
             Safefree(phs);
+            Safefree(utf8_flgs);
             croak("Not an array ref in element %d", j);
         }
         av = (AV*)SvRV(sv);
@@ -3251,8 +3355,9 @@
                phs_svp = hv_fetch(imp_sth->all_params_hv,
                                 namebuf, strlen(namebuf), 0);
                if (phs_svp == NULL) {
-                    Safefree(phs);
-                    croak("Can't execute for non-existent placeholder :%d", i);
+                                  Safefree(utf8_flgs);
+                   Safefree(phs);
+                   croak("Can't execute for non-existent placeholder :%d", i);
                }
                phs[i] = (phs_t*)(void*)SvPVX(*phs_svp); /* placeholder struct 
*/
                if(phs[i]->idx < 0) {
@@ -3263,6 +3368,7 @@
             }
             sv_p = av_fetch(av, phs[i]->idx, 0);
             if(sv_p == NULL) {
+                               Safefree(utf8_flgs);
                 Safefree(phs);
                 croak("Cannot fetch value for param %d in entry %d", i, j);
                }
@@ -3281,22 +3387,39 @@
                /* Find the value length, and increase maxlen if needed. */
                if(SvROK(sv)) {
                    Safefree(phs);
+                   Safefree(utf8_flgs);
                    croak("Can't bind a reference (%s) for param %d, entry %d",
                    neatsvpv(sv,0), i, j);
                }
                if(len > (unsigned int) phs[i]->maxlen)
                    phs[i]->maxlen = len;
 
+                       /* update the utf8_flgs for this value */
+                       if (SvUTF8(sv)) {
+                               utf8_flgs[i] |= ARRAY_BIND_UTF8;
+                               if (SvTRUE(tuples_status)){
+                                       av_push(tuples_utf8_av,newSViv(j));
+                               }
+
+
+                       }
+                       else {
+                               utf8_flgs[i] |= ARRAY_BIND_NATIVE;
+
+                       }
                /* Do OCI bind calls on last iteration. */
                if( ((unsigned int) j ) == exe_count - 1 ) {
-                   if(!do_bind_array_exec(sth, imp_sth, phs[i])) {
-                       Safefree(phs);
-                       }
+
+                               if(!do_bind_array_exec(sth, imp_sth, phs[i], 
utf8_flgs[i],i,tuples_utf8_av,tuples_status_av)) {
+                                       Safefree(phs);
+                                       Safefree(utf8_flgs);
+                                       /*Safefree(tuples_utf8_av);*/
+                               }
                        }
        }
        }
        Safefree(phs);
-
+       Safefree(utf8_flgs);
     /* Store array of bind typles, for use in OCIBindDynamic() callback. */
     imp_sth->bind_tuples = tuples_av;
     imp_sth->rowwise = (columns_av == NULL);

Modified: dbd-oracle/trunk/dbdimp.h
==============================================================================
--- dbd-oracle/trunk/dbdimp.h   (original)
+++ dbd-oracle/trunk/dbdimp.h   Fri Oct 17 07:22:39 2008
@@ -254,12 +254,19 @@
 
 extern ub2 charsetid;
 extern ub2 ncharsetid;
+extern ub2 us7ascii_csid;
 extern ub2 utf8_csid;
 extern ub2 al32utf8_csid;
 extern ub2 al16utf16_csid;
 
+#define CS_IS_NOT_UTF8( cs ) ( cs == us7ascii_csid )
+
 #define CS_IS_UTF8( cs ) \
-   (  ( cs == utf8_csid ) || ( cs == al32utf8_csid ) )
+   (  ( cs == utf8_csid )  )
+
+#define CS_IS_UTF8_COMPATIBLE( cs ) \
+  ( CS_IS_UTF8(cs) || ( (cs) == us7ascii_csid ) )
+
 
 #define CS_IS_UTF16( cs ) ( cs == al16utf16_csid )
 

Modified: dbd-oracle/trunk/oci8.c
==============================================================================
--- dbd-oracle/trunk/oci8.c     (original)
+++ dbd-oracle/trunk/oci8.c     Fri Oct 17 07:22:39 2008
@@ -658,50 +658,51 @@
        if( bindp ) { /* For GCC not to warn on unused parameter*/ }
 
                /* Check for bind values supplied by tuple array. */
-               tuples_av = phs->imp_sth->bind_tuples;
-               if(tuples_av) {
-                       /* NOTE: we already checked the validity in 
ora_st_bind_for_array_exec(). */
-                       sv_p = av_fetch(tuples_av, phs->imp_sth->rowwise ? 
(int)iter : phs->idx, 0);
-                       av = (AV*)SvRV(*sv_p);
-                       sv_p = av_fetch(av, phs->imp_sth->rowwise ? phs->idx : 
(int)iter, 0);
-                       sv = *sv_p;
-                       if(SvOK(sv)) {
-                       *bufpp = SvPV(sv, phs_len);
-                       phs->alen = (phs->alen_incnull) ? phs_len+1 : phs_len;
-                       phs->indp = 0;
-                       } else {
-                       *bufpp = SvPVX(sv);
-                       phs->alen = 0;
-                       phs->indp = -1;
-                       }
-       }
-       else
-               if (phs->desc_h) {
-                               *bufpp  = phs->desc_h;
-                               phs->alen = 0;
-                               phs->indp = 0;
-       }
-       else
-               if (SvOK(phs->sv)) {
-                               *bufpp  = SvPV(phs->sv, phs_len);
+       tuples_av = phs->imp_sth->bind_tuples;
+       if(tuples_av) {
+               /* NOTE: we already checked the validity in 
ora_st_bind_for_array_exec(). */
+               sv_p = av_fetch(tuples_av, phs->imp_sth->rowwise ? (int)iter : 
phs->idx, 0);
+               av = (AV*)SvRV(*sv_p);
+               sv_p = av_fetch(av, phs->imp_sth->rowwise ? phs->idx : 
(int)iter, 0);
+               sv = *sv_p;
+               if(SvOK(sv)) {
+                       *bufpp = SvPV(sv, phs_len);
+                       phs->alen = (phs->alen_incnull) ? phs_len+1 : phs_len;
+                       phs->indp = 0;
+               } else {
+                       *bufpp = SvPVX(sv);
+                       phs->alen = 0;
+                       phs->indp = -1;
+               }
+    }
+    else
+       if (phs->desc_h) {
+               *bufpp  = phs->desc_h;
+               phs->alen = 0;
+               phs->indp = 0;
+    }
+    else
+       if (SvOK(phs->sv)) {
+               *bufpp  = SvPV(phs->sv, phs_len);
                phs->alen = (phs->alen_incnull) ? phs_len+1 : phs_len;;
                phs->indp = 0;
-       }
-    else {
+       }
+       else {
                *bufpp  = SvPVX(phs->sv);       /* not actually used? */
                phs->alen = 0;
                phs->indp = -1;
-    }
-    *alenp  = phs->alen;
-    *indpp  = &phs->indp;
-    *piecep = OCI_ONE_PIECE;
-    if (DBIS->debug >= 3 || dbd_verbose >=3)
-               PerlIO_printf(DBILOGFP, "       in  '%s' [%lu,%lu]: len %2lu, 
ind %d%s, value=%s\n",
+       }
+       *alenp  = phs->alen;
+       *indpp  = &phs->indp;
+       *piecep = OCI_ONE_PIECE;
+       if (DBIS->debug >= 3 || dbd_verbose >=3)
+               PerlIO_printf(DBILOGFP, "       in  '%s' [%lu,%lu]: len %2lu, 
ind %d%s, value=%s\n",
                        phs->name, ul_t(iter), ul_t(index), ul_t(phs->alen), 
phs->indp,
                        (phs->desc_h) ? " via descriptor" : 
"",neatsvpv(phs->sv,10));
-    if (!tuples_av && (index > 0 || iter > 0))
+       if (!tuples_av && (index > 0 || iter > 0))
                croak(" Arrays and multiple iterations not currently supported 
by DBD::Oracle (in %d/%d)", index,iter);
-    return OCI_CONTINUE;
+
+       return OCI_CONTINUE;
 }
 
 /*
@@ -1625,7 +1626,7 @@
     return cache_rows;
 }
 
-/* called by get_object to return the actual value in the proerty */
+/* called by get_object to return the actual value in the property */
 
 static void get_attr_val(SV *sth,AV *list,imp_fbh_t *fbh, text  *name , 
OCITypeCode  typecode, dvoid   *attr_value )
 {
@@ -2082,7 +2083,7 @@
     sv_setpvn(dest_sv, (char*)fb_ary->cb_abuf,(STRLEN)actual_bufl);
 
        if (fbh->ftype != SQLT_BIN){
-               
+
                if (CSFORM_IMPLIES_UTF8(fbh->csform) ){ /* do the UTF 8 magic*/
                        SvUTF8_on(dest_sv);
                }
@@ -3396,7 +3397,7 @@
        char new_tablename[100];
        ub4 syn_schema_len = 0, syn_name_len = 0,tn_len;
        OCIAttrGet_log_stat(imp_sth->dschp,  OCI_HTYPE_DESCRIBE,
-                                 &parmhp, 0, OCI_ATTR_PARAM, errhp, status);   
                          
+                                 &parmhp, 0, OCI_ATTR_PARAM, errhp, status);
        OCIAttrGet_log_stat(parmhp, OCI_DTYPE_PARAM,
                      &syn_schema, &syn_schema_len, OCI_ATTR_SCHEMA_NAME, 
errhp, status);
                OCIAttrGet_log_stat(parmhp, OCI_DTYPE_PARAM,

Modified: dbd-oracle/trunk/t/26exe_array.t
==============================================================================
--- dbd-oracle/trunk/t/26exe_array.t    (original)
+++ dbd-oracle/trunk/t/26exe_array.t    Fri Oct 17 07:22:39 2008
@@ -4,7 +4,7 @@
 use DBD::Oracle qw(ORA_RSET SQLCS_NCHAR);
 use strict;
 
-use Test::More tests =>14 ;
+use Test::More tests =>17 ;
 unshift @INC ,'t';
 require 'nchar_test_lib.pl';
 
@@ -15,7 +15,8 @@
 ## By John Scoles, The Pythian Group
 ## ----------------------------------------------------------------------------
 ##  Just a few checks to see if execute array works in Oracle::DBD
-##  Nothing fancy. 
+##  Nothing fancy. I also checks for warnings when utf8 is inserted into 
+##  an ASCII only DB
 ## ----------------------------------------------------------------------------
 
 BEGIN {
@@ -25,21 +26,27 @@
 # create a database handle
 my $dsn = oracle_test_dsn();
 my $dbuser = $ENV{ORACLE_USERID} || 'scott/tiger';
+$ENV{NLS_NCHAR} = "US7ASCII";
 my $dbh = DBI->connect($dsn, $dbuser, '', { RaiseError=>1, 
                                                AutoCommit=>1,
-                                               PrintError => 0 });
+                                               PrintError => 0,
+                                               ora_envhp  => 0});
 
 
 # check that our db handle is good
 isa_ok($dbh, "DBI::db");
 
+
 my $table = table();
-    
+eval{
+ drop_table($dbh);
+};
 $dbh->do(qq{
             CREATE TABLE $table (
            row_1 INTEGER NOT NULL,
            row_2 INTEGER NOT NULL,
-           row_3 INTEGER NOT NULL
+           row_3 INTEGER NOT NULL,
+           row_4 CHAR(5)
        )
     });
     
@@ -47,7 +54,7 @@
 my @var1         = (1,1,1,1,1,1,1,1,1,1);
 my @var2         = (2,2,2,2,2,2,2,2,2,2);
 my @var3         = (3,3,3,3,3,3,3,3,3,3);
-
+my @utf8_string =  ("A","A","A","A","\x{6e9}","A","A","A","A","A");
 my $tuple_status = [];
 my $dumped ;
 
@@ -146,6 +153,19 @@
  cmp_ok(scalar @$problems, '==',48, '... we should have 48 rows');
 
 
+$sth = $dbh->prepare("INSERT INTO $table ( row_1,  row_2, row_3,row_4) VALUES 
(1,2,3,?)");
+
+ok ($sth->execute_array(
+      {ArrayTupleStatus => $tuple_status},
+       [EMAIL PROTECTED] 
+ ), '... execute_array should return true');
+
+
+cmp_ok(@$tuple_status[4],'ne','-1','... #5 should be a warning');
+cmp_ok(scalar @{$tuple_status}, '==', 10, '... we should have 10 
tuple_status');
+
+
+
  drop_table($dbh);
 
 

Reply via email to