Re: problem with dbconvert from float to money

Frediano Ziglio <[email protected]>
Newsgroups gmane.comp.db.tds.freetds
Message-ID <[email protected]>
2009/9/29 Stenuit, Pascal <[email protected]>:
> Hi,
>
> We are happily using FreeTDS as a replacement for Sybase's dblib and
> noticed a difference between the two implementations.
>
> It turns out that for the following code snippet:
>
>    double            amt = 123456.78;
>
>    dbconvert(0, SYBFLT8, (unsigned char *) &amt, (DBINT)-1,
>              SYBMONEY, out, (DBINT)-1);
>
> Sybase will encode the SYBMONEY as 1234567800 (fixed point, 4 decimals)
> while freetds will encode the value as 1234560000, in effect losing the
> decimals. I believe Sybase is probably right (or at least consistent
> with the reverse operation) but what do I know !
>
> The following patch to src/tds/convert.c could be what's needed (I'm not
> too sure about the bound checks).
>
> Thanks for a great software,
> pascal
>
>
> ~> ident convert.c.orig
> convert.c.orig:
>     $Id: convert.c,v 1.192 2009/06/12 08:53:49 freddy77 Exp $
> ~> diff -u convert.c.orig  convert.c
> --- convert.c.orig      2009-09-29 07:41:00.670880900 +0200
> +++ convert.c   2009-09-29 07:47:05.144408900 +0200
> @@ -1428,7 +1428,7 @@
>        case SYBMONEY:
>                if (the_value > (TDS_REAL) (TDS_INT8_MAX / 10000) ||
> the_value < (TDS_REAL) (TDS_INT8_MIN / 10000))
>                        return TDS_CONVERT_OVERFLOW;
> -               mymoney = ((TDS_INT8) the_value) * 10000;
> +               mymoney = (TDS_INT8) (the_value * 10000);
>                cr->m.mny = mymoney;
>                return sizeof(TDS_MONEY);
>                break;
> @@ -1436,7 +1436,7 @@
>        case SYBMONEY4:
>                if (the_value > (TDS_REAL) (TDS_INT_MAX / 10000) ||
> the_value < (TDS_REAL) (TDS_INT_MIN / 10000))
>                        return TDS_CONVERT_OVERFLOW;
> -               mymoney4 = ((TDS_INT) the_value) * 10000;
> +               mymoney4 = (TDS_INT) (the_value * 10000);
>                cr->m4.mny4 = mymoney4;
>                return sizeof(TDS_MONEY4);
>                break;
> @@ -1512,14 +1512,14 @@
>        case SYBMONEY:
>                if (the_value > (TDS_FLOAT) (TDS_INT8_MAX / 10000) ||
> the_value < (TDS_FLOAT) (TDS_INT8_MIN / 10000))
>                        return TDS_CONVERT_OVERFLOW;
> -               cr->m.mny = ((TDS_INT8) the_value) * 10000;
> +               cr->m.mny = (TDS_INT8) (the_value * 10000);
>
>                return sizeof(TDS_MONEY);
>                break;
>        case SYBMONEY4:
>                if (the_value > (TDS_FLOAT) (TDS_INT_MAX / 10000) ||
> the_value < (TDS_FLOAT) (TDS_INT_MIN / 10000))
>                        return TDS_CONVERT_OVERFLOW;
> -               cr->m4.mny4 = ((TDS_INT) the_value) * 10000;
> +               cr->m4.mny4 = (TDS_INT) (the_value * 10000);
>                return sizeof(TDS_MONEY4);
>                break;
>        case SYBREAL:
>

I perfectly agree with this patch

freddy77
_______________________________________________
FreeTDS mailing list
[email protected]
http://lists.ibiblio.org/mailman/listinfo/freetds
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.