Martin J. Evans wrote:
> Hi,
>
> With reference to the rt I created "Support binding of integers so they
> are returned as IVs" at http://rt.cpan.org/Public/Bug/Display.html?id=49818
>
> I am now at the point where being unable to bind columns to results-sets
> in DBD::Oracle with a bind type of SQL_INTEGER (or whatever) so they
> look like integers in Perl is slowing some code of ours down
> dramatically. We convert a fetchall_arrayref returned structure into
> JSON with JSON::XS and JSON::XS converts strings to "string" and numbers
> to a plain number. Our select returns a number of columns which are
> really integer columns and as the result-set is very large the extra
> space we use encoding integers as "number" is more than just annoying.
> JSON::XS appears to know a perl scalar has been used in the context of a
> number as if we add 0 to the integer columns returned in
> fetchall_arrayref it encodes them as plain numbers instead of strings
> like "number" (see the rt for the snippet from JSON::XS which does
> this). As a result, a workaround we are using now is to loop through the
> rows adding 0 to all integer columns. I believe DBI allows bind_col to
> be called without a destination scalar so you can use it to specify the
> type of the bind e.g., SQL_INTEGER but still call fetchall_arrayref.
>
> Does anyone know if it is feasible to make this work with DBD::Oracle
> and if so do you have some pointers as to how it may be achieved. I am
> not looking for anyone else to do the work but would like to sound
> people out about the possibility before I launch into it.
>
> Thanks
>
> Martin
>
>
What follows is a very rough patch (definitely not finished) which
proves you can do what I wanted to do. However, there on no checks on
the column being bound existing and I'm not sure how to save the TYPE
attribute when bind_col is called before execute (that is when the
result-set is not described yet). Basically, I think more is required in
dbd_st_bind_col but I've not sure as yet what that is and it is possible
returning 1 is a total hack. I'd appreciate any advice to complete this.
Index: oci8.c
===================================================================
--- oci8.c (revision 13427)
+++ oci8.c (working copy)
@@ -3279,10 +3279,31 @@
while(datalen && p[datalen -
1]==' ')
--datalen;
}
- sv_setpvn(sv, p, (STRLEN)datalen);
- if (CSFORM_IMPLIES_UTF8(fbh->csform) ){
- SvUTF8_on(sv);
- }
+
+ if ((fbh->req_type == 3) &&
+ ((fbh->dbtype == 2) || (fbh->dbtype == 3))){
+ char *e;
+ char zval[32];
+ long val;
+
+ memcpy(zval, p, datalen);
+ zval[datalen] = '\0';
+ val = strtol(zval, &e, 10);
+
+ if ((val == LONG_MAX) || (val == LONG_MIN) ||
+ (e && (*e != '\0'))) {
+ oci_error(sth, imp_sth->errhp, OCI_ERROR,
+ "invalid number or over/under flow");
+ return Nullav;
+ }
+
+ sv_setiv(sv, val);
+ } else {
+ sv_setpvn(sv, p, (STRLEN)datalen);
+ if (CSFORM_IMPLIES_UTF8(fbh->csform) ){
+ SvUTF8_on(sv);
+ }
+ }
}
}
Index: dbdimp.c
===================================================================
--- dbdimp.c (revision 13427)
+++ dbdimp.c (working copy)
@@ -869,7 +869,16 @@
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 = SvIV(col);
+
+ imp_sth->fbh[field-1].req_type = type;
+
+ return 1;
+}
+
int
dbd_db_disconnect(SV *dbh, imp_dbh_t *imp_dbh)
{
Index: dbdimp.h
===================================================================
--- dbdimp.h (revision 13427)
+++ dbdimp.h (working copy)
@@ -191,6 +191,8 @@
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 */
+
fb_ary_t *fb_ary ; /* field buffer array
*/
/* if this is an embedded object we use this */
fbh_obj_t *obj;
@@ -371,6 +373,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 13427)
+++ 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));
Martin
--
Martin J. Evans
Easysoft Limited
http://www.easysoft.com