Skip to Content.
Sympa Menu

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

freetds AT lists.ibiblio.org

Subject: FreeTDS Development Group

List archive

Chronological Thread  
  • From: "Stenuit, Pascal" <Pascal.Stenuit AT GTECH.COM>
  • To: <freetds AT lists.ibiblio.org>
  • Subject: [freetds] problem with dbconvert from float to money
  • Date: Tue, 29 Sep 2009 08:01:05 +0200

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:

CONFIDENTIALITY NOTICE: The contents of this email are confidential
and for the exclusive use of the intended recipient. If you receive this
email in error, please delete it from your system immediately and
notify us either by email, telephone or fax. You should not copy,
forward, or otherwise disclose the content of the email.





Archive powered by MHonArc 2.6.24.

Top of Page