Freetds bigint support patch

Jason Borden jborden at sorenson.com
Wed Oct 9 03:17:06 EDT 2002


Here's a patch for bigint conversion support in src/tds and also bigint
support in src/odbc.

Cheers,
Jason

diff -r -u freetds/include/tdsconvert.h freetds-jb/include/tdsconvert.h
--- freetds/include/tdsconvert.h        Fri Sep 13 14:13:16 2002
+++ freetds-jb/include/tdsconvert.h     Tue Oct  8 23:54:56 2002
@@ -29,6 +29,7 @@
     TDS_TINYINT     ti;
     TDS_SMALLINT    si;
     TDS_INT         i;
+    TDS_INT8       bi;
     TDS_FLOAT       f;
     TDS_REAL        r;
     TDS_CHAR        *c;
@@ -55,6 +56,8 @@
        int desttype,unsigned char *dest,TDS_INT destlen);
 TDS_INT _convert_int4(int srctype,unsigned char *src,
        int desttype,unsigned char *dest,TDS_INT destlen);
+TDS_INT _convert_int8(int srctype,unsigned char *src,
+       int desttype,unsigned char *dest,TDS_INT destlen);
 TDS_INT _convert_flt8(int srctype,unsigned char *src,int
desttype,unsigned char *dest,TDS_INT destlen);
 TDS_INT _convert_datetime(int srctype,unsigned char *src,int
desttype,unsigned char *dest,TDS_INT destlen);
 int _get_conversion_type(int srctype, int colsize);
diff -r -u freetds/src/odbc/convert_sql2string.c
freetds-jb/src/odbc/convert_sql2string.c
--- freetds/src/odbc/convert_sql2string.c       Sun Sep 15 10:08:24 2002
+++ freetds-jb/src/odbc/convert_sql2string.c    Tue Oct  8 23:54:56 2002
@@ -46,6 +46,7 @@
                case SQL_C_BIT:
                        return SYBBIT;
 #if (ODBCVER >= 0x0300)
+               case SQL_BIGINT:
                case SQL_C_SBIGINT:
                case SQL_C_UBIGINT:
                        return SYBINT8;
diff -r -u freetds/src/odbc/convert_tds2sql.c
freetds-jb/src/odbc/convert_tds2sql.c
--- freetds/src/odbc/convert_tds2sql.c  Sun Sep 15 10:08:24 2002
+++ freetds-jb/src/odbc/convert_tds2sql.c       Tue Oct  8 23:54:56 2002
@@ -50,6 +50,11 @@
        case SQL_C_TIMESTAMP:
                return SYBDATETIME;

+       case SQL_BIGINT:
+       case SQL_C_SBIGINT:
+       case SQL_C_UBIGINT:
+               return SYBINT8;
+
        case SQL_C_LONG:
        case SQL_C_ULONG:
        case SQL_C_SLONG:
@@ -96,6 +101,7 @@
     TIMESTAMP_STRUCT *tssp;
     SQL_NUMERIC_STRUCT   *num;

+    TDS_UINT8       *uip8;
     TDS_UINT         *uip;
     TDS_USMALLINT    *usip;

@@ -196,6 +202,18 @@
              ret = sizeof(TIMESTAMP_STRUCT);
              break;

+          case SQL_BIGINT:
+          case SQL_C_SBIGINT:
+            memcpy(dest, &(ores.i), sizeof(TDS_INT8));
+            ret = sizeof(TDS_INT8);
+            break;
+
+          case SQL_C_UBIGINT:
+            uip = (TDS_UINT8 *)dest;
+            *uip = ores.i;
+            ret = sizeof(TDS_UINT8);
+            break;
+
               case SQL_C_LONG:
                   case SQL_C_SLONG:
              memcpy(dest, &(ores.i), sizeof(TDS_INT));
diff -r -u freetds/src/odbc/odbc.c freetds-jb/src/odbc/odbc.c
--- freetds/src/odbc/odbc.c     Sun Sep 15 10:08:24 2002
+++ freetds-jb/src/odbc/odbc.c  Tue Oct  8 23:54:56 2002
@@ -2265,6 +2265,8 @@
                        return SQL_C_SSHORT;
                case SQL_INTEGER:
                        return SQL_C_SLONG;
