1 : /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
2 : * Copyright (C) 1998-1999 Brian Bruns
3 : * Copyright (C) 2003, 2004, 2005 Frediano Ziglio
4 : *
5 : * This library is free software; you can redistribute it and/or
6 : * modify it under the terms of the GNU Library General Public
7 : * License as published by the Free Software Foundation; either
8 : * version 2 of the License, or (at your option) any later version.
9 : *
10 : * This library 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 GNU
13 : * Library General Public License for more details.
14 : *
15 : * You should have received a copy of the GNU Library General Public
16 : * License along with this library; if not, write to the
17 : * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 : * Boston, MA 02111-1307, USA.
19 : */
20 :
21 : #if HAVE_CONFIG_H
22 : #include <config.h>
23 : #endif /* HAVE_CONFIG_H */
24 :
25 : #include <stdio.h>
26 :
27 : #if HAVE_STDLIB_H
28 : #include <stdlib.h>
29 : #endif /* HAVE_STDLIB_H */
30 :
31 : #if HAVE_STRING_H
32 : #include <string.h>
33 : #endif /* HAVE_STRING_H */
34 :
35 : #include <assert.h>
36 :
37 : #include "tdsodbc.h"
38 : #include "tdsstring.h"
39 : #include "replacements.h"
40 :
41 : #if HAVE_ODBCSS_H
42 : #include <odbcss.h>
43 : #endif
44 :
45 : #ifdef DMALLOC
46 : #include <dmalloc.h>
47 : #endif
48 :
49 : TDS_RCSID(var, "$Id: error.c,v 1.43 2005/07/17 07:48:10 freddy77 Exp $");
50 :
51 : static void odbc_errs_pop(struct _sql_errors *errs);
52 : static const char *odbc_get_msg(const char *sqlstate);
53 : static void odbc_get_v2state(const char *sqlstate, char *dest_state);
54 : static void sqlstate2to3(char *state);
55 :
56 : struct s_SqlMsgMap
57 : {
58 : const char *msg;
59 : char sqlstate[6];
60 : };
61 :
62 : /* This list contains both v2 and v3 messages */
63 : #define ODBCERR(s3,msg) { msg, s3 }
64 : static const struct s_SqlMsgMap SqlMsgMap[] = {
65 : ODBCERR("IM007", "No data source or driver specified"),
66 : ODBCERR("01000", "Warning"),
67 : ODBCERR("01002", "Disconnect error"),
68 : ODBCERR("01004", "Data truncated"),
69 : ODBCERR("01504", "The UPDATE or DELETE statement does not include a WHERE clause"),
70 : ODBCERR("01508", "Statement disqualified for blocking"),
71 : ODBCERR("01S00", "Invalid connection string attribute"),
72 : ODBCERR("01S01", "Error in row"),
73 : ODBCERR("01S02", "Option value changed"),
74 : ODBCERR("01S06", "Attempt to fetch before the result set returned the first rowset"),
75 : ODBCERR("01S07", "Fractional truncation"),
76 : ODBCERR("07001", "Wrong number of parameters"),
77 : ODBCERR("07002", "Too many columns"),
78 : ODBCERR("07005", "The statement did not return a result set"),
79 : ODBCERR("07006", "Invalid conversion"),
80 : ODBCERR("07009", "Invalid descriptor index"),
81 : ODBCERR("08001", "Unable to connect to data source"),
82 : ODBCERR("08002", "Connection in use"),
83 : ODBCERR("08003", "Connection is closed"),
84 : ODBCERR("08004", "The application server rejected establishment of the connection"),
85 : ODBCERR("08007", "Connection failure during transaction"),
86 : ODBCERR("08S01", "Communication link failure"),
87 : ODBCERR("0F001", "The LOB token variable does not currently represent any value"),
88 : ODBCERR("21S01", "Insert value list does not match column list"),
89 : ODBCERR("22001", "String data right truncation"),
90 : ODBCERR("22002", "Invalid output or indicator buffer specified"),
91 : ODBCERR("22003", "Numeric value out of range"),
92 : ODBCERR("22005", "Error in assignment"),
93 : ODBCERR("22007", "Invalid datetime format"),
94 : ODBCERR("22008", "Datetime field overflow"),
95 : ODBCERR("22011", "A substring error occurred"),
96 : ODBCERR("22012", "Division by zero is invalid"),
97 : ODBCERR("22015", "Interval field overflow"),
98 : ODBCERR("22018", "Invalid character value for cast specification"),
99 : ODBCERR("22019", "Invalid escape character"),
100 : ODBCERR("22025", "Invalid escape sequence"),
101 : ODBCERR("22026", "String data, length mismatch"),
102 : ODBCERR("23000", "Integrity constraint violation"),
103 : ODBCERR("24000", "Invalid cursor state"),
104 : ODBCERR("24504", "The cursor identified in the UPDATE, DELETE, SET, or GET statement is not positioned on a row"),
105 : ODBCERR("25501", "Invalid transaction state"),
106 : ODBCERR("28000", "Invalid authorization specification"),
107 : ODBCERR("34000", "Invalid cursor name"),
108 : ODBCERR("37000", "Invalid SQL syntax"),
109 : ODBCERR("40001", "Serialization failure"),
110 : ODBCERR("40003", "Statement completion unknown"),
111 : ODBCERR("42000", "Syntax error or access violation"),
112 : ODBCERR("42601", "PARMLIST syntax error"),
113 : ODBCERR("42818", "The operands of an operator or function are not compatible"),
114 : ODBCERR("42895", "The value of a host variable in the EXECUTE or OPEN statement cannot be used because of its data type"),
115 : ODBCERR("428A1", "Unable to access a file referenced by a host file variable"),
116 : ODBCERR("44000", "Integrity constraint violation"),
117 : ODBCERR("54028", "The maximum number of concurrent LOB handles has been reached"),
118 : ODBCERR("56084", "LOB data is not supported in DRDA"),
119 : ODBCERR("58004", "Unexpected system failure"),
120 : ODBCERR("HY000", "General driver error"),
121 : ODBCERR("HY001", "Memory allocation failure"),
122 : ODBCERR("HY002", "Invalid column number"),
123 : ODBCERR("HY003", "Program type out of range"),
124 : ODBCERR("HY004", "Invalid data type"),
125 : ODBCERR("HY007", "Associated statement is not prepared"),
126 : ODBCERR("HY008", "Operation was cancelled"),
127 : ODBCERR("HY009", "Invalid argument value"),
128 : ODBCERR("HY010", "Function sequence error"),
129 : ODBCERR("HY011", "Operation invalid at this time"),
130 : ODBCERR("HY012", "Invalid transaction code"),
131 : ODBCERR("HY013", "Unexpected memory handling error"),
132 : ODBCERR("HY014", "No more handles"),
133 : ODBCERR("HY016", "Cannot modify an implementation row descriptor"),
134 : ODBCERR("HY017", "Invalid use of an automatically allocated descriptor handle"),
135 : ODBCERR("HY018", "Server declined cancel request"),
136 : ODBCERR("HY021", "Inconsistent descriptor information"),
137 : ODBCERR("HY024", "Invalid attribute value"),
138 : ODBCERR("HY090", "Invalid string or buffer length"),
139 : ODBCERR("HY091", "Descriptor type out of range"),
140 : ODBCERR("HY092", "Invalid option"),
141 : ODBCERR("HY093", "Invalid parameter number"),
142 : ODBCERR("HY094", "Invalid scale value"),
143 : ODBCERR("HY096", "Information type out of range"),
144 : ODBCERR("HY097", "Column type out of range"),
145 : ODBCERR("HY098", "Scope type out of range"),
146 : ODBCERR("HY099", "Nullable type out of range"),
147 : ODBCERR("HY100", "Uniqueness option type out of range"),
148 : ODBCERR("HY101", "Accuracy option type out of range"),
149 : ODBCERR("HY103", "Direction option out of range"),
150 : ODBCERR("HY104", "Invalid precision value"),
151 : ODBCERR("HY105", "Invalid parameter type"),
152 : ODBCERR("HY106", "Fetch type out of range"),
153 : ODBCERR("HY107", "Row value out of range"),
154 : ODBCERR("HY109", "Invalid cursor position"),
155 : ODBCERR("HY110", "Invalid driver completion"),
156 : ODBCERR("HY111", "Invalid bookmark value"),
157 : ODBCERR("HY501", "Invalid data source name"),
158 : ODBCERR("HY503", "Invalid file name length"),
159 : ODBCERR("HY506", "Error closing a file"),
160 : ODBCERR("HY509", "Error deleting a file"),
161 : ODBCERR("HYC00", "Driver not capable"),
162 : ODBCERR("HYT00", "Timeout expired"),
163 : ODBCERR("HYT01", "Connection timeout expired"),
164 : ODBCERR("S0001", "Database object already exists"),
165 : ODBCERR("S0002", "Database object does not exist"),
166 : ODBCERR("S0011", "Index already exists"),
167 : ODBCERR("S0012", "Index not found"),
168 : ODBCERR("S0021", "Column already exists"),
169 : ODBCERR("S0022", "Column not found"),
170 : ODBCERR("", NULL)
171 : };
172 :
173 : #undef ODBCERR
174 :
175 : struct s_v3to2map
176 : {
177 : char v3[6];
178 : char v2[6];
179 : };
180 :
181 : /* Map a v3 SQLSTATE to a v2 */
182 : static const struct s_v3to2map v3to2map[] = {
183 : {"01001", "01S03"},
184 : {"01001", "01S04"},
185 : {"HY019", "22003"},
186 : {"22007", "22008"},
187 : {"22018", "22005"},
188 : {"07005", "24000"},
189 : {"42000", "37000"},
190 : {"HY018", "70100"},
191 : {"42S01", "S0001"},
192 : {"42S02", "S0002"},
193 : {"42S11", "S0011"},
194 : {"42S12", "S0012"},
195 : {"42S21", "S0021"},
196 : {"42S22", "S0022"},
197 : {"42S23", "S0023"},
198 : {"HY000", "S1000"},
199 : {"HY001", "S1001"},
200 : {"07009", "S1002"},
201 : {"HY003", "S1003"},
202 : {"HY004", "S1004"},
203 : {"HY008", "S1008"},
204 : {"HY009", "S1009"},
205 : {"HY024", "S1009"},
206 : {"HY007", "S1010"},
207 : {"HY010", "S1010"},
208 : {"HY011", "S1011"},
209 : {"HY012", "S1012"},
210 : {"HY090", "S1090"},
211 : {"HY091", "S1091"},
212 : {"HY092", "S1092"},
213 : /* {"07009", "S1093"}, */
214 : {"HY096", "S1096"},
215 : {"HY097", "S1097"},
216 : {"HY098", "S1098"},
217 : {"HY099", "S1099"},
218 : {"HY100", "S1100"},
219 : {"HY101", "S1101"},
220 : {"HY103", "S1103"},
221 : {"HY104", "S1104"},
222 : {"HY105", "S1105"},
223 : {"HY106", "S1106"},
224 : {"HY107", "S1107"},
225 : {"HY108", "S1108"},
226 : {"HY109", "S1109"},
227 : {"HY110", "S1110"},
228 : {"HY111", "S1111"},
229 : {"HYC00", "S1C00"},
230 : {"HYT00", "S1T00"},
231 : {"08001", "S1000"},
232 : {"IM007", "S1000"},
233 : {"", ""}
234 : };
235 :
236 : /*
237 : * ODBC messages must be sorted by importance
238 : * 1. Errors regarding the status of a transaction
239 : * 2. Other errors (level ordered)
240 : * 3. No-Data messages with a state class of 02 ??
241 : * 4. Warning
242 : * 5. Informational
243 : */
244 : static void
245 : rank_errors(struct _sql_errors *errs)
246 40 : {
247 : int settled, current, best;
248 : struct _sql_error swapbuf;
249 : char istrans;
250 :
251 40 : if (errs->ranked == 0 && errs->num_errors > 1) {
252 : /* Find the highest of all unranked errors until there are none left */
253 12 : for (settled = 0; settled < errs->num_errors; settled++) {
254 8 : best = -1;
255 20 : for (current = settled; current < errs->num_errors; current++) {
256 12 : istrans = 0;
257 12 : switch (errs->errs[current].native) {
258 : case 1205:
259 : case 1211:
260 : case 2625:
261 : case 3309:
262 : case 7112:
263 : case 266:
264 : case 277:
265 : case 611:
266 : case 628:
267 : case 3902:
268 : case 3903:
269 : case 3906:
270 : case 3908:
271 : case 6401:
272 0 : istrans = 1;
273 : break;
274 : }
275 :
276 12 : if (istrans == 0) {
277 12 : if (strcmp(errs->errs[current].state3,"25000") == 0)
278 0 : istrans = 1;
279 12 : else if (strcmp(errs->errs[current].state3,"S1012") == 0)
280 0 : istrans = 1;
281 12 : else if (strcmp(errs->errs[current].state3,"08007") == 0)
282 0 : istrans = 1;
283 : }
284 :
285 : /* Transaction errors are always best */
286 12 : if (istrans == 1 && errs->errs[current].msgstate >= 10) {
287 0 : best = current;
288 0 : break;
289 : }
290 :
291 12 : if (best == -1)
292 8 : best = current;
293 :
294 : /* Non-terminating comparisons only below this point */
295 12 : if (errs->errs[current].msgstate > errs->errs[best].msgstate)
296 0 : best = current;
297 : }
298 :
299 : /* swap settled position with best */
300 8 : if (best != settled) {
301 0 : swapbuf = errs->errs[settled];
302 0 : errs->errs[settled] = errs->errs[best];
303 0 : errs->errs[best] = swapbuf;
304 : }
305 : }
306 : }
307 40 : errs->ranked = 1;
308 40 : }
309 :
310 : static const char *
311 : odbc_get_msg(const char *sqlstate)
312 119 : {
313 119 : const struct s_SqlMsgMap *pmap = SqlMsgMap;
314 :
315 : /* TODO set flag and use pointers (no strdup) ?? */
316 7288 : while (pmap->msg) {
317 7169 : if (!strcasecmp(sqlstate, pmap->sqlstate)) {
318 119 : return strdup(pmap->msg);
319 : }
320 7050 : ++pmap;
321 : }
322 0 : return strdup("");
323 : }
324 :
325 : static void
326 : odbc_get_v2state(const char *sqlstate, char *dest_state)
327 125 : {
328 125 : const struct s_v3to2map *pmap = v3to2map;
329 :
330 5833 : while (pmap->v3[0]) {
331 5609 : if (!strcasecmp(pmap->v3, sqlstate)) {
332 26 : tds_strlcpy(dest_state, pmap->v2, 6);
333 26 : return;
334 : }
335 5583 : ++pmap;
336 : }
337 : /* return the original if a v2 state is not found */
338 99 : tds_strlcpy(dest_state, sqlstate, 6);
339 : }
340 :
341 : void
342 : odbc_errs_reset(struct _sql_errors *errs)
343 7070 : {
344 : int i;
345 :
346 7070 : if (errs->errs) {
347 981 : for (i = 0; i < errs->num_errors; ++i) {
348 : /* TODO see flags */
349 596 : if (errs->errs[i].msg)
350 596 : free((char *) errs->errs[i].msg);
351 596 : if (errs->errs[i].server)
352 596 : free(errs->errs[i].server);
353 : }
354 385 : TDS_ZERO_FREE(errs->errs);
355 385 : errs->num_errors = 0;
356 : }
357 7070 : errs->lastrc = SQL_SUCCESS;
358 7070 : errs->ranked = 0;
359 7070 : assert(errs->num_errors == 0);
360 7070 : }
361 :
362 : /** Remove first element */
363 : static void
364 : odbc_errs_pop(struct _sql_errors *errs)
365 0 : {
366 0 : if (!errs || !errs->errs || errs->num_errors <= 0)
367 0 : return;
368 :
369 0 : if (errs->num_errors == 1) {
370 0 : odbc_errs_reset(errs);
371 0 : return;
372 : }
373 :
374 : /* TODO see flags */
375 0 : if (errs->errs[0].msg)
376 0 : free((char *) errs->errs[0].msg);
377 0 : if (errs->errs[0].server)
378 0 : free(errs->errs[0].server);
379 :
380 0 : --errs->num_errors;
381 0 : memmove(&(errs->errs[0]), &(errs->errs[1]), errs->num_errors * sizeof(errs->errs[0]));
382 : }
383 :
384 : void
385 : odbc_errs_add(struct _sql_errors *errs, const char *sqlstate, const char *msg)
386 125 : {
387 : struct _sql_error *p;
388 125 : int n = errs->num_errors;
389 :
390 125 : assert(sqlstate);
391 :
392 125 : if (errs->errs)
393 2 : p = (struct _sql_error *) realloc(errs->errs, sizeof(struct _sql_error) * (n + 1));
394 : else
395 123 : p = (struct _sql_error *) malloc(sizeof(struct _sql_error));
396 125 : if (!p)
397 0 : return;
398 125 : errs->errs = p;
399 :
400 125 : memset(&errs->errs[n], 0, sizeof(struct _sql_error));
401 125 : errs->errs[n].native = 0;
402 125 : tds_strlcpy(errs->errs[n].state3, sqlstate, 6);
403 125 : odbc_get_v2state(errs->errs[n].state3, errs->errs[n].state2);
404 :
405 : /* TODO why driver ?? -- freddy77 */
406 125 : errs->errs[n].server = strdup("DRIVER");
407 125 : errs->errs[n].msg = msg ? strdup(msg) : odbc_get_msg(errs->errs[n].state3);
408 125 : ++errs->num_errors;
409 : }
410 :
411 : /* TODO check if TDS_UINT is correct for native error */
412 : void
413 : odbc_errs_add_rdbms(struct _sql_errors *errs, TDS_UINT native, const char *sqlstate, const char *msg, int linenum, int msgstate,
414 : const char *server)
415 471 : {
416 : struct _sql_error *p;
417 471 : int n = errs->num_errors;
418 :
419 471 : if (errs->errs)
420 209 : p = (struct _sql_error *) realloc(errs->errs, sizeof(struct _sql_error) * (n + 1));
421 : else
422 262 : p = (struct _sql_error *) malloc(sizeof(struct _sql_error));
423 471 : if (!p)
424 0 : return;
425 471 : errs->errs = p;
426 :
427 471 : memset(&errs->errs[n], 0, sizeof(struct _sql_error));
428 471 : errs->errs[n].native = native;
429 471 : if (sqlstate)
430 471 : tds_strlcpy(errs->errs[n].state2, sqlstate, 6);
431 : else
432 0 : errs->errs[n].state2[0] = '\0';
433 471 : strcpy(errs->errs[n].state3, errs->errs[n].state2);
434 471 : sqlstate2to3(errs->errs[n].state3);
435 :
436 : /* TODO why driver ?? -- freddy77 */
437 471 : errs->errs[n].server = (server) ? strdup(server) : strdup("DRIVER");
438 471 : errs->errs[n].msg = msg ? strdup(msg) : odbc_get_msg(errs->errs[n].state3);
439 471 : errs->errs[n].linenum = linenum;
440 471 : errs->errs[n].msgstate = msgstate;
441 471 : ++errs->num_errors;
442 : }
443 :
444 : #define SQLS_MAP(v2,v3) if (strcmp(p,v2) == 0) {strcpy(p,v3); return;}
445 : static void
446 : sqlstate2to3(char *state)
447 471 : {
448 471 : char *p = state;
449 :
450 471 : if (p[0] == 'S' && p[1] == '0' && p[2] == '0') {
451 39 : p[0] = '4';
452 39 : p[1] = '2';
453 39 : p[2] = 'S';
454 39 : return;
455 : }
456 :
457 : /* TODO optimize with a switch */
458 432 : SQLS_MAP("01S03", "01001");
459 432 : SQLS_MAP("01S04", "01001");
460 432 : SQLS_MAP("22003", "HY019");
461 392 : SQLS_MAP("22008", "22007");
462 388 : SQLS_MAP("22005", "22018");
463 386 : SQLS_MAP("24000", "07005");
464 386 : SQLS_MAP("37000", "42000");
465 386 : SQLS_MAP("70100", "HY018");
466 386 : SQLS_MAP("S1000", "HY000");
467 386 : SQLS_MAP("S1001", "HY001");
468 386 : SQLS_MAP("S1002", "07009");
469 386 : SQLS_MAP("S1003", "HY003");
470 386 : SQLS_MAP("S1004", "HY004");
471 386 : SQLS_MAP("S1008", "HY008");
472 386 : SQLS_MAP("S1009", "HY009");
473 386 : SQLS_MAP("S1010", "HY007");
474 386 : SQLS_MAP("S1011", "HY011");
475 386 : SQLS_MAP("S1012", "HY012");
476 386 : SQLS_MAP("S1090", "HY090");
477 386 : SQLS_MAP("S1091", "HY091");
478 386 : SQLS_MAP("S1092", "HY092");
479 386 : SQLS_MAP("S1093", "07009");
480 386 : SQLS_MAP("S1096", "HY096");
481 386 : SQLS_MAP("S1097", "HY097");
482 386 : SQLS_MAP("S1098", "HY098");
483 386 : SQLS_MAP("S1099", "HY099");
484 386 : SQLS_MAP("S1100", "HY100");
485 386 : SQLS_MAP("S1101", "HY101");
486 386 : SQLS_MAP("S1103", "HY103");
487 386 : SQLS_MAP("S1104", "HY104");
488 386 : SQLS_MAP("S1105", "HY105");
489 386 : SQLS_MAP("S1106", "HY106");
490 386 : SQLS_MAP("S1107", "HY107");
491 386 : SQLS_MAP("S1108", "HY108");
492 386 : SQLS_MAP("S1109", "HY109");
493 386 : SQLS_MAP("S1110", "HY110");
494 386 : SQLS_MAP("S1111", "HY111");
495 386 : SQLS_MAP("S1C00", "HYC00");
496 386 : SQLS_MAP("S1T00", "HYT00");
497 : }
498 :
499 : static SQLRETURN
500 : _SQLGetDiagRec(SQLSMALLINT handleType, SQLHANDLE handle, SQLSMALLINT numRecord, SQLCHAR FAR * szSqlState,
501 : SQLINTEGER FAR * pfNativeError, SQLCHAR * szErrorMsg, SQLSMALLINT cbErrorMsgMax, SQLSMALLINT FAR * pcbErrorMsg)
502 40 : {
503 : SQLRETURN result;
504 40 : struct _sql_errors *errs = NULL;
505 : const char *msg;
506 : char *p;
507 :
508 : static const char msgprefix[] = "[FreeTDS][SQL Server]";
509 :
510 40 : SQLINTEGER odbc_ver = SQL_OV_ODBC2;
511 :
512 40 : if (numRecord <= 0 || cbErrorMsgMax < 0)
513 0 : return SQL_ERROR;
514 :
515 40 : if (!handle)
516 0 : return SQL_INVALID_HANDLE;
517 :
518 40 : switch (handleType) {
519 : case SQL_HANDLE_STMT:
520 38 : odbc_ver = ((TDS_STMT *) handle)->dbc->env->attr.odbc_version;
521 38 : errs = &((TDS_STMT *) handle)->errs;
522 38 : break;
523 :
524 : case SQL_HANDLE_DBC:
525 2 : odbc_ver = ((TDS_DBC *) handle)->env->attr.odbc_version;
526 2 : errs = &((TDS_DBC *) handle)->errs;
527 2 : break;
528 :
529 : case SQL_HANDLE_ENV:
530 0 : odbc_ver = ((TDS_ENV *) handle)->attr.odbc_version;
531 0 : errs = &((TDS_ENV *) handle)->errs;
532 0 : break;
533 :
534 : default:
535 0 : return SQL_INVALID_HANDLE;
536 : }
537 :
538 40 : if (numRecord > errs->num_errors)
539 0 : return SQL_NO_DATA_FOUND;
540 40 : --numRecord;
541 :
542 40 : rank_errors(errs);
543 :
544 40 : if (szSqlState) {
545 16 : if (odbc_ver == SQL_OV_ODBC3)
546 2 : strcpy((char *) szSqlState, errs->errs[numRecord].state3);
547 : else
548 14 : strcpy((char *) szSqlState, errs->errs[numRecord].state2);
549 : }
550 :
551 40 : msg = errs->errs[numRecord].msg;
552 :
553 40 : if (asprintf(&p, "%s%s", msgprefix, msg) < 0)
554 0 : return SQL_ERROR;
555 40 : result = odbc_set_string(szErrorMsg, cbErrorMsgMax, pcbErrorMsg, p, -1);
556 40 : free(p);
557 :
558 40 : if (pfNativeError)
559 4 : *pfNativeError = errs->errs[numRecord].native;
560 :
561 40 : return result;
562 : }
563 :
564 : SQLRETURN SQL_API
565 : SQLError(SQLHENV henv, SQLHDBC hdbc, SQLHSTMT hstmt, SQLCHAR FAR * szSqlState, SQLINTEGER FAR * pfNativeError,
566 : SQLCHAR FAR * szErrorMsg, SQLSMALLINT cbErrorMsgMax, SQLSMALLINT FAR * pcbErrorMsg)
567 0 : {
568 : SQLRETURN result;
569 0 : struct _sql_errors *errs = NULL;
570 : SQLSMALLINT type;
571 : SQLHANDLE handle;
572 :
573 0 : if (hstmt) {
574 0 : errs = &((TDS_STMT *) hstmt)->errs;
575 0 : handle = hstmt;
576 0 : type = SQL_HANDLE_STMT;
577 0 : } else if (hdbc) {
578 0 : errs = &((TDS_DBC *) hdbc)->errs;
579 0 : handle = hdbc;
580 0 : type = SQL_HANDLE_DBC;
581 0 : } else if (henv) {
582 0 : errs = &((TDS_ENV *) henv)->errs;
583 0 : handle = henv;
584 0 : type = SQL_HANDLE_ENV;
585 : } else
586 0 : return SQL_INVALID_HANDLE;
587 :
588 0 : rank_errors(errs);
589 :
590 0 : result = _SQLGetDiagRec(type, handle, 1, szSqlState, pfNativeError, szErrorMsg, cbErrorMsgMax, pcbErrorMsg);
591 :
592 0 : if (result == SQL_SUCCESS) {
593 : /* remove first error */
594 0 : odbc_errs_pop(errs);
595 : }
596 :
597 0 : return result;
598 : }
599 :
600 : #if (ODBCVER >= 0x0300)
601 : SQLRETURN SQL_API
602 : SQLGetDiagRec(SQLSMALLINT handleType, SQLHANDLE handle, SQLSMALLINT numRecord, SQLCHAR FAR * szSqlState,
603 : SQLINTEGER FAR * pfNativeError, SQLCHAR * szErrorMsg, SQLSMALLINT cbErrorMsgMax, SQLSMALLINT FAR * pcbErrorMsg)
604 40 : {
605 40 : return _SQLGetDiagRec(handleType, handle, numRecord, szSqlState, pfNativeError, szErrorMsg, cbErrorMsgMax, pcbErrorMsg);
606 : }
607 :
608 : SQLRETURN SQL_API
609 : SQLGetDiagField(SQLSMALLINT handleType, SQLHANDLE handle, SQLSMALLINT numRecord, SQLSMALLINT diagIdentifier, SQLPOINTER buffer,
610 : SQLSMALLINT cbBuffer, SQLSMALLINT FAR * pcbBuffer)
611 0 : {
612 0 : SQLRETURN result = SQL_SUCCESS;
613 0 : struct _sql_errors *errs = NULL;
614 : const char *msg;
615 :
616 0 : SQLINTEGER odbc_ver = SQL_OV_ODBC2;
617 : int cplen;
618 0 : TDS_STMT *stmt = NULL;
619 0 : TDS_DBC *dbc = NULL;
620 0 : TDS_ENV *env = NULL;
621 : char tmp[16];
622 :
623 0 : if (cbBuffer < 0)
624 0 : return SQL_ERROR;
625 :
626 0 : if (!handle)
627 0 : return SQL_INVALID_HANDLE;
628 :
629 0 : switch (handleType) {
630 : case SQL_HANDLE_STMT:
631 0 : stmt = ((TDS_STMT *) handle);
632 0 : dbc = stmt->dbc;
633 0 : env = dbc->env;
634 0 : errs = &stmt->errs;
635 0 : break;
636 :
637 : case SQL_HANDLE_DBC:
638 0 : dbc = ((TDS_DBC *) handle);
639 0 : env = dbc->env;
640 0 : errs = &dbc->errs;
641 0 : break;
642 :
643 : case SQL_HANDLE_ENV:
644 0 : env = ((TDS_ENV *) handle);
645 0 : errs = &env->errs;
646 0 : break;
647 :
648 : default:
649 0 : return SQL_INVALID_HANDLE;
650 : }
651 0 : odbc_ver = env->attr.odbc_version;
652 :
653 : /* header (numRecord ignored) */
654 0 : switch (diagIdentifier) {
655 : case SQL_DIAG_DYNAMIC_FUNCTION:
656 0 : if (handleType != SQL_HANDLE_STMT)
657 0 : return SQL_ERROR;
658 :
659 : /* TODO */
660 0 : return odbc_set_string(buffer, cbBuffer, pcbBuffer, "", 0);
661 :
662 : case SQL_DIAG_DYNAMIC_FUNCTION_CODE:
663 0 : *(SQLINTEGER *) buffer = 0;
664 0 : return SQL_SUCCESS;
665 :
666 : case SQL_DIAG_NUMBER:
667 0 : *(SQLINTEGER *) buffer = errs->num_errors;
668 0 : return SQL_SUCCESS;
669 :
670 : case SQL_DIAG_RETURNCODE:
671 0 : *(SQLRETURN *) buffer = errs->lastrc;
672 0 : return SQL_SUCCESS;
673 :
674 : case SQL_DIAG_CURSOR_ROW_COUNT:
675 0 : if (handleType != SQL_HANDLE_STMT)
676 0 : return SQL_ERROR;
677 :
678 : /* TODO */
679 0 : *(SQLINTEGER *) buffer = 0;
680 0 : return SQL_SUCCESS;
681 :
682 : case SQL_DIAG_ROW_COUNT:
683 0 : if (handleType != SQL_HANDLE_STMT)
684 0 : return SQL_ERROR;
685 :
686 0 : return _SQLRowCount((SQLHSTMT) handle, (SQLLEN FAR *) buffer);
687 : }
688 :
689 0 : if (numRecord > errs->num_errors)
690 0 : return SQL_NO_DATA_FOUND;
691 :
692 0 : if (numRecord <= 0)
693 0 : return SQL_ERROR;
694 0 : --numRecord;
695 :
696 0 : switch (diagIdentifier) {
697 : case SQL_DIAG_ROW_NUMBER:
698 0 : *(SQLINTEGER *) buffer = SQL_ROW_NUMBER_UNKNOWN;
699 0 : break;
700 :
701 : case SQL_DIAG_CLASS_ORIGIN:
702 : case SQL_DIAG_SUBCLASS_ORIGIN:
703 0 : if (odbc_ver == SQL_OV_ODBC2)
704 0 : result = odbc_set_string(buffer, cbBuffer, pcbBuffer, "ISO 9075", -1);
705 : else
706 0 : result = odbc_set_string(buffer, cbBuffer, pcbBuffer, "ODBC 3.0", -1);
707 0 : break;
708 :
709 : case SQL_DIAG_COLUMN_NUMBER:
710 0 : *(SQLINTEGER *) buffer = SQL_COLUMN_NUMBER_UNKNOWN;
711 0 : break;
712 :
713 : #ifdef SQL_DIAG_SS_MSGSTATE
714 : case SQL_DIAG_SS_MSGSTATE:
715 : if (errs->errs[numRecord].msgstate == 0)
716 : return SQL_ERROR;
717 : else
718 : *(SQLINTEGER *) buffer = errs->errs[numRecord].msgstate;
719 : break;
720 : #endif
721 :
722 : #ifdef SQL_DIAG_SS_LINE
723 : case SQL_DIAG_SS_LINE:
724 : if (errs->errs[numRecord].linenum == 0)
725 : return SQL_ERROR;
726 : else
727 : *(SQLUSMALLINT *) buffer = errs->errs[numRecord].linenum;
728 : break;
729 : #endif
730 :
731 : case SQL_DIAG_CONNECTION_NAME:
732 0 : if (dbc && dbc->tds_socket && dbc->tds_socket->spid > 0)
733 0 : cplen = sprintf(tmp, "%d", dbc->tds_socket->spid);
734 : else
735 0 : cplen = 0;
736 :
737 0 : result = odbc_set_string(buffer, cbBuffer, pcbBuffer, tmp, cplen);
738 0 : break;
739 :
740 : case SQL_DIAG_MESSAGE_TEXT:
741 0 : msg = errs->errs[numRecord].msg;
742 0 : result = odbc_set_string(buffer, cbBuffer, pcbBuffer, msg, -1);
743 0 : break;
744 :
745 : case SQL_DIAG_NATIVE:
746 0 : *(SQLINTEGER *) buffer = errs->errs[numRecord].native;
747 0 : break;
748 :
749 : case SQL_DIAG_SERVER_NAME:
750 0 : msg = "";
751 0 : switch (handleType) {
752 : case SQL_HANDLE_ENV:
753 0 : break;
754 : case SQL_HANDLE_DBC:
755 0 : msg = tds_dstr_cstr(&dbc->server);
756 0 : break;
757 : case SQL_HANDLE_STMT:
758 0 : msg = tds_dstr_cstr(&stmt->dbc->server);
759 : /*
760 : * if dbc->server is not initialized, init it
761 : * from the errs structure
762 : */
763 0 : if (!msg[0] && errs->errs[numRecord].server) {
764 0 : tds_dstr_copy(&stmt->dbc->server, errs->errs[numRecord].server);
765 0 : msg = errs->errs[numRecord].server;
766 : }
767 : break;
768 : }
769 0 : result = odbc_set_string(buffer, cbBuffer, pcbBuffer, msg, -1);
770 0 : break;
771 :
772 : case SQL_DIAG_SQLSTATE:
773 0 : if (odbc_ver == SQL_OV_ODBC3)
774 0 : msg = errs->errs[numRecord].state3;
775 : else
776 0 : msg = errs->errs[numRecord].state2;
777 :
778 0 : result = odbc_set_string(buffer, cbBuffer, pcbBuffer, msg, 5);
779 0 : break;
780 :
781 : default:
782 0 : return SQL_ERROR;
783 : }
784 0 : return result;
785 : }
786 : #endif
|