[svn:dbd-oracle] r11745 - dbd-oracle/branches/utf8_ea

[email protected]
Newsgroups perl.dbd.oracle.changes
Message-ID <[email protected]>
Author: byterock
Date: Fri Sep  5 09:43:43 2008
New Revision: 11745

Modified:
   dbd-oracle/branches/utf8_ea/dbdimp.c
   dbd-oracle/branches/utf8_ea/dbdimp.h

Log:
applied patch

Modified: dbd-oracle/branches/utf8_ea/dbdimp.c
==============================================================================
--- dbd-oracle/branches/utf8_ea/dbdimp.c	(original)
+++ dbd-oracle/branches/utf8_ea/dbdimp.c	Fri Sep  5 09:43:43 2008
@@ -43,8 +43,14 @@
 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;
@@ -3086,13 +3092,18 @@
 }
 
 static int
-do_bind_array_exec(sth, imp_sth, phs)
+do_bind_array_exec(sth, imp_sth, phs, utf8)
     SV *sth;
     imp_sth_t *imp_sth;
     phs_t *phs;
+    int utf8;
 {
 	dTHX;
     sword status;
+    ub1 csform;
+    ub2 csid;
+    int trace_level = DBIS->debug;
+  
     OCIBindByName_log_stat(imp_sth->stmhp, &phs->bndhp, imp_sth->errhp,
             (text*)phs->name, (sb4)strlen(phs->name),
             0,
@@ -3117,6 +3128,71 @@
         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_UTF8_COMPATIBLE(csid)) {
+			croak("Can't mix utf8 and non-utf8 in array bind");
+	    }
+		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;
 }
 
@@ -3166,7 +3242,8 @@
     char namebuf[30];
     STRLEN len;
     int outparams = (imp_sth->out_params_av) ? AvFILL(imp_sth->out_params_av)+1 : 0;
-
+    int *utf8_flgs;
+    
     if (debug >= 2  || dbd_verbose >=2)
  		PerlIO_printf(DBILOGFP, "  ora_st_execute_array %s count=%d (%s %s %s)...\n",
                       oci_stmt_type_name(imp_sth->stmt_type), exe_count,
@@ -3229,18 +3306,23 @@
 
     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++) {
 
     	sv_p = av_fetch(tuples_av, j, 0);
         if(sv_p == NULL) {
-            Safefree(phs);
-             croak("Cannot fetch tuple %d", j);
+        	Safefree(phs);
+        	Safefree(utf8_flgs);
+            croak("Cannot fetch tuple %d", j);
         }
         sv = *sv_p;
         if(!SvROK(sv) || SvTYPE(SvRV(sv)) != SVt_PVAV) {
-            Safefree(phs);
+        	Safefree(phs);
+        	Safefree(utf8_flgs);
             croak("Not an array ref in element %d", j);
         }
         av = (AV*)SvRV(sv);
@@ -3252,11 +3334,13 @@
                                 namebuf, strlen(namebuf), 0);
                if (phs_svp == NULL) {
                     Safefree(phs);
+                    Safefree(utf8_flgs);
                     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) {
                    Safefree(phs);
+                   Safefree(utf8_flgs);
                    croak("Placeholder %d not of ?/:1 type", i);
                 }
                 init_bind_for_array_exec(phs[i]);
@@ -3264,6 +3348,7 @@
             sv_p = av_fetch(av, phs[i]->idx, 0);
             if(sv_p == NULL) {
                 Safefree(phs);
+                Safefree(utf8_flgs);
                 croak("Cannot fetch value for param %d in entry %d", i, j);
         	}
 
@@ -3281,22 +3366,33 @@
         	/* 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;
+			} 
+			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])) {
+					Safefree(phs);
+	                Safefree(utf8_flgs);
         		}
 			}
     	}
   	}
 	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/branches/utf8_ea/dbdimp.h
==============================================================================
--- dbd-oracle/branches/utf8_ea/dbdimp.h	(original)
+++ dbd-oracle/branches/utf8_ea/dbdimp.h	Fri Sep  5 09:43:43 2008
@@ -254,6 +254,7 @@
 
 extern ub2 charsetid;
 extern ub2 ncharsetid;
+extern ub2 us7ascii_csid;
 extern ub2 utf8_csid;
 extern ub2 al32utf8_csid;
 extern ub2 al16utf16_csid;
@@ -261,6 +262,9 @@
 #define CS_IS_UTF8( cs ) \
    (  ( cs == utf8_csid ) || ( cs == al32utf8_csid ) )
 
+#define CS_IS_UTF8_COMPATIBLE( cs ) \
+  ( CS_IS_UTF8(cs) || ( (cs) == us7ascii_csid ) )
+
 #define CS_IS_UTF16( cs ) ( cs == al16utf16_csid )
 
 #define CSFORM_IMPLIED_CSID(csform) \
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.