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