1/* 2 * herr.c 3 * 4 * $Id: herr.c 2613 1999-06-01 15:32:12Z VZ $ 5 * 6 * Error stack management functions 7 * 8 * The iODBC driver manager. 9 * 10 * Copyright (C) 1995 by Ke Jin <kejin@empress.com> 11 * 12 * This library is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU Library General Public 14 * License as published by the Free Software Foundation; either 15 * version 2 of the License, or (at your option) any later version. 16 * 17 * This library is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 * Library General Public License for more details. 21 * 22 * You should have received a copy of the GNU Library General Public 23 * License along with this library; if not, write to the Free 24 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 25 */ 26 27#include "config.h" 28 29#include "isql.h" 30#include "isqlext.h" 31 32#include "dlproc.h" 33 34#include "herr.h" 35#include "henv.h" 36#include "hdbc.h" 37#include "hstmt.h" 38 39#include "itrace.h" 40 41#include "herr.ci" 42 43static HERR 44_iodbcdm_popsqlerr (HERR herr) 45{ 46 sqlerr_t *list = (sqlerr_t *) herr; 47 sqlerr_t *next; 48 49 if (herr == SQL_NULL_HERR) 50 { 51 return herr; 52 } 53 54 next = list->next; 55 56 MEM_FREE (list); 57 58 return next; 59} 60 61 62void 63_iodbcdm_freesqlerrlist (HERR herrlist) 64{ 65 HERR list; 66 67 for (list = herrlist; list != 0;) 68 { 69 list = _iodbcdm_popsqlerr (list); 70 } 71} 72 73 74HERR 75_iodbcdm_pushsqlerr ( 76 HERR herr, 77 sqlstcode_t code, 78 char *msg) 79{ 80 sqlerr_t *ebuf; 81 sqlerr_t *perr = (sqlerr_t *) herr; 82 int idx = 0; 83 84 if (herr != SQL_NULL_HERR) 85 { 86 idx = perr->idx + 1; 87 } 88 89 if (idx == 64) 90 /* over wirte the top entry to prevent error stack blow out */ 91 { 92 perr->code = code; 93 perr->msg = msg; 94 95 return herr; 96 } 97 98 ebuf = (sqlerr_t *) MEM_ALLOC (sizeof (sqlerr_t)); 99 100 if (ebuf == NULL) 101 { 102 return NULL; 103 } 104 105 ebuf->msg = msg; 106 ebuf->code = code; 107 ebuf->idx = idx; 108 ebuf->next = (sqlerr_t *) herr; 109 110 return (HERR) ebuf; 111} 112 113 114static char FAR * 115_iodbcdm_getsqlstate ( 116 HERR herr, 117 void FAR * tab) 118{ 119 sqlerr_t *perr = (sqlerr_t *) herr; 120 sqlerrmsg_t *ptr; 121 122 if (herr == SQL_NULL_HERR || tab == NULL) 123 { 124 return (char FAR *) NULL; 125 } 126 127 for (ptr = tab; 128 ptr->code != en_sqlstat_total; 129 ptr++) 130 { 131 if (ptr->code == perr->code) 132 { 133 return (char FAR *) (ptr->stat); 134 } 135 } 136 137 return (char FAR *) NULL; 138} 139 140 141static char FAR * 142_iodbcdm_getsqlerrmsg ( 143 HERR herr, 144 void FAR * errtab) 145{ 146 sqlerr_t *perr = (sqlerr_t *) herr; 147 sqlerrmsg_t *ptr; 148 149 if (herr == SQL_NULL_HERR) 150 { 151 return NULL; 152 } 153 154 if (perr->msg == NULL && errtab == NULL) 155 { 156 return NULL; 157 } 158 159 if (perr->msg != NULL) 160 { 161 return perr->msg; 162 } 163 164 for (ptr = (sqlerrmsg_t *) errtab; 165 ptr->code != en_sqlstat_total; 166 ptr++) 167 { 168 if (ptr->code == perr->code) 169 { 170 return (char FAR *) ptr->msg; 171 } 172 } 173 174 return (char FAR *) NULL; 175} 176 177 178RETCODE SQL_API 179SQLError ( 180 HENV henv, 181 HDBC hdbc, 182 HSTMT hstmt, 183 UCHAR FAR * szSqlstate, 184 SDWORD FAR * pfNativeError, 185 UCHAR FAR * szErrorMsg, 186 SWORD cbErrorMsgMax, 187 SWORD FAR * pcbErrorMsg) 188{ 189 GENV_t FAR *genv = (GENV_t FAR *) henv; 190 DBC_t FAR *pdbc = (DBC_t FAR *) hdbc; 191 STMT_t FAR *pstmt = (STMT_t FAR *) hstmt; 192 HDBC thdbc; 193 194 HENV dhenv = SQL_NULL_HENV; 195 HDBC dhdbc = SQL_NULL_HDBC; 196 HSTMT dhstmt = SQL_NULL_HSTMT; 197 198 HERR herr = SQL_NULL_HERR; 199 HPROC hproc = SQL_NULL_HPROC; 200 201 char FAR *errmsg = NULL; 202 char FAR *ststr = NULL; 203 204 int handle = 0; 205 RETCODE retcode = SQL_SUCCESS; 206 207 if (hstmt != SQL_NULL_HSTMT) /* retrive stmt err */ 208 { 209 herr = pstmt->herr; 210 thdbc = pstmt->hdbc; 211 212 if (thdbc == SQL_NULL_HDBC) 213 { 214 return SQL_INVALID_HANDLE; 215 } 216 hproc = _iodbcdm_getproc (thdbc, en_Error); 217 dhstmt = pstmt->dhstmt; 218 handle = 3; 219 } 220 else if (hdbc != SQL_NULL_HDBC) /* retrive dbc err */ 221 { 222 herr = pdbc->herr; 223 thdbc = hdbc; 224 if (thdbc == SQL_NULL_HDBC) 225 { 226 return SQL_INVALID_HANDLE; 227 } 228 hproc = _iodbcdm_getproc (thdbc, en_Error); 229 dhdbc = pdbc->dhdbc; 230 handle = 2; 231 232 if (herr == SQL_NULL_HERR 233 && pdbc->henv == SQL_NULL_HENV) 234 { 235 return SQL_NO_DATA_FOUND; 236 } 237 } 238 else if (henv != SQL_NULL_HENV) /* retrive env err */ 239 { 240 herr = genv->herr; 241 242 /* Drivers shouldn't push error message 243 * on envoriment handle */ 244 245 if (herr == SQL_NULL_HERR) 246 { 247 return SQL_NO_DATA_FOUND; 248 } 249 250 handle = 1; 251 } 252 else 253 { 254 return SQL_INVALID_HANDLE; 255 } 256 257 if (szErrorMsg != NULL) 258 { 259 if (cbErrorMsgMax < 0 260 || cbErrorMsgMax > SQL_MAX_MESSAGE_LENGTH - 1) 261 { 262 return SQL_ERROR; 263 /* SQLError() doesn't post error for itself */ 264 } 265 } 266 267 if (herr == SQL_NULL_HERR) /* no err on drv mng */ 268 { 269 /* call driver */ 270 if (hproc == SQL_NULL_HPROC) 271 { 272 PUSHSQLERR (herr, en_IM001); 273 274 return SQL_ERROR; 275 } 276 277 CALL_DRIVER (thdbc, retcode, hproc, en_Error, 278 (dhenv, dhdbc, dhstmt, szSqlstate, pfNativeError, szErrorMsg, 279 cbErrorMsgMax, pcbErrorMsg)) 280 281 return retcode; 282 } 283 284 if (szSqlstate != NULL) 285 { 286 int len; 287 288 /* get sql state string */ 289 ststr = (char FAR *) _iodbcdm_getsqlstate (herr, 290 (void FAR *) sqlerrmsg_tab); 291 292 if (ststr == NULL) 293 { 294 len = 0; 295 } 296 else 297 { 298 len = (int) STRLEN (ststr); 299 } 300 301 STRNCPY (szSqlstate, ststr, len); 302 szSqlstate[len] = 0; 303 /* buffer size of szSqlstate is not checked. Applications 304 * suppose provide enough ( not less than 6 bytes ) buffer 305 * or NULL for it. 306 */ 307 } 308 309 if (pfNativeError != NULL) 310 { 311 /* native error code is specific to data source */ 312 *pfNativeError = (SDWORD) 0L; 313 } 314 315 if (szErrorMsg == NULL || cbErrorMsgMax == 0) 316 { 317 if (pcbErrorMsg != NULL) 318 { 319 *pcbErrorMsg = (SWORD) 0; 320 } 321 } 322 else 323 { 324 int len; 325 char msgbuf[256] = {'\0'}; 326 327 /* get sql state message */ 328 errmsg = _iodbcdm_getsqlerrmsg (herr, (void FAR *) sqlerrmsg_tab); 329 330 if (errmsg == NULL) 331 { 332 errmsg = (char FAR *) ""; 333 } 334 335 sprintf (msgbuf, "%s%s", sqlerrhd, errmsg); 336 337 len = STRLEN (msgbuf); 338 339 if (len < cbErrorMsgMax - 1) 340 { 341 retcode = SQL_SUCCESS; 342 } 343 else 344 { 345 len = cbErrorMsgMax - 1; 346 retcode = SQL_SUCCESS_WITH_INFO; 347 /* and not posts error for itself */ 348 } 349 350 STRNCPY ((char *) szErrorMsg, msgbuf, len); 351 szErrorMsg[len] = 0; 352 353 if (pcbErrorMsg != NULL) 354 { 355 *pcbErrorMsg = (SWORD) len; 356 } 357 } 358 359 switch (handle) /* free this err */ 360 { 361 case 1: 362 genv->herr = _iodbcdm_popsqlerr (genv->herr); 363 break; 364 365 case 2: 366 pdbc->herr = _iodbcdm_popsqlerr (pdbc->herr); 367 break; 368 369 case 3: 370 pstmt->herr = _iodbcdm_popsqlerr (pstmt->herr); 371 break; 372 373 default: 374 break; 375 } 376 377 return retcode; 378} 379