[PATCH] SYBUINT<n> support
Ian Lister <[email protected]>
| Newsgroups | gmane.comp.db.tds.freetds |
|---|---|
| Message-ID | <[email protected]> |
Hi, I was running into a problem due to FreeTDS not supporting Sybase's unsigned integer types (SYBUINT1/2/4/8). It was manifested as cs_convert failing to convert other types (such as SYBNUMERIC) to those unsigned types, and reporting: cs_convert: cslib user api layer: external error: Conversion between 108 and -1 datatypes is not supported I have attached a patch that addresses the issue for me, in the hope that it might be useful for others. I tried to make it fairly complete in the areas of the code that I touched, but I was only following my nose so have quite likely overlooked other parts of the code (including test cases) that are also lacking SYBUINTn support. YMMV etc. Ian _______________________________________________ FreeTDS mailing list [email protected] http://lists.ibiblio.org/mailman/listinfo/freetds
freetds-uint.patch
(application/octet-stream, 25.3 KB)
Index: include/tdsconvert.h
===================================================================
RCS file: /cvsroot/freetds/freetds/include/tdsconvert.h,v
retrieving revision 1.29
diff -u -d -r1.29 tdsconvert.h
--- include/tdsconvert.h 8 Aug 2011 12:33:18 -0000 1.29
+++ include/tdsconvert.h 22 Dec 2012 20:18:46 -0000
@@ -38,8 +38,11 @@
{
TDS_TINYINT ti;
TDS_SMALLINT si;
+ TDS_USMALLINT usi;
TDS_INT i;
+ TDS_UINT ui;
TDS_INT8 bi;
+ TDS_UINT8 ubi;
TDS_FLOAT f;
TDS_REAL r;
TDS_CHAR *c;
Index: src/ctlib/cs.c
===================================================================
RCS file: /cvsroot/freetds/freetds/src/ctlib/cs.c,v
retrieving revision 1.82
diff -u -d -r1.82 cs.c
--- src/ctlib/cs.c 25 Sep 2011 11:36:24 -0000 1.82
+++ src/ctlib/cs.c 22 Dec 2012 20:18:46 -0000
@@ -661,9 +661,13 @@
}
break;
case SYBINT1:
+ case SYBUINT1:
case SYBINT2:
+ case SYBUINT2:
case SYBINT4:
+ case SYBUINT4:
case SYBINT8:
+ case SYBUINT8:
case SYBFLT8:
case SYBREAL:
case SYBBIT:
@@ -770,6 +774,7 @@
case SYBBITN:
/* fall trough, act same way of TINYINT */
case SYBINT1:
+ case SYBUINT1:
memcpy(dest, &(cres.ti), 1);
*resultlen = 1;
ret = CS_SUCCEED;
@@ -779,16 +784,31 @@
*resultlen = 2;
ret = CS_SUCCEED;
break;
+ case SYBUINT2:
+ memcpy(dest, &(cres.usi), 2);
+ *resultlen = 2;
+ ret = CS_SUCCEED;
+ break;
case SYBINT4:
memcpy(dest, &(cres.i), 4);
*resultlen = 4;
ret = CS_SUCCEED;
break;
+ case SYBUINT4:
+ memcpy(dest, &(cres.ui), 4);
+ *resultlen = 4;
+ ret = CS_SUCCEED;
+ break;
case SYBINT8:
memcpy(dest, &(cres.bi), 8);
*resultlen = 8;
ret = CS_SUCCEED;
break;
+ case SYBUINT8:
+ memcpy(dest, &(cres.ubi), 8);
+ *resultlen = 8;
+ ret = CS_SUCCEED;
+ break;
case SYBFLT8:
memcpy(dest, &(cres.f), 8);
*resultlen = 8;
Index: src/ctlib/ct.c
===================================================================
RCS file: /cvsroot/freetds/freetds/src/ctlib/ct.c,v
retrieving revision 1.225
diff -u -d -r1.225 ct.c
--- src/ctlib/ct.c 11 Mar 2012 15:52:22 -0000 1.225
+++ src/ctlib/ct.c 22 Dec 2012 20:18:47 -0000
@@ -2016,8 +2016,11 @@
case CS_VARCHAR_TYPE: return SYBVARCHAR;
case CS_LONG_TYPE:
case CS_BIGINT_TYPE: return SYBINT8;
+ case CS_UBIGINT_TYPE: return SYBUINT8;
case CS_INT_TYPE: return SYBINT4;
+ case CS_UINT_TYPE: return SYBUINT4;
case CS_SMALLINT_TYPE: return SYBINT2;
+ case CS_USMALLINT_TYPE: return SYBUINT2;
case CS_TINYINT_TYPE: return SYBINT1;
case CS_REAL_TYPE: return SYBREAL;
case CS_FLOAT_TYPE: return SYBFLT8;
Index: src/tds/convert.c
===================================================================
RCS file: /cvsroot/freetds/freetds/src/tds/convert.c,v
retrieving revision 1.217
diff -u -d -r1.217 convert.c
--- src/tds/convert.c 11 Aug 2011 12:50:26 -0000 1.217
+++ src/tds/convert.c 22 Dec 2012 20:18:47 -0000
@@ -90,6 +90,7 @@
#define IS_TINYINT(x) ( 0 <= (x) && (x) <= 0xff )
#define IS_SMALLINT(x) ( -32768 <= (x) && (x) <= 32767 )
+#define IS_USMALLINT(x) ( 0 <= (x) && (x) <= 65535 )
/*
* f77: I don't write -2147483648, some compiler seem to have some problem
* with this constant although is a valid 32bit value
@@ -98,10 +99,16 @@
#define TDS_INT_MAX 2147483647l
#define IS_INT(x) (TDS_INT_MIN <= (x) && (x) <= TDS_INT_MAX)
+#define TDS_UINT_MAX 4294967295lu
+#define IS_UINT(x) (0 <= (x) && (x) <= TDS_UINT_MAX)
+
#define TDS_INT8_MAX ((((TDS_INT8) 0x7fffffffl) << 32) + 0xfffffffflu)
#define TDS_INT8_MIN (((TDS_INT8) (-0x7fffffffl-1)) << 32)
#define IS_INT8(x) (TDS_INT8_MIN <= (x) && (x) <= TDS_INT8_MAX)
+#define TDS_UINT8_MAX ((((TDS_UINT8) 0xfffffffflu) << 32) + 0xfffffffflu)
+#define IS_UINT8(x) (0 <= (x) && (x) <= TDS_UINT8_MAX)
+
/**
* \ingroup libtds
* \defgroup convert Conversion
@@ -127,6 +134,7 @@
static TDS_INT string_to_int(const char *buf, const char *pend, TDS_INT * res);
static TDS_INT string_to_int8(const char *buf, const char *pend, TDS_INT8 * res);
+static TDS_INT string_to_uint8(const char *buf, const char *pend, TDS_UINT8 * res);
static int store_hour(const char *, const char *, struct tds_time *);
static int store_time(const char *, struct tds_time *);
@@ -255,9 +263,13 @@
return binary_to_result(src, srclen, cr);
break;
case SYBINT1:
+ case SYBUINT1:
case SYBINT2:
+ case SYBUINT2:
case SYBINT4:
+ case SYBUINT4:
case SYBINT8:
+ case SYBUINT8:
case SYBMONEY4:
case SYBMONEY:
case SYBREAL:
@@ -341,6 +353,7 @@
unsigned int places;
TDS_INT tds_i;
TDS_INT8 tds_i8;
+ TDS_UINT8 tds_ui8;
TDS_INT rc;
TDS_CHAR *ib;
@@ -383,6 +396,7 @@
return tds_char2hex(ib, desttype == TDS_CONVERT_BINARY ? cr->cb.len : 0xffffffffu, src, srclen);
break;
case SYBINT1:
+ case SYBUINT1:
if ((rc = string_to_int(src, src + srclen, &tds_i)) < 0)
return rc;
if (!IS_TINYINT(tds_i))
@@ -398,18 +412,38 @@
cr->si = tds_i;
return sizeof(TDS_SMALLINT);
break;
+ case SYBUINT2:
+ if ((rc = string_to_int(src, src + srclen, &tds_i)) < 0)
+ return rc;
+ if (!IS_USMALLINT(tds_i))
+ return TDS_CONVERT_OVERFLOW;
+ cr->usi = tds_i;
+ return sizeof(TDS_USMALLINT);
+ break;
case SYBINT4:
if ((rc = string_to_int(src, src + srclen, &tds_i)) < 0)
return rc;
cr->i = tds_i;
return sizeof(TDS_INT);
break;
+ case SYBUINT4:
+ if ((rc = string_to_int8(src, src + srclen, &tds_i8)) < 0)
+ return rc;
+ cr->ui = tds_i8;
+ return sizeof(TDS_UINT);
+ break;
case SYBINT8:
if ((rc = string_to_int8(src, src + srclen, &tds_i8)) < 0)
return rc;
cr->bi = tds_i8;
return sizeof(TDS_INT8);
break;
+ case SYBUINT8:
+ if ((rc = string_to_uint8(src, src + srclen, &tds_ui8)) < 0)
+ return rc;
+ cr->ubi = tds_ui8;
+ return sizeof(TDS_UINT8);
+ break;
case SYBFLT8:
/* FIXME not null terminated */
/* TODO check syntax and overflow */
@@ -598,6 +632,7 @@
return binary_to_result(src, 1, cr);
break;
case SYBINT1:
+ case SYBUINT1:
cr->ti = canonic;
return sizeof(TDS_TINYINT);
break;
@@ -605,14 +640,26 @@
cr->si = canonic;
return sizeof(TDS_SMALLINT);
break;
+ case SYBUINT2:
+ cr->usi = canonic;
+ return sizeof(TDS_USMALLINT);
+ break;
case SYBINT4:
cr->i = canonic;
return sizeof(TDS_INT);
break;
+ case SYBUINT4:
+ cr->ui = canonic;
+ return sizeof(TDS_UINT);
+ break;
case SYBINT8:
cr->bi = canonic;
return sizeof(TDS_INT8);
break;
+ case SYBUINT8:
+ cr->ubi = canonic;
+ return sizeof(TDS_UINT8);
+ break;
case SYBFLT8:
cr->f = canonic;
return sizeof(TDS_FLOAT);
@@ -663,6 +710,7 @@
return binary_to_result(src, 1, cr);
break;
case SYBINT1:
+ case SYBUINT1:
cr->ti = buf;
return sizeof(TDS_TINYINT);
break;
@@ -670,14 +718,26 @@
cr->si = buf;
return sizeof(TDS_SMALLINT);
break;
+ case SYBUINT2:
+ cr->usi = buf;
+ return sizeof(TDS_USMALLINT);
+ break;
case SYBINT4:
cr->i = buf;
return sizeof(TDS_INT);
break;
+ case SYBUINT4:
+ cr->ui = buf;
+ return sizeof(TDS_UINT);
+ break;
case SYBINT8:
cr->bi = buf;
return sizeof(TDS_INT8);
break;
+ case SYBUINT8:
+ cr->ubi = buf;
+ return sizeof(TDS_UINT8);
+ break;
case SYBBIT:
case SYBBITN:
cr->ti = buf ? 1 : 0;
@@ -732,6 +792,7 @@
return binary_to_result(src, 2, cr);
break;
case SYBINT1:
+ case SYBUINT1:
if (!IS_TINYINT(buf))
return TDS_CONVERT_OVERFLOW;
cr->ti = (TDS_TINYINT) buf;
@@ -741,14 +802,26 @@
cr->si = buf;
return sizeof(TDS_SMALLINT);
break;
+ case SYBUINT2:
+ cr->usi = buf;
+ return sizeof(TDS_USMALLINT);
+ break;
case SYBINT4:
cr->i = buf;
return sizeof(TDS_INT);
break;
+ case SYBUINT4:
+ cr->ui = buf;
+ return sizeof(TDS_UINT);
+ break;
case SYBINT8:
cr->bi = buf;
return sizeof(TDS_INT8);
break;
+ case SYBUINT8:
+ cr->ubi = buf;
+ return sizeof(TDS_UINT8);
+ break;
case SYBBIT:
case SYBBITN:
cr->ti = buf ? 1 : 0;
@@ -803,6 +876,7 @@
return binary_to_result(src, 4, cr);
break;
case SYBINT1:
+ case SYBUINT1:
if (!IS_TINYINT(buf))
return TDS_CONVERT_OVERFLOW;
cr->ti = buf;
@@ -814,14 +888,28 @@
cr->si = buf;
return sizeof(TDS_SMALLINT);
break;
+ case SYBUINT2:
+ if (!IS_USMALLINT(buf))
+ return TDS_CONVERT_OVERFLOW;
+ cr->usi = buf;
+ return sizeof(TDS_USMALLINT);
+ break;
case SYBINT4:
cr->i = buf;
return sizeof(TDS_INT);
break;
+ case SYBUINT4:
+ cr->ui = buf;
+ return sizeof(TDS_UINT);
+ break;
case SYBINT8:
cr->bi = buf;
return sizeof(TDS_INT8);
break;
+ case SYBUINT8:
+ cr->ubi = buf;
+ return sizeof(TDS_UINT8);
+ break;
case SYBBIT:
case SYBBITN:
cr->ti = buf ? 1 : 0;
@@ -879,6 +967,7 @@
return binary_to_result(src, sizeof(TDS_INT8), cr);
break;
case SYBINT1:
+ case SYBUINT1:
if (!IS_TINYINT(buf))
return TDS_CONVERT_OVERFLOW;
cr->ti = (TDS_TINYINT) buf;
@@ -890,16 +979,32 @@
cr->si = (TDS_SMALLINT) buf;
return sizeof(TDS_SMALLINT);
break;
+ case SYBUINT2:
+ if (!IS_USMALLINT(buf))
+ return TDS_CONVERT_OVERFLOW;
+ cr->usi = (TDS_USMALLINT) buf;
+ return sizeof(TDS_USMALLINT);
+ break;
case SYBINT4:
if (!IS_INT(buf))
return TDS_CONVERT_OVERFLOW;
cr->i = (TDS_INT) buf;
return sizeof(TDS_INT);
break;
+ case SYBUINT4:
+ if (!IS_UINT(buf))
+ return TDS_CONVERT_OVERFLOW;
+ cr->ui = (TDS_UINT) buf;
+ return sizeof(TDS_UINT);
+ break;
case SYBINT8:
cr->bi = buf;
return sizeof(TDS_INT8);
break;
+ case SYBUINT8:
+ cr->ubi = buf;
+ return sizeof(TDS_UINT8);
+ break;
case SYBBIT:
case SYBBITN:
cr->ti = buf ? 1 : 0;
@@ -959,6 +1064,7 @@
return binary_to_result(src, sizeof(TDS_NUMERIC), cr);
break;
case SYBINT1:
+ case SYBUINT1:
cr->n = *src;
ret = tds_numeric_change_prec_scale(&(cr->n), 3, 0);
if (ret < 0)
@@ -983,6 +1089,21 @@
cr->si = (TDS_SMALLINT) i;
return sizeof(TDS_SMALLINT);
break;
+ case SYBUINT2:
+ cr->n = *src;
+ ret = tds_numeric_change_prec_scale(&(cr->n), 5, 0);
+ if (ret < 0)
+ return ret;
+ if (cr->n.array[1])
+ return TDS_CONVERT_OVERFLOW;
+ i = TDS_GET_UA2BE(&(cr->n.array[2]));
+ if (cr->n.array[0])
+ return TDS_CONVERT_OVERFLOW;
+ if (i > 65535)
+ return TDS_CONVERT_OVERFLOW;
+ cr->usi = (TDS_USMALLINT) i;
+ return sizeof(TDS_USMALLINT);
+ break;
case SYBINT4:
cr->n = *src;
ret = tds_numeric_change_prec_scale(&(cr->n), 10, 0);
@@ -998,6 +1119,17 @@
cr->i = i;
return sizeof(TDS_INT);
break;
+ case SYBUINT4:
+ cr->n = *src;
+ ret = tds_numeric_change_prec_scale(&(cr->n), 10, 0);
+ if (ret < 0)
+ return ret;
+ if (cr->n.array[0] || cr->n.array[1])
+ return TDS_CONVERT_OVERFLOW;
+ i = TDS_GET_UA4BE(&(cr->n.array[2]));
+ cr->ui = i;
+ return sizeof(TDS_UINT);
+ break;
case SYBINT8:
cr->n = *src;
ret = tds_numeric_change_prec_scale(&(cr->n), 20, 0);
@@ -1014,6 +1146,18 @@
cr->bi = bi;
return sizeof(TDS_INT8);
break;
+ case SYBUINT8:
+ cr->n = *src;
+ ret = tds_numeric_change_prec_scale(&(cr->n), 20, 0);
+ if (ret < 0)
+ return ret;
+ if (cr->n.array[0] || cr->n.array[1])
+ return TDS_CONVERT_OVERFLOW;
+ bi = TDS_GET_UA4BE(&(cr->n.array[2]));
+ bi = (bi << 32) + TDS_GET_UA4BE(&(cr->n.array[6]));
+ cr->ubi = bi;
+ return sizeof(TDS_UINT8);
+ break;
case SYBBIT:
case SYBBITN:
cr->ti = 0;
@@ -1091,6 +1235,7 @@
return binary_to_result(src, sizeof(TDS_MONEY4), cr);
break;
case SYBINT1:
+ case SYBUINT1:
dollars = mny.mny4 / 10000;
if (!IS_TINYINT(dollars))
return TDS_CONVERT_OVERFLOW;
@@ -1104,14 +1249,29 @@
cr->si = (TDS_SMALLINT) dollars;
return sizeof(TDS_SMALLINT);
break;
+ case SYBUINT2:
+ dollars = mny.mny4 / 10000;
+ if (!IS_USMALLINT(dollars))
+ return TDS_CONVERT_OVERFLOW;
+ cr->usi = (TDS_USMALLINT) dollars;
+ return sizeof(TDS_USMALLINT);
+ break;
case SYBINT4:
cr->i = mny.mny4 / 10000;
return sizeof(TDS_INT);
break;
+ case SYBUINT4:
+ cr->ui = mny.mny4 / 10000;
+ return sizeof(TDS_UINT);
+ break;
case SYBINT8:
cr->bi = mny.mny4 / 10000;
return sizeof(TDS_INT8);
break;
+ case SYBUINT8:
+ cr->ubi = mny.mny4 / 10000;
+ return sizeof(TDS_UINT8);
+ break;
case SYBBIT:
case SYBBITN:
cr->ti = mny.mny4 ? 1 : 0;
@@ -1181,6 +1341,7 @@
return binary_to_result(src, sizeof(TDS_MONEY), cr);
break;
case SYBINT1:
+ case SYBUINT1:
if (mymoney <= -10000 || mymoney >= 256 * 10000)
return TDS_CONVERT_OVERFLOW;
/* TODO: round ?? */
@@ -1193,6 +1354,12 @@
cr->si = (TDS_SMALLINT) (((TDS_INT) mymoney) / 10000);
return sizeof(TDS_SMALLINT);
break;
+ case SYBUINT2:
+ if (mymoney <= -1 * 10000 || mymoney >= 65536 * 10000)
+ return TDS_CONVERT_OVERFLOW;
+ cr->usi = (TDS_USMALLINT) (((TDS_INT) mymoney) / 10000);
+ return sizeof(TDS_USMALLINT);
+ break;
case SYBINT4:
dollars = mymoney / 10000;
if (!IS_INT(dollars))
@@ -1200,10 +1367,21 @@
cr->i = (TDS_INT) dollars;
return sizeof(TDS_INT);
break;
+ case SYBUINT4:
+ dollars = mymoney / 10000;
+ if (!IS_UINT(dollars))
+ return TDS_CONVERT_OVERFLOW;
+ cr->ui = (TDS_UINT) dollars;
+ return sizeof(TDS_UINT);
+ break;
case SYBINT8:
cr->bi = mymoney / 10000;
return sizeof(TDS_INT8);
break;
+ case SYBUINT8:
+ cr->ubi = mymoney / 10000;
+ return sizeof(TDS_UINT8);
+ break;
case SYBBIT:
case SYBBITN:
cr->ti = mymoney ? 1 : 0;
@@ -1281,9 +1459,13 @@
case SYBBIT:
case SYBBITN:
case SYBINT1:
+ case SYBUINT1:
case SYBINT2:
+ case SYBUINT2:
case SYBINT4:
+ case SYBUINT4:
case SYBINT8:
+ case SYBUINT8:
case SYBMONEY4:
case SYBMONEY:
case SYBNUMERIC:
@@ -1340,9 +1522,13 @@
case SYBBIT:
case SYBBITN:
case SYBINT1:
+ case SYBUINT1:
case SYBINT2:
+ case SYBUINT2:
case SYBINT4:
+ case SYBUINT4:
case SYBINT8:
+ case SYBUINT8:
case SYBMONEY4:
case SYBMONEY:
case SYBNUMERIC:
@@ -1397,6 +1583,7 @@
return binary_to_result(src, sizeof(TDS_REAL), cr);
break;
case SYBINT1:
+ case SYBUINT1:
if (!IS_TINYINT(the_value))
return TDS_CONVERT_OVERFLOW;
cr->ti = (TDS_TINYINT) the_value;
@@ -1408,18 +1595,36 @@
cr->si = (TDS_SMALLINT) the_value;
return sizeof(TDS_SMALLINT);
break;
+ case SYBUINT2:
+ if (!IS_USMALLINT(the_value))
+ return TDS_CONVERT_OVERFLOW;
+ cr->usi = (TDS_USMALLINT) the_value;
+ return sizeof(TDS_USMALLINT);
+ break;
case SYBINT4:
if (!IS_INT(the_value))
return TDS_CONVERT_OVERFLOW;
cr->i = (TDS_INT) the_value;
return sizeof(TDS_INT);
break;
+ case SYBUINT4:
+ if (!IS_UINT(the_value))
+ return TDS_CONVERT_OVERFLOW;
+ cr->ui = (TDS_UINT) the_value;
+ return sizeof(TDS_UINT);
+ break;
case SYBINT8:
if (the_value > (TDS_REAL) TDS_INT8_MAX || the_value < (TDS_REAL) TDS_INT8_MIN)
return TDS_CONVERT_OVERFLOW;
cr->bi = (TDS_INT8) the_value;
return sizeof(TDS_INT8);
break;
+ case SYBUINT8:
+ if (the_value > (TDS_REAL) TDS_UINT8_MAX || the_value < 0)
+ return TDS_CONVERT_OVERFLOW;
+ cr->ubi = (TDS_UINT8) the_value;
+ return sizeof(TDS_UINT8);
+ break;
case SYBBIT:
case SYBBITN:
cr->ti = the_value ? 1 : 0;
@@ -1491,6 +1696,7 @@
return binary_to_result(src, sizeof(TDS_FLOAT), cr);
break;
case SYBINT1:
+ case SYBUINT1:
if (!IS_TINYINT(the_value))
return TDS_CONVERT_OVERFLOW;
cr->ti = (TDS_TINYINT) the_value;
@@ -1502,18 +1708,36 @@
cr->si = (TDS_SMALLINT) the_value;
return sizeof(TDS_SMALLINT);
break;
+ case SYBUINT2:
+ if (!IS_USMALLINT(the_value))
+ return TDS_CONVERT_OVERFLOW;
+ cr->usi = (TDS_USMALLINT) the_value;
+ return sizeof(TDS_USMALLINT);
+ break;
case SYBINT4:
if (!IS_INT(the_value))
return TDS_CONVERT_OVERFLOW;
cr->i = (TDS_INT) the_value;
return sizeof(TDS_INT);
break;
+ case SYBUINT4:
+ if (!IS_UINT(the_value))
+ return TDS_CONVERT_OVERFLOW;
+ cr->ui = (TDS_UINT) the_value;
+ return sizeof(TDS_UINT);
+ break;
case SYBINT8:
if (the_value > (TDS_FLOAT) TDS_INT8_MAX || the_value < (TDS_FLOAT) TDS_INT8_MIN)
return TDS_CONVERT_OVERFLOW;
cr->bi = (TDS_INT8) the_value;
return sizeof(TDS_INT8);
break;
+ case SYBUINT8:
+ if (the_value > (TDS_FLOAT) TDS_UINT8_MAX || the_value < 0)
+ return TDS_CONVERT_OVERFLOW;
+ cr->ubi = (TDS_UINT8) the_value;
+ return sizeof(TDS_UINT8);
+ break;
case SYBBIT:
case SYBBITN:
cr->ti = the_value ? 1 : 0;
@@ -1591,9 +1815,13 @@
case SYBBIT:
case SYBBITN:
case SYBINT1:
+ case SYBUINT1:
case SYBINT2:
+ case SYBUINT2:
case SYBINT4:
+ case SYBUINT4:
case SYBINT8:
+ case SYBUINT8:
case SYBMONEY4:
case SYBMONEY:
case SYBDATETIME4:
@@ -1657,15 +1885,19 @@
length = tds_convert_bit(srctype, src, desttype, cr);
break;
case SYBINT1:
+ case SYBUINT1:
length = tds_convert_int1(srctype, src, desttype, cr);
break;
case SYBINT2:
+ case SYBUINT2:
length = tds_convert_int2(srctype, src, desttype, cr);
break;
case SYBINT4:
+ case SYBUINT4:
length = tds_convert_int4(srctype, src, desttype, cr);
break;
case SYBINT8:
+ case SYBUINT8:
length = tds_convert_int8(srctype, src, desttype, cr);
break;
case SYBREAL:
@@ -2688,9 +2920,13 @@
return SYBVARCHAR;
break;
case SYBINT1:
+ case SYBUINT1:
case SYBINT2:
+ case SYBUINT2:
case SYBINT4:
+ case SYBUINT4:
case SYBINT8:
+ case SYBUINT8:
return SYBINTN;
break;
case SYBREAL:
@@ -3201,5 +3437,56 @@
return sizeof(TDS_INT8);
}
+/**
+ * \brief convert a number in string to TDS_UINT8
+ *
+ * \return TDS_CONVERT_* or failure code on error
+ */
+static TDS_INT /* copied from string_to_int8 and modified */
+string_to_uint8(const char *buf, const char *pend, TDS_UINT8 * res)
+{
+ enum
+ { blank = ' ' };
+ const char *p;
+ TDS_UINT8 num;
+
+ p = buf;
+
+ /* ignore leading spaces */
+ while (p != pend && *p == blank)
+ ++p;
+ if (p == pend) {
+ *res = 0;
+ return sizeof(TDS_UINT8);
+ }
+
+ num = 0;
+ for (; p != pend; ++p) {
+ /* check for trailing spaces */
+ if (*p == blank) {
+ while (p != pend && *++p == blank);
+ if (p != pend)
+ return TDS_CONVERT_SYNTAX;
+ break;
+ }
+
+ /* must be a digit */
+ if (!isdigit((unsigned char) *p))
+ return TDS_CONVERT_SYNTAX;
+
+ /* add a digit to number and check for overflow */
+ if (num > ((((TDS_UINT8) 1) << 63) / ((TDS_UINT8) 10)))
+ return TDS_CONVERT_OVERFLOW;
+ num = num * 10u + (*p - '0');
+ }
+
+ /* check for overflow and convert unsigned to signed */
+ if (num >= (((TDS_UINT8) 1) << 63))
+ return TDS_CONVERT_OVERFLOW;
+ *res = num;
+
+ return sizeof(TDS_UINT8);
+}
+
/** @} */
Index: src/tds/tds_willconvert.pl
===================================================================
RCS file: /cvsroot/freetds/freetds/src/tds/tds_willconvert.pl,v
retrieving revision 1.3
diff -u -d -r1.3 tds_willconvert.pl
--- src/tds/tds_willconvert.pl 3 Jan 2009 15:26:09 -0000 1.3
+++ src/tds/tds_willconvert.pl 22 Dec 2012 20:18:47 -0000
@@ -35,26 +35,30 @@
__DATA__
To
From
- VARCHAR CHAR TEXT BINARY VARBINARY IMAGE INT1 INT2 INT4 INT8 FLT8 REAL NUMERIC DECIMAL BIT MONEY MONEY4 DATETIME DATETIME4 BOUNDARY UNIQUE SENSITIVITY
-VARCHAR T T T T T T T T T T T T T T T T T T T T T t
-CHAR T T T T T T T T T T T T T T T T T T T T T t
-TEXT T T T T T T T T T T T T T T T T T T T T T t
-BINARY T T T T T T T T T T T T T T T T T F F F F F
-VARBINARY T T T T T T T T T T T T T T T T T F F F F F
-IMAGE T T T T T T T T T T T T T T T T T F F F F F
-INT1 T T T T T T T T T T T T T T T T T F F F F F
-INT2 T T T T T T T T T T T T T T T T T F F F F F
-INT4 T T T T T T T T T T T T T T T T T F F F F F
-INT8 T T T T T T T T T T T T T T T T T F F F F F
-FLT8 T T T T T T T T T T T T T T T T T F F F F F
-REAL T T T T T T T T T T T T T T T T T F F F F F
-NUMERIC T T T T T T T T T T T T T T T T T F F F F F
-DECIMAL T T T T T T T T T T T T T T T T T F F F F F
-BIT T T T T T T T T T T T T T T T T T F F F F F
-MONEY T T T T T T T T T T T T T T T T T F F F F F
-MONEY4 T T T T T T T T T T T T T T T T T F F F F F
-DATETIME T T T T T T F F F F F F F F F F F T T F F F
-DATETIME4 T T T T T T F F F F F F F F F F F T T F F F
-BOUNDARY T T T F F F F F F F F F F F F F F F F T F F
-UNIQUE T T T F F F F F F F F F F F F F F F F F T F
-SENSITIVITY t t t F F F F F F F F F F F F F F F F F F t
+ VARCHAR CHAR TEXT BINARY VARBINARY IMAGE INT1 UINT1 INT2 UINT2 INT4 UINT4 INT8 UINT8 FLT8 REAL NUMERIC DECIMAL BIT MONEY MONEY4 DATETIME DATETIME4 BOUNDARY UNIQUE SENSITIVITY
+VARCHAR T T T T T T T T T T T T T T T T T T T T T T T T T t
+CHAR T T T T T T T T T T T T T T T T T T T T T T T T T t
+TEXT T T T T T T T T T T T T T T T T T T T T T T T T T t
+BINARY T T T T T T T T T T T T T T T T T T T T T F F F F F
+VARBINARY T T T T T T T T T T T T T T T T T T T T T F F F F F
+IMAGE T T T T T T T T T T T T T T T T T T T T T F F F F F
+INT1 T T T T T T T T T T T T T T T T T T T T T F F F F F
+UINT1 T T T T T T T T T T T T T T T T T T T T T F F F F F
+INT2 T T T T T T T T T T T T T T T T T T T T T F F F F F
+UINT2 T T T T T T T T T T T T T T T T T T T T T F F F F F
+INT4 T T T T T T T T T T T T T T T T T T T T T F F F F F
+UINT4 T T T T T T T T T T T T T T T T T T T T T F F F F F
+INT8 T T T T T T T T T T T T T T T T T T T T T F F F F F
+UINT8 T T T T T T T T T T T T T T T T T T T T T F F F F F
+FLT8 T T T T T T T T T T T T T T T T T T T T T F F F F F
+REAL T T T T T T T T T T T T T T T T T T T T T F F F F F
+NUMERIC T T T T T T T T T T T T T T T T T T T T T F F F F F
+DECIMAL T T T T T T T T T T T T T T T T T T T T T F F F F F
+BIT T T T T T T T T T T T T T T T T T T T T T F F F F F
+MONEY T T T T T T T T T T T T T T T T T T T T T F F F F F
+MONEY4 T T T T T T T T T T T T T T T T T T T T T F F F F F
+DATETIME T T T T T T F F F F F F F T F F F F F F F T T F F F
+DATETIME4 T T T T T T F F F F F F F T F F F F F F F T T F F F
+BOUNDARY T T T F F F F F F F F F F T F F F F F F F F F T F F
+UNIQUE T T T F F F F F F F F F F T F F F F F F F F F F T F
+SENSITIVITY t t t F F F F F F F F F F T F F F F F F F F F F F t