+               case SQL_BIGINT:
+                       return SQL_C_SBIGINT;
                case SQL_REAL:
                        return SQL_C_FLOAT;
                case SQL_FLOAT:
--- freetds/src/tds/convert.c   Fri Sep 13 17:43:58 2002
+++ freetds-jb/src/tds/convert.c        Tue Oct  8 23:55:09 2002
@@ -63,6 +63,12 @@
  */
 static TDS_INT string_to_int(const char *buf,const char *pend,TDS_INT*
res);

+/**
+ * conver a number in string to TDS_INT8
+ * @return TDS_FAIL if failure
+ */
+static TDS_INT8 string_to_int8(const char *buf, const char *pend,
TDS_INT8* res);
+
 #define TDS_CONVERT_NOAVAIL -2
 /**
  * convert, same as tds_convert but not return error to client
@@ -256,6 +262,7 @@
        case SYBINT1:
        case SYBINT2:
        case SYBINT4:
+       case SYBINT8:
        case SYBMONEY4:
        case SYBMONEY:
        case SYBREAL:
@@ -301,6 +308,7 @@
 const char *ptr, *pend;
 int point_found, places;
 TDS_INT tds_i;
+TDS_INT8 tds_i8;


    switch(desttype) {
@@ -425,7 +433,13 @@
                        return TDS_FAIL;
                cr->i = tds_i;
          return 4;
-         break;
+         break;
+      case SYBINT8:
+               if (string_to_int8(src, src + srclen, &tds_i8) ==
TDS_FAIL)
+                       return TDS_FAIL;
+               cr->bi = tds_i8;
+       return 8;
+       break;
       case SYBFLT8:
          cr->f = atof(src);
          return 8;
@@ -601,6 +615,10 @@
                        cr->i = canonic;
                        return 4;
                        break;
+               case SYBINT8:
+                       cr->bi = canonic;
+                       return 8;
+                       break;
                case SYBFLT8:
                        cr->f = canonic;
                        return 8;
@@ -667,6 +685,10 @@
                        cr->i = buf;
             return 4;
                        break;
+               case SYBINT8:
+                       cr->bi = buf;
+           return 8;
+                       break;
                case SYBBIT:
                case SYBBITN:
                        cr->ti = buf ? 1 : 0;
@@ -738,6 +760,10 @@
                        cr->i = buf;
             return 4;
                        break;
+               case SYBINT8:
+                       cr->bi = buf;
+           return 8;
+                       break;
                case SYBBIT:
                case SYBBITN:
                        cr->ti = buf ? 1 : 0;
@@ -811,6 +837,10 @@
                        cr->i = buf;
             return 4;
                        break;
+               case SYBINT8:
+                       cr->bi = buf;
+           return 8;
+                       break;
                case SYBBIT:
                case SYBBITN:
                        cr->ti = buf ? 1 : 0;
@@ -852,6 +882,85 @@
        return TDS_FAIL;
 }
 static TDS_INT
+tds_convert_int8(int srctype,TDS_CHAR *src,
+       int desttype,TDS_INT destlen, CONV_RESULT *cr)
+{
+TDS_INT8 buf;
+TDS_CHAR tmp_str[20];
+
+       memcpy(&buf,src,sizeof(buf));
+       switch(desttype) {
+               case SYBCHAR:
+               case SYBTEXT:
+               case SYBVARCHAR:
+                       sprintf(tmp_str,"%lld",buf);
+                       return string_to_result(tmp_str,cr);
+                       break;
+               case SYBBINARY:
+               case SYBIMAGE:
+                       return binary_to_result(src,8,cr);
+                       break;
+               case SYBINT1:
+                       if (!IS_TINYINT(buf))
+                               return TDS_FAIL;
+                       cr->ti = buf;
+            return 1;
+                       break;
+               case SYBINT2:
+                       if ( !IS_SMALLINT(buf) )
+                               return TDS_FAIL;
+                       cr->si = buf;
+            return 2;
+                       break;
+               case SYBINT4:
+                       cr->i = buf;
+            return 4;
+                       break;
+               case SYBINT8:
+                       cr->bi = buf;
+           return 8;
+                       break;
+               case SYBBIT:
+               case SYBBITN:
+                       cr->ti = buf ? 1 : 0;
+                       return 1;
+                       break;
+               case SYBFLT8:
+                       cr->f = buf;
+            return 8;
+                       break;
+               case SYBREAL:
+                       cr->r = buf;
+            return 4;
+                       break;
+               case SYBMONEY4:
+                       if (buf > 214748 || buf < -214748)
+                               return TDS_FAIL;
+                       cr->m4.mny4 = buf * 10000;
+                       return 4;
+                       break;
+               case SYBMONEY:
+                       cr->m.mny = (TDS_INT8)buf * 10000;
+                       return sizeof(TDS_MONEY);
+                       break;
+               case SYBNUMERIC:
+               case SYBDECIMAL:
+                       sprintf(tmp_str,"%lld",buf);
+                       return stringz_to_numeric(tmp_str,cr);
+                       break;
+               /* conversions not allowed */
+               case SYBUNIQUE:
+               case SYBDATETIME4:
+               case SYBDATETIME:
+               case SYBDATETIMN:
+                       break;
+               default:
+                       LOG_CONVERT();
+                       return TDS_FAIL;
+       }
+       return TDS_FAIL;
+}
+static TDS_INT
 tds_convert_numeric(int srctype,TDS_NUMERIC *src,TDS_INT srclen,
        int desttype,TDS_INT destlen, CONV_RESULT *cr)
 {
@@ -893,6 +1002,11 @@
                        cr->i = i;
                        return 4;
                        break;
+               case SYBINT8:
+                       tds_numeric_to_string(src,tmpstr);
+                       cr->bi = atoll(tmpstr);
+                       return 8;
+                       break;
                case SYBBIT:
                case SYBBITN:
                        cr->ti = 0;
@@ -978,6 +1092,10 @@
                        cr->i = mny.mny4 / 10000;
                        return 4;
                        break;
+               case SYBINT8:
+                       cr->bi = (TDS_INT8)mny.mny4 / 10000;
+                       return 8;
+                       break;
                case SYBBIT:
                case SYBBITN:
                        cr->ti = mny.mny4 ? 1 : 0;
@@ -1110,6 +1228,11 @@
                        cr->i = dollars;
                        return 4;
                        break;
+               case SYBINT8:
+                       dollars = mymoney / 10000;
+                       cr->bi = dollars;
+                       return 8;
+                       break;
                case SYBBIT:
                case SYBBITN:
                        cr->ti = mymoney ? 1 : 0;
@@ -1263,6 +1386,7 @@
                case SYBINT1:
                case SYBINT2:
                case SYBINT4:
+               case SYBINT8:
                case SYBMONEY4:
                case SYBMONEY:
                case SYBNUMERIC:
@@ -1373,6 +1497,7 @@
                case SYBINT1:
                case SYBINT2:
                case SYBINT4:
+               case SYBINT8:
                case SYBMONEY4:
                case SYBMONEY:
                case SYBNUMERIC:
@@ -1428,6 +1553,10 @@
                        cr->i = the_value;
                        return 4;
                        break;
+               case SYBINT8:
+                       cr->bi = the_value;
+                       return 8;
+                       break;
                case SYBBIT:
                case SYBBITN:
                        cr->ti = the_value ? 1 : 0;
@@ -1511,6 +1640,10 @@
                        cr->i = the_value;
                        return 4;
                        break;
+               case SYBINT8:
+                       cr->bi = the_value;
+                       return 8;
+                       break;
                case SYBBIT:
                case SYBBITN:
                        cr->ti = the_value ? 1 : 0;
@@ -1589,6 +1722,7 @@
                case SYBINT1:
                case SYBINT2:
                case SYBINT4:
+               case SYBINT8:
                case SYBMONEY4:
                case SYBMONEY:
                case SYBDATETIME4:
@@ -1721,6 +1855,9 @@
                case SYBINT4:
                        length= tds_convert_int4(srctype,src,
desttype,destlen, cr);
                        break;
+               case SYBINT8:
+                       length= tds_convert_int8(srctype,src,
desttype,destlen, cr);
+                       break;
                case SYBREAL:
                        length= tds_convert_real(srctype,src,
desttype,destlen, cr);
                        break;
@@ -2645,6 +2782,7 @@
                case SYBINT1:
                case SYBINT2:
                case SYBINT4:
+               case SYBINT8:
                        return SYBINTN;
                        break;
                case SYBREAL:
@@ -3004,6 +3142,72 @@
                        return TDS_FAIL;
                *res = num;
        }
