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) \