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