+
+       return TDS_SUCCEED;
+}
+
+static TDS_INT8
+string_to_int8(const char *buf,const char *pend,TDS_INT8* res)
+{
+enum { blank = ' ' };
+const char *p;
+int    sign;
+unsigned int num; /* we use unsigned here for best overflow check */
+
+       p = buf;
+
+       /* ignore leading spaces */
+       while( p != pend && *p == blank )
+               ++p;
+       if (p==pend) return TDS_FAIL;
+
+       /* check for sign */
+       sign = 0;
+       switch ( *p ) {
+       case '-':
+               sign = 1;
+               /* fall thru */
+       case '+':
+               /* skip spaces between sign and number */
+               ++p;
+               while( p != pend && *p == blank )
+                       ++p;
+               break;
+       }
+
+       /* a digit must be present */
+       if (p == pend )
+               return TDS_FAIL;
+
+       num = 0;
+       for(;p != pend;++p) {
+               /* check for trailing spaces */
+               if (*p == blank) {
+                       while( p != pend && *++p == blank);
+                       if (p!=pend) return TDS_FAIL;
+                       break;
+               }
+
+               /* must be a digit */
+               if (!isdigit(*p))
+                       return TDS_FAIL;
+
+               /* add a digit to number and check for overflow */
+               if (num > 922337203685477580ull)
+                       return TDS_FAIL;
+               num = num * 10u + (*p-'0');
+       }
+
+       /* check for overflow and convert unsigned to signed */
+       if (sign) {
+               if (num > 9223372036854775808ull)
+                       return TDS_FAIL;
+               *res = 0 - num;
+       } else {
+               if (num >= 9223372036854775808ull)
+                       return TDS_FAIL;
+               *res = num;
+       }

        return TDS_SUCCEED;
 }
