1/* 2 * herr.c 3 * 4 * $Id: herr.c,v 1.30 2007/10/07 14:09:10 source Exp $ 5 * 6 * Error stack management functions 7 * 8 * The iODBC driver manager. 9 * 10 * Copyright (C) 1995 by Ke Jin <kejin@empress.com> 11 * Copyright (C) 1996-2006 by OpenLink Software <iodbc@openlinksw.com> 12 * All Rights Reserved. 13 * 14 * This software is released under the terms of either of the following 15 * licenses: 16 * 17 * - GNU Library General Public License (see LICENSE.LGPL) 18 * - The BSD License (see LICENSE.BSD). 19 * 20 * Note that the only valid version of the LGPL license as far as this 21 * project is concerned is the original GNU Library General Public License 22 * Version 2, dated June 1991. 23 * 24 * While not mandated by the BSD license, any patches you make to the 25 * iODBC source code may be contributed back into the iODBC project 26 * at your discretion. Contributions will benefit the Open Source and 27 * Data Access community as a whole. Submissions may be made at: 28 * 29 * http://www.iodbc.org 30 * 31 * 32 * GNU Library Generic Public License Version 2 33 * ============================================ 34 * This library is free software; you can redistribute it and/or 35 * modify it under the terms of the GNU Library General Public 36 * License as published by the Free Software Foundation; only 37 * Version 2 of the License dated June 1991. 38 * 39 * This library is distributed in the hope that it will be useful, 40 * but WITHOUT ANY WARRANTY; without even the implied warranty of 41 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 42 * Library General Public License for more details. 43 * 44 * You should have received a copy of the GNU Library General Public 45 * License along with this library; if not, write to the Free 46 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 47 * 48 * 49 * The BSD License 50 * =============== 51 * Redistribution and use in source and binary forms, with or without 52 * modification, are permitted provided that the following conditions 53 * are met: 54 * 55 * 1. Redistributions of source code must retain the above copyright 56 * notice, this list of conditions and the following disclaimer. 57 * 2. Redistributions in binary form must reproduce the above copyright 58 * notice, this list of conditions and the following disclaimer in 59 * the documentation and/or other materials provided with the 60 * distribution. 61 * 3. Neither the name of OpenLink Software Inc. nor the names of its 62 * contributors may be used to endorse or promote products derived 63 * from this software without specific prior written permission. 64 * 65 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 66 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 67 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 68 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OPENLINK OR 69 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 70 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 71 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 72 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 73 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 74 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 75 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 76 */ 77 78 79#include <iodbc.h> 80 81#include <sql.h> 82#include <sqlext.h> 83#include <sqlucode.h> 84 85#include <unicode.h> 86 87#include <dlproc.h> 88 89#include <herr.h> 90#if (ODBCVER >= 0x0300) 91#include <hdesc.h> 92#endif 93#include <henv.h> 94#include <hdbc.h> 95#include <hstmt.h> 96 97#include <itrace.h> 98 99#include "herr.ci" 100#include "misc.h" 101 102static HERR 103_iodbcdm_popsqlerr (HERR herr) 104{ 105 sqlerr_t *list = (sqlerr_t *) herr; 106 sqlerr_t *next; 107 108 if (herr == SQL_NULL_HERR) 109 { 110 return herr; 111 } 112 113 next = list->next; 114 list->next = NULL; 115 116 MEM_FREE (list); 117 118 return next; 119} 120 121 122void 123_iodbcdm_freesqlerrlist (HERR herrlist) 124{ 125 HERR list = herrlist; 126 127 while (list != SQL_NULL_HERR) 128 { 129 list = _iodbcdm_popsqlerr (list); 130 } 131} 132 133 134HERR 135_iodbcdm_pushsqlerr ( 136 HERR herr, 137 sqlstcode_t code, 138 void *msg) 139{ 140 sqlerr_t *ebuf; 141 sqlerr_t *perr = (sqlerr_t *) herr; 142 int idx = 0; 143 144 if (herr != SQL_NULL_HERR) 145 { 146 idx = perr->idx + 1; 147 } 148 149 if (idx == 64) 150 /* overwrite the top entry to prevent error stack blow out */ 151 { 152 perr->code = code; 153 perr->msg = (char *) msg; 154 155 return herr; 156 } 157 158 ebuf = (sqlerr_t *) MEM_ALLOC (sizeof (sqlerr_t)); 159 160 if (ebuf == NULL) 161 { 162 return NULL; 163 } 164 165 ebuf->msg = (char *) msg; 166 ebuf->code = code; 167 ebuf->idx = idx; 168 ebuf->next = (sqlerr_t *) herr; 169 return (HERR) ebuf; 170} 171 172 173static char * 174_iodbcdm_getsqlstate ( 175 HERR herr, 176 void * tab) 177{ 178 sqlerr_t *perr = (sqlerr_t *) herr; 179 sqlerrmsg_t *ptr; 180 sqlstcode_t perr_code; 181 182 if (herr == SQL_NULL_HERR || tab == NULL) 183 { 184 return (char *) NULL; 185 } 186 187 perr_code = perr->code; 188#if (ODBCVER >= 0x0300) 189 switch (perr_code) 190 { 191 case en_S1009: 192 perr_code = en_HY009; 193 break; 194 195 default: 196 break; 197 } 198#endif 199 for (ptr = (sqlerrmsg_t *) tab; ptr->code != en_sqlstat_total; ptr++) 200 { 201 if (ptr->code == perr_code) 202 { 203 return (char *) (ptr->stat); 204 } 205 } 206 207 return (char *) NULL; 208} 209 210 211static char * 212_iodbcdm_getsqlerrmsg ( 213 HERR herr, 214 void * errtab) 215{ 216 sqlerr_t *perr = (sqlerr_t *) herr; 217 sqlerrmsg_t *ptr; 218 219 if (herr == SQL_NULL_HERR) 220 { 221 return NULL; 222 } 223 224 if (perr->msg == NULL && errtab == NULL) 225 { 226 return NULL; 227 } 228 229 if (perr->msg != NULL) 230 { 231 return perr->msg; 232 } 233 234 for (ptr = (sqlerrmsg_t *) errtab; 235 ptr->code != en_sqlstat_total; 236 ptr++) 237 { 238 if (ptr->code == perr->code) 239 { 240 return (char *) ptr->msg; 241 } 242 } 243 244 return (char *) NULL; 245} 246 247 248SQLRETURN SQL_API 249_iodbcdm_sqlerror ( 250 SQLHENV henv, 251 SQLHDBC hdbc, 252 SQLHSTMT hstmt, 253 SQLPOINTER szSqlstate, 254 SQLINTEGER * pfNativeError, 255 SQLPOINTER szErrorMsg, 256 SQLSMALLINT cbErrorMsgMax, 257 SQLSMALLINT * pcbErrorMsg, 258 int bDelete, 259 SQLCHAR waMode) 260{ 261 GENV (genv, henv); 262 CONN (pdbc, hdbc); 263 STMT (pstmt, hstmt); 264 HDBC thdbc = SQL_NULL_HDBC; 265 266 HENV dhenv = SQL_NULL_HENV; 267 HDBC dhdbc = SQL_NULL_HDBC; 268 HSTMT dhstmt = SQL_NULL_HSTMT; 269 270 HERR herr = SQL_NULL_HERR; 271 HPROC hproc2 = SQL_NULL_HPROC; 272 HPROC hproc3 = SQL_NULL_HPROC; 273#if (ODBCVER >= 0x0300) 274 SQLINTEGER handleType = 0; 275 SQLHANDLE handle3; 276 SQLHANDLE dhandle3 = 0; 277 SQLSMALLINT *perr_rec = NULL; 278#endif 279 SWORD unicode_driver = 0; 280 SQLUINTEGER dodbc_ver = SQL_OV_ODBC2; 281 SQLUINTEGER odbc_ver = SQL_OV_ODBC2; 282 wchar_t _sqlState[6] = {L"\0"}; 283 void *SqlstateOut = szSqlstate; 284 void *_ErrorMsg = NULL; 285 void *errorMsgOut = szErrorMsg; 286 287 void *errmsg = NULL; 288 void *ststr = NULL; 289 290 int handle = 0; 291 SQLRETURN retcode = SQL_SUCCESS; 292 293 if (IS_VALID_HSTMT (hstmt)) /* retrieve stmt err */ 294 { 295 herr = pstmt->herr; 296 thdbc = pstmt->hdbc; 297 298 if (thdbc == SQL_NULL_HDBC) 299 { 300 return SQL_INVALID_HANDLE; 301 } 302 303#if (ODBCVER >= 0x0300) 304 handleType = SQL_HANDLE_STMT; 305 handle3 = hstmt; 306 dhandle3 = pstmt->dhstmt; 307 perr_rec = &((STMT_t *)pstmt)->err_rec; 308#endif 309 dhstmt = pstmt->dhstmt; 310 handle = 3; 311 } 312 else if (IS_VALID_HDBC (hdbc)) /* retrieve dbc err */ 313 { 314 herr = pdbc->herr; 315 thdbc = pdbc; 316 if (thdbc == SQL_NULL_HDBC) 317 { 318 return SQL_INVALID_HANDLE; 319 } 320 321#if (ODBCVER >= 0x0300) 322 handleType = SQL_HANDLE_DBC; 323 handle3 = hdbc; 324 dhandle3 = pdbc->dhdbc; 325 perr_rec = &((DBC_t *)pdbc)->err_rec; 326#endif 327 dhdbc = pdbc->dhdbc; 328 handle = 2; 329 330 if (herr == SQL_NULL_HERR 331 && pdbc->henv == SQL_NULL_HENV) 332 { 333 return SQL_NO_DATA_FOUND; 334 } 335 } 336 else if (IS_VALID_HENV (henv)) /* retrieve env err */ 337 { 338 herr = genv->herr; 339 340 /* Drivers shouldn't push error message 341 * on environment handle */ 342 343 if (herr == SQL_NULL_HERR) 344 { 345 return SQL_NO_DATA_FOUND; 346 } 347 348 handle = 1; 349 } 350 else 351 { 352 return SQL_INVALID_HANDLE; 353 } 354 355 if (szErrorMsg != NULL) 356 { 357 if (cbErrorMsgMax < 0) 358 { 359 return SQL_ERROR; 360 /* SQLError() doesn't post error for itself */ 361 } 362 } 363 364 if (herr == SQL_NULL_HERR) /* no err on drv mng */ 365 { 366 if (((DBC_t *)hdbc)->genv) 367 odbc_ver = ((GENV_t *) ((DBC_t *)hdbc)->genv)->odbc_ver; 368 369 if (((DBC_t *)hdbc)->henv) 370 { 371 unicode_driver = ((ENV_t *) ((DBC_t *)hdbc)->henv)->unicode_driver; 372 dodbc_ver = ((ENV_t *) ((DBC_t *)hdbc)->henv)->dodbc_ver; 373 } 374 375 /* call driver */ 376 if ((unicode_driver && waMode != 'W') 377 || (!unicode_driver && waMode == 'W')) 378 { 379 if (waMode != 'W') 380 { 381 /* ansi=>unicode*/ 382 if ((_ErrorMsg = malloc(cbErrorMsgMax * sizeof(wchar_t) + 1)) == NULL) 383 return SQL_ERROR; 384 } 385 else 386 { 387 /* unicode=>ansi*/ 388 if ((_ErrorMsg = malloc(cbErrorMsgMax + 1)) == NULL) 389 return SQL_ERROR; 390 } 391 errorMsgOut = _ErrorMsg; 392 SqlstateOut = _sqlState; 393 } 394 395 /* call driver */ 396 if (unicode_driver) 397 { 398 /* SQL_XXX_W */ 399 hproc2 = _iodbcdm_getproc (thdbc, en_ErrorW); 400#if (ODBCVER >= 0x300) 401 hproc3 = _iodbcdm_getproc (thdbc, en_GetDiagRecW); 402#endif 403 } 404 else 405 { 406 /* SQL_XXX */ 407 /* SQL_XXX_A */ 408 hproc2 = _iodbcdm_getproc (thdbc, en_Error); 409 if (hproc2 == SQL_NULL_HPROC) 410 hproc2 = _iodbcdm_getproc (thdbc, en_ErrorA); 411#if (ODBCVER >= 0x300) 412 hproc3 = _iodbcdm_getproc (thdbc, en_GetDiagRec); 413 if (hproc3 == SQL_NULL_HPROC) 414 hproc3 = _iodbcdm_getproc (thdbc, en_GetDiagRecA); 415#endif 416 } 417 418 if (odbc_ver == SQL_OV_ODBC2 && 419 ( dodbc_ver == SQL_OV_ODBC2 420 || (dodbc_ver == SQL_OV_ODBC3 && hproc2 != SQL_NULL_HPROC))) 421 hproc3 = SQL_NULL_HPROC; 422 423#if (ODBCVER >= 0x300) 424 if (hproc3 != SQL_NULL_HPROC) 425 { 426 (*perr_rec) = (*perr_rec) + 1; 427 CALL_DRIVER (thdbc, NULL, retcode, hproc3, ( 428 handleType, 429 dhandle3, 430 (*perr_rec), 431 SqlstateOut, 432 pfNativeError, 433 errorMsgOut, 434 cbErrorMsgMax, 435 pcbErrorMsg)); 436 } 437 else 438#endif 439 { 440 if (hproc2 == SQL_NULL_HPROC) 441 { 442 MEM_FREE(_ErrorMsg); 443 return SQL_NO_DATA_FOUND; 444 } 445 CALL_DRIVER (thdbc, NULL, retcode, hproc2, ( 446 dhenv, 447 dhdbc, 448 dhstmt, 449 SqlstateOut, 450 pfNativeError, 451 errorMsgOut, 452 cbErrorMsgMax, 453 pcbErrorMsg)); 454 } 455 456 if (szErrorMsg 457 && SQL_SUCCEEDED (retcode) 458 && ((unicode_driver && waMode != 'W') 459 || (!unicode_driver && waMode == 'W'))) 460 { 461 if (waMode != 'W') 462 { 463 /* ansi<=unicode*/ 464 dm_StrCopyOut2_W2A ((SQLWCHAR *)errorMsgOut, (SQLCHAR *)szErrorMsg, cbErrorMsgMax, NULL); 465 dm_StrCopyOut2_W2A ((SQLWCHAR *)SqlstateOut, (SQLCHAR *)szSqlstate, 6, NULL); 466 } 467 else 468 { 469 /* unicode<=ansi*/ 470 dm_StrCopyOut2_A2W ((SQLCHAR *)errorMsgOut, (SQLWCHAR *)szErrorMsg, cbErrorMsgMax, NULL); 471 dm_StrCopyOut2_A2W ((SQLCHAR *)SqlstateOut, (SQLWCHAR *)szSqlstate, 6, NULL); 472 } 473 } 474 475 MEM_FREE(_ErrorMsg); 476 477 return retcode; 478 } 479 480 if (szSqlstate != NULL) 481 { 482 int len; 483 484 /* get sql state string */ 485 ststr = (char *) _iodbcdm_getsqlstate (herr, 486 (void *) sqlerrmsg_tab); 487 488 if (ststr == NULL) 489 { 490 len = 0; 491 } 492 else 493 { 494 len = (int) STRLEN (ststr); 495 } 496 497 /* buffer size of szSqlstate is not checked. Applications 498 * suppose provide enough ( not less than 6 bytes ) buffer 499 * or NULL for it. 500 */ 501 if (waMode != 'W') 502 { 503 STRNCPY (szSqlstate, ststr, len); 504 ((char*)szSqlstate)[len] = 0; 505 } 506 else 507 { 508 dm_StrCopyOut2_A2W ((SQLCHAR *)ststr, (SQLWCHAR *)szSqlstate, 6, NULL); 509 ((wchar_t*)szSqlstate)[len] = 0; 510 } 511 } 512 513 if (pfNativeError != NULL) 514 { 515 /* native error code is specific to data source */ 516 *pfNativeError = (SDWORD) 0L; 517 } 518 519 if (szErrorMsg == NULL || cbErrorMsgMax == 0) 520 { 521 if (pcbErrorMsg != NULL) 522 { 523 *pcbErrorMsg = (SWORD) 0; 524 } 525 } 526 else 527 { 528 int len; 529 char msgbuf[256] = {'\0'}; 530 531 /* get sql state message */ 532 errmsg = _iodbcdm_getsqlerrmsg (herr, (void *) sqlerrmsg_tab); 533 534 if (errmsg == NULL) 535 { 536 errmsg = (char *) ""; 537 } 538 539#if defined(HAVE_SNPRINTF) 540 snprintf (msgbuf, sizeof(msgbuf), "%s%s", sqlerrhd, (char*)errmsg); 541#else 542 sprintf (msgbuf, "%s%s", sqlerrhd, (char*)errmsg); 543#endif 544 545 len = STRLEN (msgbuf); 546 547 if (len < cbErrorMsgMax - 1) 548 { 549 retcode = SQL_SUCCESS; 550 } 551 else 552 { 553 len = cbErrorMsgMax - 1; 554 retcode = SQL_SUCCESS_WITH_INFO; 555 /* and not posts error for itself */ 556 } 557 558 if (waMode != 'W') 559 { 560 STRNCPY ((char *) szErrorMsg, msgbuf, len); 561 ((char*)szErrorMsg)[len] = 0; 562 if (pcbErrorMsg != NULL) 563 *pcbErrorMsg = (SWORD) len; 564 } 565 else 566 { 567 dm_StrCopyOut2_A2W ((SQLCHAR *) msgbuf, 568 (SQLWCHAR *) szErrorMsg, cbErrorMsgMax, pcbErrorMsg); 569 } 570 } 571 572 if (bDelete) 573 switch (handle) /* free this err */ 574 { 575 case 1: 576 genv->herr = _iodbcdm_popsqlerr (genv->herr); 577 break; 578 579 case 2: 580 pdbc->herr = _iodbcdm_popsqlerr (pdbc->herr); 581 break; 582 583 case 3: 584 pstmt->herr = _iodbcdm_popsqlerr (pstmt->herr); 585 break; 586 587 default: 588 break; 589 } 590 591 return retcode; 592} 593 594 595SQLRETURN SQL_API 596SQLError ( 597 SQLHENV henv, 598 SQLHDBC hdbc, 599 SQLHSTMT hstmt, 600 SQLCHAR * szSqlstate, 601 SQLINTEGER * pfNativeError, 602 SQLCHAR * szErrorMsg, 603 SQLSMALLINT cbErrorMsgMax, 604 SQLSMALLINT * pcbErrorMsg) 605{ 606 SQLRETURN retcode = SQL_SUCCESS; 607 608 ODBC_LOCK (); 609 TRACE (trace_SQLError (TRACE_ENTER, 610 henv, 611 hdbc, 612 hstmt, 613 szSqlstate, 614 pfNativeError, 615 szErrorMsg, cbErrorMsgMax, pcbErrorMsg)); 616 617 retcode = _iodbcdm_sqlerror ( 618 henv, 619 hdbc, 620 hstmt, 621 szSqlstate, 622 pfNativeError, 623 szErrorMsg, cbErrorMsgMax, pcbErrorMsg, 624 1, 625 'A'); 626 627 TRACE (trace_SQLError (TRACE_LEAVE, 628 henv, 629 hdbc, 630 hstmt, 631 szSqlstate, 632 pfNativeError, 633 szErrorMsg, cbErrorMsgMax, pcbErrorMsg)); 634 635 ODBC_UNLOCK (); 636 return retcode; 637} 638 639 640#if ODBCVER >= 0x0300 641SQLRETURN SQL_API 642SQLErrorA ( 643 SQLHENV henv, 644 SQLHDBC hdbc, 645 SQLHSTMT hstmt, 646 SQLCHAR * szSqlstate, 647 SQLINTEGER * pfNativeError, 648 SQLCHAR * szErrorMsg, 649 SQLSMALLINT cbErrorMsgMax, 650 SQLSMALLINT * pcbErrorMsg) 651{ 652 SQLRETURN retcode = SQL_SUCCESS; 653 654 ODBC_LOCK (); 655 TRACE (trace_SQLError (TRACE_ENTER, 656 henv, 657 hdbc, 658 hstmt, 659 szSqlstate, 660 pfNativeError, 661 szErrorMsg, cbErrorMsgMax, pcbErrorMsg)); 662 663 retcode = _iodbcdm_sqlerror ( 664 henv, 665 hdbc, 666 hstmt, 667 szSqlstate, 668 pfNativeError, 669 szErrorMsg, cbErrorMsgMax, pcbErrorMsg, 670 1, 671 'A'); 672 673 TRACE (trace_SQLError (TRACE_LEAVE, 674 henv, 675 hdbc, 676 hstmt, 677 szSqlstate, 678 pfNativeError, 679 szErrorMsg, cbErrorMsgMax, pcbErrorMsg)); 680 681 ODBC_UNLOCK (); 682 return retcode; 683} 684 685 686SQLRETURN SQL_API 687SQLErrorW ( 688 SQLHENV henv, 689 SQLHDBC hdbc, 690 SQLHSTMT hstmt, 691 SQLWCHAR * szSqlstate, 692 SQLINTEGER * pfNativeError, 693 SQLWCHAR * szErrorMsg, 694 SQLSMALLINT cbErrorMsgMax, 695 SQLSMALLINT * pcbErrorMsg) 696{ 697 SQLRETURN retcode = SQL_SUCCESS; 698 699 ODBC_LOCK (); 700 TRACE (trace_SQLErrorW (TRACE_ENTER, 701 henv, 702 hdbc, 703 hstmt, 704 szSqlstate, 705 pfNativeError, 706 szErrorMsg, cbErrorMsgMax, pcbErrorMsg)); 707 708 retcode = _iodbcdm_sqlerror ( 709 henv, 710 hdbc, 711 hstmt, 712 szSqlstate, 713 pfNativeError, 714 szErrorMsg, cbErrorMsgMax, pcbErrorMsg, 715 1, 716 'W'); 717 718 TRACE (trace_SQLErrorW (TRACE_LEAVE, 719 henv, 720 hdbc, 721 hstmt, 722 szSqlstate, 723 pfNativeError, 724 szErrorMsg, cbErrorMsgMax, pcbErrorMsg)); 725 726 ODBC_UNLOCK (); 727 return retcode; 728} 729#endif 730 731 732#if (ODBCVER >= 0x0300) 733static int 734error_rec_count (HERR herr) 735{ 736 sqlerr_t *err = (sqlerr_t *)herr; 737 if (err) 738 return err->idx + 1; 739 else 740 return 0; 741} 742 743 744static sqlerr_t * 745get_nth_error(HERR herr, int nIndex) 746{ 747 sqlerr_t *err = (sqlerr_t *) herr; 748 while (err && err->idx != nIndex) 749 err = err->next; 750 return err; 751} 752 753 754RETCODE SQL_API 755SQLGetDiagRec_Internal ( 756 SQLSMALLINT HandleType, 757 SQLHANDLE Handle, 758 SQLSMALLINT RecNumber, 759 SQLPOINTER Sqlstate, 760 SQLINTEGER * NativeErrorPtr, 761 SQLPOINTER MessageText, 762 SQLSMALLINT BufferLength, 763 SQLSMALLINT * TextLengthPtr, 764 SQLCHAR waMode) 765{ 766 sqlerr_t *curr_err = NULL; 767 HERR err = NULL; 768 int nRecs; 769 HPROC hproc2 = SQL_NULL_HPROC; 770 HPROC hproc3 = SQL_NULL_HPROC; 771 HDBC hdbc = SQL_NULL_HDBC; 772 RETCODE retcode = SQL_SUCCESS; 773 SQLHANDLE dhandle = SQL_NULL_HANDLE; 774 SWORD unicode_driver = 0; 775 SQLUINTEGER dodbc_ver = SQL_OV_ODBC3; 776 SQLUINTEGER odbc_ver = SQL_OV_ODBC3; 777 wchar_t _sqlState[6] = {L"\0"}; 778 void *_MessageText = NULL; 779 void *messageTextOut = MessageText; 780 void *SqlstateOut = Sqlstate; 781 782 783 if (RecNumber < 1) 784 return SQL_ERROR; 785 786 if (BufferLength < 0) 787 return SQL_ERROR; 788 789 switch (HandleType) 790 { 791 case SQL_HANDLE_ENV: 792 if (!IS_VALID_HENV (Handle)) 793 { 794 return SQL_INVALID_HANDLE; 795 } 796 err = ((GENV_t *) Handle)->herr; 797 break; 798 799 case SQL_HANDLE_DBC: 800 if (!IS_VALID_HDBC (Handle)) 801 { 802 return SQL_INVALID_HANDLE; 803 } 804 err = ((DBC_t *) Handle)->herr; 805 dhandle = ((DBC_t *) Handle)->dhdbc; 806 hdbc = Handle; 807 break; 808 809 case SQL_HANDLE_STMT: 810 if (!IS_VALID_HSTMT (Handle)) 811 { 812 return SQL_INVALID_HANDLE; 813 } 814 err = ((STMT_t *) Handle)->herr; 815 dhandle = ((STMT_t *) Handle)->dhstmt; 816 hdbc = ((STMT_t *) Handle)->hdbc; 817 break; 818 819 case SQL_HANDLE_DESC: 820 if (!IS_VALID_HDESC (Handle)) 821 { 822 return SQL_INVALID_HANDLE; 823 } 824 err = ((DESC_t *) Handle)->herr; 825 dhandle = ((DESC_t *) Handle)->dhdesc; 826 hdbc = ((DESC_t *) Handle)->hdbc; 827 break; 828 829 default: 830 return SQL_INVALID_HANDLE; 831 } 832 833 nRecs = error_rec_count (err); 834 835 if (nRecs >= RecNumber) 836 { /* DM error range */ 837 curr_err = get_nth_error (err, RecNumber - 1); 838 839 if (!curr_err) 840 { 841 return (SQL_NO_DATA_FOUND); 842 } 843 844 retcode = SQL_SUCCESS; 845 846 if (Sqlstate != NULL) 847 { 848 int len; 849 char *ststr = (char *) _iodbcdm_getsqlstate (curr_err, 850 (void *) sqlerrmsg_tab); 851 852 if (ststr == NULL) 853 { 854 len = 0; 855 } 856 else 857 { 858 len = (int) STRLEN (ststr); 859 } 860 861 /* buffer size of szSqlstate is not checked. Applications 862 * suppose provide enough ( not less than 6 bytes ) buffer 863 * or NULL for it. 864 */ 865 if (waMode != 'W') 866 { 867 STRNCPY (Sqlstate, ststr, len); 868 ((char*)Sqlstate)[len] = 0; 869 } 870 else 871 { 872 dm_StrCopyOut2_A2W ((SQLCHAR *) ststr, 873 (SQLWCHAR *) Sqlstate, 6, NULL); 874 ((wchar_t*)Sqlstate)[len] = 0; 875 } 876 } 877 878 if (MessageText == NULL || BufferLength == 0) 879 { 880 if (TextLengthPtr != NULL) 881 { 882 *TextLengthPtr = (SWORD) 0; 883 } 884 } 885 else 886 { 887 int len; 888 char msgbuf[256] = { '\0' }; 889 char *errmsg; 890 891 /* get sql state message */ 892 errmsg = 893 _iodbcdm_getsqlerrmsg (curr_err, (void *) sqlerrmsg_tab); 894 895 if (errmsg == NULL) 896 { 897 errmsg = (char *) ""; 898 } 899 900#if defined(HAVE_SNPRINTF) 901 snprintf (msgbuf, sizeof (msgbuf), "%s%s", sqlerrhd, errmsg); 902#else 903 sprintf (msgbuf, "%s%s", sqlerrhd, errmsg); 904#endif 905 906 len = STRLEN (msgbuf); 907 908 if (len < BufferLength - 1) 909 { 910 retcode = SQL_SUCCESS; 911 } 912 else 913 { 914 len = BufferLength - 1; 915 retcode = SQL_SUCCESS_WITH_INFO; 916 /* and not posts error for itself */ 917 } 918 919 if (waMode != 'W') 920 { 921 STRNCPY ((char *) MessageText, msgbuf, len); 922 ((char*)MessageText)[len] = 0; 923 if (TextLengthPtr != NULL) 924 *TextLengthPtr = (SWORD) len; 925 } 926 else 927 { 928 dm_StrCopyOut2_A2W ((SQLCHAR *) msgbuf, 929 (SQLWCHAR *) MessageText, BufferLength, TextLengthPtr); 930 } 931 } 932 return retcode; 933 } 934 else 935 { /* Driver errors */ 936 if (hdbc == SQL_NULL_HDBC) 937 { 938 return SQL_NO_DATA_FOUND; 939 } 940 RecNumber -= nRecs; 941 942 if (((DBC_t *)hdbc)->henv) 943 { 944 unicode_driver = ((ENV_t *) ((DBC_t *)hdbc)->henv)->unicode_driver; 945 dodbc_ver = ((ENV_t *) ((DBC_t *)hdbc)->henv)->dodbc_ver; 946 } 947 948 if (((DBC_t *)hdbc)->genv) 949 odbc_ver = ((GENV_t *) ((DBC_t *)hdbc)->genv)->odbc_ver; 950 951 if ((unicode_driver && waMode != 'W') 952 || (!unicode_driver && waMode == 'W')) 953 { 954 if (waMode != 'W') 955 { 956 /* ansi=>unicode*/ 957 if ((_MessageText = malloc((BufferLength + 1) * sizeof(wchar_t))) == NULL) 958 { 959 return SQL_ERROR; 960 } 961 } 962 else 963 { 964 /* unicode=>ansi*/ 965 if ((_MessageText = malloc(BufferLength + 1)) == NULL) 966 { 967 return SQL_ERROR; 968 } 969 } 970 messageTextOut = _MessageText; 971 SqlstateOut = _sqlState; 972 } 973 974 /* call driver */ 975 if (unicode_driver) 976 { 977 /* SQL_XXX_W */ 978 hproc2 = _iodbcdm_getproc (hdbc, en_ErrorW); 979#if (ODBCVER >= 0x300) 980 hproc3 = _iodbcdm_getproc (hdbc, en_GetDiagRecW); 981#endif 982 } 983 else 984 { 985 /* SQL_XXX */ 986 /* SQL_XXX_A */ 987 hproc2 = _iodbcdm_getproc (hdbc, en_Error); 988 if (hproc2 == SQL_NULL_HPROC) 989 hproc2 = _iodbcdm_getproc (hdbc, en_ErrorA); 990#if (ODBCVER >= 0x300) 991 hproc3 = _iodbcdm_getproc (hdbc, en_GetDiagRec); 992 if (hproc3 == SQL_NULL_HPROC) 993 hproc3 = _iodbcdm_getproc (hdbc, en_GetDiagRecA); 994#endif 995 } 996 997 if (odbc_ver == SQL_OV_ODBC2 && 998 ( dodbc_ver == SQL_OV_ODBC2 999 || (dodbc_ver == SQL_OV_ODBC3 && hproc2 != SQL_NULL_HPROC))) 1000 hproc3 = SQL_NULL_HPROC; 1001 1002#if (ODBCVER >= 0x300) 1003 if (hproc3 != SQL_NULL_HPROC) 1004 { 1005 CALL_DRIVER (hdbc, Handle, retcode, hproc3, ( 1006 HandleType, 1007 dhandle, 1008 RecNumber, 1009 SqlstateOut, 1010 NativeErrorPtr, 1011 messageTextOut, 1012 BufferLength, 1013 TextLengthPtr)); 1014 } 1015 else 1016#endif 1017 { 1018 if (hproc2 == SQL_NULL_HPROC) 1019 { 1020 MEM_FREE(_MessageText); 1021 return SQL_ERROR; 1022 } 1023 1024 if (RecNumber > 1 || HandleType == SQL_HANDLE_DESC) 1025 { 1026 MEM_FREE(_MessageText); 1027 return SQL_NO_DATA_FOUND; 1028 } 1029 CALL_DRIVER (hdbc, Handle, retcode, hproc2, ( 1030 SQL_NULL_HENV, 1031 HandleType == SQL_HANDLE_DBC ? dhandle : SQL_NULL_HDBC, 1032 HandleType == SQL_HANDLE_STMT ? dhandle : SQL_NULL_HSTMT, 1033 SqlstateOut, 1034 NativeErrorPtr, 1035 messageTextOut, 1036 BufferLength, 1037 TextLengthPtr)); 1038 } 1039 1040 if (MessageText 1041 && SQL_SUCCEEDED (retcode) 1042 && ((unicode_driver && waMode != 'W') 1043 || (!unicode_driver && waMode == 'W'))) 1044 { 1045 if (waMode != 'W') 1046 { 1047 /* ansi<=unicode*/ 1048 dm_StrCopyOut2_W2A ((SQLWCHAR *)messageTextOut, (SQLCHAR *)MessageText, BufferLength, NULL); 1049 dm_StrCopyOut2_W2A ((SQLWCHAR *)SqlstateOut, (SQLCHAR *)Sqlstate, 6, NULL); 1050 } 1051 else 1052 { 1053 /* unicode<=ansi*/ 1054 dm_StrCopyOut2_A2W ((SQLCHAR *) messageTextOut, (SQLWCHAR *) MessageText, BufferLength, NULL); 1055 dm_StrCopyOut2_A2W ((SQLCHAR *) SqlstateOut, (SQLWCHAR *) Sqlstate, 6, NULL); 1056 } 1057 } 1058 1059 MEM_FREE(_MessageText); 1060 1061 return retcode; 1062 } 1063} 1064 1065 1066RETCODE SQL_API 1067SQLGetDiagRec ( 1068 SQLSMALLINT HandleType, 1069 SQLHANDLE Handle, 1070 SQLSMALLINT RecNumber, 1071 SQLCHAR * Sqlstate, 1072 SQLINTEGER * NativeErrorPtr, 1073 SQLCHAR * MessageText, 1074 SQLSMALLINT BufferLength, 1075 SQLSMALLINT * TextLengthPtr) 1076{ 1077 SQLRETURN retcode = SQL_SUCCESS; 1078 1079 ODBC_LOCK (); 1080 1081 TRACE (trace_SQLGetDiagRec (TRACE_ENTER, 1082 HandleType, 1083 Handle, 1084 RecNumber, 1085 Sqlstate, 1086 NativeErrorPtr, 1087 MessageText, BufferLength, TextLengthPtr)); 1088 1089 retcode = SQLGetDiagRec_Internal ( 1090 HandleType, 1091 Handle, 1092 RecNumber, 1093 Sqlstate, 1094 NativeErrorPtr, 1095 MessageText, BufferLength, TextLengthPtr, 1096 'A'); 1097 1098 TRACE (trace_SQLGetDiagRec (TRACE_LEAVE, 1099 HandleType, 1100 Handle, 1101 RecNumber, 1102 Sqlstate, 1103 NativeErrorPtr, 1104 MessageText, BufferLength, TextLengthPtr)); 1105 1106 ODBC_UNLOCK (); 1107 1108 return retcode; 1109} 1110 1111 1112RETCODE SQL_API 1113SQLGetDiagRecA ( 1114 SQLSMALLINT HandleType, 1115 SQLHANDLE Handle, 1116 SQLSMALLINT RecNumber, 1117 SQLCHAR * Sqlstate, 1118 SQLINTEGER * NativeErrorPtr, 1119 SQLCHAR * MessageText, 1120 SQLSMALLINT BufferLength, 1121 SQLSMALLINT * TextLengthPtr) 1122{ 1123 SQLRETURN retcode = SQL_SUCCESS; 1124 1125 ODBC_LOCK (); 1126 1127 TRACE (trace_SQLGetDiagRec (TRACE_ENTER, 1128 HandleType, 1129 Handle, 1130 RecNumber, 1131 Sqlstate, 1132 NativeErrorPtr, 1133 MessageText, BufferLength, TextLengthPtr)); 1134 1135 retcode = SQLGetDiagRec_Internal ( 1136 HandleType, 1137 Handle, 1138 RecNumber, 1139 Sqlstate, 1140 NativeErrorPtr, 1141 MessageText, BufferLength, TextLengthPtr, 1142 'A'); 1143 1144 TRACE (trace_SQLGetDiagRec (TRACE_LEAVE, 1145 HandleType, 1146 Handle, 1147 RecNumber, 1148 Sqlstate, 1149 NativeErrorPtr, 1150 MessageText, BufferLength, TextLengthPtr)); 1151 1152 ODBC_UNLOCK (); 1153 1154 return retcode; 1155} 1156 1157 1158RETCODE SQL_API 1159SQLGetDiagRecW ( 1160 SQLSMALLINT HandleType, 1161 SQLHANDLE Handle, 1162 SQLSMALLINT RecNumber, 1163 SQLWCHAR * Sqlstate, 1164 SQLINTEGER * NativeErrorPtr, 1165 SQLWCHAR * MessageText, 1166 SQLSMALLINT BufferLength, 1167 SQLSMALLINT * TextLengthPtr) 1168{ 1169 SQLRETURN retcode = SQL_SUCCESS; 1170 1171 ODBC_LOCK (); 1172 1173 TRACE (trace_SQLGetDiagRecW (TRACE_ENTER, 1174 HandleType, 1175 Handle, 1176 RecNumber, 1177 Sqlstate, 1178 NativeErrorPtr, 1179 MessageText, BufferLength, TextLengthPtr)); 1180 1181 retcode = SQLGetDiagRec_Internal ( 1182 HandleType, 1183 Handle, 1184 RecNumber, 1185 Sqlstate, 1186 NativeErrorPtr, 1187 MessageText, BufferLength, TextLengthPtr, 1188 'W'); 1189 1190 TRACE (trace_SQLGetDiagRecW (TRACE_LEAVE, 1191 HandleType, 1192 Handle, 1193 RecNumber, 1194 Sqlstate, 1195 NativeErrorPtr, 1196 MessageText, BufferLength, TextLengthPtr)); 1197 1198 ODBC_UNLOCK (); 1199 1200 return retcode; 1201} 1202 1203 1204RETCODE SQL_API 1205SQLGetDiagField_Internal ( 1206 SQLSMALLINT nHandleType, 1207 SQLHANDLE Handle, 1208 SQLSMALLINT nRecNumber, 1209 SQLSMALLINT nDiagIdentifier, 1210 SQLPOINTER pDiagInfoPtr, 1211 SQLSMALLINT nBufferLength, 1212 SQLSMALLINT * pnStringLengthPtr, 1213 SQLCHAR waMode) 1214{ 1215 GENV (genv, Handle); 1216 CONN (con, Handle); 1217 STMT (stmt, Handle); 1218 DESC (desc, Handle); 1219 HERR err; 1220 HPROC hproc = SQL_NULL_HPROC; 1221 RETCODE retcode = SQL_SUCCESS; 1222 SQLHANDLE dhandle = SQL_NULL_HANDLE; 1223 SWORD unicode_driver = 0; 1224 void *_DiagInfoPtr = NULL; 1225 void *diagInfoPtr = pDiagInfoPtr; 1226 1227 1228 switch (nHandleType) 1229 { 1230 case SQL_HANDLE_ENV: 1231 if (!IS_VALID_HENV (Handle)) 1232 { 1233 return SQL_INVALID_HANDLE; 1234 } 1235 err = genv->herr; 1236 con = NULL; 1237 stmt = NULL; 1238 desc = NULL; 1239 break; 1240 1241 case SQL_HANDLE_DBC: 1242 if (!IS_VALID_HDBC (Handle)) 1243 { 1244 return SQL_INVALID_HANDLE; 1245 } 1246 err = con->herr; 1247 genv = (GENV_t *) con->genv; 1248 stmt = NULL; 1249 desc = NULL; 1250 dhandle = con->dhdbc; 1251 break; 1252 1253 case SQL_HANDLE_STMT: 1254 if (!IS_VALID_HSTMT (Handle)) 1255 { 1256 return SQL_INVALID_HANDLE; 1257 } 1258 err = stmt->herr; 1259 con = (DBC_t *) stmt->hdbc; 1260 genv = (GENV_t *) con->genv; 1261 desc = NULL; 1262 dhandle = stmt->dhstmt; 1263 break; 1264 1265 case SQL_HANDLE_DESC: 1266 if (!IS_VALID_HDESC (Handle)) 1267 { 1268 return SQL_INVALID_HANDLE; 1269 } 1270 err = desc->herr; 1271 stmt = (STMT_t *) desc->hstmt; 1272 con = (DBC_t *) desc->hdbc; 1273 genv = (GENV_t *) con->genv; 1274 dhandle = desc->dhdesc; 1275 break; 1276 1277 default: 1278 return SQL_INVALID_HANDLE; 1279 } 1280 1281 if (con != NULL && con->henv != SQL_NULL_HENV) 1282 unicode_driver = ((ENV_t *) con->henv)->unicode_driver; 1283 1284 switch (nRecNumber) 1285 { 1286 1287 case 0: /* Header record */ 1288 switch (nDiagIdentifier) 1289 { 1290 case SQL_DIAG_ROW_COUNT: 1291 { 1292 if (nHandleType != SQL_HANDLE_STMT || !stmt) 1293 { 1294 return SQL_ERROR; 1295 } 1296 1297 if (stmt->state != en_stmt_executed_with_info && 1298 stmt->state != en_stmt_executed && 1299 stmt->state != en_stmt_cursoropen) 1300 { 1301 return SQL_ERROR; 1302 } 1303 if (!con) 1304 { 1305 return SQL_INVALID_HANDLE; 1306 } 1307 1308 CALL_UDRIVER(con, stmt, retcode, hproc, unicode_driver, en_GetDiagField, 1309 (SQL_HANDLE_DBC, stmt->dhstmt, nRecNumber, nDiagIdentifier, 1310 pDiagInfoPtr, nBufferLength, pnStringLengthPtr )); 1311 if (hproc == SQL_NULL_HPROC) 1312 { 1313 if (!con) 1314 { 1315 return SQL_INVALID_HANDLE; 1316 } 1317 hproc = _iodbcdm_getproc (con, en_RowCount); 1318 if (!hproc) 1319 { 1320 return SQL_ERROR; 1321 } 1322 CALL_DRIVER (stmt->hdbc, stmt, retcode, hproc, 1323 (stmt->dhstmt, pDiagInfoPtr)); 1324 } 1325 return retcode; 1326 } 1327 1328 case SQL_DIAG_CURSOR_ROW_COUNT: 1329 case SQL_DIAG_DYNAMIC_FUNCTION: 1330 case SQL_DIAG_DYNAMIC_FUNCTION_CODE: 1331 1332 { 1333 if (nHandleType != SQL_HANDLE_STMT || !stmt) 1334 { 1335 return SQL_ERROR; 1336 } 1337 1338 if (stmt->state != en_stmt_executed_with_info && 1339 stmt->state != en_stmt_executed && 1340 stmt->state != en_stmt_cursoropen) 1341 { 1342 return SQL_ERROR; 1343 } 1344 if (!con) 1345 { 1346 return SQL_INVALID_HANDLE; 1347 } 1348 1349 CALL_UDRIVER(con, stmt, retcode, hproc, unicode_driver, en_GetDiagField, 1350 (SQL_HANDLE_DBC, stmt->dhstmt, nRecNumber, nDiagIdentifier, 1351 pDiagInfoPtr, nBufferLength, pnStringLengthPtr )); 1352 if (hproc == SQL_NULL_HPROC) 1353 return SQL_ERROR; 1354 else 1355 return retcode; 1356 } 1357 1358 case SQL_DIAG_RETURNCODE: 1359 1360 if (pDiagInfoPtr) 1361 *((SQLRETURN *) pDiagInfoPtr) = ((GENV_t *) Handle)->rc; 1362 { 1363 return SQL_SUCCESS; 1364 } 1365 1366 case SQL_DIAG_NUMBER: 1367 1368 if (pDiagInfoPtr) 1369 { 1370 (*(SQLINTEGER *) pDiagInfoPtr) = 0; 1371 /* get the number from the driver */ 1372 if (con) 1373 { 1374 CALL_UDRIVER(con, Handle, retcode, hproc, unicode_driver, en_GetDiagField, 1375 (nHandleType, dhandle, 0, nDiagIdentifier, 1376 pDiagInfoPtr, nBufferLength, pnStringLengthPtr )); 1377 if (hproc != SQL_NULL_HPROC) 1378 { 1379 if (retcode != SQL_SUCCESS) 1380 { 1381 return retcode; 1382 } 1383 1384 /* and add the DM's value */ 1385 (*(SQLINTEGER *) pDiagInfoPtr) += error_rec_count (err); 1386 } 1387 else if (((ENV_t *) con->henv)->dodbc_ver == SQL_OV_ODBC2 && 1388 ((GENV_t *) Handle)->rc) 1389 { /* ODBC2 drivers can only have one error */ 1390 (*(SQLINTEGER *) pDiagInfoPtr) = 1; 1391 } 1392 } 1393 else if (genv) 1394 { 1395 (*(SQLINTEGER *) pDiagInfoPtr) = error_rec_count (err); 1396 } 1397 1398 } 1399 break; 1400 1401 default: 1402 return SQL_ERROR; 1403 } 1404 break; 1405 1406 default: /* status records */ 1407 { 1408 int nRecs = 0; 1409 1410 if (nRecNumber < 1) 1411 { 1412 return SQL_ERROR; 1413 } 1414 nRecs = error_rec_count (err); 1415 if (nRecNumber <= nRecs) 1416 { /* DM Errors */ 1417 char *szval = ""; 1418 int ival = 0; 1419 int isInt = 0; 1420 sqlerr_t *rec = NULL; 1421 1422 rec = get_nth_error (err, nRecNumber - 1); 1423 1424 if (!rec) 1425 { 1426 return (SQL_NO_DATA_FOUND); 1427 } 1428 1429 switch (nDiagIdentifier) 1430 { 1431 1432 case SQL_DIAG_SUBCLASS_ORIGIN: 1433 case SQL_DIAG_CLASS_ORIGIN: 1434 isInt = 0; 1435 1436 szval = (rec->code >= en_HY001 1437 && rec->code <= en_IM014) ? (char *) "ODBC 3.0" : (char *) "ISO 9075"; 1438 break; 1439 1440 case SQL_DIAG_COLUMN_NUMBER: 1441 1442 if (nHandleType != SQL_HANDLE_STMT || !stmt) 1443 { 1444 return SQL_ERROR; 1445 } 1446 if (!con) 1447 { 1448 return SQL_INVALID_HANDLE; 1449 } 1450 1451 if (pDiagInfoPtr) 1452 *((SQLINTEGER *) pDiagInfoPtr) = SQL_COLUMN_NUMBER_UNKNOWN; 1453 1454 return SQL_SUCCESS; 1455 1456 case SQL_DIAG_CONNECTION_NAME: 1457 case SQL_DIAG_SERVER_NAME: 1458 1459 isInt = 0; 1460 if (con) 1461 { 1462 if (waMode != 'W') 1463 retcode = SQLGetInfo (con, SQL_DATA_SOURCE_NAME, 1464 pDiagInfoPtr, nBufferLength, pnStringLengthPtr); 1465 else 1466 retcode = SQLGetInfoW (con, SQL_DATA_SOURCE_NAME, 1467 pDiagInfoPtr, nBufferLength, pnStringLengthPtr); 1468 1469 return retcode; 1470 } 1471 else 1472 break; 1473 1474 case SQL_DIAG_MESSAGE_TEXT: 1475 1476 isInt = 0; 1477 szval = 1478 _iodbcdm_getsqlerrmsg (rec, (void *) sqlerrmsg_tab); 1479 break; 1480 1481 case SQL_DIAG_NATIVE: 1482 1483 isInt = 1; 1484 ival = 0; 1485 break; 1486 1487 case SQL_DIAG_ROW_NUMBER: 1488 1489 isInt = 1; 1490 if (nHandleType != SQL_HANDLE_STMT || !stmt) 1491 { 1492 return SQL_ERROR; 1493 } 1494 if (!con) 1495 { 1496 return SQL_INVALID_HANDLE; 1497 } 1498 CALL_UDRIVER(con, Handle, retcode, hproc, unicode_driver, en_GetDiagField, 1499 (nHandleType, dhandle, nRecNumber, nDiagIdentifier, 1500 pDiagInfoPtr, nBufferLength, pnStringLengthPtr )); 1501 if (hproc != SQL_NULL_HPROC) 1502 { 1503 return retcode; 1504 } 1505 else 1506 { 1507 ival = SQL_ROW_NUMBER_UNKNOWN; 1508 break; 1509 } 1510 1511 case SQL_DIAG_SQLSTATE: 1512 1513 isInt = 0; 1514 szval = _iodbcdm_getsqlstate (rec, (void *) sqlerrmsg_tab); 1515 break; 1516 1517 default: 1518 return SQL_ERROR; 1519 } 1520 if (isInt) 1521 { 1522 if (pDiagInfoPtr) 1523 *((SQLINTEGER *) pDiagInfoPtr) = ival; 1524 } 1525 else 1526 { 1527 if (waMode != 'W') 1528 { 1529 int len = strlen (szval), len1; 1530 len1 = len > nBufferLength ? nBufferLength : len; 1531 if (pnStringLengthPtr) 1532 *pnStringLengthPtr = len; 1533 if (pDiagInfoPtr) 1534 { 1535 STRNCPY (pDiagInfoPtr, szval, len1); 1536 *(((SQLCHAR *) pDiagInfoPtr) + len1) = 0; 1537 } 1538 } 1539 else 1540 { 1541 dm_StrCopyOut2_A2W((SQLCHAR *) szval, 1542 (SQLWCHAR *) pDiagInfoPtr, nBufferLength, pnStringLengthPtr); 1543 } 1544 1545 } 1546 break; 1547 } 1548 else 1549 { /* Driver's errors */ 1550 nRecNumber -= nRecs; 1551 1552 if (!con) 1553 { 1554 return SQL_NO_DATA_FOUND; 1555 } 1556 1557 if ((unicode_driver && waMode != 'W') 1558 || (!unicode_driver && waMode == 'W')) 1559 { 1560 switch(nDiagIdentifier) 1561 { 1562 case SQL_DIAG_DYNAMIC_FUNCTION: 1563 case SQL_DIAG_CLASS_ORIGIN: 1564 case SQL_DIAG_CONNECTION_NAME: 1565 case SQL_DIAG_MESSAGE_TEXT: 1566 case SQL_DIAG_SERVER_NAME: 1567 case SQL_DIAG_SQLSTATE: 1568 case SQL_DIAG_SUBCLASS_ORIGIN: 1569 if (waMode != 'W') 1570 { 1571 /* ansi=>unicode*/ 1572 if ((_DiagInfoPtr = malloc((nBufferLength + 1) * 1573 sizeof(wchar_t))) == NULL) 1574 { 1575 return SQL_ERROR; 1576 } 1577 } 1578 else 1579 { 1580 /* unicode=>ansi*/ 1581 if ((_DiagInfoPtr = malloc(nBufferLength + 1)) == NULL) 1582 { 1583 return SQL_ERROR; 1584 } 1585 } 1586 diagInfoPtr = _DiagInfoPtr; 1587 break; 1588 } 1589 } 1590 1591 CALL_UDRIVER(con, Handle, retcode, hproc, unicode_driver, en_GetDiagField, 1592 (nHandleType, dhandle, nRecNumber, nDiagIdentifier, 1593 diagInfoPtr, nBufferLength, pnStringLengthPtr )); 1594 if (hproc != SQL_NULL_HPROC) 1595 { 1596 if (pDiagInfoPtr 1597 && SQL_SUCCEEDED (retcode) 1598 && ((unicode_driver && waMode != 'W') 1599 || (!unicode_driver && waMode == 'W'))) 1600 { 1601 switch(nDiagIdentifier) 1602 { 1603 case SQL_DIAG_DYNAMIC_FUNCTION: 1604 case SQL_DIAG_CLASS_ORIGIN: 1605 case SQL_DIAG_CONNECTION_NAME: 1606 case SQL_DIAG_MESSAGE_TEXT: 1607 case SQL_DIAG_SERVER_NAME: 1608 case SQL_DIAG_SQLSTATE: 1609 case SQL_DIAG_SUBCLASS_ORIGIN: 1610 if (waMode != 'W') 1611 { 1612 /* ansi<=unicode*/ 1613 dm_StrCopyOut2_W2A ((SQLWCHAR *) diagInfoPtr, 1614 (SQLCHAR *) pDiagInfoPtr, 1615 nBufferLength, pnStringLengthPtr); 1616 } 1617 else 1618 { 1619 /* unicode<=ansi*/ 1620 dm_StrCopyOut2_A2W ((SQLCHAR *)diagInfoPtr, 1621 (SQLWCHAR *) pDiagInfoPtr, 1622 nBufferLength, pnStringLengthPtr); 1623 } 1624 } 1625 } 1626 1627 MEM_FREE(_DiagInfoPtr); 1628 return retcode; 1629 } 1630 else 1631 { /* an ODBC2->ODBC3 translation */ 1632 char *szval = ""; 1633 wchar_t szState[6]; 1634 SQLINTEGER nNative; 1635 1636 if (nRecNumber > 1) 1637 { 1638 MEM_FREE(_DiagInfoPtr); 1639 return SQL_NO_DATA_FOUND; 1640 } 1641 1642 if (nHandleType == SQL_HANDLE_DESC) 1643 { 1644 MEM_FREE(_DiagInfoPtr); 1645 return SQL_INVALID_HANDLE; 1646 } 1647 1648 if (nDiagIdentifier != SQL_DIAG_MESSAGE_TEXT) 1649 MEM_FREE(_DiagInfoPtr); 1650 1651 switch (nDiagIdentifier) 1652 { 1653 case SQL_DIAG_SUBCLASS_ORIGIN: 1654 case SQL_DIAG_CLASS_ORIGIN: 1655 1656 CALL_UDRIVER (con, Handle, retcode, hproc, unicode_driver, 1657 en_Error, (SQL_NULL_HENV, 1658 nHandleType == SQL_HANDLE_DBC ? dhandle : SQL_NULL_HDBC, 1659 nHandleType == SQL_HANDLE_STMT ? dhandle : SQL_NULL_HSTMT, 1660 szState, &nNative, NULL, 0, NULL)); 1661 if (hproc == SQL_NULL_HPROC) 1662 { 1663 return SQL_INVALID_HANDLE; 1664 } 1665 if (retcode != SQL_SUCCESS) 1666 { 1667 return SQL_NO_DATA_FOUND; 1668 } 1669 if (waMode != 'W') 1670 { 1671 szval = !STRNEQ (szState, "IM", 2) ? (char *) "ODBC 3.0" : (char *) "ISO 9075"; 1672 } 1673 else 1674 { 1675 if (szState[0] != L'I' && szState[1] != L'M') 1676 szval = (char *) "ODBC 3.0"; 1677 else 1678 szval = (char *) "ISO 9075"; 1679 } 1680 break; 1681 1682 case SQL_DIAG_ROW_NUMBER: 1683 case SQL_DIAG_COLUMN_NUMBER: 1684 if (nHandleType != SQL_HANDLE_STMT || !stmt) 1685 { 1686 return SQL_ERROR; 1687 } 1688 if (!con) 1689 { 1690 return SQL_INVALID_HANDLE; 1691 } 1692 if (pDiagInfoPtr) 1693 *((SQLINTEGER *) pDiagInfoPtr) = 1694 SQL_COLUMN_NUMBER_UNKNOWN; 1695 { 1696 return SQL_SUCCESS; 1697 } 1698 1699 case SQL_DIAG_SERVER_NAME: 1700 case SQL_DIAG_CONNECTION_NAME: 1701 break; 1702 1703 case SQL_DIAG_MESSAGE_TEXT: 1704 CALL_UDRIVER (con, Handle, retcode, hproc, unicode_driver, 1705 en_Error, (SQL_NULL_HENV, 1706 nHandleType == SQL_HANDLE_DBC ? dhandle : SQL_NULL_HDBC, 1707 nHandleType == SQL_HANDLE_STMT ? dhandle : SQL_NULL_HSTMT, 1708 szState, &nNative, diagInfoPtr, nBufferLength, 1709 pnStringLengthPtr)); 1710 if (hproc == SQL_NULL_HPROC) 1711 { 1712 MEM_FREE(_DiagInfoPtr); 1713 return SQL_INVALID_HANDLE; 1714 } 1715 if (pDiagInfoPtr 1716 && SQL_SUCCEEDED (retcode) 1717 && ((unicode_driver && waMode != 'W') 1718 || (!unicode_driver && waMode == 'W'))) 1719 { 1720 if (waMode != 'W') 1721 { 1722 /* ansi<=unicode*/ 1723 dm_StrCopyOut2_W2A ((SQLWCHAR *) diagInfoPtr, 1724 (SQLCHAR *) pDiagInfoPtr, 1725 nBufferLength, pnStringLengthPtr); 1726 } 1727 else 1728 { 1729 /* unicode<=ansi*/ 1730 dm_StrCopyOut2_A2W ((SQLCHAR *)diagInfoPtr, 1731 (SQLWCHAR *) pDiagInfoPtr, 1732 nBufferLength, pnStringLengthPtr); 1733 } 1734 } 1735 1736 MEM_FREE(_DiagInfoPtr); 1737 return retcode; 1738 1739 case SQL_DIAG_NATIVE: 1740 CALL_UDRIVER (con, Handle, retcode, hproc, unicode_driver, 1741 en_Error, (SQL_NULL_HENV, 1742 nHandleType == SQL_HANDLE_DBC ? dhandle : SQL_NULL_HDBC, 1743 nHandleType == SQL_HANDLE_STMT ? dhandle : SQL_NULL_HSTMT, 1744 szState, &nNative, NULL, 0, NULL)); 1745 if (hproc == SQL_NULL_HPROC) 1746 { 1747 return SQL_INVALID_HANDLE; 1748 } 1749 if (pDiagInfoPtr) 1750 *((SQLINTEGER *) pDiagInfoPtr) = nNative; 1751 return retcode; 1752 1753 case SQL_DIAG_SQLSTATE: 1754 CALL_UDRIVER (con, Handle, retcode, hproc, unicode_driver, 1755 en_Error, (SQL_NULL_HENV, 1756 nHandleType == SQL_HANDLE_DBC ? dhandle : SQL_NULL_HDBC, 1757 nHandleType == SQL_HANDLE_STMT ? dhandle : SQL_NULL_HSTMT, 1758 szState, &nNative, NULL, 0, NULL)); 1759 if (hproc == SQL_NULL_HPROC) 1760 { 1761 return SQL_INVALID_HANDLE; 1762 } 1763 if (pDiagInfoPtr 1764 && SQL_SUCCEEDED (retcode) 1765 && ((unicode_driver && waMode != 'W') 1766 || (!unicode_driver && waMode == 'W'))) 1767 { 1768 if (waMode != 'W') 1769 { 1770 /* ansi<=unicode*/ 1771 dm_StrCopyOut2_W2A ((SQLWCHAR *) szState, 1772 (SQLCHAR *) pDiagInfoPtr, 1773 nBufferLength, pnStringLengthPtr); 1774 } 1775 else 1776 { 1777 /* unicode<=ansi*/ 1778 dm_StrCopyOut2_A2W ((SQLCHAR *)szState, 1779 (SQLWCHAR *) pDiagInfoPtr, 1780 nBufferLength, pnStringLengthPtr); 1781 } 1782 } 1783 1784 return retcode; 1785 1786 default: 1787 return SQL_ERROR; 1788 } 1789 1790 if (waMode != 'W') 1791 { 1792 if (pDiagInfoPtr) 1793 { 1794 int len = strlen (szval); 1795 if (len > nBufferLength) 1796 len = nBufferLength; 1797 if (len) 1798 _iodbcdm_strlcpy ((char *) pDiagInfoPtr, szval, len); 1799 } 1800 if (pnStringLengthPtr) 1801 *pnStringLengthPtr = strlen (szval); 1802 } 1803 else 1804 { 1805 dm_StrCopyOut2_A2W((SQLCHAR *) szval, 1806 (SQLWCHAR *) pDiagInfoPtr, 1807 nBufferLength, pnStringLengthPtr); 1808 } 1809 } /* ODBC3->ODBC2 */ 1810 } /* driver's errors */ 1811 } /* status records */ 1812 } /* switch (nRecNumber */ 1813 return (SQL_SUCCESS); 1814} 1815 1816 1817RETCODE SQL_API 1818SQLGetDiagField ( 1819 SQLSMALLINT HandleType, 1820 SQLHANDLE Handle, 1821 SQLSMALLINT RecNumber, 1822 SQLSMALLINT DiagIdentifier, 1823 SQLPOINTER DiagInfoPtr, 1824 SQLSMALLINT BufferLength, 1825 SQLSMALLINT * StringLengthPtr) 1826{ 1827 SQLRETURN retcode = SQL_SUCCESS; 1828 1829 ODBC_LOCK (); 1830 1831 TRACE (trace_SQLGetDiagField (TRACE_ENTER, 1832 HandleType, 1833 Handle, 1834 RecNumber, 1835 DiagIdentifier, 1836 DiagInfoPtr, BufferLength, StringLengthPtr)); 1837 1838 retcode = SQLGetDiagField_Internal ( 1839 HandleType, 1840 Handle, 1841 RecNumber, 1842 DiagIdentifier, 1843 DiagInfoPtr, BufferLength, StringLengthPtr, 1844 'A'); 1845 1846 TRACE (trace_SQLGetDiagField (TRACE_LEAVE, 1847 HandleType, 1848 Handle, 1849 RecNumber, 1850 DiagIdentifier, 1851 DiagInfoPtr, BufferLength, StringLengthPtr)); 1852 1853 ODBC_UNLOCK (); 1854 1855 return retcode; 1856} 1857 1858 1859RETCODE SQL_API 1860SQLGetDiagFieldA ( 1861 SQLSMALLINT HandleType, 1862 SQLHANDLE Handle, 1863 SQLSMALLINT RecNumber, 1864 SQLSMALLINT DiagIdentifier, 1865 SQLPOINTER DiagInfoPtr, 1866 SQLSMALLINT BufferLength, 1867 SQLSMALLINT * StringLengthPtr) 1868{ 1869 SQLRETURN retcode = SQL_SUCCESS; 1870 1871 ODBC_LOCK (); 1872 1873 TRACE (trace_SQLGetDiagField (TRACE_ENTER, 1874 HandleType, 1875 Handle, 1876 RecNumber, 1877 DiagIdentifier, 1878 DiagInfoPtr, BufferLength, StringLengthPtr)); 1879 1880 retcode = SQLGetDiagField_Internal ( 1881 HandleType, 1882 Handle, 1883 RecNumber, 1884 DiagIdentifier, 1885 DiagInfoPtr, BufferLength, StringLengthPtr, 1886 'A'); 1887 1888 TRACE (trace_SQLGetDiagField (TRACE_LEAVE, 1889 HandleType, 1890 Handle, 1891 RecNumber, 1892 DiagIdentifier, 1893 DiagInfoPtr, BufferLength, StringLengthPtr)); 1894 1895 ODBC_UNLOCK (); 1896 1897 return retcode; 1898} 1899 1900 1901RETCODE SQL_API 1902SQLGetDiagFieldW ( 1903 SQLSMALLINT HandleType, 1904 SQLHANDLE Handle, 1905 SQLSMALLINT RecNumber, 1906 SQLSMALLINT DiagIdentifier, 1907 SQLPOINTER DiagInfoPtr, 1908 SQLSMALLINT BufferLength, 1909 SQLSMALLINT * StringLengthPtr) 1910{ 1911 SQLRETURN retcode = SQL_SUCCESS; 1912 1913 ODBC_LOCK (); 1914 1915 TRACE (trace_SQLGetDiagFieldW (TRACE_ENTER, 1916 HandleType, 1917 Handle, 1918 RecNumber, 1919 DiagIdentifier, 1920 DiagInfoPtr, BufferLength, StringLengthPtr)); 1921 1922 retcode = SQLGetDiagField_Internal ( 1923 HandleType, 1924 Handle, 1925 RecNumber, 1926 DiagIdentifier, 1927 DiagInfoPtr, BufferLength, StringLengthPtr, 1928 'W'); 1929 1930 TRACE (trace_SQLGetDiagFieldW (TRACE_LEAVE, 1931 HandleType, 1932 Handle, 1933 RecNumber, 1934 DiagIdentifier, 1935 DiagInfoPtr, BufferLength, StringLengthPtr)); 1936 1937 ODBC_UNLOCK (); 1938 1939 return retcode; 1940} 1941#endif 1942