On Mon, Oct 26, 2009 at 05:29:21PM +0000, Martin Evans wrote:
> 
> 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 @@
> +
> +                    if ((fbh->req_type == 3) &&
> +                        ((fbh->dbtype == 2) || (fbh->dbtype == 3))){

Best to avoid 'magic numbers'.

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

A simpler safer and more portable approach may be to just let the
existing code store the value in an sv and then add these lines:

    if (fbh->req_type == 3)
        sv_2iv(sv);

If the number is too large for an IV (or UV) you'll get an NV (float).
The original string of digits is preserved in all cases. That's all very
natural and predictable perlish behaviour.

The next question is whether overflowing to an NV should be an error.
I'm thinking we could adopt these semantics for bind_col types:

  SQL_INTEGER  IV or UV via sv_2iv(sv) with error on overflow
  SQL_DOUBLE   NV via sv_2nv(sv)
  SQL_NUMERIC  IV else UV else NV via grok_number() with no error

I could sketch out the logic for those cases if you'd be happy to polish
up and test.

Tim.

Reply via email to