00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #if HAVE_CONFIG_H
00022 #include <config.h>
00023 #endif
00024
00025 #include <stdio.h>
00026
00027 #if HAVE_STDLIB_H
00028 #include <stdlib.h>
00029 #endif
00030
00031 #if HAVE_STRING_H
00032 #include <string.h>
00033 #endif
00034
00035 #include <assert.h>
00036
00037 #include "tdsodbc.h"
00038 #include "tdsstring.h"
00039 #include "replacements.h"
00040
00041 #if HAVE_ODBCSS_H
00042 #include <odbcss.h>
00043 #endif
00044
00045 #ifdef DMALLOC
00046 #include <dmalloc.h>
00047 #endif
00048
00049 TDS_RCSID(var, "$Id: error.c 86967 2006-07-31 15:44:10Z ssikorsk $");
00050
00051 static void odbc_errs_pop(struct _sql_errors *errs);
00052 static const char *odbc_get_msg(const char *sqlstate);
00053 static void odbc_get_v2state(const char *sqlstate, char *dest_state);
00054 static void sqlstate2to3(char *state);
00055
00056 struct s_SqlMsgMap
00057 {
00058 const char *msg;
00059 char sqlstate[6];
00060 };
00061
00062
00063 #define ODBCERR(s3,msg) { msg, s3 }
00064 static const struct s_SqlMsgMap SqlMsgMap[] = {
00065 ODBCERR("IM007", "No data source or driver specified"),
00066 ODBCERR("01000", "Warning"),
00067 ODBCERR("01002", "Disconnect error"),
00068 ODBCERR("01004", "Data truncated"),
00069 ODBCERR("01504", "The UPDATE or DELETE statement does not include a WHERE clause"),
00070 ODBCERR("01508", "Statement disqualified for blocking"),
00071 ODBCERR("01S00", "Invalid connection string attribute"),
00072 ODBCERR("01S01", "Error in row"),
00073 ODBCERR("01S02", "Option value changed"),
00074 ODBCERR("01S06", "Attempt to fetch before the result set returned the first rowset"),
00075 ODBCERR("01S07", "Fractional truncation"),
00076 ODBCERR("07001", "Wrong number of parameters"),
00077 ODBCERR("07002", "Too many columns"),
00078 ODBCERR("07005", "The statement did not return a result set"),
00079 ODBCERR("07006", "Invalid conversion"),
00080 ODBCERR("07009", "Invalid descriptor index"),
00081 ODBCERR("08001", "Unable to connect to data source"),
00082 ODBCERR("08002", "Connection in use"),
00083 ODBCERR("08003", "Connection is closed"),
00084 ODBCERR("08004", "The application server rejected establishment of the connection"),
00085 ODBCERR("08007", "Connection failure during transaction"),
00086 ODBCERR("08S01", "Communication link failure"),
00087 ODBCERR("0F001", "The LOB token variable does not currently represent any value"),
00088 ODBCERR("21S01", "Insert value list does not match column list"),
00089 ODBCERR("22001", "String data right truncation"),
00090 ODBCERR("22002", "Invalid output or indicator buffer specified"),
00091 ODBCERR("22003", "Numeric value out of range"),
00092 ODBCERR("22005", "Error in assignment"),
00093 ODBCERR("22007", "Invalid datetime format"),
00094 ODBCERR("22008", "Datetime field overflow"),
00095 ODBCERR("22011", "A substring error occurred"),
00096 ODBCERR("22012", "Division by zero is invalid"),
00097 ODBCERR("22015", "Interval field overflow"),
00098 ODBCERR("22018", "Invalid character value for cast specification"),
00099 ODBCERR("22019", "Invalid escape character"),
00100 ODBCERR("22025", "Invalid escape sequence"),
00101 ODBCERR("22026", "String data, length mismatch"),
00102 ODBCERR("23000", "Integrity constraint violation"),
00103 ODBCERR("24000", "Invalid cursor state"),
00104 ODBCERR("24504", "The cursor identified in the UPDATE, DELETE, SET, or GET statement is not positioned on a row"),
00105 ODBCERR("25501", "Invalid transaction state"),
00106 ODBCERR("28000", "Invalid authorization specification"),
00107 ODBCERR("34000", "Invalid cursor name"),
00108 ODBCERR("37000", "Invalid SQL syntax"),
00109 ODBCERR("40001", "Serialization failure"),
00110 ODBCERR("40003", "Statement completion unknown"),
00111 ODBCERR("42000", "Syntax error or access violation"),
00112 ODBCERR("42601", "PARMLIST syntax error"),
00113 ODBCERR("42818", "The operands of an operator or function are not compatible"),
00114 ODBCERR("42895", "The value of a host variable in the EXECUTE or OPEN statement cannot be used because of its data type"),
00115 ODBCERR("428A1", "Unable to access a file referenced by a host file variable"),
00116 ODBCERR("44000", "Integrity constraint violation"),
00117 ODBCERR("54028", "The maximum number of concurrent LOB handles has been reached"),
00118 ODBCERR("56084", "LOB data is not supported in DRDA"),
00119 ODBCERR("58004", "Unexpected system failure"),
00120 ODBCERR("HY000", "General driver error"),
00121 ODBCERR("HY001", "Memory allocation failure"),
00122 ODBCERR("HY002", "Invalid column number"),
00123 ODBCERR("HY003", "Program type out of range"),
00124 ODBCERR("HY004", "Invalid data type"),
00125 ODBCERR("HY007", "Associated statement is not prepared"),
00126 ODBCERR("HY008", "Operation was cancelled"),
00127 ODBCERR("HY009", "Invalid argument value"),
00128 ODBCERR("HY010", "Function sequence error"),
00129 ODBCERR("HY011", "Operation invalid at this time"),
00130 ODBCERR("HY012", "Invalid transaction code"),
00131 ODBCERR("HY013", "Unexpected memory handling error"),
00132 ODBCERR("HY014", "No more handles"),
00133 ODBCERR("HY016", "Cannot modify an implementation row descriptor"),
00134 ODBCERR("HY017", "Invalid use of an automatically allocated descriptor handle"),
00135 ODBCERR("HY018", "Server declined cancel request"),
00136 ODBCERR("HY021", "Inconsistent descriptor information"),
00137 ODBCERR("HY024", "Invalid attribute value"),
00138 ODBCERR("HY090", "Invalid string or buffer length"),
00139 ODBCERR("HY091", "Descriptor type out of range"),
00140 ODBCERR("HY092", "Invalid option"),
00141 ODBCERR("HY093", "Invalid parameter number"),
00142 ODBCERR("HY094", "Invalid scale value"),
00143 ODBCERR("HY096", "Information type out of range"),
00144 ODBCERR("HY097", "Column type out of range"),
00145 ODBCERR("HY098", "Scope type out of range"),
00146 ODBCERR("HY099", "Nullable type out of range"),
00147 ODBCERR("HY100", "Uniqueness option type out of range"),
00148 ODBCERR("HY101", "Accuracy option type out of range"),
00149 ODBCERR("HY103", "Direction option out of range"),
00150 ODBCERR("HY104", "Invalid precision value"),
00151 ODBCERR("HY105", "Invalid parameter type"),
00152 ODBCERR("HY106", "Fetch type out of range"),
00153 ODBCERR("HY107", "Row value out of range"),
00154 ODBCERR("HY109", "Invalid cursor position"),
00155 ODBCERR("HY110", "Invalid driver completion"),
00156 ODBCERR("HY111", "Invalid bookmark value"),
00157 ODBCERR("HY501", "Invalid data source name"),
00158 ODBCERR("HY503", "Invalid file name length"),
00159 ODBCERR("HY506", "Error closing a file"),
00160 ODBCERR("HY509", "Error deleting a file"),
00161 ODBCERR("HYC00", "Driver not capable"),
00162 ODBCERR("HYT00", "Timeout expired"),
00163 ODBCERR("HYT01", "Connection timeout expired"),
00164 ODBCERR("S0001", "Database object already exists"),
00165 ODBCERR("S0002", "Database object does not exist"),
00166 ODBCERR("S0011", "Index already exists"),
00167 ODBCERR("S0012", "Index not found"),
00168 ODBCERR("S0021", "Column already exists"),
00169 ODBCERR("S0022", "Column not found"),
00170 ODBCERR("", NULL)
00171 };
00172
00173 #undef ODBCERR
00174
00175 struct s_v3to2map
00176 {
00177 char v3[6];
00178 char v2[6];
00179 };
00180
00181
00182 static const struct s_v3to2map v3to2map[] = {
00183 {"01001", "01S03"},
00184 {"01001", "01S04"},
00185 {"HY019", "22003"},
00186 {"22007", "22008"},
00187 {"22018", "22005"},
00188 {"07005", "24000"},
00189 {"42000", "37000"},
00190 {"HY018", "70100"},
00191 {"42S01", "S0001"},
00192 {"42S02", "S0002"},
00193 {"42S11", "S0011"},
00194 {"42S12", "S0012"},
00195 {"42S21", "S0021"},
00196 {"42S22", "S0022"},
00197 {"42S23", "S0023"},
00198 {"HY000", "S1000"},
00199 {"HY001", "S1001"},
00200 {"07009", "S1002"},
00201 {"HY003", "S1003"},
00202 {"HY004", "S1004"},
00203 {"HY008", "S1008"},
00204 {"HY009", "S1009"},
00205 {"HY024", "S1009"},
00206 {"HY007", "S1010"},
00207 {"HY010", "S1010"},
00208 {"HY011", "S1011"},
00209 {"HY012", "S1012"},
00210 {"HY090", "S1090"},
00211 {"HY091", "S1091"},
00212 {"HY092", "S1092"},
00213
00214 {"HY096", "S1096"},
00215 {"HY097", "S1097"},
00216 {"HY098", "S1098"},
00217 {"HY099", "S1099"},
00218 {"HY100", "S1100"},
00219 {"HY101", "S1101"},
00220 {"HY103", "S1103"},
00221 {"HY104", "S1104"},
00222 {"HY105", "S1105"},
00223 {"HY106", "S1106"},
00224 {"HY107", "S1107"},
00225 {"HY108", "S1108"},
00226 {"HY109", "S1109"},
00227 {"HY110", "S1110"},
00228 {"HY111", "S1111"},
00229 {"HYC00", "S1C00"},
00230 {"HYT00", "S1T00"},
00231 {"08001", "S1000"},
00232 {"IM007", "S1000"},
00233 {"", ""}
00234 };
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244 static void
00245 rank_errors(struct _sql_errors *errs)
00246 {
00247 int settled, current, best;
00248 struct _sql_error swapbuf;
00249 char istrans;
00250
00251 if (errs->ranked == 0 && errs->num_errors > 1) {
00252
00253 for (settled = 0; settled < errs->num_errors; settled++) {
00254 best = -1;
00255 for (current = settled; current < errs->num_errors; current++) {
00256 istrans = 0;
00257 switch (errs->errs[current].native) {
00258 case 1205:
00259 case 1211:
00260 case 2625:
00261 case 3309:
00262 case 7112:
00263 case 266:
00264 case 277:
00265 case 611:
00266 case 628:
00267 case 3902:
00268 case 3903:
00269 case 3906:
00270 case 3908:
00271 case 6401:
00272 istrans = 1;
00273 break;
00274 }
00275
00276 if (istrans == 0) {
00277 if (strcmp(errs->errs[current].state3,"25000") == 0)
00278 istrans = 1;
00279 else if (strcmp(errs->errs[current].state3,"S1012") == 0)
00280 istrans = 1;
00281 else if (strcmp(errs->errs[current].state3,"08007") == 0)
00282 istrans = 1;
00283 }
00284
00285
00286 if (istrans == 1 && errs->errs[current].msgstate >= 10) {
00287 best = current;
00288 break;
00289 }
00290
00291 if (best == -1)
00292 best = current;
00293
00294
00295 if (errs->errs[current].msgstate > errs->errs[best].msgstate)
00296 best = current;
00297 }
00298
00299
00300 if (best != settled) {
00301 swapbuf = errs->errs[settled];
00302 errs->errs[settled] = errs->errs[best];
00303 errs->errs[best] = swapbuf;
00304 }
00305 }
00306 }
00307 errs->ranked = 1;
00308 }
00309
00310 static const char *
00311 odbc_get_msg(const char *sqlstate)
00312 {
00313 const struct s_SqlMsgMap *pmap = SqlMsgMap;
00314
00315
00316 while (pmap->msg) {
00317 if (!strcasecmp(sqlstate, pmap->sqlstate)) {
00318 return strdup(pmap->msg);
00319 }
00320 ++pmap;
00321 }
00322 return strdup("");
00323 }
00324
00325 static void
00326 odbc_get_v2state(const char *sqlstate, char *dest_state)
00327 {
00328 const struct s_v3to2map *pmap = v3to2map;
00329
00330 while (pmap->v3[0]) {
00331 if (!strcasecmp(pmap->v3, sqlstate)) {
00332 tds_strlcpy(dest_state, pmap->v2, 6);
00333 return;
00334 }
00335 ++pmap;
00336 }
00337
00338 tds_strlcpy(dest_state, sqlstate, 6);
00339 }
00340
00341 void
00342 odbc_errs_reset(struct _sql_errors *errs)
00343 {
00344 int i;
00345
00346 if (errs->errs) {
00347 for (i = 0; i < errs->num_errors; ++i) {
00348
00349 if (errs->errs[i].msg)
00350 free((char *) errs->errs[i].msg);
00351 if (errs->errs[i].server)
00352 free(errs->errs[i].server);
00353 }
00354 TDS_ZERO_FREE(errs->errs);
00355 errs->num_errors = 0;
00356 }
00357 errs->lastrc = SQL_SUCCESS;
00358 errs->ranked = 0;
00359 assert(errs->num_errors == 0);
00360 }
00361
00362
00363 static void
00364 odbc_errs_pop(struct _sql_errors *errs)
00365 {
00366 if (!errs || !errs->errs || errs->num_errors <= 0)
00367 return;
00368
00369 if (errs->num_errors == 1) {
00370 odbc_errs_reset(errs);
00371 return;
00372 }
00373
00374
00375 if (errs->errs[0].msg)
00376 free((char *) errs->errs[0].msg);
00377 if (errs->errs[0].server)
00378 free(errs->errs[0].server);
00379
00380 --errs->num_errors;
00381 memmove(&(errs->errs[0]), &(errs->errs[1]), errs->num_errors * sizeof(errs->errs[0]));
00382 }
00383
00384 void
00385 odbc_errs_add(struct _sql_errors *errs, const char *sqlstate, const char *msg)
00386 {
00387 struct _sql_error *p;
00388 int n = errs->num_errors;
00389
00390 assert(sqlstate);
00391
00392 if (errs->errs)
00393 p = (struct _sql_error *) realloc(errs->errs, sizeof(struct _sql_error) * (n + 1));
00394 else
00395 p = (struct _sql_error *) malloc(sizeof(struct _sql_error));
00396 if (!p)
00397 return;
00398 errs->errs = p;
00399
00400 memset(&errs->errs[n], 0, sizeof(struct _sql_error));
00401 errs->errs[n].native = 0;
00402 tds_strlcpy(errs->errs[n].state3, sqlstate, 6);
00403 odbc_get_v2state(errs->errs[n].state3, errs->errs[n].state2);
00404
00405
00406 errs->errs[n].server = strdup("DRIVER");
00407 errs->errs[n].msg = msg ? strdup(msg) : odbc_get_msg(errs->errs[n].state3);
00408 ++errs->num_errors;
00409 }
00410
00411
00412 void
00413 odbc_errs_add_rdbms(struct _sql_errors *errs, TDS_UINT native, const char *sqlstate, const char *msg, int linenum, int msgstate,
00414 const char *server)
00415 {
00416 struct _sql_error *p;
00417 int n = errs->num_errors;
00418
00419 if (errs->errs)
00420 p = (struct _sql_error *) realloc(errs->errs, sizeof(struct _sql_error) * (n + 1));
00421 else
00422 p = (struct _sql_error *) malloc(sizeof(struct _sql_error));
00423 if (!p)
00424 return;
00425 errs->errs = p;
00426
00427 memset(&errs->errs[n], 0, sizeof(struct _sql_error));
00428 errs->errs[n].native = native;
00429 if (sqlstate)
00430 tds_strlcpy(errs->errs[n].state2, sqlstate, 6);
00431 else
00432 errs->errs[n].state2[0] = '\0';
00433 strcpy(errs->errs[n].state3, errs->errs[n].state2);
00434 sqlstate2to3(errs->errs[n].state3);
00435
00436
00437 errs->errs[n].server = (server) ? strdup(server) : strdup("DRIVER");
00438 errs->errs[n].msg = msg ? strdup(msg) : odbc_get_msg(errs->errs[n].state3);
00439 errs->errs[n].linenum = linenum;
00440 errs->errs[n].msgstate = msgstate;
00441 ++errs->num_errors;
00442 }
00443
00444 #define SQLS_MAP(v2,v3) if (strcmp(p,v2) == 0) {strcpy(p,v3); return;}
00445 static void
00446 sqlstate2to3(char *state)
00447 {
00448 char *p = state;
00449
00450 if (p[0] == 'S' && p[1] == '0' && p[2] == '0') {
00451 p[0] = '4';
00452 p[1] = '2';
00453 p[2] = 'S';
00454 return;
00455 }
00456
00457
00458 SQLS_MAP("01S03", "01001");
00459 SQLS_MAP("01S04", "01001");
00460 SQLS_MAP("22003", "HY019");
00461 SQLS_MAP("22008", "22007");
00462 SQLS_MAP("22005", "22018");
00463 SQLS_MAP("24000", "07005");
00464 SQLS_MAP("37000", "42000");
00465 SQLS_MAP("70100", "HY018");
00466 SQLS_MAP("S1000", "HY000");
00467 SQLS_MAP("S1001", "HY001");
00468 SQLS_MAP("S1002", "07009");
00469 SQLS_MAP("S1003", "HY003");
00470 SQLS_MAP("S1004", "HY004");
00471 SQLS_MAP("S1008", "HY008");
00472 SQLS_MAP("S1009", "HY009");
00473 SQLS_MAP("S1010", "HY007");
00474 SQLS_MAP("S1011", "HY011");
00475 SQLS_MAP("S1012", "HY012");
00476 SQLS_MAP("S1090", "HY090");
00477 SQLS_MAP("S1091", "HY091");
00478 SQLS_MAP("S1092", "HY092");
00479 SQLS_MAP("S1093", "07009");
00480 SQLS_MAP("S1096", "HY096");
00481 SQLS_MAP("S1097", "HY097");
00482 SQLS_MAP("S1098", "HY098");
00483 SQLS_MAP("S1099", "HY099");
00484 SQLS_MAP("S1100", "HY100");
00485 SQLS_MAP("S1101", "HY101");
00486 SQLS_MAP("S1103", "HY103");
00487 SQLS_MAP("S1104", "HY104");
00488 SQLS_MAP("S1105", "HY105");
00489 SQLS_MAP("S1106", "HY106");
00490 SQLS_MAP("S1107", "HY107");
00491 SQLS_MAP("S1108", "HY108");
00492 SQLS_MAP("S1109", "HY109");
00493 SQLS_MAP("S1110", "HY110");
00494 SQLS_MAP("S1111", "HY111");
00495 SQLS_MAP("S1C00", "HYC00");
00496 SQLS_MAP("S1T00", "HYT00");
00497 }
00498
00499 static SQLRETURN
00500 _SQLGetDiagRec(SQLSMALLINT handleType, SQLHANDLE handle, SQLSMALLINT numRecord, SQLCHAR FAR * szSqlState,
00501 SQLINTEGER FAR * pfNativeError, SQLCHAR * szErrorMsg, SQLSMALLINT cbErrorMsgMax, SQLSMALLINT FAR * pcbErrorMsg)
00502 {
00503 SQLRETURN result;
00504 struct _sql_errors *errs = NULL;
00505 const char *msg;
00506 char *p;
00507
00508 static const char msgprefix[] = "[FreeTDS][SQL Server]";
00509
00510 SQLINTEGER odbc_ver = SQL_OV_ODBC2;
00511
00512 if (numRecord <= 0 || cbErrorMsgMax < 0)
00513 return SQL_ERROR;
00514
00515 if (!handle)
00516 return SQL_INVALID_HANDLE;
00517
00518 switch (handleType) {
00519 case SQL_HANDLE_STMT:
00520 odbc_ver = ((TDS_STMT *) handle)->dbc->env->attr.odbc_version;
00521 errs = &((TDS_STMT *) handle)->errs;
00522 break;
00523
00524 case SQL_HANDLE_DBC:
00525 odbc_ver = ((TDS_DBC *) handle)->env->attr.odbc_version;
00526 errs = &((TDS_DBC *) handle)->errs;
00527 break;
00528
00529 case SQL_HANDLE_ENV:
00530 odbc_ver = ((TDS_ENV *) handle)->attr.odbc_version;
00531 errs = &((TDS_ENV *) handle)->errs;
00532 break;
00533
00534 default:
00535 return SQL_INVALID_HANDLE;
00536 }
00537
00538 if (numRecord > errs->num_errors)
00539 return SQL_NO_DATA_FOUND;
00540 --numRecord;
00541
00542 rank_errors(errs);
00543
00544 if (szSqlState) {
00545 if (odbc_ver == SQL_OV_ODBC3)
00546 strcpy((char *) szSqlState, errs->errs[numRecord].state3);
00547 else
00548 strcpy((char *) szSqlState, errs->errs[numRecord].state2);
00549 }
00550
00551 msg = errs->errs[numRecord].msg;
00552
00553 if (asprintf(&p, "%s%s", msgprefix, msg) < 0)
00554 return SQL_ERROR;
00555 result = odbc_set_string(szErrorMsg, cbErrorMsgMax, pcbErrorMsg, p, -1);
00556 free(p);
00557
00558 if (pfNativeError)
00559 *pfNativeError = errs->errs[numRecord].native;
00560
00561 return result;
00562 }
00563
00564 SQLRETURN SQL_API
00565 SQLError(SQLHENV henv, SQLHDBC hdbc, SQLHSTMT hstmt, SQLCHAR FAR * szSqlState, SQLINTEGER FAR * pfNativeError,
00566 SQLCHAR FAR * szErrorMsg, SQLSMALLINT cbErrorMsgMax, SQLSMALLINT FAR * pcbErrorMsg)
00567 {
00568 SQLRETURN result;
00569 struct _sql_errors *errs = NULL;
00570 SQLSMALLINT type;
00571 SQLHANDLE handle;
00572
00573 if (hstmt) {
00574 errs = &((TDS_STMT *) hstmt)->errs;
00575 handle = hstmt;
00576 type = SQL_HANDLE_STMT;
00577 } else if (hdbc) {
00578 errs = &((TDS_DBC *) hdbc)->errs;
00579 handle = hdbc;
00580 type = SQL_HANDLE_DBC;
00581 } else if (henv) {
00582 errs = &((TDS_ENV *) henv)->errs;
00583 handle = henv;
00584 type = SQL_HANDLE_ENV;
00585 } else
00586 return SQL_INVALID_HANDLE;
00587
00588 rank_errors(errs);
00589
00590 result = _SQLGetDiagRec(type, handle, 1, szSqlState, pfNativeError, szErrorMsg, cbErrorMsgMax, pcbErrorMsg);
00591
00592 if (result == SQL_SUCCESS) {
00593
00594 odbc_errs_pop(errs);
00595 }
00596
00597 return result;
00598 }
00599
00600 #if (ODBCVER >= 0x0300)
00601 SQLRETURN SQL_API
00602 SQLGetDiagRec(SQLSMALLINT handleType, SQLHANDLE handle, SQLSMALLINT numRecord, SQLCHAR FAR * szSqlState,
00603 SQLINTEGER FAR * pfNativeError, SQLCHAR * szErrorMsg, SQLSMALLINT cbErrorMsgMax, SQLSMALLINT FAR * pcbErrorMsg)
00604 {
00605 return _SQLGetDiagRec(handleType, handle, numRecord, szSqlState, pfNativeError, szErrorMsg, cbErrorMsgMax, pcbErrorMsg);
00606 }
00607
00608 SQLRETURN SQL_API
00609 SQLGetDiagField(SQLSMALLINT handleType, SQLHANDLE handle, SQLSMALLINT numRecord, SQLSMALLINT diagIdentifier, SQLPOINTER buffer,
00610 SQLSMALLINT cbBuffer, SQLSMALLINT FAR * pcbBuffer)
00611 {
00612 SQLRETURN result = SQL_SUCCESS;
00613 struct _sql_errors *errs = NULL;
00614 const char *msg;
00615
00616 SQLINTEGER odbc_ver = SQL_OV_ODBC2;
00617 int cplen;
00618 TDS_STMT *stmt = NULL;
00619 TDS_DBC *dbc = NULL;
00620 TDS_ENV *env = NULL;
00621 char tmp[16];
00622
00623 if (cbBuffer < 0)
00624 return SQL_ERROR;
00625
00626 if (!handle)
00627 return SQL_INVALID_HANDLE;
00628
00629 switch (handleType) {
00630 case SQL_HANDLE_STMT:
00631 stmt = ((TDS_STMT *) handle);
00632 dbc = stmt->dbc;
00633 env = dbc->env;
00634 errs = &stmt->errs;
00635 break;
00636
00637 case SQL_HANDLE_DBC:
00638 dbc = ((TDS_DBC *) handle);
00639 env = dbc->env;
00640 errs = &dbc->errs;
00641 break;
00642
00643 case SQL_HANDLE_ENV:
00644 env = ((TDS_ENV *) handle);
00645 errs = &env->errs;
00646 break;
00647
00648 default:
00649 return SQL_INVALID_HANDLE;
00650 }
00651 odbc_ver = env->attr.odbc_version;
00652
00653
00654 switch (diagIdentifier) {
00655 case SQL_DIAG_DYNAMIC_FUNCTION:
00656 if (handleType != SQL_HANDLE_STMT)
00657 return SQL_ERROR;
00658
00659
00660 return odbc_set_string(buffer, cbBuffer, pcbBuffer, "", 0);
00661
00662 case SQL_DIAG_DYNAMIC_FUNCTION_CODE:
00663 *(SQLINTEGER *) buffer = 0;
00664 return SQL_SUCCESS;
00665
00666 case SQL_DIAG_NUMBER:
00667 *(SQLINTEGER *) buffer = errs->num_errors;
00668 return SQL_SUCCESS;
00669
00670 case SQL_DIAG_RETURNCODE:
00671 *(SQLRETURN *) buffer = errs->lastrc;
00672 return SQL_SUCCESS;
00673
00674 case SQL_DIAG_CURSOR_ROW_COUNT:
00675 if (handleType != SQL_HANDLE_STMT)
00676 return SQL_ERROR;
00677
00678
00679 *(SQLINTEGER *) buffer = 0;
00680 return SQL_SUCCESS;
00681
00682 case SQL_DIAG_ROW_COUNT:
00683 if (handleType != SQL_HANDLE_STMT)
00684 return SQL_ERROR;
00685
00686 return _SQLRowCount((SQLHSTMT) handle, (SQLLEN FAR *) buffer);
00687 }
00688
00689 if (numRecord > errs->num_errors)
00690 return SQL_NO_DATA_FOUND;
00691
00692 if (numRecord <= 0)
00693 return SQL_ERROR;
00694 --numRecord;
00695
00696 switch (diagIdentifier) {
00697 case SQL_DIAG_ROW_NUMBER:
00698 *(SQLINTEGER *) buffer = SQL_ROW_NUMBER_UNKNOWN;
00699 break;
00700
00701 case SQL_DIAG_CLASS_ORIGIN:
00702 case SQL_DIAG_SUBCLASS_ORIGIN:
00703 if (odbc_ver == SQL_OV_ODBC2)
00704 result = odbc_set_string(buffer, cbBuffer, pcbBuffer, "ISO 9075", -1);
00705 else
00706 result = odbc_set_string(buffer, cbBuffer, pcbBuffer, "ODBC 3.0", -1);
00707 break;
00708
00709 case SQL_DIAG_COLUMN_NUMBER:
00710 *(SQLINTEGER *) buffer = SQL_COLUMN_NUMBER_UNKNOWN;
00711 break;
00712
00713 #ifdef SQL_DIAG_SS_MSGSTATE
00714 case SQL_DIAG_SS_MSGSTATE:
00715 if (errs->errs[numRecord].msgstate == 0)
00716 return SQL_ERROR;
00717 else
00718 *(SQLINTEGER *) buffer = errs->errs[numRecord].msgstate;
00719 break;
00720 #endif
00721
00722 #ifdef SQL_DIAG_SS_LINE
00723 case SQL_DIAG_SS_LINE:
00724 if (errs->errs[numRecord].linenum == 0)
00725 return SQL_ERROR;
00726 else
00727 *(SQLUSMALLINT *) buffer = errs->errs[numRecord].linenum;
00728 break;
00729 #endif
00730
00731 case SQL_DIAG_CONNECTION_NAME:
00732 if (dbc && dbc->tds_socket && dbc->tds_socket->spid > 0)
00733 cplen = sprintf(tmp, "%d", dbc->tds_socket->spid);
00734 else
00735 cplen = 0;
00736
00737 result = odbc_set_string(buffer, cbBuffer, pcbBuffer, tmp, cplen);
00738 break;
00739
00740 case SQL_DIAG_MESSAGE_TEXT:
00741 msg = errs->errs[numRecord].msg;
00742 result = odbc_set_string(buffer, cbBuffer, pcbBuffer, msg, -1);
00743 break;
00744
00745 case SQL_DIAG_NATIVE:
00746 *(SQLINTEGER *) buffer = errs->errs[numRecord].native;
00747 break;
00748
00749 case SQL_DIAG_SERVER_NAME:
00750 msg = "";
00751 switch (handleType) {
00752 case SQL_HANDLE_ENV:
00753 break;
00754 case SQL_HANDLE_DBC:
00755 msg = tds_dstr_cstr(&dbc->server);
00756 break;
00757 case SQL_HANDLE_STMT:
00758 msg = tds_dstr_cstr(&stmt->dbc->server);
00759
00760
00761
00762
00763 if (!msg[0] && errs->errs[numRecord].server) {
00764 tds_dstr_copy(&stmt->dbc->server, errs->errs[numRecord].server);
00765 msg = errs->errs[numRecord].server;
00766 }
00767 break;
00768 }
00769 result = odbc_set_string(buffer, cbBuffer, pcbBuffer, msg, -1);
00770 break;
00771
00772 case SQL_DIAG_SQLSTATE:
00773 if (odbc_ver == SQL_OV_ODBC3)
00774 msg = errs->errs[numRecord].state3;
00775 else
00776 msg = errs->errs[numRecord].state2;
00777
00778 result = odbc_set_string(buffer, cbBuffer, pcbBuffer, msg, 5);
00779 break;
00780
00781 default:
00782 return SQL_ERROR;
00783 }
00784 return result;
00785 }
00786 #endif
00787
00788