diff -r -u freetds/src/tds/tds_willconvert.h
freetds-jb/src/tds/tds_willconvert.h
--- freetds/src/tds/tds_willconvert.h   Thu Aug 15 23:58:04 2002
+++ freetds-jb/src/tds/tds_willconvert.h        Tue Oct  8 23:55:09 2002
@@ -13,6 +13,7 @@
        , { SYBVARCHAR, SYBINT1         , 1 }
        , { SYBVARCHAR, SYBINT2         , 1 }
        , { SYBVARCHAR, SYBINT4         , 1 }
+       , { SYBVARCHAR, SYBINT8         , 1 }
        , { SYBVARCHAR, SYBFLT8         , 1 }
        , { SYBVARCHAR, SYBREAL         , 1 }
        , { SYBVARCHAR, SYBNUMERIC      , 1 }
@@ -30,6 +31,7 @@
        , { SYBCHAR, SYBINT1            , 1 }
        , { SYBCHAR, SYBINT2            , 1 }
        , { SYBCHAR, SYBINT4            , 1 }
+       , { SYBCHAR, SYBINT8            , 1 }
        , { SYBCHAR, SYBFLT8            , 1 }
        , { SYBCHAR, SYBREAL            , 1 }
        , { SYBCHAR, SYBNUMERIC         , 1 }
@@ -47,6 +49,7 @@
        , { SYBTEXT, SYBINT1            , 1 }
        , { SYBTEXT, SYBINT2            , 1 }
        , { SYBTEXT, SYBINT4            , 1 }
+       , { SYBTEXT, SYBINT8            , 1 }
        , { SYBTEXT, SYBFLT8            , 1 }
        , { SYBTEXT, SYBREAL            , 1 }
        , { SYBTEXT, SYBNUMERIC         , 1 }
