Skip to Content.
Sympa Menu

freetds - Re: [freetds] problem with dbconvert from float to money

freetds AT lists.ibiblio.org

Subject: FreeTDS Development Group

List archive

Chronological Thread  
  • From: Frediano Ziglio <freddy77 AT gmail.com>
  • To: FreeTDS Development Group <freetds AT lists.ibiblio.org>
  • Subject: Re: [freetds] problem with dbconvert from float to money
  • Date: Tue, 29 Sep 2009 08:04:12 +0200

2009/9/29 Stenuit, Pascal <Pascal.Stenuit AT gtech.com>:
> 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




Archive powered by MHonArc 2.6.24.

Top of Page