Re: DBD::Oracle, Support binding of integers so they are returned as IVs

Martin Evans <[email protected]>
Newsgroups gmane.comp.lang.perl.modules.dbi.sybase.devel
Organization Easysoft Limited
Message-ID <[email protected]>
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
sql_type_cast.diff (text/x-patch, 8.1 KB)
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));
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.