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