@@ -64,6 +67,7 @@
        , { SYBBINARY, SYBINT1          , 1 }
        , { SYBBINARY, SYBINT2          , 1 }
        , { SYBBINARY, SYBINT4          , 1 }
+       , { SYBBINARY, SYBINT8          , 1 }
        , { SYBBINARY, SYBFLT8          , 1 }
        , { SYBBINARY, SYBREAL          , 1 }
        , { SYBBINARY, SYBNUMERIC       , 1 }
@@ -81,6 +85,7 @@
        , { SYBIMAGE, SYBINT1           , 1 }
        , { SYBIMAGE, SYBINT2           , 1 }
        , { SYBIMAGE, SYBINT4           , 1 }
+       , { SYBIMAGE, SYBINT8           , 1 }
        , { SYBIMAGE, SYBFLT8           , 1 }
        , { SYBIMAGE, SYBREAL           , 1 }
        , { SYBIMAGE, SYBNUMERIC        , 1 }
@@ -98,6 +103,7 @@
        , { SYBINT1, SYBINT1            , 1 }
        , { SYBINT1, SYBINT2            , 1 }
        , { SYBINT1, SYBINT4            , 1 }
+       , { SYBINT1, SYBINT8            , 1 }
        , { SYBINT1, SYBFLT8            , 1 }
        , { SYBINT1, SYBREAL            , 1 }
        , { SYBINT1, SYBNUMERIC         , 1 }
@@ -115,6 +121,7 @@
        , { SYBINT2, SYBINT1            , 1 }
        , { SYBINT2, SYBINT2            , 1 }
        , { SYBINT2, SYBINT4            , 1 }
+       , { SYBINT2, SYBINT8            , 1 }
        , { SYBINT2, SYBFLT8            , 1 }
        , { SYBINT2, SYBREAL            , 1 }
        , { SYBINT2, SYBNUMERIC         , 1 }
@@ -132,6 +139,7 @@
        , { SYBINT4, SYBINT1            , 1 }
        , { SYBINT4, SYBINT2            , 1 }
        , { SYBINT4, SYBINT4            , 1 }
+       , { SYBINT4, SYBINT8            , 1 }
        , { SYBINT4, SYBFLT8            , 1 }
        , { SYBINT4, SYBREAL            , 1 }
        , { SYBINT4, SYBNUMERIC         , 1 }
@@ -141,6 +149,24 @@
        , { SYBINT4, SYBMONEY4          , 1 }
        , { SYBINT4, SYBDATETIME        , 0 }
        , { SYBINT4, SYBDATETIME4       , 0 }
+       , { SYBINT8, SYBVARCHAR         , 1 }
+       , { SYBINT8, SYBCHAR            , 1 }
+       , { SYBINT8, SYBTEXT            , 1 }
+       , { SYBINT8, SYBBINARY          , 1 }
+       , { SYBINT8, SYBIMAGE           , 1 }
+       , { SYBINT8, SYBINT1            , 1 }
+       , { SYBINT8, SYBINT2            , 1 }
+       , { SYBINT8, SYBINT4            , 1 }
+       , { SYBINT8, SYBINT8            , 1 }
+       , { SYBINT8, SYBFLT8            , 1 }
+       , { SYBINT8, SYBREAL            , 1 }
+       , { SYBINT8, SYBNUMERIC         , 1 }
+       , { SYBINT8, SYBDECIMAL         , 1 }
+       , { SYBINT8, SYBBIT             , 1 }
+       , { SYBINT8, SYBMONEY           , 1 }
+       , { SYBINT8, SYBMONEY4          , 1 }
+       , { SYBINT8, SYBDATETIME        , 0 }
+       , { SYBINT8, SYBDATETIME4       , 0 }
        , { SYBFLT8, SYBVARCHAR         , 1 }
        , { SYBFLT8, SYBCHAR            , 1 }
        , { SYBFLT8, SYBTEXT            , 1 }
@@ -149,6 +175,7 @@
        , { SYBFLT8, SYBINT1            , 1 }
        , { SYBFLT8, SYBINT2            , 1 }
        , { SYBFLT8, SYBINT4            , 1 }
