LCOV - code coverage report
Current view: top level - include/freetds - tds.h (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 6 8 75.0 %
Date: 2026-11-07 23:58:45 Functions: 0 0 -

          Line data    Source code
       1             : /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
       2             :  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005  Brian Bruns
       3             :  * Copyright (C) 2010, 2011  Frediano Ziglio
       4             :  *
       5             :  * This library is free software; you can redistribute it and/or
       6             :  * modify it under the terms of the GNU Library General Public
       7             :  * License as published by the Free Software Foundation; either
       8             :  * version 2 of the License, or (at your option) any later version.
       9             :  *
      10             :  * This library is distributed in the hope that it will be useful,
      11             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      12             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13             :  * Library General Public License for more details.
      14             :  *
      15             :  * You should have received a copy of the GNU Library General Public
      16             :  * License along with this library; if not, write to the
      17             :  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      18             :  * Boston, MA 02111-1307, USA.
      19             :  */
      20             : 
      21             : #ifndef _tdsguard_hfOrWb5znoUCWdBPoNQvqN_
      22             : #define _tdsguard_hfOrWb5znoUCWdBPoNQvqN_
      23             : 
      24             : #ifndef _freetds_config_h_
      25             : #error should include config.h before
      26             : #endif
      27             : 
      28             : #include <stdarg.h>
      29             : #include <stdio.h>
      30             : #include <time.h>
      31             : 
      32             : #ifdef HAVE_STDDEF_H
      33             : #include <stddef.h>
      34             : #endif
      35             : 
      36             : #if HAVE_NETDB_H
      37             : #include <netdb.h>
      38             : #endif /* HAVE_NETDB_H */
      39             : 
      40             : #if HAVE_NETINET_IN_H
      41             : #include <netinet/in.h>
      42             : #endif /* HAVE_NET_INET_IN_H */
      43             : #if HAVE_ARPA_INET_H
      44             : #include <arpa/inet.h>
      45             : #endif /* HAVE_ARPA_INET_H */
      46             : 
      47             : #if HAVE_SYS_SOCKET_H
      48             : #include <sys/socket.h>
      49             : #endif /* HAVE_SYS_SOCKET_H */
      50             : 
      51             : /* forward declaration */
      52             : typedef struct tdsiconvinfo TDSICONV;
      53             : typedef struct tds_connection TDSCONNECTION;
      54             : typedef struct tds_socket TDSSOCKET;
      55             : typedef struct tds_column TDSCOLUMN;
      56             : typedef struct tds_bcpinfo TDSBCPINFO;
      57             : typedef struct tds_result_info TDSRESULTINFO;
      58             : 
      59             : #include <freetds/version.h>
      60             : #include <freetds/sysdep_private.h>
      61             : #include <freetds/thread.h>
      62             : #include <freetds/bool.h>
      63             : #include <freetds/macros.h>
      64             : #include <freetds/utils/string.h>
      65             : #include <freetds/utils/path.h>
      66             : #include <freetds/replacements.h>
      67             : 
      68             : #include <freetds/pushvis.h>
      69             : 
      70             : #ifdef __cplusplus
      71             : extern "C"
      72             : {
      73             : #if 0
      74             : }
      75             : #endif
      76             : #endif
      77             : 
      78             : /**
      79             :  * A structure to hold all the compile-time settings.
      80             :  * This structure is returned by tds_get_compiletime_settings
      81             :  */
      82             : 
      83             : typedef struct tds_compiletime_settings
      84             : {
      85             :         const char *freetds_version;    /* release version of FreeTDS */
      86             :         const tds_dir_char *sysconfdir;         /* location of freetds.conf */
      87             :         const char *last_update;        /* latest software_version date among the modules */
      88             :         const char *tdsver;     /* TDS protocol version (4.2/4.6/5.0/7.0/7.1/8.0) 5.0 */
      89             :         bool msdblib;           /* for MS style dblib */
      90             :         bool sybase_compat;     /* enable increased Open Client binary compatibility */
      91             :         bool threadsafe;                /* compile for thread safety default=no */
      92             :         bool libiconv;          /* search for libiconv in DIR/include and DIR/lib */
      93             :         bool iodbc;             /* build odbc driver against iODBC in DIR */
      94             :         bool unixodbc;          /* build odbc driver against unixODBC in DIR */
      95             :         bool openssl;           /* build against OpenSSL */
      96             :         bool gnutls;            /* build against GnuTLS */
      97             :         bool mars;              /* MARS enabled */
      98             :         bool sspi;              /* SSPI enabled */
      99             :         bool kerberos;          /* Kerberos enabled */
     100             : } TDS_COMPILETIME_SETTINGS;
     101             : 
     102             : /**
     103             :  * @file tds.h
     104             :  * Main include file for libtds
     105             :  */
     106             : 
     107             : /**
     108             :  * \defgroup libtds LibTDS API
     109             :  * Callable functions in \c libtds.
     110             :  * 
     111             :  * The \c libtds library is for use internal to \em FreeTDS.  It is not
     112             :  * intended for use by applications.  Although any use is \em permitted, you're
     113             :  * encouraged to use one of the established public APIs instead, because their
     114             :  * interfaces are stable and documented by the vendors.  
     115             :  */
     116             : 
     117             : /* 
     118             :  * All references to data that touch the wire should use the following typedefs.  
     119             :  *
     120             :  * If you have problems on 64-bit machines and the code is 
     121             :  * using a native datatype, please change it to use
     122             :  * these. (In the TDS layer only, the API layers have their
     123             :  * own typedefs which equate to these).
     124             :  */
     125             : typedef char TDS_CHAR;                          /*  8-bit char     */
     126             : typedef uint8_t TDS_UCHAR;                      /*  8-bit uchar    */
     127             : typedef uint8_t  TDS_TINYINT;                   /*  8-bit unsigned */
     128             : typedef int16_t  TDS_SMALLINT;                  /* 16-bit int      */
     129             : typedef uint16_t TDS_USMALLINT;                 /* 16-bit unsigned */
     130             : typedef int32_t TDS_INT;                        /* 32-bit int      */
     131             : typedef uint32_t TDS_UINT;                      /* 32-bit unsigned */
     132             : typedef int64_t TDS_INT8;                       /* 64-bit integer  */
     133             : typedef uint64_t TDS_UINT8;                     /* 64-bit unsigned */
     134             : typedef tds_sysdep_real32_type TDS_REAL;        /* 32-bit real     */
     135             : typedef tds_sysdep_real64_type TDS_FLOAT;       /* 64-bit real     */
     136             : 
     137             : #include <freetds/proto.h>
     138             : 
     139             : #define TDS_INVALID_TYPE ((TDS_SERVER_TYPE) 0)
     140             : 
     141             : /**
     142             :  * This structure is not directly connected to TDS protocol but
     143             :  * keeps any DATE/TIME information.
     144             :  */
     145             : typedef struct
     146             : {
     147             :         TDS_UINT8   time;       /**< time, 7 digit precision */
     148             :         TDS_INT      date;      /**< date, 0 = 1900-01-01 */
     149             :         TDS_SMALLINT offset;    /**< time offset */
     150             :         TDS_USMALLINT time_prec:3;
     151             :         TDS_USMALLINT _tds_reserved:10;
     152             :         TDS_USMALLINT has_time:1;
     153             :         TDS_USMALLINT has_date:1;
     154             :         TDS_USMALLINT has_offset:1;
     155             : } TDS_DATETIMEALL;
     156             : 
     157             : /** Used by tds_datecrack */
     158             : typedef struct tdsdaterec
     159             : {
     160             :         TDS_INT year;          /**< year */
     161             :         TDS_INT quarter;       /**< quarter (0-3) */
     162             :         TDS_INT month;         /**< month number (0-11) */
     163             :         TDS_INT day;           /**< day of month (1-31) */
     164             :         TDS_INT dayofyear;     /**< day of year  (1-366) */
     165             :         TDS_INT weekday;       /**< day of week  (0-6, 0 = sunday) */
     166             :         TDS_INT hour;          /**< 0-23 */
     167             :         TDS_INT minute;        /**< 0-59 */
     168             :         TDS_INT second;        /**< 0-59 */
     169             :         TDS_INT decimicrosecond;   /**< 0-9999999 */
     170             :         TDS_INT timezone;      /**< -840 - 840 minutes from UTC */
     171             : } TDSDATEREC;
     172             : 
     173             : /**
     174             :  * The following little table is indexed by precision and will
     175             :  * tell us the number of bytes required to store the specified
     176             :  * precision.
     177             :  */
     178             : extern const uint8_t tds_numeric_bytes_per_prec[];
     179             : 
     180             : typedef int TDSRET;
     181             : #define TDS_NO_MORE_RESULTS  ((TDSRET)1)
     182             : #define TDS_SUCCESS          ((TDSRET)0)
     183             : #define TDS_FAIL             ((TDSRET)-1)
     184             : #define TDS_CANCELLED        ((TDSRET)-2)
     185             : #define TDS_FAILED(rc) ((rc)<0)
     186             : #define TDS_SUCCEED(rc) ((rc)>=0)
     187             : #define TDS_PROPAGATE(rc) \
     188             :         do { TDSRET _tds_ret = (rc); if (TDS_FAILED(_tds_ret)) return _tds_ret; } while(0)
     189             : 
     190             : #define TDS_INT_CONTINUE 1
     191             : #define TDS_INT_CANCEL 2
     192             : #define TDS_INT_TIMEOUT 3
     193             : 
     194             : 
     195             : #define TDS_NO_COUNT         -1
     196             : 
     197             : #define TDS_ROW_RESULT        4040
     198             : #define TDS_PARAM_RESULT      4042
     199             : #define TDS_STATUS_RESULT     4043
     200             : #define TDS_MSG_RESULT        4044
     201             : #define TDS_COMPUTE_RESULT    4045
     202             : #define TDS_CMD_DONE          4046
     203             : #define TDS_CMD_SUCCEED       4047
     204             : #define TDS_CMD_FAIL          4048
     205             : #define TDS_ROWFMT_RESULT     4049
     206             : #define TDS_COMPUTEFMT_RESULT 4050
     207             : #define TDS_DESCRIBE_RESULT   4051
     208             : #define TDS_DONE_RESULT       4052
     209             : #define TDS_DONEPROC_RESULT   4053
     210             : #define TDS_DONEINPROC_RESULT 4054
     211             : #define TDS_OTHERS_RESULT     4055
     212             : 
     213             : enum tds_token_results
     214             : {
     215             :         TDS_TOKEN_RES_OTHERS,
     216             :         TDS_TOKEN_RES_ROWFMT,
     217             :         TDS_TOKEN_RES_COMPUTEFMT,
     218             :         TDS_TOKEN_RES_PARAMFMT,
     219             :         TDS_TOKEN_RES_DONE,
     220             :         TDS_TOKEN_RES_ROW,
     221             :         TDS_TOKEN_RES_COMPUTE,
     222             :         TDS_TOKEN_RES_PROC,
     223             :         TDS_TOKEN_RES_MSG,
     224             :         TDS_TOKEN_RES_ENV,
     225             : };
     226             : 
     227             : #define TDS_TOKEN_FLAG(flag) TDS_RETURN_##flag = (1 << (TDS_TOKEN_RES_##flag*2)), TDS_STOPAT_##flag = (2 << (TDS_TOKEN_RES_##flag*2))
     228             : 
     229             : enum tds_token_flags
     230             : {
     231             :         TDS_HANDLE_ALL = 0,
     232             :         TDS_TOKEN_FLAG(OTHERS),
     233             :         TDS_TOKEN_FLAG(ROWFMT),
     234             :         TDS_TOKEN_FLAG(COMPUTEFMT),
     235             :         TDS_TOKEN_FLAG(PARAMFMT),
     236             :         TDS_TOKEN_FLAG(DONE),
     237             :         TDS_TOKEN_FLAG(ROW),
     238             :         TDS_TOKEN_FLAG(COMPUTE),
     239             :         TDS_TOKEN_FLAG(PROC),
     240             :         TDS_TOKEN_FLAG(MSG),
     241             :         TDS_TOKEN_FLAG(ENV),
     242             :         TDS_TOKEN_RESULTS = TDS_RETURN_ROWFMT|TDS_RETURN_COMPUTEFMT|TDS_RETURN_DONE|TDS_STOPAT_ROW|TDS_STOPAT_COMPUTE|TDS_RETURN_PROC,
     243             :         TDS_TOKEN_TRAILING = TDS_STOPAT_ROWFMT|TDS_STOPAT_COMPUTEFMT|TDS_STOPAT_ROW|TDS_STOPAT_COMPUTE|TDS_STOPAT_MSG|TDS_STOPAT_OTHERS
     244             : };
     245             : 
     246             : /*
     247             :  * TDSERRNO is emitted by libtds to the client library's error handler
     248             :  * (which may in turn call the client's error handler).
     249             :  * These match the db-lib msgno, because the same values have the same meaning
     250             :  * in db-lib and ODBC.  ct-lib maps them to ct-lib numbers (todo). 
     251             :  */
     252             : typedef enum {  TDSEOK    = TDS_SUCCESS, 
     253             :                 TDSEVERDOWN    =  100,
     254             :                 TDSEINPROGRESS,
     255             :                 TDSEICONVIU    = 2400, 
     256             :                 TDSEICONVAVAIL = 2401, 
     257             :                 TDSEICONVO     = 2402, 
     258             :                 TDSEICONVI     = 2403, 
     259             :                 TDSEICONV2BIG  = 2404,
     260             :                 TDSEICONVPARTIAL = 2433,
     261             :                 TDSEPORTINSTANCE        = 2500,
     262             :                 TDSESYNC = 20001, 
     263             :                 TDSEFCON = 20002, 
     264             :                 TDSETIME = 20003, 
     265             :                 TDSEREAD = 20004, 
     266             :                 TDSEWRIT = 20006, 
     267             :                 TDSESOCK = 20008, 
     268             :                 TDSECONN = 20009, 
     269             :                 TDSEMEM  = 20010,
     270             :                 TDSEINTF = 20012,       /* Server name not found in interface file */
     271             :                 TDSEUHST = 20013,       /* Unknown host machine name. */
     272             :                 TDSEPWD  = 20014, 
     273             :                 TDSESEOF = 20017, 
     274             :                 TDSERPND = 20019, 
     275             :                 TDSEBTOK = 20020, 
     276             :                 TDSEOOB  = 20022, 
     277             :                 TDSECLOS = 20056,
     278             :                 TDSEUSCT = 20058, 
     279             :                 TDSEUTDS = 20146, 
     280             :                 TDSEEUNR = 20185, 
     281             :                 TDSECAP  = 20203, 
     282             :                 TDSENEG  = 20210, 
     283             :                 TDSEUMSG = 20212, 
     284             :                 TDSECAPTYP  = 20213, 
     285             :                 TDSECONF = 20214,
     286             :                 TDSEBPROBADTYP = 20250,
     287             :                 TDSECLOSEIN = 20292 
     288             : } TDSERRNO;
     289             : 
     290             : 
     291             : enum {
     292             :         TDS_CUR_ISTAT_UNUSED    = 0x00,
     293             :         TDS_CUR_ISTAT_DECLARED  = 0x01,
     294             :         TDS_CUR_ISTAT_OPEN      = 0x02,
     295             :         TDS_CUR_ISTAT_CLOSED    = 0x04,
     296             :         TDS_CUR_ISTAT_RDONLY    = 0x08,
     297             :         TDS_CUR_ISTAT_UPDATABLE = 0x10,
     298             :         TDS_CUR_ISTAT_ROWCNT    = 0x20,
     299             :         TDS_CUR_ISTAT_DEALLOC   = 0x40
     300             : };
     301             : 
     302             : /* string types */
     303             : #define TDS_NULLTERM -9
     304             : 
     305             : 
     306             : typedef union tds_option_arg
     307             : {
     308             :         TDS_TINYINT ti;
     309             :         TDS_INT i;
     310             :         TDS_CHAR *c;
     311             : } TDS_OPTION_ARG;
     312             : 
     313             : 
     314             : typedef enum tds_encryption_level {
     315             :         TDS_ENCRYPTION_DEFAULT,
     316             :         TDS_ENCRYPTION_OFF,
     317             :         TDS_ENCRYPTION_REQUEST,
     318             :         TDS_ENCRYPTION_REQUIRE,
     319             :         TDS_ENCRYPTION_STRICT
     320             : } TDS_ENCRYPTION_LEVEL;
     321             : 
     322             : /*
     323             :  * TODO use system macros for optimization
     324             :  * See mcrypt for reference and linux kernel source for optimization
     325             :  * check if unaligned access and use fast write/read when implemented
     326             :  */
     327             : #define TDS_BYTE_SWAP16(value)                 \
     328             :          (((((uint16_t)value)<<8) & 0xFF00u) | \
     329             :           ((((uint16_t)value)>>8) & 0x00FFu))
     330             : 
     331             : #define TDS_BYTE_SWAP32(value)                     \
     332             :          (((((uint32_t)value)<<24) & 0xFF000000u)| \
     333             :           ((((uint32_t)value)<< 8) & 0x00FF0000u)| \
     334             :           ((((uint32_t)value)>> 8) & 0x0000FF00u)| \
     335             :           ((((uint32_t)value)>>24) & 0x000000FFu))
     336             : 
     337             : #define is_end_token(x) ((x) >= TDS_DONE_TOKEN && (x) <= TDS_DONEINPROC_TOKEN)
     338             : 
     339             : enum {
     340             :         TDS_TYPEFLAG_INVALID  = 0,
     341             :         TDS_TYPEFLAG_NULLABLE = 1,
     342             :         TDS_TYPEFLAG_FIXED    = 2,
     343             :         TDS_TYPEFLAG_VARIABLE = 4,
     344             :         TDS_TYPEFLAG_COLLATE  = 8,
     345             :         TDS_TYPEFLAG_ASCII    = 16,
     346             :         TDS_TYPEFLAG_UNICODE  = 32,
     347             :         TDS_TYPEFLAG_BINARY   = 64,
     348             :         TDS_TYPEFLAG_DATETIME = 128,
     349             :         TDS_TYPEFLAG_NUMERIC  = 256,
     350             :         TDS_TYPEFLAG_VARIANT  = 512,
     351             :         TDS_TYPEFLAG_TEXTPTR  = 1024,
     352             : };
     353             : 
     354             : extern const uint16_t tds_type_flags_ms[256];
     355             : #if 0
     356             : extern const uint16_t tds_type_flags_syb[256];
     357             : extern const char *const tds_type_names[256];
     358             : #endif
     359             : 
     360             : #define is_fixed_type(x)      ((tds_type_flags_ms[x] & TDS_TYPEFLAG_FIXED)    != 0)
     361             : #define is_nullable_type(x)   ((tds_type_flags_ms[x] & TDS_TYPEFLAG_NULLABLE) != 0)
     362             : #define is_variable_type(x)   ((tds_type_flags_ms[x] & TDS_TYPEFLAG_VARIABLE) != 0)
     363             : #define is_variant_inner_type(x)   ((tds_type_flags_ms[x] & TDS_TYPEFLAG_VARIANT) != 0)
     364             : 
     365             : 
     366             : #define type_has_textptr(x)   ((tds_type_flags_ms[(x)&255] & TDS_TYPEFLAG_TEXTPTR) != 0)
     367             : #define is_blob_col(x)        ((x)->column_varint_size > 2)
     368             : /* large type means it has a two byte size field */
     369             : /* define is_large_type(x) (x>128) */
     370             : #define is_numeric_type(x)    ((x)==SYBNUMERIC || (x)==SYBDECIMAL)
     371             : /** return true if type is a datetime (but not date or time) */
     372             : #define is_datetime_type(x)   ((tds_type_flags_ms[x] & TDS_TYPEFLAG_DATETIME) != 0)
     373             : #define is_unicode_type(x)    ((tds_type_flags_ms[x] & TDS_TYPEFLAG_UNICODE) != 0)
     374             : #define is_collate_type(x)    ((tds_type_flags_ms[x] & TDS_TYPEFLAG_COLLATE) != 0)
     375             : #define is_ascii_type(x)      ((tds_type_flags_ms[x] & TDS_TYPEFLAG_ASCII) != 0)
     376             : #define is_binary_type(x)     ((tds_type_flags_ms[x] & TDS_TYPEFLAG_BINARY) != 0)
     377             : #define is_char_type(x)       ((tds_type_flags_ms[x] & (TDS_TYPEFLAG_ASCII|TDS_TYPEFLAG_UNICODE)) != 0)
     378             : #define is_similar_type(x, y) (is_char_type(x) && is_char_type(y))
     379             : static inline bool
     380             : is_tds_type_valid(int type)
     381             : {
     382       94401 :         return (unsigned) type < 256u && tds_type_flags_ms[type] != 0;
     383             : }
     384             : 
     385             : 
     386             : #define TDS_MAX_CAPABILITY      32
     387             : #define MAXPRECISION            77
     388             : #define TDS_MAX_CONN            4096
     389             : #define TDS_MAX_DYNID_LEN       30
     390             : 
     391             : /* defaults to use if no others are found */
     392             : #define TDS_DEF_SERVER          "SYBASE"
     393             : #define TDS_DEF_BLKSZ           512
     394             : #define TDS_DEF_CHARSET         "iso_1"
     395             : #define TDS_DEF_LANG            "us_english"
     396             : #if TDS50
     397             : #define TDS_DEFAULT_VERSION     0x500
     398             : #define TDS_DEF_PORT            4000
     399             : #elif TDS71
     400             : #define TDS_DEFAULT_VERSION     0x701
     401             : #define TDS_DEF_PORT            1433
     402             : #elif TDS72
     403             : #define TDS_DEFAULT_VERSION     0x702
     404             : #define TDS_DEF_PORT            1433
     405             : #elif TDS73
     406             : #define TDS_DEFAULT_VERSION     0x703
     407             : #define TDS_DEF_PORT            1433
     408             : #elif TDS74
     409             : #define TDS_DEFAULT_VERSION     0x704
     410             : #define TDS_DEF_PORT            1433
     411             : #else
     412             : #define TDS_DEFAULT_VERSION     0x000
     413             : #define TDS_DEF_PORT            1433
     414             : #endif
     415             : 
     416             : /* normalized strings from freetds.conf file */
     417             : #define TDS_STR_VERSION  "tds version"
     418             : #define TDS_STR_BLKSZ    "initial block size"
     419             : #define TDS_STR_SWAPDT   "swap broken dates"
     420             : #define TDS_STR_DUMPFILE "dump file"
     421             : #define TDS_STR_DEBUGLVL "debug level"
     422             : #define TDS_STR_DEBUGFLAGS "debug flags"
     423             : #define TDS_STR_TIMEOUT  "timeout"
     424             : #define TDS_STR_QUERY_TIMEOUT  "query timeout"
     425             : #define TDS_STR_CONNTIMEOUT "connect timeout"
     426             : #define TDS_STR_HOSTNAME "hostname"
     427             : #define TDS_STR_HOST     "host"
     428             : #define TDS_STR_PORT     "port"
     429             : #define TDS_STR_TEXTSZ   "text size"
     430             : /* for big endian hosts, obsolete, ignored */
     431             : #define TDS_STR_EMUL_LE "emulate little endian"
     432             : #define TDS_STR_CHARSET "charset"
     433             : #define TDS_STR_CLCHARSET       "client charset"
     434             : #define TDS_STR_USE_UTF_16      "use utf-16"
     435             : #define TDS_STR_LANGUAGE        "language"
     436             : #define TDS_STR_APPENDMODE      "dump file append"
     437             : #define TDS_STR_DATETIMEFMT     "date format"
     438             : #define TDS_STR_DATEFMT "date-only format"
     439             : #define TDS_STR_TIMEFMT "time-only format"
     440             : #define TDS_STR_INSTANCE "instance"
     441             : #define TDS_STR_ASA_DATABASE    "asa database"
     442             : #define TDS_STR_DATABASE        "database"
     443             : #define TDS_STR_ENCRYPTION       "encryption"
     444             : #define TDS_STR_USENTLMV2       "use ntlmv2"
     445             : #define TDS_STR_USELANMAN       "use lanman"
     446             : /* conf values */
     447             : #define TDS_STR_ENCRYPTION_OFF   "off"
     448             : #define TDS_STR_ENCRYPTION_REQUEST "request"
     449             : #define TDS_STR_ENCRYPTION_REQUIRE "require"
     450             : #define TDS_STR_ENCRYPTION_STRICT "strict"
     451             : /* Defines to enable optional GSSAPI delegation */
     452             : #define TDS_GSSAPI_DELEGATION "enable gssapi delegation"
     453             : /* Mutual authentication */
     454             : #define TDS_STR_MUTUAL_AUTHENTICATION "mutual authentication"
     455             : /* Kerberos realm name */
     456             : #define TDS_STR_REALM   "realm"
     457             : /* Kerberos SPN */
     458             : #define TDS_STR_SPN     "spn"
     459             : /* CA file */
     460             : #define TDS_STR_CAFILE  "ca file"
     461             : /* CRL file */
     462             : #define TDS_STR_CRLFILE "crl file"
     463             : /* check SSL hostname */
     464             : #define TDS_STR_CHECKSSLHOSTNAME        "check certificate hostname"
     465             : /* SSL hostname to check certificate */
     466             : #define TDS_STR_SSLHOSTNAME     "certificate hostname"
     467             : /* database filename to attach on login (MSSQL) */
     468             : #define TDS_STR_DBFILENAME      "database filename"
     469             : /* Application Intent MSSQL 2012 support */
     470             : #define TDS_STR_READONLY_INTENT "read-only intent"
     471             : /* configurable cipher suite to send to openssl's SSL_set_cipher_list() function */
     472             : #define TLS_STR_OPENSSL_CIPHERS "openssl ciphers"
     473             : /* configurable cipher suite to send to gnutls's gnutls_priority_set_direct() function */
     474             : #define TLS_STR_GNUTLS_CIPHERS "gnutls ciphers"
     475             : /* enable old TLS v1, required for instance if you are using a really old Windows XP */
     476             : #define TDS_STR_ENABLE_TLS_V1 "enable tls v1"
     477             : /* enable old TLS v1.1 */
     478             : #define TDS_STR_ENABLE_TLS_V1_1 "enable tls v1.1"
     479             : 
     480             : 
     481             : /* TODO do a better check for alignment than this */
     482             : typedef union
     483             : {
     484             :         void *p;
     485             :         int i;
     486             :         int64_t ui;
     487             : } tds_align_struct;
     488             : 
     489             : #define TDS_ALIGN_SIZE sizeof(tds_align_struct)
     490             : 
     491             : typedef struct tds_capability_type
     492             : {
     493             :         unsigned char type;
     494             :         unsigned char len; /* always sizeof(values) */
     495             :         unsigned char values[TDS_MAX_CAPABILITY/2-2];
     496             : } TDS_CAPABILITY_TYPE;
     497             : 
     498             : typedef struct tds_capabilities
     499             : {
     500             :         TDS_CAPABILITY_TYPE types[2];
     501             : } TDS_CAPABILITIES;
     502             : 
     503             : #define TDS_MAX_LOGIN_STR_SZ 128
     504             : typedef struct tds_login
     505             : {
     506             :         DSTR server_name;               /**< server name (in freetds.conf) */
     507             :         int port;                       /**< port of database service */
     508             :         TDS_USMALLINT tds_version;      /**< TDS version */
     509             :         int block_size;
     510             :         DSTR language;                  /* e.g. us-english */
     511             :         DSTR server_charset;            /**< charset of server e.g. iso_1 */
     512             :         TDS_INT connect_timeout;
     513             :         DSTR client_host_name;
     514             :         DSTR server_host_name;
     515             :         DSTR server_realm_name;         /**< server realm name (in freetds.conf) */
     516             :         DSTR server_spn;                /**< server SPN (in freetds.conf) */
     517             :         DSTR db_filename;               /**< database filename to attach (MSSQL) */
     518             :         DSTR cafile;                    /**< certificate authorities file */
     519             :         DSTR crlfile;                   /**< certificate revocation file */
     520             :         DSTR certificate_host_name;     /**< certificate hostname to check, if empty use server_host_name */
     521             :         DSTR openssl_ciphers;
     522             :         DSTR gnutls_ciphers;            /**< gnutls ciphers to use */
     523             :         DSTR app_name;
     524             :         DSTR user_name;         /**< account for login */
     525             :         DSTR password;          /**< password of account login */
     526             :         DSTR new_password;              /**< new password to set (TDS 7.2+) */
     527             : 
     528             :         DSTR library;   /* Ct-Library, DB-Library,  TDS-Library or ODBC */
     529             :         TDS_TINYINT encryption_level;
     530             : 
     531             :         TDS_INT query_timeout;
     532             :         TDS_CAPABILITIES capabilities;
     533             :         DSTR client_charset;
     534             :         DSTR database;
     535             : 
     536             :         struct addrinfo *ip_addrs;                      /**< ip(s) of server */
     537             :         DSTR instance_name;
     538             :         tds_dir_char *dump_file;
     539             :         int debug_flags;
     540             :         int text_size;
     541             :         DSTR routing_address;
     542             :         uint16_t routing_port;
     543             : 
     544             :         unsigned char option_flag2;
     545             : 
     546             :         uint8_t bulk_copy:1;    /**< if bulk copy should be enabled */
     547             :         uint8_t suppress_language:1;
     548             :         uint8_t gssapi_use_delegation:1;
     549             :         uint8_t mutual_authentication:1;
     550             :         uint8_t use_ntlmv2:1;
     551             :         uint8_t use_ntlmv2_specified:1;
     552             :         uint8_t use_lanman:1;
     553             :         uint8_t mars:1;
     554             :         uint8_t use_utf16:1;
     555             :         uint8_t use_new_password:1;
     556             :         uint8_t valid_configuration:1;
     557             :         uint8_t check_ssl_hostname:1;
     558             :         uint8_t readonly_intent:1;
     559             :         uint8_t enable_tls_v1:1;
     560             :         uint8_t enable_tls_v1_specified:1;
     561             :         uint8_t enable_tls_v1_1:1;
     562             :         uint8_t enable_tls_v1_1_specified:1;
     563             :         uint8_t server_is_valid:1;
     564             : } TDSLOGIN;
     565             : 
     566             : typedef struct tds_headers
     567             : {
     568             :         const char *qn_options;
     569             :         const char *qn_msgtext;
     570             :         TDS_INT qn_timeout;
     571             :         /* TDS 7.4+: trace activity ID char[20] */
     572             : } TDSHEADERS;
     573             : 
     574             : typedef struct tds_locale
     575             : {
     576             :         char *language;
     577             :         char *server_charset;
     578             :         char *datetime_fmt;
     579             :         char *date_fmt;
     580             :         char *time_fmt;
     581             : } TDSLOCALE;
     582             : 
     583             : /** 
     584             :  * Information about blobs (e.g. text or image).
     585             :  * current_row contains this structure.
     586             :  */
     587             : typedef struct tds_blob
     588             : {
     589             :         TDS_CHAR *textvalue;
     590             :         TDS_CHAR textptr[16];
     591             :         TDS_CHAR timestamp[8];
     592             :         bool valid_ptr;
     593             : } TDSBLOB;
     594             : 
     595             : /**
     596             :  * Store variant information
     597             :  */
     598             : typedef struct tds_variant
     599             : {
     600             :         /* this MUST have same position and place of textvalue in tds_blob */
     601             :         TDS_CHAR *data;
     602             :         TDS_INT size;
     603             :         TDS_INT data_len;
     604             :         TDS_SERVER_TYPE type;
     605             :         TDS_UCHAR collation[5];
     606             : } TDSVARIANT;
     607             : 
     608             : /**
     609             :  * Information relevant to libiconv.  The name is an iconv name, not 
     610             :  * the same as found in master..syslanguages. 
     611             :  */
     612             : typedef struct tds_encoding
     613             : {
     614             :         /** name of the encoding (ie UTF-8) */
     615             :         const char *name;
     616             :         unsigned char min_bytes_per_char;
     617             :         unsigned char max_bytes_per_char;
     618             :         /** internal numeric index into array of all encodings */
     619             :         unsigned char canonic;
     620             : } TDS_ENCODING;
     621             : 
     622             : typedef struct tds_bcpcoldata
     623             : {
     624             :         TDS_UCHAR *data;
     625             :         TDS_INT datalen;
     626             :         bool is_null;
     627             :         /**
     628             :          * Blob data will be sent later using tds_bcp_send_blob_data,
     629             :          * datalen contains the total length.
     630             :          */
     631             :         bool deferred;
     632             : } BCPCOLDATA;
     633             : 
     634             : 
     635             : typedef TDSRET  tds_func_get_info(TDSSOCKET *tds, TDSCOLUMN *col);
     636             : typedef TDSRET  tds_func_get_data(TDSSOCKET *tds, TDSCOLUMN *col);
     637             : typedef TDS_INT tds_func_row_len(TDSCOLUMN *col);
     638             : typedef TDSRET  tds_func_put_info(TDSSOCKET *tds, TDSCOLUMN *col);
     639             : typedef TDSRET  tds_func_put_data(TDSSOCKET *tds, TDSCOLUMN *col, bool bcp7);
     640             : typedef int     tds_func_check(const TDSCOLUMN *col);
     641             : 
     642             : typedef struct tds_column_funcs
     643             : {
     644             :         tds_func_get_info *get_info;
     645             :         tds_func_get_data *get_data;
     646             :         tds_func_row_len  *row_len;
     647             :         /**
     648             :          * Send metadata column information to server.
     649             :          * \tds
     650             :          * \param col  column to send
     651             :          */
     652             :         tds_func_put_info *put_info;
     653             :         /**
     654             :          * Send column data to server.
     655             :          * Usually send parameters unless bcp7 is specified, in
     656             :          * this case send BCP for TDS7+ (Sybase use a completely
     657             :          * different format for BCP)
     658             :          * \tds
     659             :          * \param col  column to send
     660             :          * \param bcp7 1 to send BCP column on TDS7+
     661             :          */
     662             :         tds_func_put_data *put_data;
     663             : #if ENABLE_EXTRA_CHECKS
     664             :         /**
     665             :          * Check column is valid.
     666             :          * Some things should be checked:
     667             :          * - column_type and on_server.column_type;
     668             :          * - column_size and on_server.column_size;
     669             :          * - column_cur_size;
     670             :          * - column_prec and column_scale;
     671             :          * - is_XXXX_type macros/functions (nullable/fixed/blob/variable);
     672             :          * - tds_get_size_by_type;
     673             :          * - tds_get_conversion_type.
     674             :          *
     675             :          * \tds
     676             :          * \param col  column to check
     677             :          */
     678             :         tds_func_check    *check;
     679             : #endif
     680             : #if 0
     681             :         TDSRET (*convert)(TDSSOCKET *tds, TDSCOLUMN *col);
     682             : #endif
     683             : } TDSCOLUMNFUNCS;
     684             : 
     685             : /** 
     686             :  * Metadata about columns in regular and compute rows 
     687             :  */
     688             : struct tds_column
     689             : {
     690             :         const TDSCOLUMNFUNCS *funcs;
     691             :         TDS_INT column_usertype;
     692             :         TDS_INT column_flags;
     693             : 
     694             :         /**
     695             :          * Maximun size of data. For fixed types is the size.
     696             :          */
     697             :         TDS_INT column_size;
     698             : 
     699             :         /**
     700             :          * This type can be different from wire type because
     701             :          * conversion (e.g. UCS-2->Ascii) can be applied.
     702             :          * I'm beginning to wonder about the wisdom of this, however.
     703             :          * April 2003 jkl
     704             :          */
     705             :         TDS_SERVER_TYPE column_type;
     706             : 
     707             :         /**
     708             :          * Size of length when reading from wire (0, 1, 2, 4, 5 or 8).
     709             :          * 0 means fixed type.
     710             :          * 1, 2 and 4 means the data stream contains a length exactly these bytes.
     711             :          * 5 means old BLOB types having TEXTPTR on them. 5 as they contain 2 lengths,
     712             :          * one 4 bytes for data length and another 1 byte for TEXTPTR length.
     713             :          * 8 are MSSQL VARBINARY/VARCHAR(MAX) which have a 8 byte length, although
     714             :          * data types are still limited to 2GB.
     715             :          */
     716             :         TDS_TINYINT column_varint_size;
     717             : 
     718             :         TDS_TINYINT column_prec;        /**< precision for decimal/numeric and some datetime types */
     719             :         TDS_TINYINT column_scale;       /**< scale for decimal/numeric */
     720             : 
     721             :         struct
     722             :         {
     723             :                 TDS_SERVER_TYPE column_type;    /**< type of data, saved from wire */
     724             :                 TDS_INT column_size;
     725             :         } on_server;
     726             : 
     727             :         TDSICONV *char_conv;    /**< refers to previously allocated iconv information */
     728             : 
     729             :         DSTR table_name;
     730             :         DSTR column_name;
     731             :         DSTR table_column_name;
     732             : 
     733             :         unsigned char *column_data;
     734             :         void (*column_data_free)(struct tds_column * column);
     735             :         uint8_t column_nullable:1;
     736             :         uint8_t column_writeable:1;
     737             :         uint8_t column_identity:1;
     738             :         uint8_t column_key:1;
     739             :         uint8_t column_hidden:1;
     740             :         uint8_t column_output:1;
     741             :         uint8_t column_timestamp:1;
     742             :         uint8_t column_computed:1;
     743             :         TDS_UCHAR column_collation[5];
     744             : 
     745             :         uint8_t use_iconv_out:1;
     746             : 
     747             :         /* additional fields flags for compute results */
     748             :         TDS_SMALLINT column_operand;
     749             :         TDS_TINYINT column_operator;
     750             : 
     751             :         /* FIXME this is data related, not column */
     752             :         /** size written in variable (ie: char, text, binary). -1 if NULL. */
     753             :         TDS_INT column_cur_size;
     754             : 
     755             :         /* related to binding or info stored by client libraries */
     756             :         /* FIXME find a best place to store these data, some are unused */
     757             :         TDS_SMALLINT column_bindtype;
     758             :         TDS_SMALLINT column_bindfmt;
     759             :         TDS_INT column_bindlen;
     760             :         TDS_SMALLINT *column_nullbind;
     761             :         TDS_CHAR *column_varaddr;
     762             :         TDS_INT *column_lenbind;
     763             :         TDS_INT column_textpos;
     764             :         TDS_INT column_text_sqlgetdatapos;
     765             :         TDS_CHAR column_text_sqlputdatainfo;
     766             :         unsigned char column_iconv_left;
     767             :         char column_iconv_buf[9];
     768             : 
     769             :         BCPCOLDATA *bcp_column_data;
     770             :         /**
     771             :          * The length, in bytes, of any length prefix this column may have.
     772             :          * For example, strings in some non-C programming languages are
     773             :          * made up of a one-byte length prefix, followed by the string
     774             :          * data itself.
     775             :          * If the data do not have a length prefix, set prefixlen to 0.
     776             :          * Currently not very used in code, however do not remove.
     777             :          */
     778             :         TDS_INT bcp_prefix_len;
     779             :         TDS_INT bcp_term_len;
     780             :         TDS_CHAR *bcp_terminator;
     781             : };
     782             : 
     783             : 
     784             : /** Hold information for any results */
     785             : struct tds_result_info
     786             : {
     787             :         /* TODO those fields can became a struct */
     788             :         TDSCOLUMN **columns;
     789             :         TDS_USMALLINT num_cols;
     790             :         TDS_USMALLINT computeid;
     791             :         TDS_INT ref_count;
     792             :         TDSSOCKET *attached_to;
     793             :         unsigned char *current_row;
     794             :         void (*row_free)(TDSRESULTINFO* result, unsigned char *row);
     795             :         TDS_INT row_size;
     796             : 
     797             :         TDS_SMALLINT *bycolumns;
     798             :         TDS_USMALLINT by_cols;
     799             :         bool rows_exist;
     800             :         /* TODO remove ?? used only in dblib */
     801             :         bool more_results;
     802             : };
     803             : 
     804             : /** values for tds->state */
     805             : typedef enum tds_states
     806             : {
     807             :         TDS_IDLE,       /**< no data expected */
     808             :         TDS_WRITING,    /**< client is writing data */
     809             :         TDS_SENDING,    /**< client would send data */
     810             :         TDS_PENDING,    /**< client is waiting for data */
     811             :         TDS_READING,    /**< client is reading data */
     812             :         TDS_DEAD        /**< no connection */
     813             : } TDS_STATE;
     814             : 
     815             : typedef enum tds_operations
     816             : {
     817             :         TDS_OP_NONE             = 0,
     818             : 
     819             :         /* MSSQL operations, these matches protocol definitions */
     820             :         TDS_OP_CURSOR           = TDS_SP_CURSOR,
     821             :         TDS_OP_CURSOROPEN       = TDS_SP_CURSOROPEN,
     822             :         TDS_OP_CURSORPREPARE    = TDS_SP_CURSORPREPARE,
     823             :         TDS_OP_CURSOREXECUTE    = TDS_SP_CURSOREXECUTE,
     824             :         TDS_OP_CURSORPREPEXEC   = TDS_SP_CURSORPREPEXEC,
     825             :         TDS_OP_CURSORUNPREPARE  = TDS_SP_CURSORUNPREPARE,
     826             :         TDS_OP_CURSORFETCH      = TDS_SP_CURSORFETCH,
     827             :         TDS_OP_CURSOROPTION     = TDS_SP_CURSOROPTION,
     828             :         TDS_OP_CURSORCLOSE      = TDS_SP_CURSORCLOSE,
     829             :         TDS_OP_EXECUTESQL       = TDS_SP_EXECUTESQL,
     830             :         TDS_OP_PREPARE          = TDS_SP_PREPARE,
     831             :         TDS_OP_EXECUTE          = TDS_SP_EXECUTE,
     832             :         TDS_OP_PREPEXEC         = TDS_SP_PREPEXEC,
     833             :         TDS_OP_PREPEXECRPC      = TDS_SP_PREPEXECRPC,
     834             :         TDS_OP_UNPREPARE        = TDS_SP_UNPREPARE,
     835             : 
     836             :         /* sybase operations */
     837             :         TDS_OP_DYN_DEALLOC      = 100,
     838             : } TDS_OPERATION;
     839             : 
     840             : #define TDS_DBG_LOGIN   __FILE__, ((__LINE__ << 4) | 11)
     841             : #define TDS_DBG_HEADER  __FILE__, ((__LINE__ << 4) | 10)
     842             : #define TDS_DBG_FUNC    __FILE__, ((__LINE__ << 4) |  7)
     843             : #define TDS_DBG_INFO2   __FILE__, ((__LINE__ << 4) |  6)
     844             : #define TDS_DBG_INFO1   __FILE__, ((__LINE__ << 4) |  5)
     845             : #define TDS_DBG_NETWORK __FILE__, ((__LINE__ << 4) |  4)
     846             : #define TDS_DBG_WARN    __FILE__, ((__LINE__ << 4) |  3)
     847             : #define TDS_DBG_ERROR   __FILE__, ((__LINE__ << 4) |  2)
     848             : #define TDS_DBG_SEVERE  __FILE__, ((__LINE__ << 4) |  1)
     849             : 
     850             : #define TDS_DBGFLAG_FUNC    0x80
     851             : #define TDS_DBGFLAG_INFO2   0x40
     852             : #define TDS_DBGFLAG_INFO1   0x20
     853             : #define TDS_DBGFLAG_NETWORK 0x10
     854             : #define TDS_DBGFLAG_WARN    0x08
     855             : #define TDS_DBGFLAG_ERROR   0x04
     856             : #define TDS_DBGFLAG_SEVERE  0x02
     857             : #define TDS_DBGFLAG_ALL     0xfff
     858             : #define TDS_DBGFLAG_LOGIN   0x0800
     859             : #define TDS_DBGFLAG_HEADER  0x0400
     860             : #define TDS_DBGFLAG_PID     0x1000
     861             : #define TDS_DBGFLAG_TIME    0x2000
     862             : #define TDS_DBGFLAG_SOURCE  0x4000
     863             : #define TDS_DBGFLAG_THREAD  0x8000
     864             : 
     865             : #if 0
     866             : /**
     867             :  * An attempt at better logging.
     868             :  * Using these bitmapped values, various logging features can be turned on and off.
     869             :  * It can be especially helpful to turn packet data on/off for security reasons.
     870             :  */
     871             : enum TDS_DBG_LOG_STATE
     872             : {
     873             :           TDS_DBG_LOGIN =  (1 << 0)       /**< for diagnosing login problems;                                       
     874             :                                            otherwise the username/password information is suppressed. */
     875             :         , TDS_DBG_API =    (1 << 1)       /**< Log calls to client libraries */
     876             :         , TDS_DBG_ASYNC =  (1 << 2)       /**< Log asynchronous function starts or completes. */
     877             :         , TDS_DBG_DIAG =   (1 << 3)       /**< Log client- and server-generated messages */
     878             :         , TDS_DBG_error =  (1 << 4)
     879             :         /* TODO:  ^^^^^ make upper case when old #defines (above) are removed */
     880             :         /* Log FreeTDS runtime/logic error occurs. */
     881             :         , TDS_DBG_PACKET = (1 << 5)       /**< Log hex dump of packets to/from the server. */
     882             :         , TDS_DBG_LIBTDS = (1 << 6)       /**< Log calls to (and in) libtds */
     883             :         , TDS_DBG_CONFIG = (1 << 7)       /**< replaces TDSDUMPCONFIG */
     884             :         , TDS_DBG_DEFAULT = 0xFE        /**< all above except login packets */
     885             : };
     886             : #endif
     887             : 
     888             : typedef TDSRESULTINFO TDSCOMPUTEINFO;
     889             : 
     890             : typedef TDSRESULTINFO TDSPARAMINFO;
     891             : 
     892             : typedef struct tds_message
     893             : {
     894             :         TDS_CHAR *server;
     895             :         TDS_CHAR *message;
     896             :         TDS_CHAR *proc_name;
     897             :         TDS_CHAR *sql_state;
     898             :         TDS_INT msgno;
     899             :         TDS_INT line_number;
     900             :         /* -1 .. 255 */
     901             :         TDS_SMALLINT state;
     902             :         TDS_TINYINT priv_msg_type;
     903             :         TDS_TINYINT severity;
     904             :         /* for library-generated errors */
     905             :         int oserr;
     906             :         /* message was allocated, otherwise is a constant string or owned by the caller */
     907             :         bool message_allocated;
     908             : } TDSMESSAGE;
     909             : 
     910             : typedef struct tds_upd_col
     911             : {
     912             :         struct tds_upd_col *next;       
     913             :         TDS_INT colnamelength;
     914             :         char * columnname;
     915             : } TDSUPDCOL;
     916             : 
     917             : typedef enum {
     918             :           TDS_CURSOR_STATE_UNACTIONED = 0       /* initial value */
     919             :         , TDS_CURSOR_STATE_REQUESTED = 1        /* called by ct_cursor */ 
     920             :         , TDS_CURSOR_STATE_SENT = 2             /* sent to server */
     921             :         , TDS_CURSOR_STATE_ACTIONED = 3         /* acknowledged by server */
     922             : } TDS_CURSOR_STATE;
     923             : 
     924             : typedef struct tds_cursor_status
     925             : {
     926             :         TDS_CURSOR_STATE declare;
     927             :         TDS_CURSOR_STATE cursor_row;
     928             :         TDS_CURSOR_STATE open;
     929             :         TDS_CURSOR_STATE fetch;
     930             :         TDS_CURSOR_STATE close; 
     931             :         TDS_CURSOR_STATE dealloc;
     932             : } TDS_CURSOR_STATUS;
     933             : 
     934             : typedef enum tds_cursor_operation
     935             : {
     936             :         TDS_CURSOR_POSITION = 0,
     937             :         TDS_CURSOR_UPDATE = 1,
     938             :         TDS_CURSOR_DELETE = 2,
     939             :         TDS_CURSOR_INSERT = 4
     940             : } TDS_CURSOR_OPERATION;
     941             : 
     942             : typedef enum tds_cursor_fetch
     943             : {
     944             :         TDS_CURSOR_FETCH_NEXT = 1,
     945             :         TDS_CURSOR_FETCH_PREV,
     946             :         TDS_CURSOR_FETCH_FIRST,
     947             :         TDS_CURSOR_FETCH_LAST,
     948             :         TDS_CURSOR_FETCH_ABSOLUTE,
     949             :         TDS_CURSOR_FETCH_RELATIVE
     950             : } TDS_CURSOR_FETCH;
     951             : 
     952             : /**
     953             :  * Holds information about a cursor
     954             :  */
     955             : typedef struct tds_cursor
     956             : {
     957             :         struct tds_cursor *next;        /**< next in linked list, keep first */
     958             :         TDS_INT ref_count;              /**< reference counter so client can retain safely a pointer */
     959             :         char *cursor_name;              /**< name of the cursor */
     960             :         TDS_INT cursor_id;              /**< cursor id returned by the server after cursor declare */
     961             :         TDS_TINYINT options;            /**< read only|updatable TODO use it */
     962             :         /**
     963             :          * true if cursor was marker to be closed when connection is idle
     964             :          */
     965             :         bool defer_close;
     966             :         char *query;                    /**< SQL query */
     967             :         /* TODO for updatable columns */
     968             :         /* TDS_TINYINT number_upd_cols; */      /**< number of updatable columns */
     969             :         /* TDSUPDCOL *cur_col_list; */  /**< updatable column list */
     970             :         TDS_INT cursor_rows;            /**< number of cursor rows to fetch */
     971             :         /* TDSPARAMINFO *params; */     /** cursor parameter */
     972             :         TDS_CURSOR_STATUS status;
     973             :         TDS_USMALLINT srv_status;
     974             :         TDSRESULTINFO *res_info;        /** row fetched from this cursor */
     975             :         TDS_INT type;
     976             :         TDS_INT concurrency;
     977             : } TDSCURSOR;
     978             : 
     979             : /**
     980             :  * Current environment as reported by the server
     981             :  */
     982             : typedef struct tds_env
     983             : {
     984             :         /** packet size (512-65535) */
     985             :         int block_size;
     986             :         char *language;
     987             :         /** character set encoding */
     988             :         char *charset;
     989             :         /** database name */
     990             :         char *database;
     991             : } TDSENV;
     992             : 
     993             : /**
     994             :  * Holds information for a dynamic (also called prepared) query.
     995             :  */
     996             : typedef struct tds_dynamic
     997             : {
     998             :         struct tds_dynamic *next;       /**< next in linked list, keep first */
     999             :         TDS_INT ref_count;              /**< reference counter so client can retain safely a pointer */
    1000             :         /** numeric id for mssql7+*/
    1001             :         TDS_INT num_id;
    1002             :         /** 
    1003             :          * id of dynamic.
    1004             :          * Usually this id correspond to server one but if not specified
    1005             :          * is generated automatically by libTDS
    1006             :          */
    1007             :         char id[30];
    1008             :         /**
    1009             :          * this dynamic query cannot be prepared so libTDS have to construct a simple query.
    1010             :          * This can happen for instance is tds protocol doesn't support dynamics or trying
    1011             :          * to prepare query under Sybase that have BLOBs as parameters.
    1012             :          */
    1013             :         bool emulated;
    1014             :         /**
    1015             :          * true if dynamic was marker to be closed when connection is idle
    1016             :          */
    1017             :         bool defer_close;
    1018             :         /* int dyn_state; */ /* TODO use it */
    1019             :         TDSPARAMINFO *res_info; /**< query results */
    1020             :         /**
    1021             :          * query parameters.
    1022             :          * Mostly used executing query however is a good idea to prepare query
    1023             :          * again if parameter type change in an incompatible way (ie different
    1024             :          * types or larger size). Is also better to prepare a query knowing
    1025             :          * parameter types earlier.
    1026             :          */
    1027             :         TDSPARAMINFO *params;
    1028             :         /** saved query, we need to know original query if prepare is impossible */
    1029             :         char *query;
    1030             : } TDSDYNAMIC;
    1031             : 
    1032             : typedef enum {
    1033             :         TDS_MULTIPLE_QUERY,
    1034             :         TDS_MULTIPLE_EXECUTE,
    1035             :         TDS_MULTIPLE_RPC
    1036             : } TDS_MULTIPLE_TYPE;
    1037             : 
    1038             : typedef struct tds_multiple
    1039             : {
    1040             :         TDS_MULTIPLE_TYPE type;
    1041             :         unsigned int flags;
    1042             : } TDSMULTIPLE;
    1043             : 
    1044             : /* forward declaration */
    1045             : typedef struct tds_context TDSCONTEXT;
    1046             : typedef int (*err_handler_t) (const TDSCONTEXT *, TDSSOCKET *, TDSMESSAGE *);
    1047             : typedef int (*int_handler_t) (void *);
    1048             : 
    1049             : struct tds_context
    1050             : {
    1051             :         TDSLOCALE *locale;
    1052             :         void *parent;
    1053             :         /* handlers */
    1054             :         int (*msg_handler) (const TDSCONTEXT *, TDSSOCKET *, TDSMESSAGE *);
    1055             :         int (*err_handler) (const TDSCONTEXT *, TDSSOCKET *, TDSMESSAGE *);
    1056             :         int (*int_handler) (void *);
    1057             :         bool money_use_2_digits;
    1058             : };
    1059             : 
    1060             : enum TDS_ICONV_ENTRY
    1061             : { 
    1062             :           client2ucs2
    1063             :         , client2server_chardata
    1064             :         , initial_char_conv_count       /* keep last */
    1065             : };
    1066             : 
    1067             : typedef struct tds_authentication
    1068             : {
    1069             :         uint8_t *packet;
    1070             :         int packet_len;
    1071             :         /* TDS_MSG_TOKEN type, for TDS5 */
    1072             :         uint16_t msg_type;
    1073             :         TDSRET (*free)(TDSCONNECTION* conn, struct tds_authentication * auth);
    1074             :         TDSRET (*handle_next)(TDSSOCKET * tds, struct tds_authentication * auth, size_t len);
    1075             : } TDSAUTHENTICATION;
    1076             : 
    1077             : typedef struct tds_packet
    1078             : {
    1079             :         struct tds_packet *next;
    1080             :         uint16_t sid;
    1081             : 
    1082             : #if ENABLE_ODBC_MARS
    1083             :         /**
    1084             :          * Data before TDS data, currently can be 0 or sizeof(TDS72_SMP_HEADER)
    1085             :          */
    1086             :         uint8_t data_start;
    1087             : #endif
    1088             : 
    1089             :         /**
    1090             :          * data length, this does not account SMP header, only TDS part
    1091             :          */
    1092             :         unsigned data_len;
    1093             :         unsigned capacity;
    1094             :         unsigned char buf[1];
    1095             : } TDSPACKET;
    1096             : 
    1097             : #if ENABLE_ODBC_MARS
    1098             : #define tds_packet_zero_data_start(pkt) do { (pkt)->data_start = 0; } while(0)
    1099             : #define tds_packet_get_data_start(pkt) ((pkt)->data_start)
    1100             : #else
    1101             : #define tds_packet_zero_data_start(pkt) do { } while(0)
    1102             : #define tds_packet_get_data_start(pkt) 0
    1103             : #endif
    1104             : 
    1105             : typedef struct tds_poll_wakeup
    1106             : {
    1107             :         TDS_SYS_SOCKET s_signal, s_signaled;
    1108             : } TDSPOLLWAKEUP;
    1109             : 
    1110             : /* field related to connection */
    1111             : struct tds_connection
    1112             : {
    1113             :         TDS_USMALLINT tds_version;
    1114             :         bool corked;
    1115             :         TDS_UINT product_version;       /**< version of product (Sybase/MS and full version) */
    1116             :         char *product_name;
    1117             : 
    1118             :         TDS_SYS_SOCKET s;               /**< tcp socket, INVALID_SOCKET if not connected */
    1119             :         TDSPOLLWAKEUP wakeup;
    1120             :         const TDSCONTEXT *tds_ctx;
    1121             : 
    1122             :         /** environment is shared between all sessions */
    1123             :         TDSENV env;
    1124             : 
    1125             :         /**
    1126             :          * linked list of cursors allocated for this connection
    1127             :          * contains only cursors allocated on the server
    1128             :          */
    1129             :         TDSCURSOR *cursors;
    1130             :         /**
    1131             :          * list of dynamic allocated for this connection
    1132             :          * contains only dynamic allocated on the server
    1133             :          */
    1134             :         TDSDYNAMIC *dyns;
    1135             : 
    1136             :         int char_conv_count;
    1137             :         TDSICONV **char_convs;
    1138             : 
    1139             :         TDS_UCHAR collation[5];
    1140             :         TDS_UCHAR tds72_transaction[8];
    1141             : 
    1142             :         TDS_CAPABILITIES capabilities;
    1143             :         uint8_t use_iconv_in:1;
    1144             :         uint8_t tds71rev1:1;
    1145             :         uint8_t pending_close:1;        /**< true is connection has pending closing (cursors or dynamic) */
    1146             :         uint8_t encrypt_single_packet:1;
    1147             : #if ENABLE_ODBC_MARS
    1148             :         uint8_t mars:1;
    1149             : 
    1150             :         TDSSOCKET *in_net_tds;
    1151             :         TDSPACKET *packets;
    1152             :         TDSPACKET *recv_packet;
    1153             :         TDSPACKET *send_packets;
    1154             :         unsigned send_pos, recv_pos;
    1155             : 
    1156             : #define BUSY_SOCKET ((TDSSOCKET*)(TDS_UINTPTR)1)
    1157             : #define TDSSOCKET_VALID(tds) (((TDS_UINTPTR)(tds)) > 1)
    1158             :         TDSSOCKET **sessions;
    1159             :         unsigned num_sessions;
    1160             : #endif
    1161             :         tds_mutex list_mtx;
    1162             : 
    1163             :         unsigned num_cached_packets;
    1164             :         TDSPACKET *packet_cache;
    1165             : 
    1166             :         int spid;
    1167             :         int client_spid;
    1168             : 
    1169             :         /**
    1170             :          * Ratio between bytes allocated for a NCHAR type and type length (Sybase).
    1171             :          * For instance in case a NVARCHAR(3) takes 9 bytes it's 3.
    1172             :          */
    1173             :         uint8_t ncharsize;
    1174             : 
    1175             :         /**
    1176             :          * Ratio between bytes allocated for a UNICHAR type and type length (Sybase).
    1177             :          * For instance in case a UNIVARCHAR(2) takes 4 bytes it's 2.
    1178             :          * It really should be only 2.
    1179             :          */
    1180             :         uint8_t unicharsize;
    1181             : 
    1182             :         void *tls_session;
    1183             : #if defined(HAVE_GNUTLS)
    1184             :         void *tls_credentials;
    1185             : #elif defined(HAVE_OPENSSL)
    1186             :         void *tls_ctx;
    1187             : #else
    1188             :         void *tls_dummy;
    1189             : #endif
    1190             :         TDSAUTHENTICATION *authentication;
    1191             :         char *server;
    1192             : };
    1193             : 
    1194             : /**
    1195             :  * Information for a server connection
    1196             :  */
    1197             : struct tds_socket
    1198             : {
    1199             : #if ENABLE_ODBC_MARS
    1200             :         TDSCONNECTION *conn;
    1201             : #else
    1202             :         TDSCONNECTION conn[1];
    1203             : #endif
    1204             : 
    1205             :         void *parent;
    1206             : 
    1207             :         /** Input buffer.
    1208             :          * Points to receiving packet buffer.
    1209             :          * As input buffer contains just the raw packet actually this pointer
    1210             :          * is the address of recv_packet->buf.
    1211             :          */
    1212             :         unsigned char *in_buf;
    1213             : 
    1214             :         /** Output buffer.
    1215             :          * Points to sending packet buffer.
    1216             :          * Output buffer can contain additional data before the raw TDS packet
    1217             :          * so this buffer can point some bytes after send_packet->buf.
    1218             :          * Specifically this will point to send_packet->buf + send_packet->data_start.
    1219             :          */
    1220             :         unsigned char *out_buf;
    1221             : 
    1222             :         /** Maximum size of packet pointed by out_buf.
    1223             :          * The buffer is actually a bit larger to make possible to do some
    1224             :          * optimizations (at least TDS_ADDITIONAL_SPACE bytes).
    1225             :          */
    1226             :         unsigned out_buf_max;
    1227             :         unsigned in_pos;                /**< current position in in_buf */
    1228             :         unsigned out_pos;               /**< current position in out_buf */
    1229             :         unsigned in_len;                /**< input buffer length */
    1230             :         unsigned char in_flag;          /**< input buffer type */
    1231             :         unsigned char out_flag;         /**< output buffer type */
    1232             : 
    1233             :         unsigned frozen;
    1234             :         /**
    1235             :          * list of packets frozen, points to first one.
    1236             :          * send_packet is the last packet in the list.
    1237             :          */
    1238             :         TDSPACKET *frozen_packets;
    1239             : 
    1240             : #if ENABLE_ODBC_MARS
    1241             :         /** SID of MARS session.
    1242             :          * ==0  Not in a MARS session or first session
    1243             :          * >0   SID of MARS session valid.
    1244             :          */
    1245             :         uint16_t sid;
    1246             : 
    1247             :         /**
    1248             :          * This condition will be signaled by the network thread on packet
    1249             :          * received or sent for this session
    1250             :          */
    1251             :         tds_condition packet_cond;
    1252             : 
    1253             :         /**
    1254             :          * Packet we are trying to send to network.
    1255             :          * This field should be protected by conn->list_mtx
    1256             :          */
    1257             :         TDSPACKET *sending_packet;
    1258             :         TDS_UINT recv_seq;
    1259             :         TDS_UINT send_seq;
    1260             :         TDS_UINT recv_wnd;
    1261             :         TDS_UINT send_wnd;
    1262             : #endif
    1263             :         /* packet we received */
    1264             :         TDSPACKET *recv_packet;
    1265             :         /** packet we are preparing to send */
    1266             :         TDSPACKET *send_packet;
    1267             : 
    1268             :         /**
    1269             :          * Current query information. 
    1270             :          * Contains information in process, both normal and compute results.
    1271             :          * This pointer shouldn't be freed; it's just an alias to another structure.
    1272             :          */
    1273             :         TDSRESULTINFO *current_results;
    1274             :         TDSRESULTINFO *res_info;
    1275             :         TDS_UINT num_comp_info;
    1276             :         TDSCOMPUTEINFO **comp_info;
    1277             :         TDSPARAMINFO *param_info;
    1278             :         TDSCURSOR *cur_cursor;          /**< cursor in use */
    1279             :         bool bulk_query;                /**< true is query sent was a bulk query so we need to switch state to QUERYING */
    1280             :         bool has_status;                /**< true is ret_status is valid */
    1281             :         bool in_row;                    /**< true if we are getting rows */
    1282             :         volatile 
    1283             :         unsigned char in_cancel;        /**< indicate we are waiting a cancel reply; discard tokens till acknowledge; 
    1284             :         1 mean we have to send cancel packet, 2 already sent. */
    1285             :         TDS_INT ret_status;             /**< return status from store procedure */
    1286             :         TDS_STATE state;
    1287             : 
    1288             :         TDS_INT query_timeout;
    1289             :         TDS_INT8 rows_affected;         /**< rows updated/deleted/inserted/selected, TDS_NO_COUNT if not valid */
    1290             : 
    1291             :         TDSDYNAMIC *cur_dyn;            /**< dynamic structure in use */
    1292             : 
    1293             :         TDSLOGIN *login;        /**< config for login stuff. After login this field is NULL */
    1294             : 
    1295             :         void (*env_chg_func) (TDSSOCKET * tds, int type, char *oldval, char *newval);
    1296             :         TDS_OPERATION current_op;
    1297             : 
    1298             :         int option_value;
    1299             :         tds_mutex wire_mtx;
    1300             : };
    1301             : 
    1302             : #define tds_get_ctx(tds) ((tds)->conn->tds_ctx)
    1303             : #define tds_set_ctx(tds, val) do { ((tds)->conn->tds_ctx) = (val); } while(0)
    1304             : #define tds_get_parent(tds) ((tds)->parent)
    1305             : #define tds_set_parent(tds, val) do { ((tds)->parent) = (val); } while(0)
    1306             : #define tds_get_s(tds) ((tds)->conn->s)
    1307             : #define tds_set_s(tds, val) do { ((tds)->conn->s) = (val); } while(0)
    1308             : 
    1309             : typedef struct tds_tvp_row
    1310             : {
    1311             :         TDSPARAMINFO *params;
    1312             :         struct tds_tvp_row *next;
    1313             : } TDS_TVP_ROW;
    1314             : 
    1315             : typedef struct tds_tvp
    1316             : {
    1317             :         char *schema;
    1318             :         char *name;
    1319             :         TDSPARAMINFO *metadata;
    1320             :         TDS_TVP_ROW *row;
    1321             : } TDS_TVP;
    1322             : 
    1323             : 
    1324             : /* config.c */
    1325             : const TDS_COMPILETIME_SETTINGS *tds_get_compiletime_settings(void);
    1326             : typedef bool (*TDSCONFPARSE) (const char *option, const char *value, void *param);
    1327             : bool tds_read_conf_section(FILE * in, const char *section, TDSCONFPARSE tds_conf_parse, void *parse_param);
    1328             : bool tds_read_conf_file(TDSLOGIN * login, const char *server);
    1329             : bool tds_parse_conf_section(const char *option, const char *value, void *param);
    1330             : TDSLOGIN *tds_read_config_info(TDSSOCKET * tds, TDSLOGIN * login, TDSLOCALE * locale);
    1331             : void tds_fix_login(TDSLOGIN* login);
    1332             : TDS_USMALLINT * tds_config_verstr(const char *tdsver, TDSLOGIN* login);
    1333             : struct addrinfo *tds_lookup_host(const char *servername);
    1334             : TDSRET tds_lookup_host_set(const char *servername, struct addrinfo **addr);
    1335             : const char *tds_addrinfo2str(struct addrinfo *addr, char *name, int namemax);
    1336             : 
    1337             : TDSRET tds_set_interfaces_file_loc(const char *interfloc);
    1338             : extern const char STD_DATETIME_FMT[];
    1339             : int tds_parse_boolean(const char *value, int default_value);
    1340             : int tds_config_boolean(const char *option, const char *value, TDSLOGIN * login);
    1341             : 
    1342             : TDSLOCALE *tds_get_locale(void);
    1343             : TDSRET tds_alloc_row(TDSRESULTINFO * res_info);
    1344             : TDSRET tds_alloc_compute_row(TDSCOMPUTEINFO * res_info);
    1345             : BCPCOLDATA * tds_alloc_bcp_column_data(unsigned int column_size);
    1346             : TDSDYNAMIC *tds_lookup_dynamic(TDSCONNECTION * conn, const char *id);
    1347             : /*@observer@*/ const char *tds_prtype(int token);
    1348             : int tds_get_varint_size(TDSCONNECTION * conn, int datatype);
    1349             : TDS_SERVER_TYPE tds_get_cardinal_type(TDS_SERVER_TYPE datatype, int usertype);
    1350             : TDSRET tds8_adjust_login(TDSLOGIN *login);
    1351             : 
    1352             : 
    1353             : /* iconv.c */
    1354             : TDSRET tds_iconv_open(TDSCONNECTION * conn, const char *charset, int use_utf16);
    1355             : void tds_iconv_close(TDSCONNECTION * conn);
    1356             : void tds_srv_charset_changed(TDSCONNECTION * conn, const char *charset);
    1357             : void tds7_srv_charset_changed(TDSCONNECTION * conn, TDS_UCHAR collate[5]);
    1358             : int tds_iconv_alloc(TDSCONNECTION * conn);
    1359             : void tds_iconv_free(TDSCONNECTION * conn);
    1360             : TDSICONV *tds_iconv_from_collate(TDSCONNECTION * conn, const TDS_UCHAR collate[5]);
    1361             : 
    1362             : 
    1363             : /* mem.c */
    1364             : void tds_free_socket(TDSSOCKET * tds);
    1365             : void tds_free_all_results(TDSSOCKET * tds);
    1366             : void tds_free_results(TDSRESULTINFO * res_info);
    1367             : void tds_free_param_results(TDSPARAMINFO * param_info);
    1368             : void tds_free_param_result(TDSPARAMINFO * param_info);
    1369             : void tds_free_msg(TDSMESSAGE * message);
    1370             : void tds_cursor_deallocated(TDSCONNECTION *conn, TDSCURSOR *cursor);
    1371             : void tds_release_cursor(TDSCURSOR **pcursor);
    1372             : void tds_free_bcp_column_data(BCPCOLDATA * coldata);
    1373             : TDSRESULTINFO *tds_alloc_results(TDS_USMALLINT num_cols);
    1374             : TDSCOMPUTEINFO **tds_alloc_compute_results(TDSSOCKET * tds, TDS_USMALLINT num_cols, TDS_USMALLINT by_cols);
    1375             : TDSCONTEXT *tds_alloc_context(void * parent);
    1376             : void tds_free_context(TDSCONTEXT * locale);
    1377             : TDSPARAMINFO *tds_alloc_param_result(TDSPARAMINFO * old_param);
    1378             : void tds_free_input_params(TDSDYNAMIC * dyn);
    1379             : void tds_release_dynamic(TDSDYNAMIC ** dyn);
    1380             : inline static void
    1381             : tds_release_cur_dyn(TDSSOCKET * tds)
    1382             : {
    1383       93934 :         tds_release_dynamic(&tds->cur_dyn);
    1384             : }
    1385             : void tds_dynamic_deallocated(TDSCONNECTION *conn, TDSDYNAMIC *dyn);
    1386             : void tds_set_cur_dyn(TDSSOCKET *tds, TDSDYNAMIC *dyn);
    1387             : TDSSOCKET *tds_realloc_socket(TDSSOCKET * tds, unsigned int bufsize);
    1388             : char *tds_alloc_client_sqlstate(int msgno);
    1389             : char *tds_alloc_lookup_sqlstate(TDSSOCKET * tds, int msgno);
    1390             : TDSLOGIN *tds_alloc_login(bool use_environment);
    1391             : TDSDYNAMIC *tds_alloc_dynamic(TDSCONNECTION * conn, const char *id);
    1392             : void tds_free_login(TDSLOGIN * login);
    1393             : TDSLOGIN *tds_init_login(TDSLOGIN * login, TDSLOCALE * locale);
    1394             : TDSLOCALE *tds_alloc_locale(void);
    1395             : void *tds_alloc_param_data(TDSCOLUMN * curparam);
    1396             : void tds_free_locale(TDSLOCALE * locale);
    1397             : TDSCURSOR * tds_alloc_cursor(TDSSOCKET * tds, const char *name, size_t namelen, const char *query, size_t querylen);
    1398             : void tds_free_row(TDSRESULTINFO * res_info, unsigned char *row);
    1399             : TDSSOCKET *tds_alloc_socket(TDSCONTEXT * context, unsigned int bufsize);
    1400             : TDSSOCKET *tds_alloc_additional_socket(TDSCONNECTION *conn);
    1401             : void tds_set_current_results(TDSSOCKET *tds, TDSRESULTINFO *info);
    1402             : void tds_detach_results(TDSRESULTINFO *info);
    1403             : void * tds_realloc(void **pp, size_t new_size);
    1404             : #define TDS_RESIZE(p, n_elem) \
    1405             :         tds_realloc((void **) &(p), sizeof(*(p)) * (size_t) (n_elem))
    1406             : 
    1407             : TDSPACKET *tds_alloc_packet(void *buf, unsigned len);
    1408             : TDSPACKET *tds_realloc_packet(TDSPACKET *packet, unsigned len);
    1409             : void tds_free_packets(TDSPACKET *packet);
    1410             : TDSBCPINFO *tds_alloc_bcpinfo(void);
    1411             : void tds_free_bcpinfo(TDSBCPINFO *bcpinfo);
    1412             : void tds_deinit_bcpinfo(TDSBCPINFO *bcpinfo);
    1413             : void tds_deinit_tvp(TDS_TVP *table);
    1414             : 
    1415             : 
    1416             : /* login.c */
    1417             : void tds_set_packet(TDSLOGIN * tds_login, int packet_size);
    1418             : void tds_set_port(TDSLOGIN * tds_login, int port);
    1419             : bool tds_set_passwd(TDSLOGIN * tds_login, const char *password) TDS_WUR;
    1420             : void tds_set_bulk(TDSLOGIN * tds_login, bool enabled);
    1421             : bool tds_set_user(TDSLOGIN * tds_login, const char *username) TDS_WUR;
    1422             : bool tds_set_app(TDSLOGIN * tds_login, const char *application) TDS_WUR;
    1423             : bool tds_set_host(TDSLOGIN * tds_login, const char *hostname) TDS_WUR;
    1424             : bool tds_set_library(TDSLOGIN * tds_login, const char *library) TDS_WUR;
    1425             : bool tds_set_server(TDSLOGIN * tds_login, const char *server) TDS_WUR;
    1426             : bool tds_set_client_charset(TDSLOGIN * tds_login, const char *charset) TDS_WUR;
    1427             : bool tds_set_language(TDSLOGIN * tds_login, const char *language) TDS_WUR;
    1428             : void tds_set_version(TDSLOGIN * tds_login, TDS_TINYINT major_ver, TDS_TINYINT minor_ver);
    1429             : TDSRET tds_connect_and_login(TDSSOCKET * tds, TDSLOGIN * login);
    1430             : 
    1431             : 
    1432             : /* query.c */
    1433             : void tds_start_query(TDSSOCKET *tds, unsigned char packet_type);
    1434             : 
    1435             : TDSRET tds_submit_query(TDSSOCKET * tds, const char *query);
    1436             : TDSRET tds_submit_query_params(TDSSOCKET * tds, const char *query, TDSPARAMINFO * params, TDSHEADERS * head);
    1437             : TDSRET tds_submit_queryf(TDSSOCKET * tds, const char *queryf, ...);
    1438             : TDSRET tds_submit_prepare(TDSSOCKET * tds, const char *query, const char *id, TDSDYNAMIC ** dyn_out, TDSPARAMINFO * params);
    1439             : TDSRET tds_submit_execdirect(TDSSOCKET * tds, const char *query, TDSPARAMINFO * params, TDSHEADERS * head);
    1440             : TDSRET tds71_submit_prepexec(TDSSOCKET * tds, const char *query, const char *id, TDSDYNAMIC ** dyn_out, TDSPARAMINFO * params);
    1441             : TDSRET tds_submit_execute(TDSSOCKET * tds, TDSDYNAMIC * dyn);
    1442             : TDSRET tds_send_cancel(TDSSOCKET * tds);
    1443             : const char *tds_next_placeholder(const char *start);
    1444             : int tds_count_placeholders(const char *query);
    1445             : int tds_needs_unprepare(TDSCONNECTION * conn, TDSDYNAMIC * dyn);
    1446             : TDSRET tds_deferred_unprepare(TDSCONNECTION * conn, TDSDYNAMIC * dyn);
    1447             : TDSRET tds_submit_unprepare(TDSSOCKET * tds, TDSDYNAMIC * dyn);
    1448             : TDSRET tds_submit_rpc(TDSSOCKET * tds, const char *rpc_name, TDSPARAMINFO * params, TDSHEADERS * head);
    1449             : TDSRET tds_submit_optioncmd(TDSSOCKET * tds, TDS_OPTION_CMD command, TDS_OPTION option, TDS_OPTION_ARG *param, TDS_INT param_size);
    1450             : TDSRET tds_submit_begin_tran(TDSSOCKET *tds);
    1451             : TDSRET tds_submit_rollback(TDSSOCKET *tds, bool cont);
    1452             : TDSRET tds_submit_commit(TDSSOCKET *tds, bool cont);
    1453             : TDSRET tds_disconnect(TDSSOCKET * tds);
    1454             : size_t tds_quote_id(TDSSOCKET * tds, char *buffer, const char *id, ptrdiff_t idlen);
    1455             : size_t tds_quote_id_rpc(TDSSOCKET * tds, char *buffer, const char *id, ptrdiff_t idlen);
    1456             : size_t tds_quote_string(TDSSOCKET * tds, char *buffer, const char *str, ptrdiff_t len);
    1457             : const char *tds_skip_comment(const char *s);
    1458             : const char *tds_skip_quoted(const char *s);
    1459             : size_t tds_fix_column_size(TDSSOCKET * tds, TDSCOLUMN * curcol);
    1460             : const char *tds_convert_string(TDSSOCKET * tds, TDSICONV * char_conv, const char *s, ptrdiff_t len, size_t *out_len);
    1461             : void tds_convert_string_free(const char *original, const char *converted);
    1462             : #if !ENABLE_EXTRA_CHECKS
    1463             : #define tds_convert_string_free(original, converted) \
    1464             :         do { if (original != converted) free((char*) converted); } while(0)
    1465             : #endif
    1466             : TDSRET tds_get_column_declaration(TDSSOCKET * tds, TDSCOLUMN * curcol, char *out);
    1467             : 
    1468             : TDSRET tds_cursor_declare(TDSSOCKET * tds, TDSCURSOR * cursor, bool *send);
    1469             : TDSRET tds_cursor_setrows(TDSSOCKET * tds, TDSCURSOR * cursor, bool *send);
    1470             : TDSRET tds_cursor_open(TDSSOCKET * tds, TDSCURSOR * cursor, TDSPARAMINFO *params, bool *send);
    1471             : TDSRET tds_cursor_fetch(TDSSOCKET * tds, TDSCURSOR * cursor, TDS_CURSOR_FETCH fetch_type, TDS_INT i_row);
    1472             : TDSRET tds_cursor_get_cursor_info(TDSSOCKET * tds, TDSCURSOR * cursor, TDS_UINT * row_number, TDS_UINT * row_count);
    1473             : TDSRET tds_cursor_close(TDSSOCKET * tds, TDSCURSOR * cursor);
    1474             : TDSRET tds_cursor_dealloc(TDSSOCKET * tds, TDSCURSOR * cursor);
    1475             : TDSRET tds_deferred_cursor_dealloc(TDSCONNECTION *conn, TDSCURSOR * cursor);
    1476             : TDSRET tds_cursor_update(TDSSOCKET * tds, TDSCURSOR * cursor, TDS_CURSOR_OPERATION op, TDS_INT i_row, TDSPARAMINFO * params);
    1477             : TDSRET tds_cursor_setname(TDSSOCKET * tds, TDSCURSOR * cursor);
    1478             : 
    1479             : TDSRET tds_multiple_init(TDSSOCKET *tds, TDSMULTIPLE *multiple, TDS_MULTIPLE_TYPE type, TDSHEADERS * head);
    1480             : TDSRET tds_multiple_done(TDSSOCKET *tds, TDSMULTIPLE *multiple);
    1481             : TDSRET tds_multiple_query(TDSSOCKET *tds, TDSMULTIPLE *multiple, const char *query, TDSPARAMINFO * params);
    1482             : TDSRET tds_multiple_execute(TDSSOCKET *tds, TDSMULTIPLE *multiple, TDSDYNAMIC * dyn);
    1483             : 
    1484             : 
    1485             : /* token.c */
    1486             : TDSRET tds_process_cancel(TDSSOCKET * tds);
    1487             : TDSRET tds_process_login_tokens(TDSSOCKET * tds);
    1488             : TDSRET tds_process_simple_query(TDSSOCKET * tds);
    1489             : int tds5_send_optioncmd(TDSSOCKET * tds, TDS_OPTION_CMD tds_command, TDS_OPTION tds_option, TDS_OPTION_ARG * tds_argument,
    1490             :                         TDS_INT * tds_argsize);
    1491             : TDSRET tds_process_tokens(TDSSOCKET * tds, /*@out@*/ TDS_INT * result_type, /*@out@*/ int *done_flags, unsigned flag);
    1492             : 
    1493             : 
    1494             : /* data.c */
    1495             : void tds_set_param_type(TDSCONNECTION * conn, TDSCOLUMN * curcol, TDS_SERVER_TYPE type, size_t size);
    1496             : void tds_set_column_type(TDSCONNECTION * conn, TDSCOLUMN * curcol, TDS_SERVER_TYPE type);
    1497             : bool tds_try_get_int_col(TDSSOCKET *tds, const TDSCOLUMN *col, TDS_INT *value);
    1498             : TDS_INT tds_get_int_col(TDSSOCKET *tds, const TDSCOLUMN *col, TDS_INT default_value);
    1499             : #ifdef WORDS_BIGENDIAN
    1500             : void tds_swap_datatype(int coltype, void *b);
    1501             : #endif
    1502             : 
    1503             : 
    1504             : /* tds_convert.c */
    1505             : TDSRET tds_datecrack(TDS_INT datetype, const void *di, TDSDATEREC * dr);
    1506             : TDS_SERVER_TYPE tds_get_conversion_type(TDS_SERVER_TYPE srctype, int colsize);
    1507             : extern const char tds_hex_digits[];
    1508             : 
    1509             : 
    1510             : /* write.c */
    1511             : int tds_init_write_buf(TDSSOCKET * tds);
    1512             : int tds_put_n(TDSSOCKET * tds, const void *buf, size_t n);
    1513             : int tds_put_string(TDSSOCKET * tds, const char *buf, int len);
    1514             : int tds_put_int(TDSSOCKET * tds, TDS_INT i);
    1515             : int tds_put_int8(TDSSOCKET * tds, TDS_INT8 i);
    1516             : int tds_put_smallint(TDSSOCKET * tds, TDS_SMALLINT si);
    1517             : /** Output a tinyint value */
    1518             : #define tds_put_tinyint(tds, ti) tds_put_byte(tds,ti)
    1519             : int tds_put_byte(TDSSOCKET * tds, unsigned char c);
    1520             : TDSRET tds_flush_packet(TDSSOCKET * tds);
    1521             : 
    1522             : 
    1523             : /* read.c */
    1524             : unsigned char tds_get_byte(TDSSOCKET * tds);
    1525             : void tds_unget_byte(TDSSOCKET * tds);
    1526             : unsigned char tds_peek(TDSSOCKET * tds);
    1527             : TDS_USMALLINT tds_get_usmallint(TDSSOCKET * tds);
    1528             : #define tds_get_smallint(tds) ((TDS_SMALLINT) tds_get_usmallint(tds))
    1529             : TDS_UINT tds_get_uint(TDSSOCKET * tds);
    1530             : #define tds_get_int(tds) ((TDS_INT) tds_get_uint(tds))
    1531             : TDS_UINT8 tds_get_uint8(TDSSOCKET * tds);
    1532             : #define tds_get_int8(tds) ((TDS_INT8) tds_get_uint8(tds))
    1533             : size_t tds_get_string(TDSSOCKET * tds, size_t string_len, char *dest, size_t dest_size);
    1534             : TDSRET tds_get_char_data(TDSSOCKET * tds, char *dest, size_t wire_size, TDSCOLUMN * curcol);
    1535             : bool tds_get_n(TDSSOCKET * tds, /*@out@*/ /*@null@*/ void *dest, size_t n);
    1536             : int tds_get_size_by_type(TDS_SERVER_TYPE servertype);
    1537             : DSTR* tds_dstr_get(TDSSOCKET * tds, DSTR * s, size_t len);
    1538             : 
    1539             : 
    1540             : /* util.c */
    1541             : int tdserror(const TDSCONTEXT *tds_ctx, TDSSOCKET *tds, int msgno, int errnum);
    1542             : int tdserror_args(const TDSCONTEXT *tds_ctx, TDSSOCKET *tds, int msgno, int errnum, ...);
    1543             : TDS_STATE tds_set_state(TDSSOCKET *tds, TDS_STATE state);
    1544             : void tds_swap_bytes(void *buf, size_t bytes);
    1545             : unsigned int tds_gettime_ms(void);
    1546             : 
    1547             : 
    1548             : /* log.c */
    1549             : typedef struct tdsdump_off_item {
    1550             :         struct tdsdump_off_item *next;
    1551             :         tds_thread_id thread_id;
    1552             : } TDSDUMP_OFF_ITEM;
    1553             : void tdsdump_off(TDSDUMP_OFF_ITEM *off_item);
    1554             : void tdsdump_on(TDSDUMP_OFF_ITEM *off_item);
    1555             : int tdsdump_isopen(void);
    1556             : #include <freetds/popvis.h>
    1557             : /* This function is exported by DB-Library, do not change its ABI */
    1558             : int tdsdump_open(const char *filename);
    1559             : #ifdef _WIN32
    1560             : int tdsdump_wopen(const wchar_t *filename);
    1561             : #define tdsdump_topen tdsdump_wopen
    1562             : #else
    1563             : #define tdsdump_topen tdsdump_open
    1564             : #endif
    1565             : #include <freetds/pushvis.h>
    1566             : void tdsdump_close(void);
    1567             : void tdsdump_dump_buf_impl(const char* file, unsigned int level_line, const char *msg, const void *buf, size_t length);
    1568             : void tdsdump_col(const TDSCONTEXT *tds_ctx, const TDSCOLUMN *col);
    1569             : void tdsdump_log_impl(const char* file, unsigned int level_line, const char *fmt, ...)
    1570             : #if defined(__GNUC__) && __GNUC__ >= 2
    1571             : #if defined(__MINGW32__)
    1572             :         __attribute__ ((__format__ (ms_printf, 3, 4)))
    1573             : #else
    1574             :         __attribute__ ((__format__ (__printf__, 3, 4)))
    1575             : #endif
    1576             : #endif
    1577             : ;
    1578             : #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
    1579             : /* If available use C99 and __VA_ARGS__ */
    1580             : #define tdsdump_log(...) do { \
    1581             :         if (TDS_UNLIKELY(tds_write_dump)) tdsdump_log_impl(__VA_ARGS__); \
    1582             : } while(0)
    1583             : #define tdsdump_dump_buf(...) do { \
    1584             :         if (TDS_UNLIKELY(tds_write_dump)) tdsdump_dump_buf_impl(__VA_ARGS__); \
    1585             : } while(0)
    1586             : #else
    1587             : #define tdsdump_log if (!TDS_UNLIKELY(tds_write_dump)) {} else tdsdump_log_impl
    1588             : #define tdsdump_dump_buf if (!TDS_UNLIKELY(tds_write_dump)) {} else tdsdump_dump_buf_impl
    1589             : #endif
    1590             : 
    1591             : extern bool tds_write_dump;
    1592             : extern int tds_debug_flags;
    1593             : extern int tds_append_mode;
    1594             : 
    1595             : 
    1596             : /* net.c */
    1597             : TDSERRNO tds_open_socket(TDSSOCKET * tds, struct addrinfo *ipaddr, unsigned int port, int timeout, int *p_oserr);
    1598             : void tds_close_socket(TDSSOCKET * tds);
    1599             : int tds7_get_instance_ports(FILE *output, struct addrinfo *addr);
    1600             : int tds7_get_instance_port(struct addrinfo *addr, const char *instance);
    1601             : char *tds_prwsaerror(int erc);
    1602             : void tds_prwsaerror_free(char *s);
    1603             : ptrdiff_t tds_connection_read(TDSSOCKET * tds, unsigned char *buf, size_t buflen);
    1604             : ptrdiff_t tds_connection_write(TDSSOCKET *tds, const unsigned char *buf, size_t buflen, int final);
    1605             : void tds_connection_coalesce(TDSSOCKET *tds);
    1606             : void tds_connection_flush(TDSSOCKET *tds);
    1607             : #define TDSSELREAD  POLLIN
    1608             : #define TDSSELWRITE POLLOUT
    1609             : int tds_select(TDSSOCKET * tds, unsigned tds_sel, int timeout_seconds);
    1610             : void tds_connection_close(TDSCONNECTION *conn);
    1611             : ptrdiff_t tds_goodread(TDSSOCKET * tds, unsigned char *buf, size_t buflen);
    1612             : ptrdiff_t tds_goodwrite(TDSSOCKET * tds, const unsigned char *buffer, size_t buflen);
    1613             : int tds_socket_set_nonblocking(TDS_SYS_SOCKET sock);
    1614             : int tds_wakeup_init(TDSPOLLWAKEUP *wakeup);
    1615             : void tds_wakeup_close(TDSPOLLWAKEUP *wakeup);
    1616             : void tds_wakeup_send(TDSPOLLWAKEUP *wakeup, char cancel);
    1617             : inline static TDS_SYS_SOCKET
    1618             : tds_wakeup_get_fd(const TDSPOLLWAKEUP *wakeup)
    1619             : {
    1620             :         return wakeup->s_signaled;
    1621             : }
    1622             : 
    1623             : 
    1624             : /* packet.c */
    1625             : int tds_read_packet(TDSSOCKET * tds);
    1626             : TDSRET tds_write_packet(TDSSOCKET * tds, unsigned char final);
    1627             : #if ENABLE_ODBC_MARS
    1628             : int tds_append_cancel(TDSSOCKET *tds);
    1629             : TDSRET tds_append_syn(TDSSOCKET *tds);
    1630             : TDSRET tds_append_fin(TDSSOCKET *tds);
    1631             : #else
    1632             : int tds_put_cancel(TDSSOCKET * tds);
    1633             : #endif
    1634             : 
    1635             : typedef struct tds_freeze {
    1636             :         /** which socket we refer to */
    1637             :         TDSSOCKET *tds;
    1638             :         /** first packet frozen */
    1639             :         TDSPACKET *pkt;
    1640             :         /** position in pkt */
    1641             :         unsigned pkt_pos;
    1642             :         /** length size (0, 1, 2 or 4) */
    1643             :         unsigned size_len;
    1644             : } TDSFREEZE;
    1645             : 
    1646             : void tds_freeze(TDSSOCKET *tds, TDSFREEZE *freeze, unsigned size_len);
    1647             : unsigned int tds_freeze_written(TDSFREEZE *freeze);
    1648             : TDSRET tds_freeze_abort(TDSFREEZE *freeze);
    1649             : TDSRET tds_freeze_close(TDSFREEZE *freeze);
    1650             : TDSRET tds_freeze_close_string(TDSFREEZE *freeze);
    1651             : TDSRET tds_freeze_close_len(TDSFREEZE *freeze, int32_t size);
    1652             : 
    1653             : inline static void
    1654             : tds_set_current_send_packet(TDSSOCKET *tds, TDSPACKET *pkt)
    1655             : {
    1656       65473 :         tds->send_packet = pkt;
    1657       65473 :         tds->out_buf = pkt->buf + tds_packet_get_data_start(pkt);
    1658             : }
    1659             : 
    1660             : /* Macros to allow some indentation of the packets.
    1661             :  *
    1662             :  * The 3 nested fake loops require some explanation:
    1663             :  * - first is to allows to declare variables;
    1664             :  * - second is to force using brackets;
    1665             :  * - third is to avoids that a break inside will skip the close.
    1666             :  */
    1667             : #define TDS_START_LEN_GENERIC(tds_socket, len) do { \
    1668             :         TDSFREEZE current_freeze[1]; \
    1669             :         tds_freeze((tds_socket), current_freeze, (len)); do { do
    1670             : #define TDS_END_LEN while(0); } while(tds_freeze_close(current_freeze), 0); } while(0);
    1671             : #define TDS_END_LEN_STRING while(0); } while(tds_freeze_close_string(current_freeze), 0); } while(0);
    1672             : 
    1673             : #define TDS_START_LEN_TINYINT(tds_socket) TDS_START_LEN_GENERIC(tds_socket, 1)
    1674             : #define TDS_START_LEN_USMALLINT(tds_socket) TDS_START_LEN_GENERIC(tds_socket, 2)
    1675             : #define TDS_START_LEN_UINT(tds_socket) TDS_START_LEN_GENERIC(tds_socket, 4)
    1676             : 
    1677             : /* vstrbuild.c */
    1678             : TDSRET tds_vstrbuild(char *buffer, int buflen, int *resultlen, const char *text, int textlen, const char *formats, int formatlen,
    1679             :                   va_list ap);
    1680             : 
    1681             : 
    1682             : /* numeric.c */
    1683             : char *tds_money_to_string(TDS_INT8 money, char *s, bool use_2_digits);
    1684             : TDS_INT tds_numeric_to_string(const TDS_NUMERIC * numeric, char *s);
    1685             : TDS_INT tds_numeric_change_prec_scale(TDS_NUMERIC * numeric, unsigned char new_prec, unsigned char new_scale);
    1686             : 
    1687             : 
    1688             : /* getmac.c */
    1689             : void tds_getmac(TDS_SYS_SOCKET s, unsigned char mac[6]);
    1690             : 
    1691             : 
    1692             : /* challenge.c */
    1693             : #ifndef HAVE_SSPI
    1694             : TDSAUTHENTICATION * tds_ntlm_get_auth(TDSSOCKET * tds);
    1695             : TDSAUTHENTICATION * tds_gss_get_auth(TDSSOCKET * tds);
    1696             : #else
    1697             : TDSAUTHENTICATION * tds_sspi_get_auth(TDSSOCKET * tds);
    1698             : #endif
    1699             : TDSRET tds5_gss_send(TDSSOCKET *tds);
    1700             : 
    1701             : 
    1702             : /* random.c */
    1703             : void tds_random_buffer(unsigned char *out, int len);
    1704             : 
    1705             : 
    1706             : /* sec_negotiate.c */
    1707             : TDSAUTHENTICATION * tds5_negotiate_get_auth(TDSSOCKET * tds);
    1708             : inline static void
    1709             : tds5_negotiate_set_msg_type(TDSAUTHENTICATION * tds_auth, uint16_t msg_type)
    1710             : {
    1711           0 :         if (tds_auth)
    1712           0 :                 tds_auth->msg_type = msg_type;
    1713             : }
    1714             : 
    1715             : 
    1716             : /* bulk.c */
    1717             : 
    1718             : /** bcp direction */
    1719             : enum tds_bcp_directions
    1720             : {
    1721             :         TDS_BCP_IN = 1,
    1722             :         TDS_BCP_OUT = 2,
    1723             :         TDS_BCP_QUERYOUT = 3
    1724             : };
    1725             : 
    1726             : typedef struct tds5_colinfo
    1727             : {
    1728             :         TDS_TINYINT type;
    1729             :         TDS_TINYINT status;
    1730             :         TDS_SMALLINT offset;
    1731             :         TDS_INT length;
    1732             :         bool dflt;
    1733             : 
    1734             :         TDS_INT dflt_size;
    1735             :         TDS_UCHAR* dflt_value;
    1736             : } TDS5COLINFO;
    1737             : 
    1738             : struct tds_bcpinfo
    1739             : {
    1740             :         void *parent;
    1741             :         DSTR hint;
    1742             :         DSTR tablename;
    1743             :         TDS_CHAR *insert_stmt;
    1744             :         TDS_INT direction;
    1745             :         bool identity_insert_on;
    1746             :         bool xfer_init;
    1747             :         /** copy out, all rows were retrieved */
    1748             :         bool out_done;
    1749             :         bool datarows_locking;
    1750             :         bool dry_run;                   /** for "bcp in", validate hostfile without uploading rows. */
    1751             :         TDS_INT bind_count;
    1752             :         TDSRESULTINFO *bindinfo;
    1753             :         TDS5COLINFO *sybase_colinfo;
    1754             :         TDS_INT sybase_count;
    1755             :         TDS_INT rows_sent;
    1756             :         bool with_triggers;
    1757             :         /** a deferred blob column is waiting for data, see tds_bcp_send_blob_data */
    1758             :         bool blob_pending;
    1759             :         /** index of column waiting for data */
    1760             :         TDS_INT blob_col;
    1761             :         /** bytes still to be sent for column waiting for data */
    1762             :         TDS_INT blob_left;
    1763             :         /** number of blob columns already sent in current row (TDS 5.0) */
    1764             :         TDS_INT blob_count;
    1765             : };
    1766             : 
    1767             : TDSRET tds_bcp_init(TDSSOCKET * tds, TDSBCPINFO * bcpinfo);
    1768             : typedef TDSRET(*tds_bcp_get_col_data) (TDSBCPINFO * bulk, TDSCOLUMN * bcpcol, int index, int offset);
    1769             : typedef void (*tds_bcp_null_error)   (TDSBCPINFO *bulk, int index, int offset);
    1770             : TDSRET tds_bcp_send_record(TDSSOCKET * tds, TDSBCPINFO * bcpinfo, tds_bcp_get_col_data get_col_data, tds_bcp_null_error null_error,
    1771             :                            int offset);
    1772             : TDSRET tds_bcp_done(TDSSOCKET * tds, int *rows_copied);
    1773             : TDSRET tds_bcp_cancel(TDSSOCKET * tds);
    1774             : TDSRET tds_bcp_send_blob_data(TDSSOCKET * tds, TDSBCPINFO * bcpinfo, const void *data, TDS_INT len);
    1775             : TDSRET tds_bcp_start(TDSSOCKET * tds, TDSBCPINFO * bcpinfo);
    1776             : TDSRET tds_bcp_start_copy_in(TDSSOCKET * tds, TDSBCPINFO * bcpinfo);
    1777             : 
    1778             : struct tds_file_stream;
    1779             : TDSRET
    1780             : tds_bcp_fread(TDSSOCKET * tds, TDSICONV * char_conv, struct tds_file_stream *stream,
    1781             :               const char *terminator, size_t term_len, char **outbuf, size_t *outbytes);
    1782             : 
    1783             : TDSRET tds_writetext_start(TDSSOCKET * tds, const char *objname, const char *textptr, const char *timestamp, int with_log,
    1784             :                            TDS_UINT size);
    1785             : TDSRET tds_writetext_continue(TDSSOCKET *tds, const TDS_UCHAR *text, TDS_UINT size);
    1786             : TDSRET tds_writetext_end(TDSSOCKET *tds);
    1787             : 
    1788             : 
    1789             : inline static bool
    1790             : tds_capability_enabled(const TDS_CAPABILITY_TYPE *cap, unsigned cap_num)
    1791             : {
    1792        2384 :         return (cap->values[sizeof(cap->values)-1-(cap_num>>3)] >> (cap_num&7)) & 1;
    1793             : }
    1794             : #define tds_capability_has_req(conn, cap) \
    1795             :         tds_capability_enabled(&conn->capabilities.types[0], cap)
    1796             : #define tds_capability_has_res(conn, cap) \
    1797             :         tds_capability_enabled(&conn->capabilities.types[1], cap)
    1798             : 
    1799             : inline static void
    1800             : tds_capability_set(TDS_CAPABILITY_TYPE *cap, unsigned cap_num)
    1801             : {
    1802        1380 :         cap->values[sizeof(cap->values)-1-(cap_num>>3)] |= 1 << (cap_num&7);
    1803             : }
    1804             : #define tds_capability_set_req(caps, cap) \
    1805             :         tds_capability_set(&(caps)->types[0], cap)
    1806             : 
    1807             : #define IS_TDS42(x) (x->tds_version==0x402)
    1808             : #define IS_TDS46(x) (x->tds_version==0x406)
    1809             : #define IS_TDS50(x) (x->tds_version==0x500)
    1810             : #define IS_TDS70(x) (x->tds_version==0x700)
    1811             : #define IS_TDS71(x) (x->tds_version==0x701)
    1812             : #define IS_TDS72(x) (x->tds_version==0x702)
    1813             : #define IS_TDS73(x) (x->tds_version==0x703)
    1814             : 
    1815             : #define IS_TDS50_PLUS(x) ((x)->tds_version>=0x500)
    1816             : #define IS_TDS7_PLUS(x)  ((x)->tds_version>=0x700)
    1817             : #define IS_TDS71_PLUS(x) ((x)->tds_version>=0x701)
    1818             : #define IS_TDS72_PLUS(x) ((x)->tds_version>=0x702)
    1819             : #define IS_TDS73_PLUS(x) ((x)->tds_version>=0x703)
    1820             : #define IS_TDS74_PLUS(x) ((x)->tds_version>=0x704)
    1821             : #define IS_TDS80_PLUS(x) ((x)->tds_version>=0x800)
    1822             : 
    1823             : #define TDS_MAJOR(x) ((x)->tds_version >> 8)
    1824             : #define TDS_MINOR(x) ((x)->tds_version & 0xff)
    1825             : 
    1826             : #define IS_TDSDEAD(x) (((x) == NULL) || (x)->state == TDS_DEAD)
    1827             : 
    1828             : /** Check if product is Sybase (such as Adaptive Server Enterprise). x should be a TDSSOCKET*. */
    1829             : #define TDS_IS_SYBASE(x) (!((x)->conn->product_version & 0x80000000u))
    1830             : /** Check if product is Microsoft SQL Server. x should be a TDSSOCKET*. */
    1831             : #define TDS_IS_MSSQL(x) (((x)->conn->product_version & 0x80000000u)!=0)
    1832             : 
    1833             : /** Calc a version number for mssql. Use with TDS_MS_VER(7,0,842).
    1834             :  * For test for a range of version you can use check like
    1835             :  * if (tds->product_version >= TDS_MS_VER(7,0,0) && tds->product_version < TDS_MS_VER(8,0,0)) */
    1836             : #define TDS_MS_VER(maj,min,x) (0x80000000u|((maj)<<24)|((min)<<16)|(x))
    1837             : 
    1838             : /* TODO test if not similar to ms one*/
    1839             : /** Calc a version number for Sybase. */
    1840             : #define TDS_SYB_VER(maj,min,x) (((maj)<<24)|((min)<<16)|(x)<<8)
    1841             : 
    1842             : #ifdef __cplusplus
    1843             : #if 0
    1844             : {
    1845             : #endif
    1846             : }
    1847             : #endif
    1848             : 
    1849             : #include <freetds/popvis.h>
    1850             : 
    1851             : #define TDS_PUT_INT(tds,v) tds_put_int((tds), ((TDS_INT)(v)))
    1852             : #define TDS_PUT_SMALLINT(tds,v) tds_put_smallint((tds), ((TDS_SMALLINT)(v)))
    1853             : #define TDS_PUT_BYTE(tds,v) tds_put_byte((tds), ((unsigned char)(v)))
    1854             : 
    1855             : #endif /* _tdsguard_hfOrWb5znoUCWdBPoNQvqN_ */

Generated by: LCOV version 1.13