/* FreeTDS - Library of routines accessing Sybase and Microsoft databases * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Brian Bruns * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ #ifndef _tds_h_ #define _tds_h_ static const char rcsid_tds_h[] = "$Id: tds.h,v 1.245.2.1 2006/04/16 08:08:38 freddy77 Exp $"; static const void *const no_unused_tds_h_warn[] = { rcsid_tds_h, no_unused_tds_h_warn }; #include #include #include /* forward declaration */ typedef struct tdsiconvinfo TDSICONV; typedef struct tds_socket TDSSOCKET; #include "tdsver.h" #include "tds_sysdep_public.h" #ifdef _FREETDS_LIBRARY_SOURCE #include "tds_sysdep_private.h" #endif /* _FREETDS_LIBRARY_SOURCE */ #ifdef __cplusplus extern "C" { #if 0 } #endif #endif /** * A structure to hold all the compile-time settings. * This structure is returned by tds_get_compiletime_settings */ typedef struct _tds_compiletime_settings { const char *freetds_version; /* release version of FreeTDS */ const char *last_update; /* latest software_version date among the modules */ int msdblib; /* for MS style dblib */ int sybase_compat; /* enable increased Open Client binary compatibility */ int threadsafe; /* compile for thread safety default=no */ int libiconv; /* search for libiconv in DIR/include and DIR/lib */ const char *tdsver; /* TDS protocol version (4.2/4.6/5.0/7.0/8.0) 5.0 */ int iodbc; /* build odbc driver against iODBC in DIR */ int unixodbc; /* build odbc driver against unixODBC in DIR */ } TDS_COMPILETIME_SETTINGS; struct DSTR_STRUCT { /* keep always at last */ char dstr_s[1]; }; typedef struct DSTR_STRUCT *DSTR; /** * @file tds.h * Main include file for libtds */ /** * \defgroup libtds LibTDS API * Callable functions in \c libtds. * * The \c libtds library is for use internal to \em FreeTDS. It is not * intended for use by applications. Although any use is \em permitted, you're * encouraged to use one of the established public APIs instead, because their * interfaces are stable and documented by the vendors. */ /* * All references to data that touch the wire should use the following typedefs. * * If you have problems on 64-bit machines and the code is * using a native datatype, please change it to use * these. (In the TDS layer only, the API layers have their * own typedefs which equate to these). */ typedef char TDS_CHAR; /* 8-bit char */ typedef unsigned char TDS_UCHAR; /* 8-bit uchar */ typedef unsigned char TDS_TINYINT; /* 8-bit unsigned */ typedef tds_sysdep_int16_type TDS_SMALLINT; /* 16-bit int */ typedef unsigned tds_sysdep_int16_type TDS_USMALLINT; /* 16-bit unsigned */ typedef tds_sysdep_int32_type TDS_INT; /* 32-bit int */ typedef unsigned tds_sysdep_int32_type TDS_UINT; /* 32-bit unsigned */ typedef tds_sysdep_real32_type TDS_REAL; /* 32-bit real */ typedef tds_sysdep_real64_type TDS_FLOAT; /* 64-bit real */ typedef tds_sysdep_int64_type TDS_INT8; /* 64-bit integer */ typedef unsigned tds_sysdep_int64_type TDS_UINT8; /* 64-bit unsigned */ typedef tds_sysdep_intptr_type TDS_INTPTR; typedef struct tdsnumeric { unsigned char precision; unsigned char scale; unsigned char array[33]; } TDS_NUMERIC; typedef struct tdsoldmoney { TDS_INT mnyhigh; TDS_UINT mnylow; } TDS_OLD_MONEY; typedef union tdsmoney { TDS_OLD_MONEY tdsoldmoney; TDS_INT8 mny; } TDS_MONEY; typedef struct tdsmoney4 { TDS_INT mny4; } TDS_MONEY4; typedef struct tdsdatetime { TDS_INT dtdays; TDS_INT dttime; } TDS_DATETIME; typedef struct tdsdatetime4 { TDS_USMALLINT days; TDS_USMALLINT minutes; } TDS_DATETIME4; typedef struct tdsvarbinary { TDS_SMALLINT len; TDS_CHAR array[256]; } TDS_VARBINARY; typedef struct tdsvarchar { TDS_INT len; TDS_CHAR array[256]; } TDS_VARCHAR; typedef struct tdsunique { TDS_UINT Data1; TDS_USMALLINT Data2; TDS_USMALLINT Data3; TDS_UCHAR Data4[8]; } TDS_UNIQUE; /** information on data, used by tds_datecrack */ typedef struct tdsdaterec { TDS_INT year; /**< year */ TDS_INT month; /**< month number (0-11) */ TDS_INT day; /**< day of month (1-31) */ TDS_INT dayofyear; /**< day of year (1-366) */ TDS_INT weekday; /**< day of week (0-6, 0 = sunday) */ TDS_INT hour; /**< 0-23 */ TDS_INT minute; /**< 0-59 */ TDS_INT second; /**< 0-59 */ TDS_INT millisecond; /**< 0-999 */ TDS_INT tzone; } TDSDATEREC; /** * The following little table is indexed by precision and will * tell us the number of bytes required to store the specified * precision. */ extern const int tds_numeric_bytes_per_prec[]; #define TDS_SUCCEED 1 #define TDS_FAIL 0 #define TDS_NO_MORE_RESULTS 2 #define TDS_CANCELLED 3 #define TDS_INT_EXIT 0 #define TDS_INT_CONTINUE 1 #define TDS_INT_CANCEL 2 #define TDS_INT_TIMEOUT 3 #define TDS_NO_COUNT -1 #define TDS_ROW_RESULT 4040 #define TDS_PARAM_RESULT 4042 #define TDS_STATUS_RESULT 4043 #define TDS_MSG_RESULT 4044 #define TDS_COMPUTE_RESULT 4045 #define TDS_CMD_DONE 4046 #define TDS_CMD_SUCCEED 4047 #define TDS_CMD_FAIL 4048 #define TDS_ROWFMT_RESULT 4049 #define TDS_COMPUTEFMT_RESULT 4050 #define TDS_DESCRIBE_RESULT 4051 #define TDS_DONE_RESULT 4052 #define TDS_DONEPROC_RESULT 4053 #define TDS_DONEINPROC_RESULT 4054 #define TDS_OTHERS_RESULT 4055 enum tds_token_results { TDS_TOKEN_RES_OTHERS, TDS_TOKEN_RES_ROWFMT, TDS_TOKEN_RES_COMPUTEFMT, TDS_TOKEN_RES_PARAMFMT, TDS_TOKEN_RES_DONE, TDS_TOKEN_RES_ROW, TDS_TOKEN_RES_COMPUTE, TDS_TOKEN_RES_PROC, TDS_TOKEN_RES_MSG }; #define TDS_TOKEN_FLAG(flag) TDS_RETURN_##flag = (1 << (TDS_TOKEN_RES_##flag*2)), TDS_STOPAT_##flag = (2 << (TDS_TOKEN_RES_##flag*2)) enum tds_token_flags { TDS_HANDLE_ALL = 0, TDS_TOKEN_FLAG(OTHERS), TDS_TOKEN_FLAG(ROWFMT), TDS_TOKEN_FLAG(COMPUTEFMT), TDS_TOKEN_FLAG(PARAMFMT), TDS_TOKEN_FLAG(DONE), TDS_TOKEN_FLAG(ROW), TDS_TOKEN_FLAG(COMPUTE), TDS_TOKEN_FLAG(PROC), TDS_TOKEN_FLAG(MSG), TDS_TOKEN_RESULTS = TDS_RETURN_ROWFMT|TDS_RETURN_COMPUTEFMT|TDS_RETURN_DONE|TDS_STOPAT_ROW|TDS_STOPAT_COMPUTE|TDS_RETURN_PROC, TDS_TOKEN_TRAILING = TDS_STOPAT_ROWFMT|TDS_STOPAT_COMPUTEFMT|TDS_STOPAT_ROW|TDS_STOPAT_COMPUTE|TDS_STOPAT_MSG|TDS_STOPAT_OTHERS }; enum tds_end { TDS_DONE_FINAL = 0x00 /* final result set, command completed successfully. */ , TDS_DONE_MORE_RESULTS = 0x01 /* more results follow */ , TDS_DONE_ERROR = 0x02 /* error occurred */ , TDS_DONE_INXACT = 0x04 /* transaction in progress */ , TDS_DONE_PROC = 0x08 /* results are from a stored procedure */ , TDS_DONE_COUNT = 0x10 /* count field in packet is valid */ , TDS_DONE_CANCELLED = 0x20 /* acknowledging an attention command (usually a cancel) */ , TDS_DONE_EVENT = 0x40 /* part of an event notification. */ , TDS_DONE_SRVERROR = 0x100 /* SQL server server error */ /* after the above flags, a TDS_DONE packet has a field describing the state of the transaction */ , TDS_DONE_NO_TRAN = 0 /* No transaction in effect */ , TDS_DONE_TRAN_SUCCEED = 1 /* Transaction completed successfully */ , TDS_DONE_TRAN_PROGRESS= 2 /* Transaction in progress */ , TDS_DONE_STMT_ABORT = 3 /* A statement aborted */ , TDS_DONE_TRAN_ABORT = 4 /* Transaction aborted */ }; /* * TDS_ERROR indicates a successful processing, but that a TDS_ERROR_TOKEN or TDS_EED_TOKEN error was encountered. * TDS_FAIL indicates an unrecoverable failure. */ #define TDS_ERROR 3 #define TDS_DONT_RETURN 42 #define TDS5_PARAMFMT2_TOKEN 32 /* 0x20 */ #define TDS_LANGUAGE_TOKEN 33 /* 0x21 TDS 5.0 only */ #define TDS_ORDERBY2_TOKEN 34 /* 0x22 */ #define TDS_ROWFMT2_TOKEN 97 /* 0x61 TDS 5.0 only */ #define TDS_LOGOUT_TOKEN 113 /* 0x71 TDS 5.0 only? ct_close() */ #define TDS_RETURNSTATUS_TOKEN 121 /* 0x79 */ #define TDS_PROCID_TOKEN 124 /* 0x7C TDS 4.2 only - TDS_PROCID */ #define TDS7_RESULT_TOKEN 129 /* 0x81 TDS 7.0 only */ #define TDS7_COMPUTE_RESULT_TOKEN 136 /* 0x88 TDS 7.0 only */ #define TDS_COLNAME_TOKEN 160 /* 0xA0 TDS 4.2 only */ #define TDS_COLFMT_TOKEN 161 /* 0xA1 TDS 4.2 only - TDS_COLFMT */ #define TDS_DYNAMIC2_TOKEN 163 /* 0xA3 */ #define TDS_TABNAME_TOKEN 164 /* 0xA4 */ #define TDS_COLINFO_TOKEN 165 /* 0xA5 */ #define TDS_OPTIONCMD_TOKEN 166 /* 0xA6 */ #define TDS_COMPUTE_NAMES_TOKEN 167 /* 0xA7 */ #define TDS_COMPUTE_RESULT_TOKEN 168 /* 0xA8 */ #define TDS_ORDERBY_TOKEN 169 /* 0xA9 TDS_ORDER */ #define TDS_ERROR_TOKEN 170 /* 0xAA */ #define TDS_INFO_TOKEN 171 /* 0xAB */ #define TDS_PARAM_TOKEN 172 /* 0xAC RETURNVALUE? */ #define TDS_LOGINACK_TOKEN 173 /* 0xAD */ #define TDS_CONTROL_TOKEN 174 /* 0xAE TDS_CONTROL */ #define TDS_ROW_TOKEN 209 /* 0xD1 */ #define TDS_CMP_ROW_TOKEN 211 /* 0xD3 */ #define TDS5_PARAMS_TOKEN 215 /* 0xD7 TDS 5.0 only */ #define TDS_CAPABILITY_TOKEN 226 /* 0xE2 */ #define TDS_ENVCHANGE_TOKEN 227 /* 0xE3 */ #define TDS_EED_TOKEN 229 /* 0xE5 */ #define TDS_DBRPC_TOKEN 230 /* 0xE6 */ #define TDS5_DYNAMIC_TOKEN 231 /* 0xE7 TDS 5.0 only */ #define TDS5_PARAMFMT_TOKEN 236 /* 0xEC TDS 5.0 only */ #define TDS_AUTH_TOKEN 237 /* 0xED */ #define TDS_RESULT_TOKEN 238 /* 0xEE */ #define TDS_DONE_TOKEN 253 /* 0xFD TDS_DONE */ #define TDS_DONEPROC_TOKEN 254 /* 0xFE TDS_DONEPROC */ #define TDS_DONEINPROC_TOKEN 255 /* 0xFF TDS_DONEINPROC */ /* CURSOR support: TDS 5.0 only*/ #define TDS_CURCLOSE_TOKEN 128 /* 0x80 TDS 5.0 only */ #define TDS_CURFETCH_TOKEN 130 /* 0x82 TDS 5.0 only */ #define TDS_CURINFO_TOKEN 131 /* 0x83 TDS 5.0 only */ #define TDS_CUROPEN_TOKEN 132 /* 0x84 TDS 5.0 only */ #define TDS_CURDECLARE_TOKEN 134 /* 0x86 TDS 5.0 only */ enum { TDS_CUR_ISTAT_UNUSED = 0x00, TDS_CUR_ISTAT_DECLARED = 0x01, TDS_CUR_ISTAT_OPEN = 0x02, TDS_CUR_ISTAT_CLOSED = 0x04, TDS_CUR_ISTAT_RDONLY = 0x08, TDS_CUR_ISTAT_UPDATABLE = 0x10, TDS_CUR_ISTAT_ROWCNT = 0x20, TDS_CUR_ISTAT_DEALLOC = 0x40 }; /* * Cursor Declare, SetRows, Open and Close all return 0x83 token. * But only SetRows includes the rowcount (4 byte) in the stream. * So for Setrows we read the rowcount from the stream and not for others. * These values are useful to determine when to read the rowcount from the packet */ #define IS_DECLARE 100 #define IS_CURROW 200 #define IS_OPEN 300 #define IS_CLOSE 400 /* states for tds_process_messages() */ #define PROCESS_ROWS 0 #define PROCESS_RESULTS 1 #define CANCEL_PROCESS 2 #define GOTO_1ST_ROW 3 #define LOGIN 4 /* environment type field */ #define TDS_ENV_DATABASE 1 #define TDS_ENV_LANG 2 #define TDS_ENV_CHARSET 3 #define TDS_ENV_PACKSIZE 4 #define TDS_ENV_LCID 5 #define TDS_ENV_SQLCOLLATION 7 /* string types */ #define TDS_NULLTERM -9 /* Microsoft internal stored procedure id's */ #define TDS_SP_CURSOR 1 #define TDS_SP_CURSOROPEN 2 #define TDS_SP_CURSORPREPARE 3 #define TDS_SP_CURSOREXECUTE 4 #define TDS_SP_CURSORPREPEXEC 5 #define TDS_SP_CURSORUNPREPARE 6 #define TDS_SP_CURSORFETCH 7 #define TDS_SP_CURSOROPTION 8 #define TDS_SP_CURSORCLOSE 9 #define TDS_SP_EXECUTESQL 10 #define TDS_SP_PREPARE 11 #define TDS_SP_EXECUTE 12 #define TDS_SP_PREPEXEC 13 #define TDS_SP_PREPEXECRPC 14 #define TDS_SP_UNPREPARE 15 /* * Sybase does an awful job of this stuff, non null ints of size 1 2 * and 4 have there own codes but nullable ints are lumped into INTN * sheesh! */ typedef enum { SYBCHAR = 47, /* 0x2F */ #define SYBCHAR SYBCHAR SYBVARCHAR = 39, /* 0x27 */ #define SYBVARCHAR SYBVARCHAR SYBINTN = 38, /* 0x26 */ #define SYBINTN SYBINTN SYBINT1 = 48, /* 0x30 */ #define SYBINT1 SYBINT1 SYBINT2 = 52, /* 0x34 */ #define SYBINT2 SYBINT2 SYBINT4 = 56, /* 0x38 */ #define SYBINT4 SYBINT4 SYBINT8 = 127, /* 0x7F */ #define SYBINT8 SYBINT8 SYBFLT8 = 62, /* 0x3E */ #define SYBFLT8 SYBFLT8 SYBDATETIME = 61, /* 0x3D */ #define SYBDATETIME SYBDATETIME SYBBIT = 50, /* 0x32 */ #define SYBBIT SYBBIT SYBTEXT = 35, /* 0x23 */ #define SYBTEXT SYBTEXT SYBNTEXT = 99, /* 0x63 */ #define SYBNTEXT SYBNTEXT SYBIMAGE = 34, /* 0x22 */ #define SYBIMAGE SYBIMAGE SYBMONEY4 = 122, /* 0x7A */ #define SYBMONEY4 SYBMONEY4 SYBMONEY = 60, /* 0x3C */ #define SYBMONEY SYBMONEY SYBDATETIME4 = 58, /* 0x3A */ #define SYBDATETIME4 SYBDATETIME4 SYBREAL = 59, /* 0x3B */ #define SYBREAL SYBREAL SYBBINARY = 45, /* 0x2D */ #define SYBBINARY SYBBINARY SYBVOID = 31, /* 0x1F */ #define SYBVOID SYBVOID SYBVARBINARY = 37, /* 0x25 */ #define SYBVARBINARY SYBVARBINARY SYBNVARCHAR = 103, /* 0x67 */ #define SYBNVARCHAR SYBNVARCHAR SYBBITN = 104, /* 0x68 */ #define SYBBITN SYBBITN SYBNUMERIC = 108, /* 0x6C */ #define SYBNUMERIC SYBNUMERIC SYBDECIMAL = 106, /* 0x6A */ #define SYBDECIMAL SYBDECIMAL SYBFLTN = 109, /* 0x6D */ #define SYBFLTN SYBFLTN SYBMONEYN = 110, /* 0x6E */ #define SYBMONEYN SYBMONEYN SYBDATETIMN = 111, /* 0x6F */ #define SYBDATETIMN SYBDATETIMN XSYBCHAR = 175, /* 0xAF */ #define XSYBCHAR XSYBCHAR XSYBVARCHAR = 167, /* 0xA7 */ #define XSYBVARCHAR XSYBVARCHAR XSYBNVARCHAR = 231, /* 0xE7 */ #define XSYBNVARCHAR XSYBNVARCHAR XSYBNCHAR = 239, /* 0xEF */ #define XSYBNCHAR XSYBNCHAR XSYBVARBINARY = 165, /* 0xA5 */ #define XSYBVARBINARY XSYBVARBINARY XSYBBINARY = 173, /* 0xAD */ #define XSYBBINARY XSYBBINARY SYBLONGBINARY = 225, /* 0xE1 */ #define SYBLONGBINARY SYBLONGBINARY SYBSINT1 = 64, /* 0x40 */ #define SYBSINT1 SYBSINT1 SYBUINT2 = 65, /* 0x41 */ #define SYBUINT2 SYBUINT2 SYBUINT4 = 66, /* 0x42 */ #define SYBUINT4 SYBUINT4 SYBUINT8 = 67, /* 0x43 */ #define SYBUINT8 SYBUINT8 SYBUNIQUE = 36, /* 0x24 */ #define SYBUNIQUE SYBUNIQUE SYBVARIANT = 98 /* 0x62 */ #define SYBVARIANT SYBVARIANT } TDS_SERVER_TYPE; typedef enum { USER_UNICHAR_TYPE = 34, /* 0x22 */ USER_UNIVARCHAR_TYPE = 35 /* 0x23 */ } TDS_USER_TYPE; #define SYBAOPCNT 0x4b #define SYBAOPCNTU 0x4c #define SYBAOPSUM 0x4d #define SYBAOPSUMU 0x4e #define SYBAOPAVG 0x4f #define SYBAOPAVGU 0x50 #define SYBAOPMIN 0x51 #define SYBAOPMAX 0x52 /* mssql2k compute operator */ #define SYBAOPCNT_BIG 0x09 #define SYBAOPSTDEV 0x30 #define SYBAOPSTDEVP 0x31 #define SYBAOPVAR 0x32 #define SYBAOPVARP 0x33 #define SYBAOPCHECKSUM_AGG 0x72 /** * options that can be sent with a TDS_OPTIONCMD token */ typedef enum { TDS_OPT_SET = 1 /* Set an option. */ , TDS_OPT_DEFAULT = 2 /* Set option to its default value. */ , TDS_OPT_LIST = 3 /* Request current setting of a specific option. */ , TDS_OPT_INFO = 4 /* Report current setting of a specific option. */ } TDS_OPTION_CMD; typedef enum { TDS_OPT_DATEFIRST = 1 /* 0x01 */ , TDS_OPT_TEXTSIZE = 2 /* 0x02 */ , TDS_OPT_STAT_TIME = 3 /* 0x03 */ , TDS_OPT_STAT_IO = 4 /* 0x04 */ , TDS_OPT_ROWCOUNT = 5 /* 0x05 */ , TDS_OPT_NATLANG = 6 /* 0x06 */ , TDS_OPT_DATEFORMAT = 7 /* 0x07 */ , TDS_OPT_ISOLATION = 8 /* 0x08 */ , TDS_OPT_AUTHON = 9 /* 0x09 */ , TDS_OPT_CHARSET = 10 /* 0x0a */ , TDS_OPT_SHOWPLAN = 13 /* 0x0d */ , TDS_OPT_NOEXEC = 14 /* 0x0e */ , TDS_OPT_ARITHIGNOREON = 15 /* 0x0f */ , TDS_OPT_ARITHABORTON = 17 /* 0x11 */ , TDS_OPT_PARSEONLY = 18 /* 0x12 */ , TDS_OPT_GETDATA = 20 /* 0x14 */ , TDS_OPT_NOCOUNT = 21 /* 0x15 */ , TDS_OPT_FORCEPLAN = 23 /* 0x17 */ , TDS_OPT_FORMATONLY = 24 /* 0x18 */ , TDS_OPT_CHAINXACTS = 25 /* 0x19 */ , TDS_OPT_CURCLOSEONXACT = 26 /* 0x1a */ , TDS_OPT_FIPSFLAG = 27 /* 0x1b */ , TDS_OPT_RESTREES = 28 /* 0x1c */ , TDS_OPT_IDENTITYON = 29 /* 0x1d */ , TDS_OPT_CURREAD = 30 /* 0x1e */ , TDS_OPT_CURWRITE = 31 /* 0x1f */ , TDS_OPT_IDENTITYOFF = 32 /* 0x20 */ , TDS_OPT_AUTHOFF = 33 /* 0x21 */ , TDS_OPT_ANSINULL = 34 /* 0x22 */ , TDS_OPT_QUOTED_IDENT = 35 /* 0x23 */ , TDS_OPT_ARITHIGNOREOFF = 36 /* 0x24 */ , TDS_OPT_ARITHABORTOFF = 37 /* 0x25 */ , TDS_OPT_TRUNCABORT = 38 /* 0x26 */ } TDS_OPTION; typedef union tds_option_arg { TDS_TINYINT ti; TDS_INT i; TDS_CHAR *c; } TDS_OPTION_ARG; enum { TDS_OPT_ARITHOVERFLOW = 0x01, TDS_OPT_NUMERICTRUNC = 0x02 }; enum TDS_OPT_DATEFIRST_CHOICE { TDS_OPT_MONDAY = 1, TDS_OPT_TUESDAY = 2, TDS_OPT_WEDNESDAY = 3, TDS_OPT_THURSDAY = 4, TDS_OPT_FRIDAY = 5, TDS_OPT_SATURDAY = 6, TDS_OPT_SUNDAY = 7 }; enum TDS_OPT_DATEFORMAT_CHOICE { TDS_OPT_FMTMDY = 1, TDS_OPT_FMTDMY = 2, TDS_OPT_FMTYMD = 3, TDS_OPT_FMTYDM = 4, TDS_OPT_FMTMYD = 5, TDS_OPT_FMTDYM = 6 }; enum TDS_OPT_ISOLATION_CHOICE { TDS_OPT_LEVEL1 = 1, TDS_OPT_LEVEL3 = 3 }; typedef enum tds_packet_type { TDS_QUERY = 1, TDS_RPC = 3, TDS_CANCEL = 6, TDS_BULK = 7, TDS_NORMAL = 15 } TDS_PACKET_TYPE; #define TDS_ZERO_FREE(x) do {free((x)); (x) = NULL;} while(0) #define TDS_VECTOR_SIZE(x) (sizeof(x)/sizeof(x[0])) /* * TODO use system macros for optimization * See mcrypt for reference and linux kernel source for optimization * check if unaligned access and use fast write/read when implemented */ #define TDS_BYTE_SWAP16(value) \ (((((unsigned short)value)<<8) & 0xFF00) | \ ((((unsigned short)value)>>8) & 0x00FF)) #define TDS_BYTE_SWAP32(value) \ (((((unsigned long)value)<<24) & 0xFF000000) | \ ((((unsigned long)value)<< 8) & 0x00FF0000) | \ ((((unsigned long)value)>> 8) & 0x0000FF00) | \ ((((unsigned long)value)>>24) & 0x000000FF)) #define is_end_token(x) (x==TDS_DONE_TOKEN || \ x==TDS_DONEPROC_TOKEN || \ x==TDS_DONEINPROC_TOKEN) #define is_hard_end_token(x) (x==TDS_DONE_TOKEN || \ x==TDS_DONEPROC_TOKEN) #define is_msg_token(x) (x==TDS_INFO_TOKEN || \ x==TDS_ERROR_TOKEN || \ x==TDS_EED_TOKEN) #define is_result_token(x) (x==TDS_RESULT_TOKEN || \ x==TDS_ROWFMT2_TOKEN || \ x==TDS7_RESULT_TOKEN || \ x==TDS_COLFMT_TOKEN || \ x==TDS_COLNAME_TOKEN || \ x==TDS_RETURNSTATUS_TOKEN) /* FIX ME -- not a complete list */ #define is_fixed_type(x) (x==SYBINT1 || \ x==SYBINT2 || \ x==SYBINT4 || \ x==SYBINT8 || \ x==SYBREAL || \ x==SYBFLT8 || \ x==SYBDATETIME || \ x==SYBDATETIME4 || \ x==SYBBIT || \ x==SYBMONEY || \ x==SYBMONEY4 || \ x==SYBVOID || \ x==SYBUNIQUE) #define is_nullable_type(x) ( \ x==SYBBITN || \ x==SYBINTN || \ x==SYBFLTN || \ x==SYBMONEYN || \ x==SYBDATETIMN || \ x==SYBVARCHAR || \ x==SYBBINARY || \ x==SYBVARBINARY || \ x==SYBTEXT || \ x==SYBNTEXT || \ x==SYBIMAGE) #define is_blob_type(x) (x==SYBTEXT || x==SYBIMAGE || x==SYBNTEXT) /* large type means it has a two byte size field */ /* define is_large_type(x) (x>128) */ #define is_numeric_type(x) (x==SYBNUMERIC || x==SYBDECIMAL) #define is_unicode_type(x) (x==XSYBNVARCHAR || x==XSYBNCHAR || x==SYBNTEXT) #define is_collate_type(x) (x==XSYBVARCHAR || x==XSYBCHAR || x==SYBTEXT || x==XSYBNVARCHAR || x==XSYBNCHAR || x==SYBNTEXT) #define is_ascii_type(x) ( x==XSYBCHAR || x==XSYBVARCHAR || x==SYBTEXT || x==SYBCHAR || x==SYBVARCHAR) #define is_binary_type(x) (x==SYBLONGBINARY) #define is_char_type(x) (is_unicode_type(x) || is_ascii_type(x)) #define is_similar_type(x, y) ((is_char_type(x) && is_char_type(y)) || ((is_unicode_type(x) && is_unicode_type(y)))) #define TDS_MAX_CAPABILITY 22 #define MAXPRECISION 80 #define TDS_MAX_CONN 4096 #define TDS_MAX_DYNID_LEN 30 /* defaults to use if no others are found */ #define TDS_DEF_SERVER "SYBASE" #define TDS_DEF_BLKSZ 512 #define TDS_DEF_CHARSET "iso_1" #define TDS_DEF_LANG "us_english" #if TDS42 #define TDS_DEF_MAJOR 4 #define TDS_DEF_MINOR 2 #define TDS_DEF_PORT 1433 #elif TDS46 #define TDS_DEF_MAJOR 4 #define TDS_DEF_MINOR 6 #define TDS_DEF_PORT 4000 #elif TDS70 #define TDS_DEF_MAJOR 7 #define TDS_DEF_MINOR 0 #define TDS_DEF_PORT 1433 #elif TDS80 #define TDS_DEF_MAJOR 8 #define TDS_DEF_MINOR 0 #define TDS_DEF_PORT 1433 #else #define TDS_DEF_MAJOR 5 #define TDS_DEF_MINOR 0 #define TDS_DEF_PORT 4000 #endif /* normalized strings from freetds.conf file */ #define TDS_STR_VERSION "tds version" #define TDS_STR_BLKSZ "initial block size" #define TDS_STR_SWAPDT "swap broken dates" #define TDS_STR_SWAPMNY "swap broken money" #define TDS_STR_DUMPFILE "dump file" #define TDS_STR_DEBUGLVL "debug level" #define TDS_STR_DEBUGFLAGS "debug flags" #define TDS_STR_TIMEOUT "timeout" #define TDS_STR_QUERY_TIMEOUT "query timeout" #define TDS_STR_CONNTIMEOUT "connect timeout" #define TDS_STR_HOSTNAME "hostname" #define TDS_STR_HOST "host" #define TDS_STR_PORT "port" #define TDS_STR_TEXTSZ "text size" /* for big endian hosts */ #define TDS_STR_EMUL_LE "emulate little endian" #define TDS_STR_CHARSET "charset" #define TDS_STR_CLCHARSET "client charset" #define TDS_STR_LANGUAGE "language" #define TDS_STR_APPENDMODE "dump file append" #define TDS_STR_DATEFMT "date format" #define TDS_STR_INSTANCE "instance" /* TODO do a better check for alignment than this */ typedef union { void *p; int i; } tds_align_struct; #define TDS_ALIGN_SIZE sizeof(tds_align_struct) #define TDS_MAX_LOGIN_STR_SZ 30 typedef struct tds_login { DSTR server_name; DSTR server_addr; int port; TDS_TINYINT major_version; /* TDS version */ TDS_TINYINT minor_version; /* TDS version */ int block_size; DSTR language; /* ie us-english */ DSTR server_charset; /* ie iso_1 */ TDS_INT connect_timeout; DSTR host_name; DSTR app_name; DSTR user_name; DSTR password; DSTR library; /* Ct-Library, DB-Library, TDS-Library or ODBC */ TDS_TINYINT bulk_copy; TDS_TINYINT suppress_language; TDS_TINYINT encrypted; TDS_INT query_timeout; unsigned char capabilities[TDS_MAX_CAPABILITY]; DSTR client_charset; } TDSLOGIN; typedef struct tds_connection { /* first part of structure is the same of login one */ DSTR server_name; /**< server name (in freetds.conf) */ int port; /**< port of database service */ TDS_TINYINT major_version; TDS_TINYINT minor_version; int block_size; DSTR language; DSTR server_charset; /**< charset of server */ TDS_INT connect_timeout; DSTR host_name; /**< client hostname */ DSTR app_name; DSTR user_name; /**< account for login */ DSTR password; /**< password of account login */ DSTR library; TDS_TINYINT bulk_copy; TDS_TINYINT suppress_language; TDS_TINYINT encrypted; TDS_INT query_timeout; unsigned char capabilities[TDS_MAX_CAPABILITY]; DSTR client_charset; DSTR ip_addr; /**< ip of server */ DSTR instance_name; DSTR database; DSTR dump_file; int debug_flags; int text_size; int broken_dates; int broken_money; int emul_little_endian; } TDSCONNECTION; typedef struct tds_locale { char *language; char *server_charset; char *client_charset; char *date_fmt; } TDSLOCALE; /** * Information about blobs (e.g. text or image). * current_row contains this structure. */ typedef struct tds_blob { TDS_CHAR *textvalue; TDS_CHAR textptr[16]; TDS_CHAR timestamp[8]; } TDSBLOB; /** * TDS 8.0 collation information. */ typedef struct { TDS_USMALLINT locale_id; /* master..syslanguages.lcid */ TDS_USMALLINT flags; TDS_UCHAR charset_id; /* or zero */ } TDS8_COLLATION; /* SF stands for "sort flag" */ #define TDS_SF_BIN (TDS_USMALLINT) 0x100 #define TDS_SF_WIDTH_INSENSITIVE (TDS_USMALLINT) 0x080 #define TDS_SF_KATATYPE_INSENSITIVE (TDS_USMALLINT) 0x040 #define TDS_SF_ACCENT_SENSITIVE (TDS_USMALLINT) 0x020 #define TDS_SF_CASE_INSENSITIVE (TDS_USMALLINT) 0x010 /* UT stands for user type */ #define TDS_UT_TIMESTAMP 80 /** * Information relevant to libiconv. The name is an iconv name, not * the same as found in master..syslanguages. */ typedef struct _tds_encoding { const char *name; unsigned char min_bytes_per_char; unsigned char max_bytes_per_char; } TDS_ENCODING; typedef struct _tds_bcpcoldata { TDS_UCHAR *data; TDS_INT datalen; TDS_INT null_column; } BCPCOLDATA; enum { TDS_SYSNAME_SIZE = 512 }; /** * Metadata about columns in regular and compute rows */ typedef struct tds_column { TDS_SMALLINT column_type; /**< This type can be different from wire type because * conversion (e.g. UCS-2->Ascii) can be applied. * I'm beginning to wonder about the wisdom of this, however. * April 2003 jkl */ TDS_INT column_usertype; TDS_INT column_flags; TDS_INT column_size; /**< maximun size of data. For fixed is the size. */ TDS_TINYINT column_varint_size; /**< size of length when reading from wire (0, 1, 2 or 4) */ TDS_TINYINT column_prec; /**< precision for decimal/numeric */ TDS_TINYINT column_scale; /**< scale for decimal/numeric */ TDS_SMALLINT column_namelen; /**< length of column name */ TDS_SMALLINT table_namelen; struct { TDS_SMALLINT column_type; /**< type of data, saved from wire */ TDS_INT column_size; } on_server; const TDSICONV *char_conv; /**< refers to previously allocated iconv information */ TDS_CHAR table_name[TDS_SYSNAME_SIZE]; TDS_CHAR column_name[TDS_SYSNAME_SIZE]; TDS_INT column_offset; /**< offset into row buffer for store data */ unsigned int column_nullable:1; unsigned int column_writeable:1; unsigned int column_identity:1; unsigned int column_key:1; unsigned int column_hidden:1; unsigned int column_output:1; unsigned int column_timestamp:1; TDS_UCHAR column_collation[5]; /* additional fields flags for compute results */ TDS_TINYINT column_operator; TDS_SMALLINT column_operand; /* FIXME this is data related, not column */ /** size written in variable (ie: char, text, binary). -1 if NULL. */ TDS_INT column_cur_size; /* related to binding or info stored by client libraries */ /* FIXME find a best place to store these data, some are unused */ TDS_SMALLINT column_bindtype; TDS_SMALLINT column_bindfmt; TDS_UINT column_bindlen; TDS_SMALLINT *column_nullbind; TDS_CHAR *column_varaddr; TDS_INT *column_lenbind; TDS_INT column_textpos; TDS_INT column_text_sqlgetdatapos; BCPCOLDATA *bcp_column_data; /** * The length, in bytes, of any length prefix this column may have. * For example, strings in some non-C programming languages are * made up of a one-byte length prefix, followed by the string * data itself. * If the data does not have a length prefix, set prefixlen to 0. * Currently not very used in code, however do not remove. */ TDS_INT bcp_prefix_len; TDS_INT bcp_term_len; TDS_CHAR *bcp_terminator; } TDSCOLUMN; /** Hold information for any results */ typedef struct tds_result_info { /* TODO those fields can became a struct */ TDS_SMALLINT num_cols; TDSCOLUMN **columns; TDS_INT row_size; TDS_INT ref_count; unsigned char *current_row; TDS_SMALLINT rows_exist; /* TODO remove ?? used only in dblib */ TDS_INT row_count; /* TODO remove ?? used only in dblib */ TDS_TINYINT more_results; TDS_SMALLINT computeid; TDS_SMALLINT *bycolumns; TDS_SMALLINT by_cols; } TDSRESULTINFO; /* values for tds->state */ typedef enum _TDS_STATE { TDS_IDLE, TDS_QUERYING, TDS_PENDING, TDS_READING, TDS_DEAD } TDS_STATE; #define TDS_DBG_FUNC __FILE__, ((__LINE__ << 4) | 7) #define TDS_DBG_INFO2 __FILE__, ((__LINE__ << 4) | 6) #define TDS_DBG_INFO1 __FILE__, ((__LINE__ << 4) | 5) #define TDS_DBG_NETWORK __FILE__, ((__LINE__ << 4) | 4) #define TDS_DBG_WARN __FILE__, ((__LINE__ << 4) | 3) #define TDS_DBG_ERROR __FILE__, ((__LINE__ << 4) | 2) #define TDS_DBG_SEVERE __FILE__, ((__LINE__ << 4) | 1) #define TDS_DBGFLAG_FUNC 0x80 #define TDS_DBGFLAG_INFO2 0x40 #define TDS_DBGFLAG_INFO1 0x20 #define TDS_DBGFLAG_NETWORK 0x10 #define TDS_DBGFLAG_WARN 0x08 #define TDS_DBGFLAG_ERROR 0x04 #define TDS_DBGFLAG_SEVERE 0x02 #define TDS_DBGFLAG_ALLLVL 0xfff #define TDS_DBGFLAG_PID 0x1000 #define TDS_DBGFLAG_TIME 0x2000 #define TDS_DBGFLAG_SOURCE 0x4000 #define TDS_DBGFLAG_THREAD 0x8000 /** * An attempt at better logging. * Using these bitmapped values, various logging features can be turned on and off. * It can be especially helpful to turn packet data on/off for security reasons. */ enum TDS_DBG_LOG_STATE { TDS_DBG_LOGIN = 1 /* for diagnosing login problems; otherwise the username/password information is suppressed. */ , TDS_DBG_API = (1 << 1) /* Log calls to client libraries */ , TDS_DBG_ASYNC = (1 << 2) /* Log asynchronous function starts or completes. */ , TDS_DBG_DIAG = (1 << 3) /* Log client- and server-generated messages */ , TDS_DBG_error = (1 << 4) /* TODO: ^^^^^ make upper case when old #defines (above) are removed */ /* Log FreeTDS runtime/logic error occurs. */ , TDS_DBG_PACKET = (1 << 5) /* Log hex dump of packets to/from the server. */ , TDS_DBG_LIBTDS = (1 << 6) /* Log calls to (and in) libtds */ , TDS_DBG_CONFIG = (1 << 7) /* replaces TDSDUMPCONFIG */ , TDS_DBG_DEFAULT = 0xFE /* all above except login packets */ }; typedef struct tds_result_info TDSCOMPUTEINFO; typedef TDSRESULTINFO TDSPARAMINFO; typedef struct tds_message { TDS_SMALLINT priv_msg_type; TDS_SMALLINT line_number; TDS_UINT msgno; TDS_SMALLINT state; TDS_SMALLINT severity; TDS_CHAR *server; TDS_CHAR *message; TDS_CHAR *proc_name; TDS_CHAR *sql_state; } TDSMESSAGE; typedef struct tds_upd_col { struct tds_upd_col *next; TDS_INT colnamelength; char * columnname; } TDSUPDCOL; typedef enum { TDS_CURSOR_STATE_UNACTIONED = 0 /* initial value */ , TDS_CURSOR_STATE_REQUESTED = 1 /* called by ct_cursor */ , TDS_CURSOR_STATE_SENT = 2 /* sent to server */ , TDS_CURSOR_STATE_ACTIONED = 3 /* acknowledged by server */ } TDS_CURSOR_STATE; typedef struct _tds_cursor_status { TDS_CURSOR_STATE declare; TDS_CURSOR_STATE cursor_row; TDS_CURSOR_STATE open; TDS_CURSOR_STATE fetch; TDS_CURSOR_STATE close; TDS_CURSOR_STATE dealloc; } TDS_CURSOR_STATUS; typedef struct _tds_cursor { struct _tds_cursor *next; /**< next in linked list, keep first */ TDS_INT length; /**< total length of the remaining datastream */ TDS_TINYINT cursor_name_len; /**< length of cursor name > 0 and <= 30 */ char *cursor_name; /**< name of the cursor */ TDS_INT cursor_id; /**< cursor id returned by the server after cursor declare */ TDS_TINYINT options; /**< read only|updatable */ TDS_TINYINT hasargs; /**< cursor parameters exists ? */ TDS_USMALLINT query_len; /**< SQL query length */ char *query; /**< SQL query */ /* TODO for updatable columns */ TDS_TINYINT number_upd_cols; /**< number of updatable columns */ TDS_INT cursor_rows; /**< number of cursor rows to fetch */ /*TODO when cursor has parameters*/ /*TDS_PARAM *param_list; cursor parameter */ TDSUPDCOL *cur_col_list; /**< updatable column list */ TDS_CURSOR_STATUS status; TDS_SMALLINT srv_status; TDSRESULTINFO *res_info; } TDSCURSOR; /* * Current environment as reported by the server */ typedef struct tds_env { int block_size; char *language; char *charset; char *database; } TDSENV; typedef struct tds_dynamic { struct tds_dynamic *next; /**< next in linked list, keep first */ char id[30]; int dyn_state; /** numeric id for mssql7+*/ TDS_INT num_id; TDSPARAMINFO *res_info; TDSPARAMINFO *params; int emulated; /** saved query, we need to know original query if prepare is impossible*/ char *query; } TDSDYNAMIC; typedef enum { TDS_MULTIPLE_QUERY, TDS_MULTIPLE_EXECUTE, TDS_MULTIPLE_RPC } TDS_MULTIPLE_TYPE; typedef struct tds_multiple { TDS_MULTIPLE_TYPE type; unsigned int flags; } TDSMULTIPLE; /* forward declaration */ typedef struct tds_context TDSCONTEXT; struct tds_context { TDSLOCALE *locale; void *parent; /* handler */ int (*msg_handler) (const TDSCONTEXT *, TDSSOCKET *, TDSMESSAGE *); int (*err_handler) (const TDSCONTEXT *, TDSSOCKET *, TDSMESSAGE *); }; enum TDS_ICONV_ENTRY { client2ucs2 , client2server_chardata , iso2server_metadata , initial_char_conv_count /* keep last */ }; struct tds_socket { /* fixed and connect time */ TDS_SYS_SOCKET s; TDS_SMALLINT major_version; TDS_SMALLINT minor_version; /** version of product (Sybase/MS and full version) */ TDS_UINT product_version; char *product_name; unsigned char capabilities[TDS_MAX_CAPABILITY]; unsigned char broken_dates; unsigned char option_flag2; /* in/out buffers */ unsigned char *in_buf; unsigned char *out_buf; unsigned int in_buf_max; unsigned in_pos; unsigned out_pos; unsigned in_len; /* TODO remove blocksize from env and use out_len ?? */ /* unsigned out_len; */ unsigned char in_flag; unsigned char out_flag; unsigned char last_packet; void *parent; /** * info about current query. * Contain information in process, even normal results and compute. * This pointer shouldn't be freed it's just an alias to another structure. */ TDSRESULTINFO *current_results; TDSRESULTINFO *res_info; TDS_INT num_comp_info; TDSCOMPUTEINFO **comp_info; TDSPARAMINFO *param_info; TDSCURSOR *cur_cursor; /**< cursor in use */ TDSCURSOR *cursors; /**< linked list of cursors allocated for this connection */ TDS_TINYINT has_status; TDS_INT ret_status; TDS_STATE state; volatile unsigned char in_cancel; int rows_affected; /* timeout stuff from Jeff */ TDS_INT query_timeout; int (*query_timeout_func) (void *param, unsigned int total_timeout); void *query_timeout_param; time_t query_start_time; TDSENV env; /* dynamic placeholder stuff */ TDSDYNAMIC *cur_dyn; /**< dynamic structure in use */ TDSDYNAMIC *dyns; /**< list of dynamic allocate for this connection */ int emul_little_endian; char *date_fmt; const TDSCONTEXT *tds_ctx; int char_conv_count; TDSICONV **char_convs; /** config for login stuff. After login this field is NULL */ TDSCONNECTION *connection; int spid; TDS_UCHAR collation[5]; void (*env_chg_func) (TDSSOCKET * tds, int type, char *oldval, char *newval); int internal_sp_called; void *tls_session; void *tls_credentials; int option_value; }; int tds_init_write_buf(TDSSOCKET * tds); void tds_free_result_info(TDSRESULTINFO * info); void tds_free_socket(TDSSOCKET * tds); void tds_free_connection(TDSCONNECTION * connection); void tds_free_all_results(TDSSOCKET * tds); void tds_free_results(TDSRESULTINFO * res_info); void tds_free_param_results(TDSPARAMINFO * param_info); void tds_free_param_result(TDSPARAMINFO * param_info); void tds_free_msg(TDSMESSAGE * message); void tds_free_cursor(TDSSOCKET * tds, TDSCURSOR * cursor); void tds_free_bcp_column_data(BCPCOLDATA * coldata); int tds_put_n(TDSSOCKET * tds, const void *buf, int n); int tds_put_string(TDSSOCKET * tds, const char *buf, int len); int tds_put_int(TDSSOCKET * tds, TDS_INT i); int tds_put_int8(TDSSOCKET * tds, TDS_INT8 i); int tds_put_smallint(TDSSOCKET * tds, TDS_SMALLINT si); /** Output a tinyint value */ #define tds_put_tinyint(tds, ti) tds_put_byte(tds,ti) int tds_put_byte(TDSSOCKET * tds, unsigned char c); TDSRESULTINFO *tds_alloc_results(int num_cols); TDSCOMPUTEINFO **tds_alloc_compute_results(TDSSOCKET * tds, int num_cols, int by_cols); TDSCONTEXT *tds_alloc_context(void * parent); void tds_free_context(TDSCONTEXT * locale); TDSSOCKET *tds_alloc_socket(TDSCONTEXT * context, int bufsize); /* config.c */ const TDS_COMPILETIME_SETTINGS *tds_get_compiletime_settings(void); typedef void (*TDSCONFPARSE) (const char *option, const char *value, void *param); int tds_read_conf_section(FILE * in, const char *section, TDSCONFPARSE tds_conf_parse, void *parse_param); int tds_read_conf_file(TDSCONNECTION * connection, const char *server); TDSCONNECTION *tds_read_config_info(TDSSOCKET * tds, TDSLOGIN * login, TDSLOCALE * locale); void tds_fix_connection(TDSCONNECTION * connection); void tds_config_verstr(const char *tdsver, TDSCONNECTION * connection); void tds_lookup_host(const char *servername, char *ip); int tds_set_interfaces_file_loc(const char *interfloc); TDSLOCALE *tds_get_locale(void); unsigned char *tds_alloc_row(TDSRESULTINFO * res_info); unsigned char *tds_alloc_compute_row(TDSCOMPUTEINFO * res_info); BCPCOLDATA * tds_alloc_bcp_column_data(int column_size); int tds_alloc_get_string(TDSSOCKET * tds, char **string, int len); unsigned char *tds7_crypt_pass(const unsigned char *clear_pass, int len, unsigned char *crypt_pass); TDSDYNAMIC *tds_lookup_dynamic(TDSSOCKET * tds, char *id); const char *tds_prtype(int token); /* iconv.c */ void tds_iconv_open(TDSSOCKET * tds, const char *charset); void tds_iconv_close(TDSSOCKET * tds); void tds_srv_charset_changed(TDSSOCKET * tds, const char *charset); void tds7_srv_charset_changed(TDSSOCKET * tds, int sql_collate, int lcid); int tds_iconv_alloc(TDSSOCKET * tds); void tds_iconv_free(TDSSOCKET * tds); TDSICONV *tds_iconv_from_collate(TDSSOCKET * tds, int sql_collate, int lcid); /* threadsafe.c */ char *tds_timestamp_str(char *str, int maxlen); struct hostent *tds_gethostbyname_r(const char *servername, struct hostent *result, char *buffer, int buflen, int *h_errnop); struct hostent *tds_gethostbyaddr_r(const char *addr, int len, int type, struct hostent *result, char *buffer, int buflen, int *h_errnop); struct servent *tds_getservbyname_r(const char *name, const char *proto, struct servent *result, char *buffer, int buflen); #ifdef INADDR_NONE const char *tds_inet_ntoa_r(struct in_addr iaddr, char *ip, size_t len); #endif char *tds_get_homedir(void); /* mem.c */ TDSPARAMINFO *tds_alloc_param_result(TDSPARAMINFO * old_param); void tds_free_input_params(TDSDYNAMIC * dyn); void tds_free_dynamic(TDSSOCKET * tds, TDSDYNAMIC * dyn); TDSSOCKET *tds_realloc_socket(TDSSOCKET * tds, int bufsize); unsigned char *tds_alloc_param_row(TDSPARAMINFO * info, TDSCOLUMN * curparam); char *tds_alloc_client_sqlstate(int msgno); char *tds_alloc_lookup_sqlstate(TDSSOCKET * tds, int msgno); TDSLOGIN *tds_alloc_login(void); TDSDYNAMIC *tds_alloc_dynamic(TDSSOCKET * tds, const char *id); void tds_free_login(TDSLOGIN * login); TDSCONNECTION *tds_alloc_connection(TDSLOCALE * locale); TDSLOCALE *tds_alloc_locale(void); void tds_free_locale(TDSLOCALE * locale); TDSCURSOR * tds_alloc_cursor(TDSSOCKET * tds, const char *name, TDS_INT namelen, const char *query, TDS_INT querylen); void tds_free_row(const TDSRESULTINFO * res_info, unsigned char *row); /* login.c */ int tds7_send_auth(TDSSOCKET * tds, const unsigned char *challenge); void tds_set_packet(TDSLOGIN * tds_login, int packet_size); void tds_set_port(TDSLOGIN * tds_login, int port); void tds_set_passwd(TDSLOGIN * tds_login, const char *password); void tds_set_bulk(TDSLOGIN * tds_login, TDS_TINYINT enabled); void tds_set_user(TDSLOGIN * tds_login, const char *username); void tds_set_app(TDSLOGIN * tds_login, const char *application); void tds_set_host(TDSLOGIN * tds_login, const char *hostname); void tds_set_server_addr(TDSLOGIN * tds_login, const char *server_addr); void tds_set_library(TDSLOGIN * tds_login, const char *library); void tds_set_server(TDSLOGIN * tds_login, const char *server); void tds_set_client_charset(TDSLOGIN * tds_login, const char *charset); void tds_set_language(TDSLOGIN * tds_login, const char *language); void tds_set_version(TDSLOGIN * tds_login, short major_ver, short minor_ver); void tds_set_capabilities(TDSLOGIN * tds_login, unsigned char *capabilities, int size); int tds_connect(TDSSOCKET * tds, TDSCONNECTION * connection); /* query.c */ int tds_submit_query(TDSSOCKET * tds, const char *query); int tds_submit_query_params(TDSSOCKET * tds, const char *query, TDSPARAMINFO * params); int tds_submit_queryf(TDSSOCKET * tds, const char *queryf, ...); int tds_submit_prepare(TDSSOCKET * tds, const char *query, const char *id, TDSDYNAMIC ** dyn_out, TDSPARAMINFO * params); int tds_submit_execdirect(TDSSOCKET * tds, const char *query, TDSPARAMINFO * params); int tds_submit_execute(TDSSOCKET * tds, TDSDYNAMIC * dyn); int tds_send_cancel(TDSSOCKET * tds); const char *tds_next_placeholder(const char *start); int tds_count_placeholders(const char *query); int tds_get_dynid(TDSSOCKET * tds, char **id); int tds_submit_unprepare(TDSSOCKET * tds, TDSDYNAMIC * dyn); int tds_submit_rpc(TDSSOCKET * tds, const char *rpc_name, TDSPARAMINFO * params); int tds_submit_optioncmd(TDSSOCKET * tds, TDS_OPTION_CMD command, TDS_OPTION option, TDS_OPTION_ARG *param, TDS_INT param_size); int tds_quote_id(TDSSOCKET * tds, char *buffer, const char *id, int idlen); int tds_quote_string(TDSSOCKET * tds, char *buffer, const char *str, int len); const char *tds_skip_quoted(const char *s); int tds_cursor_declare(TDSSOCKET * tds, TDSCURSOR * cursor, int *send); int tds_cursor_setrows(TDSSOCKET * tds, TDSCURSOR * cursor, int *send); int tds_cursor_open(TDSSOCKET * tds, TDSCURSOR * cursor, int *send); int tds_cursor_fetch(TDSSOCKET * tds, TDSCURSOR * cursor); int tds_cursor_close(TDSSOCKET * tds, TDSCURSOR * cursor); int tds_cursor_dealloc(TDSSOCKET * tds, TDSCURSOR * cursor); int tds_multiple_init(TDSSOCKET *tds, TDSMULTIPLE *multiple, TDS_MULTIPLE_TYPE type); int tds_multiple_done(TDSSOCKET *tds, TDSMULTIPLE *multiple); int tds_multiple_query(TDSSOCKET *tds, TDSMULTIPLE *multiple, const char *query, TDSPARAMINFO * params); int tds_multiple_execute(TDSSOCKET *tds, TDSMULTIPLE *multiple, TDSDYNAMIC * dyn); /* token.c */ int tds_process_cancel(TDSSOCKET * tds); void tds_swap_datatype(int coltype, unsigned char *buf); void tds_swap_numeric(TDS_NUMERIC *num); int tds_get_token_size(int marker); int tds_process_login_tokens(TDSSOCKET * tds); void tds_add_row_column_size(TDSRESULTINFO * info, TDSCOLUMN * curcol); int tds_process_simple_query(TDSSOCKET * tds); int tds5_send_optioncmd(TDSSOCKET * tds, TDS_OPTION_CMD tds_command, TDS_OPTION tds_option, TDS_OPTION_ARG * tds_argument, TDS_INT * tds_argsize); int tds_client_msg(const TDSCONTEXT * tds_ctx, TDSSOCKET * tds, int msgno, int severity, int state, int line, const char *message); int tds_process_tokens(TDSSOCKET * tds, TDS_INT * result_type, int *done_flags, unsigned flag); /* data.c */ void tds_set_param_type(TDSSOCKET * tds, TDSCOLUMN * curcol, TDS_SERVER_TYPE type); void tds_set_column_type(TDSCOLUMN * curcol, int type); /* tds_convert.c */ TDS_INT tds_datecrack(TDS_INT datetype, const void *di, TDSDATEREC * dr); int tds_get_conversion_type(int srctype, int colsize); extern const char tds_hex_digits[]; /* write.c */ int tds_flush_packet(TDSSOCKET * tds); int tds_put_buf(TDSSOCKET * tds, const unsigned char *buf, int dsize, int ssize); /* read.c */ unsigned char tds_get_byte(TDSSOCKET * tds); void tds_unget_byte(TDSSOCKET * tds); unsigned char tds_peek(TDSSOCKET * tds); TDS_SMALLINT tds_get_smallint(TDSSOCKET * tds); TDS_INT tds_get_int(TDSSOCKET * tds); int tds_get_string(TDSSOCKET * tds, int string_len, char *dest, size_t dest_size); int tds_get_char_data(TDSSOCKET * tds, char *dest, size_t wire_size, TDSCOLUMN * curcol); void *tds_get_n(TDSSOCKET * tds, void *dest, int n); int tds_get_size_by_type(int servertype); /* util.c */ TDS_STATE tds_set_state(TDSSOCKET * tds, TDS_STATE state); void tds_set_parent(TDSSOCKET * tds, void *the_parent); void *tds_get_parent(TDSSOCKET * tds); int tds_swap_bytes(unsigned char *buf, int bytes); int tds_version(TDSSOCKET * tds_socket, char *pversion_string); void tdsdump_off(void); void tdsdump_on(void); int tdsdump_open(const char *filename); void tdsdump_close(void); void tdsdump_dump_buf(const char* file, unsigned int level_line, const char *msg, const void *buf, int length); void tdsdump_log(const char* file, unsigned int level_line, const char *fmt, ...) #if defined(__GNUC__) && __GNUC__ >= 2 __attribute__ ((__format__ (__printf__, 3, 4))) #endif ; extern int tds_debug_flags; /* net.c */ int tds_open_socket(TDSSOCKET * tds, const char *ip_addr, unsigned int port, int timeout); int tds_close_socket(TDSSOCKET * tds); int tds_read_packet(TDSSOCKET * tds); int tds_write_packet(TDSSOCKET * tds, unsigned char final); int tds7_get_instance_port(const char *ip_addr, const char *instance); int tds_ssl_init(TDSSOCKET *tds); void tds_ssl_deinit(TDSSOCKET *tds); /* vstrbuild.c */ int tds_vstrbuild(char *buffer, int buflen, int *resultlen, char *text, int textlen, const char *formats, int formatlen, va_list ap); /* numeric.c */ char *tds_money_to_string(const TDS_MONEY * money, char *s); TDS_INT tds_numeric_to_string(const TDS_NUMERIC * numeric, char *s); TDS_INT tds_numeric_change_prec_scale(TDS_NUMERIC * numeric, unsigned char new_prec, unsigned char new_scale); /* getmac.c */ void tds_getmac(int s, unsigned char mac[6]); typedef struct tds_answer { unsigned char lm_resp[24]; unsigned char nt_resp[24]; } TDSANSWER; void tds_answer_challenge(const char *passwd, const unsigned char *challenge, TDSANSWER * answer); #define IS_TDS42(x) (x->major_version==4 && x->minor_version==2) #define IS_TDS46(x) (x->major_version==4 && x->minor_version==6) #define IS_TDS50(x) (x->major_version==5 && x->minor_version==0) #define IS_TDS70(x) (x->major_version==7 && x->minor_version==0) #define IS_TDS80(x) (x->major_version==8 && x->minor_version==0) #define IS_TDS7_PLUS(x) ( IS_TDS70(x) || IS_TDS80(x) ) #define IS_TDSDEAD(x) (((x) == NULL) || TDS_IS_SOCKET_INVALID((x)->s)) /** Check if product is Sybase (such as Adaptive Server Enterrprice). x should be a TDS_SOCKET*. */ #define TDS_IS_SYBASE(x) (!(x->product_version & 0x80000000u)) /** Check if product is Microsft SQL Server. x should be a TDS_SOCKET*. */ #define TDS_IS_MSSQL(x) ((x->product_version & 0x80000000u)!=0) /** Calc a version number for mssql. Use with TDS_MS_VER(7,0,842). * For test for a range of version you can use check like * if (tds->product_version >= TDS_MS_VER(7,0,0) && tds->product_version < TDS_MS_VER(8,0,0)) */ #define TDS_MS_VER(maj,min,x) (0x80000000u|((maj)<<24)|((min)<<16)|(x)) /* TODO test if not similar to ms one*/ /** Calc a version number for Sybase. */ #define TDS_SYB_VER(maj,min,x) (((maj)<<24)|((min)<<16)|(x)<<8) #ifdef __cplusplus #if 0 { #endif } #endif #endif /* _tds_h_ */