+       , { SYBFLT8, SYBINT8            , 1 }
        , { SYBFLT8, SYBFLT8            , 1 }
        , { SYBFLT8, SYBREAL            , 1 }
        , { SYBFLT8, SYBNUMERIC         , 1 }
@@ -166,6 +193,7 @@
        , { SYBREAL, SYBINT1            , 1 }
        , { SYBREAL, SYBINT2            , 1 }
        , { SYBREAL, SYBINT4            , 1 }
+       , { SYBREAL, SYBINT8            , 1 }
        , { SYBREAL, SYBFLT8            , 1 }
        , { SYBREAL, SYBREAL            , 1 }
        , { SYBREAL, SYBNUMERIC         , 1 }
@@ -183,6 +211,7 @@
        , { SYBNUMERIC, SYBINT1         , 1 }
        , { SYBNUMERIC, SYBINT2         , 1 }
        , { SYBNUMERIC, SYBINT4         , 1 }
+       , { SYBNUMERIC, SYBINT8         , 1 }
        , { SYBNUMERIC, SYBFLT8         , 1 }
        , { SYBNUMERIC, SYBREAL         , 1 }
        , { SYBNUMERIC, SYBNUMERIC      , 1 }
@@ -200,6 +229,7 @@
        , { SYBDECIMAL, SYBINT1         , 1 }
        , { SYBDECIMAL, SYBINT2         , 1 }
        , { SYBDECIMAL, SYBINT4         , 1 }
+       , { SYBDECIMAL, SYBINT8         , 1 }
        , { SYBDECIMAL, SYBFLT8         , 1 }
        , { SYBDECIMAL, SYBREAL         , 1 }
        , { SYBDECIMAL, SYBNUMERIC      , 1 }
@@ -217,6 +247,7 @@
        , { SYBBIT, SYBINT1             , 1 }
        , { SYBBIT, SYBINT2             , 1 }
        , { SYBBIT, SYBINT4             , 1 }
+       , { SYBBIT, SYBINT8             , 1 }
        , { SYBBIT, SYBFLT8             , 1 }
        , { SYBBIT, SYBREAL             , 1 }
        , { SYBBIT, SYBNUMERIC          , 1 }
@@ -234,6 +265,7 @@
        , { SYBMONEY, SYBINT1           , 1 }
        , { SYBMONEY, SYBINT2           , 1 }
        , { SYBMONEY, SYBINT4           , 1 }
+       , { SYBMONEY, SYBINT8           , 1 }
        , { SYBMONEY, SYBFLT8           , 1 }
        , { SYBMONEY, SYBREAL           , 1 }
        , { SYBMONEY, SYBNUMERIC        , 1 }
@@ -251,6 +283,7 @@
        , { SYBMONEY4, SYBINT1          , 1 }
        , { SYBMONEY4, SYBINT2          , 1 }
        , { SYBMONEY4, SYBINT4          , 1 }
+       , { SYBMONEY4, SYBINT8          , 1 }
        , { SYBMONEY4, SYBFLT8          , 1 }
        , { SYBMONEY4, SYBREAL          , 1 }
        , { SYBMONEY4, SYBNUMERIC       , 1 }
@@ -268,6 +301,7 @@
        , { SYBDATETIME, SYBINT1        , 0 }
        , { SYBDATETIME, SYBINT2        , 0 }
        , { SYBDATETIME, SYBINT4        , 0 }
+       , { SYBDATETIME, SYBINT8        , 0 }
        , { SYBDATETIME, SYBFLT8        , 0 }
        , { SYBDATETIME, SYBREAL        , 0 }
        , { SYBDATETIME, SYBNUMERIC     , 0 }
@@ -285,6 +319,7 @@
        , { SYBDATETIME4, SYBINT1       , 0 }
        , { SYBDATETIME4, SYBINT2       , 0 }
        , { SYBDATETIME4, SYBINT4       , 0 }
+       , { SYBDATETIME4, SYBINT8       , 0 }
        , { SYBDATETIME4, SYBFLT8       , 0 }
        , { SYBDATETIME4, SYBREAL       , 0 }
        , { SYBDATETIME4, SYBNUMERIC    , 0 }



More information about the FreeTDS mailing list