]> git.saurik.com Git - wxWidgets.git/blob - src/iodbc/herr.c
memory leak fixed
[wxWidgets.git] / src / iodbc / herr.c
1 /*
2 * herr.c
3 *
4 * $Id$
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
43 static 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
62 void
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
74 HERR
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
114 static 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
141 static 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
178 RETCODE SQL_API
179 SQLError (
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 }