]>
Commit | Line | Data |
---|---|---|
cd5bf2a6 RR |
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) | |
1a6944fd | 45 | { |
cd5bf2a6 RR |
46 | sqlerr_t *list = (sqlerr_t *) herr; |
47 | sqlerr_t *next; | |
7e616b10 | 48 | |
cd5bf2a6 RR |
49 | if (herr == SQL_NULL_HERR) |
50 | { | |
51 | return herr; | |
52 | } | |
1a6944fd | 53 | |
cd5bf2a6 | 54 | next = list->next; |
1a6944fd | 55 | |
cd5bf2a6 | 56 | MEM_FREE (list); |
1a6944fd | 57 | |
cd5bf2a6 | 58 | return next; |
1a6944fd RR |
59 | } |
60 | ||
cd5bf2a6 RR |
61 | |
62 | void | |
63 | _iodbcdm_freesqlerrlist (HERR herrlist) | |
1a6944fd | 64 | { |
cd5bf2a6 | 65 | HERR list; |
1a6944fd | 66 | |
cd5bf2a6 RR |
67 | for (list = herrlist; list != 0;) |
68 | { | |
69 | list = _iodbcdm_popsqlerr (list); | |
70 | } | |
1a6944fd RR |
71 | } |
72 | ||
cd5bf2a6 RR |
73 | |
74 | HERR | |
75 | _iodbcdm_pushsqlerr ( | |
76 | HERR herr, | |
77 | sqlstcode_t code, | |
78 | char *msg) | |
1a6944fd | 79 | { |
cd5bf2a6 RR |
80 | sqlerr_t *ebuf; |
81 | sqlerr_t *perr = (sqlerr_t *) herr; | |
82 | int idx = 0; | |
7e616b10 | 83 | |
cd5bf2a6 RR |
84 | if (herr != SQL_NULL_HERR) |
85 | { | |
86 | idx = perr->idx + 1; | |
87 | } | |
7e616b10 | 88 | |
cd5bf2a6 RR |
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; | |
7e616b10 | 94 | |
cd5bf2a6 RR |
95 | return herr; |
96 | } | |
7e616b10 | 97 | |
cd5bf2a6 | 98 | ebuf = (sqlerr_t *) MEM_ALLOC (sizeof (sqlerr_t)); |
7e616b10 | 99 | |
cd5bf2a6 RR |
100 | if (ebuf == NULL) |
101 | { | |
102 | return NULL; | |
103 | } | |
7e616b10 | 104 | |
cd5bf2a6 RR |
105 | ebuf->msg = msg; |
106 | ebuf->code = code; | |
107 | ebuf->idx = idx; | |
108 | ebuf->next = (sqlerr_t *) herr; | |
7e616b10 | 109 | |
cd5bf2a6 | 110 | return (HERR) ebuf; |
1a6944fd RR |
111 | } |
112 | ||
cd5bf2a6 RR |
113 | |
114 | static char FAR * | |
115 | _iodbcdm_getsqlstate ( | |
116 | HERR herr, | |
117 | void FAR * tab) | |
1a6944fd | 118 | { |
cd5bf2a6 RR |
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; | |
1a6944fd RR |
138 | } |
139 | ||
cd5bf2a6 RR |
140 | |
141 | static char FAR * | |
142 | _iodbcdm_getsqlerrmsg ( | |
143 | HERR herr, | |
144 | void FAR * errtab) | |
1a6944fd | 145 | { |
cd5bf2a6 RR |
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; | |
1a6944fd RR |
175 | } |
176 | ||
cd5bf2a6 RR |
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) | |
1a6944fd | 188 | { |
cd5bf2a6 RR |
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; | |
1a6944fd | 378 | } |