Tim Bunce wrote: > > Post a diff and I'll review it for you. The code you appended previously > looks ok.
Attached is a diff for DBD::Oracle based on subversion this morning (the diffs for oci8.c may be a little difficult to read due to the large indentation of the surrounding code and there are some additional changes to fix comments). It adds support for DiscardString and StrictlyTyped bind_col attributes and casting via sql_type_cast. Most (all relevant) changes are conditional on a DBI with these features. I have verified these changes work with Oracle 11 and DBD::Oracle from subversion however, I note some lob tests were failing in DBD::Oracle before my changes were applied. There seem to be a large number of warnings compiling DBD::Oracle from subversion but I've not touched any of them preferring to keep the patch restricted to its purpose. The issue with the SQL_DECIMAL return in sql_type_castsvpv still exists (the NV_PRESERVES_UV issue) - I have not had time to look into this properly as yet. All comments appreciated. Martin -- Martin J. Evans Easysoft Limited http://www.easysoft.com
Index: oci8.c =================================================================== --- oci8.c (revision 13624) +++ oci8.c (working copy) @@ -431,7 +431,7 @@ case OCI_ATTR_FSPRECISION OCI_ATTR_PDSCL:return "";*/ /* fs prec for datetime data types */ case OCI_ATTR_PDPRC: return "OCI_ATTR_PDPRC"; /* packed decimal format - case OCI_ATTR_LFPRECISION OCI_ATTR_PDPRC: return ""; + case OCI_ATTR_LFPRECISION OCI_ATTR_PDPRC: return ""; */ /* fs prec for datetime data types */ case OCI_ATTR_PARAM_COUNT: return "OCI_ATTR_PARAM_COUNT"; /* number of column in the select list */ case OCI_ATTR_ROWID: return "OCI_ATTR_ROWID"; /* the rowid */ @@ -513,7 +513,7 @@ case OCI_ATTR_COL_COUNT: return "OCI_ATTR_COL_COUNT"; /* columns of column array processed so far. */ case OCI_ATTR_STREAM_OFFSET: return "OCI_ATTR_STREAM_OFFSET"; /* str off of last row processed - case OCI_ATTR_SHARED_HEAPALLO: return ""; /* Shared Heap Allocation Size */ + case OCI_ATTR_SHARED_HEAPALLO: return "";*/ /* Shared Heap Allocation Size */ case OCI_ATTR_SERVER_GROUP: return "OCI_ATTR_SERVER_GROUP"; /* server group name */ @@ -686,7 +686,7 @@ /* Attr to allow setting of the stream version PRIOR to calling Prepare */ case OCI_ATTR_DIRPATH_STREAM_VERSION: return "OCI_ATTR_DIRPATH_STREAM_VERSION"; /* version of the stream - case OCI_ATTR_RESERVED_11: return "OCI_ATTR_RESERVED_11"; /* reserved */ + case OCI_ATTR_RESERVED_11: return "OCI_ATTR_RESERVED_11";*/ /* reserved */ case OCI_ATTR_RESERVED_12: return "OCI_ATTR_RESERVED_12"; /* reserved */ case OCI_ATTR_RESERVED_13: return "OCI_ATTR_RESERVED_13"; /* reserved */ @@ -2668,7 +2668,7 @@ -/*static int /* --- Setup the row cache for this sth --- */ +static int /* --- Setup the row cache for this sth --- */ sth_set_row_cache(SV *h, imp_sth_t *imp_sth, int max_cache_rows, int num_fields, int has_longs) { dTHX; @@ -3742,10 +3742,38 @@ while(datalen && p[datalen - 1]==' ') --datalen; } - sv_setpvn(sv, p, (STRLEN)datalen); - if (CSFORM_IMPLIES_UTF8(fbh->csform) ){ - SvUTF8_on(sv); - } + sv_setpvn(sv, p, (STRLEN)datalen); +#if DBISTATE_VERSION > 94 + /* DBIXS_REVISION > 13590 */ + /* If a bind type was specified we use DBI's sql_type_cast + to cast it - currently only number types are handled */ + if (fbh->req_type != 0) { + int sts; + D_imp_xxh(sth); + char errstr[256]; + + sts = DBIc_DBISTATE(imp_sth)->sql_type_cast_svpv( + aTHX_ sv, fbh->req_type, fbh->bind_flags, NULL); + if (sts == 0) { + sprintf(errstr, + "over/under flow converting column %d to type %ld", + i+1, fbh->req_type); + oci_error(sth, imp_sth->errhp, OCI_ERROR, errstr); + return Nullav; + + } else if (sts == -2) { + sprintf(errstr, + "unsupported bind type %ld for column %d", + fbh->req_type, i+1); + return Nullav; + } + } else +#endif /* DBISTATE_VERSION > 94 */ + { + if (CSFORM_IMPLIES_UTF8(fbh->csform) ){ + SvUTF8_on(sv); + } + } } } Index: Changes =================================================================== --- Changes (revision 13624) +++ Changes (working copy) @@ -13,6 +13,7 @@ Fix for rt.cpan.org Ticket #=46246 fetching from nested cursor (returned from procedure) leads to application crash (abort) from John Scoles Fix for rt.cpan.org Ticket #=46016 LOBs bound with ora_field broken from RKITOVER Fix for bug in 58object.t when test run as externally identified user from Charles Jardine + Add support for the TYPE attribute on bind_col and the new DBI bind_col attributes StrictlyTyped and DiscardString from Martin J. Evans =head1 Changes in DBD-Oracle 1.23(svn rev 12724) Fix from rt.cpan.org ticket #=44788 bool in_lite should be char in_literal Index: dbdimp.c =================================================================== --- dbdimp.c (revision 13624) +++ dbdimp.c (working copy) @@ -871,7 +871,50 @@ return 1; } +int dbd_st_bind_col(SV *sth, imp_sth_t *imp_sth, SV *col, SV *ref, IV type, SV *attribs) { + dTHX; + int field; + if (!SvIOK(col)) { + croak ("Invalid column number") ; + } + + field = SvIV(col); + + if ((field < 1) || (field > DBIc_NUM_FIELDS(imp_sth))) { + croak("cannot bind to non-existent field %d", field); + } + + imp_sth->fbh[field-1].req_type = type; + imp_sth->fbh[field-1].bind_flags = 0; /* default to none */ + +#if DBIXS_REVISION >= 13590 + /* DBIXS 13590 added StrictlyTyped and DiscardString attributes */ + if (attribs) { + HV *attr_hash; + SV **attr; + + if (!SvROK(attribs)) { + croak ("attributes is not a reference"); + } else if (SvTYPE(SvRV(attribs)) != SVt_PVHV) { + croak ("attributes not a hash reference"); + } + attr_hash = (HV *)SvRV(attribs); + + attr = hv_fetch(attr_hash, "StrictlyTyped", (U32)13, 0); + if (attr && SvTRUE(*attr)) { + imp_sth->fbh[field-1].bind_flags |= DBIstcf_STRICT; + } + + attr = hv_fetch(attr_hash, "DiscardString", (U32)13, 0); + if (attr && SvTRUE(*attr)) { + imp_sth->fbh[field-1].bind_flags |= DBIstcf_DISCARD_STRING; + } + } +#endif /* DBIXS_REVISION >= 13590 */ + return 1; +} + int dbd_db_disconnect(SV *dbh, imp_dbh_t *imp_dbh) { Index: dbdimp.h =================================================================== --- dbdimp.h (revision 13624) +++ dbdimp.h (working copy) @@ -113,7 +113,7 @@ int fetch_offset; int fetch_position; int prefetch_memory; /* OCI_PREFETCH_MEMORY*/ - int prefetch_rows; /* OCI_PREFETCH_ROWS + int prefetch_rows; /* OCI_PREFETCH_ROWS */ /* array fetch: state variables */ int row_cache_off; int rs_fetch_count; /*fetch count*/ @@ -194,6 +194,9 @@ int piece_lob; /*use piecewise fetch for lobs*/ /* Our storage space for the field data as it's fetched */ sword ftype; /* external datatype we wish to get */ + IV req_type; /* type passed to bind_col */ + UV bind_flags; /* flags passed to bind_col */ + fb_ary_t *fb_ary ; /* field buffer array */ /* if this is an embedded object we use this */ fbh_obj_t *obj; @@ -376,6 +379,7 @@ #define dbd_st_FETCH_attrib ora_st_FETCH_attrib #define dbd_describe ora_describe #define dbd_bind_ph ora_bind_ph +#define dbd_st_bind_col ora_st_bind_col #include "ocitrace.h" /* end */ Index: Oracle.h =================================================================== --- Oracle.h (revision 13624) +++ Oracle.h (working copy) @@ -67,6 +67,7 @@ int dbd_db_do _((SV *sv, char *statement)); int dbd_db_commit _((SV *dbh, imp_dbh_t *imp_dbh)); int dbd_db_rollback _((SV *dbh, imp_dbh_t *imp_dbh)); +int dbd_st_bind_col(SV *sth, imp_sth_t *imp_sth, SV *col, SV *ref, IV type, SV *attribs); int dbd_db_disconnect _((SV *dbh, imp_dbh_t *imp_dbh)); void dbd_db_destroy _((SV *dbh, imp_dbh_t *imp_dbh)); int dbd_db_STORE_attrib _((SV *dbh, imp_dbh_t *imp_dbh, SV *keysv, SV *valuesv));