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