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