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