NCBI C++ ToolKit
dbutil.c
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
2  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Brian Bruns
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19 
20 #include <config.h>
21 
22 #include <stdarg.h>
23 #include <stdio.h>
24 #include <assert.h>
25 
26 #if HAVE_STDLIB_H
27 #include <stdlib.h>
28 #endif /* HAVE_STDLIB_H */
29 
30 #if HAVE_ERRNO_H
31 # include <errno.h>
32 #endif /* HAVE_ERRNO_H */
33 
34 #include <freetds/tds.h>
35 #include <freetds/convert.h>
36 #include <sybdb.h>
37 #include <syberror.h>
38 #include <dblib.h>
39 
40 /*
41  * test include consistency
42  * I don't think all compiler are able to compile this code... if not comment it
43  */
44 #if ENABLE_EXTRA_CHECKS
45 
46 /* TODO test SYBxxx consistency */
47 
48 #define TEST_ATTRIBUTE(t,sa,fa,sb,fb) \
49  TDS_COMPILE_CHECK(t,sizeof(((sa*)0)->fa) == sizeof(((sb*)0)->fb) && TDS_OFFSET(sa,fa) == TDS_OFFSET(sb,fb))
50 
51 TEST_ATTRIBUTE(t21,TDS_MONEY4,mny4,DBMONEY4,mny4);
52 TEST_ATTRIBUTE(t22,TDS_OLD_MONEY,mnyhigh,DBMONEY,mnyhigh);
53 TEST_ATTRIBUTE(t23,TDS_OLD_MONEY,mnylow,DBMONEY,mnylow);
54 TEST_ATTRIBUTE(t24,TDS_DATETIME,dtdays,DBDATETIME,dtdays);
55 TEST_ATTRIBUTE(t25,TDS_DATETIME,dttime,DBDATETIME,dttime);
56 TEST_ATTRIBUTE(t26,TDS_DATETIME4,days,DBDATETIME4,days);
57 TEST_ATTRIBUTE(t27,TDS_DATETIME4,minutes,DBDATETIME4,minutes);
58 TEST_ATTRIBUTE(t28,TDS_NUMERIC,precision,DBNUMERIC,precision);
59 TEST_ATTRIBUTE(t29,TDS_NUMERIC,scale,DBNUMERIC,scale);
60 TEST_ATTRIBUTE(t30,TDS_NUMERIC,array,DBNUMERIC,array);
61 #endif
62 
63 /*
64  * The next 2 functions receive the info and error messages that come from the TDS layer.
65  * The address of this function is passed to the TDS layer in dbinit().
66  * It takes a pointer to a DBPROCESS, it's just that the TDS layer didn't
67  * know what it really was.
68  */
69 int
71 {
73 
74  tdsdump_log(TDS_DBG_FUNC, "_dblib_handle_info_message(%p, %p, %p)\n", tds_ctx, tds, msg);
75  tdsdump_log(TDS_DBG_FUNC, "msgno %d: \"%s\"\n", msg->msgno, msg->message);
76 
77  /*
78  * Check to see if the user supplied a function, else ignore the message.
79  */
80  if (_dblib_msg_handler) {
82  msg->msgno,
83  msg->state,
84  msg->severity, msg->message, msg->server, msg->proc_name, msg->line_number);
85  }
86 
87  if (msg->severity > 10 && _dblib_err_handler) { /* call the application's error handler, if installed. */
88  /*
89  * Sybase docs say SYBESMSG is generated only in specific
90  * cases (severity greater than 16, or deadlock occurred, or
91  * a syntax error occurred.) However, actual observed
92  * behavior is that SYBESMSG is always generated for
93  * server messages with severity greater than 10.
94  */
95  /* Cannot call dbperror() here because server messsage numbers (and text) are not in its lookup table. */
96  static const char message[] = "General SQL Server error: Check messages from the SQL Server";
97  (*_dblib_err_handler)(dbproc, msg->severity, SYBESMSG, DBNOERR, (char *) message, NULL);
98  }
99  return TDS_SUCCESS;
100 }
101 
102 /** \internal
103  * \dblib_internal
104  * \brief handle errors generated by libtds
105  * \param tds_ctx actually a dbproc: contains all information needed by db-lib to manage communications with the server.
106  * \param tds contains all information needed by libtds to manage communications with the server.
107  * \param msg the message to send
108  * \returns
109  * \remarks This function is called by libtds via tds_ctx->err_handler. It exists to convert the db-lib
110  * error handler's return code into one that libtds will know how to handle.
111  * libtds conveniently issues msgno's with the same values and meanings as db-lib and ODBC use.
112  * (N.B. ODBC actually uses db-lib msgno numbers for its driver-specific "server errors".
113  */
114 /*
115  * Stack:
116  * libtds
117  * tds_ctx->err_handler (pointer to _dblib_handle_err_message)
118  * _dblib_handle_err_message
119  * dbperror
120  * client (or default) error handler
121  * returns db-lib defined return code INT_something.
122  * returns db-lib return code with Sybase semantics (adjusting client's code if need be)
123  * returns libtds return code
124  * decides what to do based on the universal libtds return code, thank you.
125  */
126 int
128 {
130  int rc = INT_CANCEL;
131 
133  assert(msg);
134 
135  rc = dbperror(dbproc, msg->msgno, msg->oserr);
136 
137  /*
138  * Preprocess the return code to handle INT_TIMEOUT/INT_CONTINUE
139  * for non-SYBETIME errors in the strange and different ways as
140  * specified by Sybase and Microsoft.
141  */
142  if (msg->msgno != SYBETIME) {
143  switch (rc) {
144  case INT_TIMEOUT:
145  rc = INT_EXIT;
146  break;
147  case INT_CONTINUE:
148  if (!dbproc || !dbproc->msdblib) {
149  /* Sybase behavior */
150  assert(0); /* dbperror() should prevent */
151  rc = INT_EXIT;
152  } else {
153  /* Microsoft behavior */
154  rc = INT_CANCEL;
155  }
156  break;
157  default:
158  break;
159  }
160  }
161 
162  /*
163  * Convert db-lib return code to libtds return code, and return.
164  */
165  switch (rc) {
166  case INT_CANCEL: return TDS_INT_CANCEL;
167  case INT_TIMEOUT: return TDS_INT_TIMEOUT;
168  case INT_CONTINUE: return TDS_INT_CONTINUE;
169 
170  case INT_EXIT:
171  assert(0); /* dbperror() should prevent */
172  default:
173  /* unknown return code from error handler */
175  break;
176  }
177 
178  /* not reached */
179  assert(0);
180  return TDS_INT_CANCEL;
181 }
182 
183 /**
184  * \ingroup dblib_internal
185  * \brief check interrupts for libtds.
186  *
187  * \param vdbproc a DBPROCESS pointer, contains all information needed by db-lib to manage communications with the server.
188  * \sa DBDEAD(), dbsetinterrupt().
189  */
190 int
192 {
193  DBPROCESS * dbproc = (DBPROCESS*) vdbproc;
194  int ret = INT_CONTINUE;
195 
196  assert( dbproc != NULL );
197 
198  if (dbproc->chkintr == NULL || dbproc->hndlintr == NULL)
199  return INT_CONTINUE;
200 
201  tdsdump_log(TDS_DBG_FUNC, "_dblib_check_and_handle_interrupt %p [%p, %p]\n", dbproc, dbproc->chkintr, dbproc->hndlintr);
202 
203  if (dbproc->chkintr(dbproc)){
204  switch (ret = dbproc->hndlintr(dbproc)) {
205  case INT_EXIT:
206  tdsdump_log(TDS_DBG_FUNC, "dbproc->hndlintr returned INT_EXIT, goodbye!\n");
207  exit(1);
208  case INT_CANCEL:
209  tdsdump_log(TDS_DBG_FUNC, "dbproc->hndlintr returned INT_CANCEL\n");
210  break;
211  case INT_CONTINUE:
212  tdsdump_log(TDS_DBG_FUNC, "dbproc->hndlintr returned INT_CONTINUE\n");
213  break;
214  default:
215  tdsdump_log(TDS_DBG_FUNC, "dbproc->hndlintr returned an invalid value (%d), returning INT_CONTINUE\n", ret);
216  ret = INT_CONTINUE;
217  break;
218  }
219  }
220  return ret;
221 }
222 
223 
224 void
226 {
227  switch (version) {
228  case DBVERSION_42:
229  tds_set_version(tds_login, 4, 2);
230  break;
231  case DBVERSION_46:
232  tds_set_version(tds_login, 4, 6);
233  break;
234  case DBVERSION_100:
235  tds_set_version(tds_login, 5, 0);
236  break;
237  }
238 }
239 
240 void
242 {
243  switch (len) {
244  case TDS_CONVERT_NOAVAIL:
245  dbperror(dbproc, SYBERDCN, 0);
246  break;
247  case TDS_CONVERT_SYNTAX:
248  dbperror(dbproc, SYBECSYN, 0);
249  break;
250  case TDS_CONVERT_NOMEM:
251  dbperror(dbproc, SYBEMEM, ENOMEM);
252  break;
254  dbperror(dbproc, SYBECOFL, 0);
255  break;
256  default:
257  case TDS_CONVERT_FAIL:
259  break;
260  }
261 }
262 
#define EXIT_FAILURE
Definition: fastme.h:73
int _dblib_handle_info_message(const TDSCONTEXT *tds_ctx, TDSSOCKET *tds, TDSMESSAGE *msg)
Definition: dbutil.c:70
void _dblib_convert_err(DBPROCESS *dbproc, TDS_INT len)
Definition: dbutil.c:241
int _dblib_handle_err_message(const TDSCONTEXT *tds_ctx, TDSSOCKET *tds, TDSMESSAGE *msg)
Definition: dbutil.c:127
void _dblib_setTDS_version(TDSLOGIN *tds_login, DBINT version)
Definition: dbutil.c:225
static DBPROCESS * dbproc
Definition: done_handling.c:29
#define TDS_CONVERT_SYNTAX
Definition: convert.h:78
#define TDS_CONVERT_OVERFLOW
Definition: convert.h:80
#define TDS_CONVERT_NOMEM
Definition: convert.h:79
#define TDS_CONVERT_NOAVAIL
Definition: convert.h:77
#define TDS_CONVERT_FAIL
Definition: convert.h:76
#define TDS_INT_TIMEOUT
Definition: tds.h:211
tds_sysdep_int32_type TDS_INT
Definition: tds.h:149
#define tds_get_parent(tds)
Definition: tds.h:1296
#define tdsdump_log
Definition: tds.h:1561
#define TDS_INT_CONTINUE
Definition: tds.h:209
#define TDS_INT_CANCEL
Definition: tds.h:210
#define TDS_SUCCESS
Definition: tds.h:203
#define TDS_DBG_FUNC
Definition: tds.h:898
static char precision
Definition: genparams.c:28
#define SYBEMEM
Definition: sybdb.h:938
#define INT_TIMEOUT
Definition: sybdb.h:63
#define SYBETIME
Definition: sybdb.h:931
#define SYBECSYN
Definition: sybdb.h:978
#define SYBECOFL
Definition: sybdb.h:977
#define DBVERSION_100
Definition: sybdb.h:74
#define SYBESMSG
Definition: sybdb.h:946
#define DBVERSION_42
Definition: sybdb.h:75
#define SYBECINTERNAL
Definition: sybdb.h:1147
#define DBNOERR
Definition: sybdb.h:58
#define INT_CONTINUE
Definition: sybdb.h:61
Int4 DBINT
Definition: sybdb.h:255
#define DBVERSION_46
Definition: sybdb.h:73
#define SYBERDCN
Definition: sybdb.h:981
#define INT_CANCEL
Definition: sybdb.h:62
#define INT_EXIT
Definition: sybdb.h:60
static TDSSOCKET * tds
Definition: collations.c:37
#define _dblib_msg_handler
#define dbperror
#define _dblib_err_handler
#define tds_set_version
#define NULL
Definition: ncbistd.hpp:225
int _dblib_check_and_handle_interrupt(void *vdbproc)
check interrupts for libtds.
Definition: dbutil.c:191
exit(2)
int len
const string version
version string
Definition: variables.hpp:66
static SLJIT_INLINE sljit_ins msg(sljit_gpr r, sljit_s32 d, sljit_gpr x, sljit_gpr b)
#define assert(x)
Definition: srv_diag.hpp:58
Definition: sybdb.h:286
DB_DBCHKINTR_FUNC chkintr
Definition: dblib.h:148
DB_DBHNDLINTR_FUNC hndlintr
Definition: dblib.h:149
int msdblib
boolean use ms behaviour
Definition: dblib.h:152
Definition: tds.h:584
Information for a server connection.
Definition: tds.h:1211
Modified on Fri Sep 20 14:58:14 2024 by modify_doxy.py rev. 669887