1/* 2 * result.c 3 * 4 * $Id: result.c,v 1.29 2007/10/08 12:37:15 source Exp $ 5 * 6 * Prepare for getting query result 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#include <iodbc.h> 79 80#include <sql.h> 81#include <sqlext.h> 82#include <sqlucode.h> 83 84#include <unicode.h> 85 86#include <dlproc.h> 87 88#include <herr.h> 89#include <henv.h> 90#include <hdbc.h> 91#include <hstmt.h> 92 93#include <itrace.h> 94 95static SQLRETURN 96SQLBindCol_Internal ( 97 SQLHSTMT hstmt, 98 SQLUSMALLINT icol, 99 SQLSMALLINT fCType, 100 SQLPOINTER rgbValue, 101 SQLLEN cbValueMax, 102 SQLLEN *pcbValue) 103{ 104 STMT(pstmt, hstmt); 105 CONN (pdbc, pstmt->hdbc); 106 ENVR (penv, pdbc->henv); 107 HPROC hproc = SQL_NULL_HPROC; 108 SQLSMALLINT nCType; 109 SQLRETURN retcode; 110 111 /* check argument */ 112 switch (fCType) 113 { 114 case SQL_C_DEFAULT: 115 case SQL_C_BIT: 116 case SQL_C_BINARY: 117 case SQL_C_CHAR: 118 case SQL_C_DATE: 119 case SQL_C_DOUBLE: 120 case SQL_C_FLOAT: 121 case SQL_C_LONG: 122 case SQL_C_SHORT: 123 case SQL_C_SLONG: 124 case SQL_C_SSHORT: 125 case SQL_C_STINYINT: 126 case SQL_C_TIME: 127 case SQL_C_TIMESTAMP: 128 case SQL_C_TINYINT: 129 case SQL_C_ULONG: 130 case SQL_C_USHORT: 131 case SQL_C_UTINYINT: 132#if (ODBCVER >= 0x0300) 133 case SQL_C_GUID: 134 case SQL_C_INTERVAL_DAY: 135 case SQL_C_INTERVAL_DAY_TO_HOUR: 136 case SQL_C_INTERVAL_DAY_TO_MINUTE: 137 case SQL_C_INTERVAL_DAY_TO_SECOND: 138 case SQL_C_INTERVAL_HOUR: 139 case SQL_C_INTERVAL_HOUR_TO_MINUTE: 140 case SQL_C_INTERVAL_HOUR_TO_SECOND: 141 case SQL_C_INTERVAL_MINUTE: 142 case SQL_C_INTERVAL_MINUTE_TO_SECOND: 143 case SQL_C_INTERVAL_MONTH: 144 case SQL_C_INTERVAL_SECOND: 145 case SQL_C_INTERVAL_YEAR: 146 case SQL_C_INTERVAL_YEAR_TO_MONTH: 147 case SQL_C_NUMERIC: 148 case SQL_C_SBIGINT: 149 case SQL_C_TYPE_DATE: 150 case SQL_C_TYPE_TIME: 151 case SQL_C_TYPE_TIMESTAMP: 152 case SQL_C_UBIGINT: 153 case SQL_C_WCHAR: 154#endif 155 break; 156 157 default: 158 PUSHSQLERR (pstmt->herr, en_S1003); 159 return SQL_ERROR; 160 } 161 162 if (cbValueMax < 0) 163 { 164 PUSHSQLERR (pstmt->herr, en_S1090); 165 166 return SQL_ERROR; 167 } 168 169 /* check state */ 170 if (pstmt->state > en_stmt_needdata || pstmt->asyn_on != en_NullProc) 171 { 172 PUSHSQLERR (pstmt->herr, en_S1010); 173 return SQL_ERROR; 174 } 175 176 /* 177 * Convert C type to ODBC version of driver 178 */ 179 nCType = _iodbcdm_map_c_type (fCType, penv->dodbc_ver); 180 181 /* call driver's function */ 182 hproc = _iodbcdm_getproc (pstmt->hdbc, en_BindCol); 183 184 if (hproc == SQL_NULL_HPROC) 185 { 186 PUSHSQLERR (pstmt->herr, en_IM001); 187 188 return SQL_ERROR; 189 } 190 191 if (icol != 0 && !penv->unicode_driver && nCType == SQL_C_WCHAR) 192 { 193 CALL_DRIVER (pstmt->hdbc, pstmt, retcode, hproc, 194 (pstmt->dhstmt, icol, SQL_C_CHAR, rgbValue, 195 cbValueMax, pcbValue)); 196 } 197 else 198 CALL_DRIVER (pstmt->hdbc, pstmt, retcode, hproc, 199 (pstmt->dhstmt, icol, nCType, rgbValue, cbValueMax, pcbValue)); 200 201 if (icol != 0 && !penv->unicode_driver && nCType == SQL_C_WCHAR 202 && SQL_SUCCEEDED (retcode)) 203 { 204 BIND_t tbind; 205 206 tbind.bn_col = icol; 207 tbind.bn_type = nCType; 208 tbind.bn_data = rgbValue; 209 tbind.bn_size = cbValueMax; 210 tbind.bn_pInd = pcbValue; 211 212 if (rgbValue) 213 _iodbcdm_BindColumn (pstmt, &tbind); 214 else 215 _iodbcdm_UnBindColumn (pstmt, &tbind); 216 } 217 218 return retcode; 219} 220 221 222SQLRETURN SQL_API 223SQLBindCol ( 224 SQLHSTMT hstmt, 225 SQLUSMALLINT icol, 226 SQLSMALLINT fCType, 227 SQLPOINTER rgbValue, 228 SQLLEN cbValueMax, 229 SQLLEN *pcbValue) 230{ 231 ENTER_STMT (hstmt, 232 trace_SQLBindCol (TRACE_ENTER, 233 hstmt, icol, fCType, rgbValue, cbValueMax, pcbValue)); 234 235 retcode = SQLBindCol_Internal ( 236 hstmt, icol, fCType, rgbValue, cbValueMax, pcbValue); 237 238 LEAVE_STMT (hstmt, 239 trace_SQLBindCol (TRACE_LEAVE, 240 hstmt, icol, fCType, rgbValue, cbValueMax, pcbValue)); 241} 242 243 244SQLRETURN SQL_API 245SQLGetCursorName_Internal ( 246 SQLHSTMT hstmt, 247 SQLCHAR * szCursor, 248 SQLSMALLINT cbCursorMax, 249 SQLSMALLINT * pcbCursor, 250 char waMode) 251{ 252 STMT(pstmt, hstmt); 253 CONN (pdbc, pstmt->hdbc); 254 ENVR (penv, pdbc->henv); 255 HPROC hproc = SQL_NULL_HPROC; 256 SQLRETURN retcode = SQL_SUCCESS; 257 void * cursorOut = szCursor; 258 void * _Cursor = NULL; 259 260 /* check argument */ 261 if (cbCursorMax < (SWORD) 0) 262 { 263 PUSHSQLERR (pstmt->herr, en_S1090); 264 265 return SQL_ERROR; 266 } 267 268 /* check state */ 269 if (pstmt->state >= en_stmt_needdata || pstmt->asyn_on != en_NullProc) 270 { 271 PUSHSQLERR (pstmt->herr, en_S1010); 272 273 return SQL_ERROR; 274 } 275 276 if (pstmt->state < en_stmt_cursoropen 277 && pstmt->cursor_state == en_stmt_cursor_no) 278 { 279 PUSHSQLERR (pstmt->herr, en_S1015); 280 281 return SQL_ERROR; 282 } 283 284 /* call driver's function */ 285 286 287 if ((penv->unicode_driver && waMode != 'W') 288 || (!penv->unicode_driver && waMode == 'W')) 289 { 290 if (waMode != 'W') 291 { 292 /* ansi=>unicode*/ 293 if ((_Cursor = malloc((cbCursorMax + 1) * sizeof(wchar_t))) == NULL) 294 { 295 PUSHSQLERR (pstmt->herr, en_HY001); 296 return SQL_ERROR; 297 } 298 } 299 else 300 { 301 /* unicode=>ansi*/ 302 if ((_Cursor = malloc(cbCursorMax + 1)) == NULL) 303 { 304 PUSHSQLERR (pstmt->herr, en_HY001); 305 return SQL_ERROR; 306 } 307 } 308 cursorOut = _Cursor; 309 } 310 311 /* call driver */ 312 CALL_UDRIVER(pstmt->hdbc, pstmt, retcode, hproc, penv->unicode_driver, 313 en_GetCursorName, ( 314 pstmt->dhstmt, 315 cursorOut, 316 cbCursorMax, 317 pcbCursor)); 318 319 if (hproc == SQL_NULL_HPROC) 320 { 321 MEM_FREE(_Cursor); 322 PUSHSQLERR (pstmt->herr, en_IM001); 323 return SQL_ERROR; 324 } 325 326 if (szCursor 327 && SQL_SUCCEEDED (retcode) 328 && ((penv->unicode_driver && waMode != 'W') 329 || (!penv->unicode_driver && waMode == 'W'))) 330 { 331 if (waMode != 'W') 332 { 333 /* ansi<=unicode*/ 334 dm_StrCopyOut2_W2A ((SQLWCHAR *) cursorOut, (SQLCHAR *) szCursor, cbCursorMax, NULL); 335 } 336 else 337 { 338 /* unicode<=ansi*/ 339 dm_StrCopyOut2_A2W ((SQLCHAR *) cursorOut, (SQLWCHAR *) szCursor, cbCursorMax, NULL); 340 } 341 } 342 343 MEM_FREE(_Cursor); 344 345 return retcode; 346} 347 348 349SQLRETURN SQL_API 350SQLGetCursorName ( 351 SQLHSTMT hstmt, 352 SQLCHAR * szCursor, 353 SQLSMALLINT cbCursorMax, 354 SQLSMALLINT * pcbCursor) 355{ 356 ENTER_STMT (hstmt, 357 trace_SQLGetCursorName (TRACE_ENTER, 358 hstmt, 359 szCursor, cbCursorMax, pcbCursor)); 360 361 retcode = SQLGetCursorName_Internal( 362 hstmt, 363 szCursor, cbCursorMax, pcbCursor, 364 'A'); 365 366 LEAVE_STMT (hstmt, 367 trace_SQLGetCursorName (TRACE_LEAVE, 368 hstmt, 369 szCursor, cbCursorMax, pcbCursor)); 370} 371 372 373#if ODBCVER >= 0x0300 374SQLRETURN SQL_API 375SQLGetCursorNameA ( 376 SQLHSTMT hstmt, 377 SQLCHAR * szCursor, 378 SQLSMALLINT cbCursorMax, 379 SQLSMALLINT * pcbCursor) 380{ 381 ENTER_STMT (hstmt, 382 trace_SQLGetCursorName (TRACE_ENTER, 383 hstmt, 384 szCursor, cbCursorMax, pcbCursor)); 385 386 retcode = SQLGetCursorName_Internal( 387 hstmt, 388 szCursor, cbCursorMax, pcbCursor, 389 'A'); 390 391 LEAVE_STMT (hstmt, 392 trace_SQLGetCursorName (TRACE_LEAVE, 393 hstmt, 394 szCursor, cbCursorMax, pcbCursor)); 395} 396 397 398SQLRETURN SQL_API 399SQLGetCursorNameW (SQLHSTMT hstmt, 400 SQLWCHAR * szCursor, 401 SQLSMALLINT cbCursorMax, 402 SQLSMALLINT * pcbCursor) 403{ 404 ENTER_STMT (hstmt, 405 trace_SQLGetCursorNameW (TRACE_ENTER, 406 hstmt, 407 szCursor, cbCursorMax, pcbCursor)); 408 409 retcode = SQLGetCursorName_Internal( 410 hstmt, 411 (SQLCHAR *) szCursor, cbCursorMax, pcbCursor, 412 'W'); 413 414 LEAVE_STMT (hstmt, 415 trace_SQLGetCursorNameW (TRACE_LEAVE, 416 hstmt, 417 szCursor, cbCursorMax, pcbCursor)); 418} 419#endif 420 421 422static SQLRETURN 423SQLRowCount_Internal ( 424 SQLHSTMT hstmt, 425 SQLLEN * pcrow) 426{ 427 STMT(pstmt, hstmt); 428 HPROC hproc; 429 SQLRETURN retcode; 430 431 /* check state */ 432 if (pstmt->state >= en_stmt_needdata 433 || pstmt->state <= en_stmt_prepared 434 || pstmt->asyn_on != en_NullProc) 435 { 436 PUSHSQLERR (pstmt->herr, en_S1010); 437 438 return SQL_ERROR; 439 } 440 441 /* call driver */ 442 hproc = _iodbcdm_getproc (pstmt->hdbc, en_RowCount); 443 444 if (hproc == SQL_NULL_HPROC) 445 { 446 PUSHSQLERR (pstmt->herr, en_IM001); 447 448 return SQL_ERROR; 449 } 450 451 CALL_DRIVER (pstmt->hdbc, pstmt, retcode, hproc, 452 (pstmt->dhstmt, pcrow)); 453 454 return retcode; 455} 456 457 458SQLRETURN SQL_API 459SQLRowCount ( 460 SQLHSTMT hstmt, 461 SQLLEN * pcrow) 462{ 463 ENTER_STMT (hstmt, 464 trace_SQLRowCount (TRACE_ENTER, hstmt, pcrow)); 465 466 retcode = SQLRowCount_Internal (hstmt, pcrow); 467 468 LEAVE_STMT (hstmt, 469 trace_SQLRowCount (TRACE_LEAVE, hstmt, pcrow)); 470} 471 472 473SQLRETURN SQL_API 474_iodbcdm_NumResultCols ( 475 SQLHSTMT hstmt, 476 SQLSMALLINT * pccol) 477{ 478 STMT (pstmt, hstmt); 479 HPROC hproc; 480 SQLRETURN retcode; 481 SWORD ccol; 482 483 /* check state */ 484 if (pstmt->asyn_on == en_NullProc) 485 { 486 if (pstmt->state == en_stmt_allocated 487 || pstmt->state >= en_stmt_needdata) 488 { 489 PUSHSQLERR (pstmt->herr, en_S1010); 490 491 return SQL_ERROR; 492 } 493 } 494 else if (pstmt->asyn_on != en_NumResultCols) 495 { 496 PUSHSQLERR (pstmt->herr, en_S1010); 497 498 return SQL_ERROR; 499 } 500 501 /* call driver */ 502 hproc = _iodbcdm_getproc (pstmt->hdbc, en_NumResultCols); 503 504 if (hproc == SQL_NULL_HPROC) 505 { 506 PUSHSQLERR (pstmt->herr, en_IM001); 507 508 return SQL_ERROR; 509 } 510 511 CALL_DRIVER (pstmt->hdbc, pstmt, retcode, hproc, 512 (pstmt->dhstmt, &ccol)); 513 514 /* state transition */ 515 if (pstmt->asyn_on == en_NumResultCols) 516 { 517 switch (retcode) 518 { 519 case SQL_SUCCESS: 520 case SQL_SUCCESS_WITH_INFO: 521 case SQL_ERROR: 522 pstmt->asyn_on = en_NullProc; 523 524 case SQL_STILL_EXECUTING: 525 default: 526 break; 527 } 528 } 529 530 switch (retcode) 531 { 532 case SQL_SUCCESS: 533 case SQL_SUCCESS_WITH_INFO: 534 break; 535 536 case SQL_STILL_EXECUTING: 537 ccol = 0; 538 pstmt->asyn_on = en_NumResultCols; 539 break; 540 541 default: 542 ccol = 0; 543 break; 544 } 545 546 if (pccol) 547 { 548 *pccol = ccol; 549 } 550 return retcode; 551} 552 553 554SQLRETURN SQL_API 555SQLNumResultCols ( 556 SQLHSTMT hstmt, 557 SQLSMALLINT * pccol) 558{ 559 ENTER_STMT (hstmt, 560 trace_SQLNumResultCols (TRACE_ENTER, hstmt, pccol)); 561 562 retcode = _iodbcdm_NumResultCols (hstmt, pccol); 563 564 LEAVE_STMT (hstmt, 565 trace_SQLNumResultCols (TRACE_LEAVE, hstmt, pccol)); 566} 567 568 569SQLSMALLINT 570_iodbcdm_map_sql_type (int type, int odbcver) 571{ 572 switch (type) 573 { 574 case SQL_DATE: 575 case SQL_TYPE_DATE: 576 return (odbcver == SQL_OV_ODBC3) ? SQL_TYPE_DATE : SQL_DATE; 577 578 case SQL_TIME: 579 case SQL_TYPE_TIME: 580 return (odbcver == SQL_OV_ODBC3) ? SQL_TYPE_TIME : SQL_TIME; 581 582 case SQL_TIMESTAMP: 583 case SQL_TYPE_TIMESTAMP: 584 return (odbcver == SQL_OV_ODBC3) ? SQL_TYPE_TIMESTAMP : SQL_TIMESTAMP; 585 } 586 587 return type; 588} 589 590 591SQLSMALLINT 592_iodbcdm_map_c_type (int type, int odbcver) 593{ 594 switch (type) 595 { 596 case SQL_C_DATE: 597 case SQL_C_TYPE_DATE: 598 return (odbcver == SQL_OV_ODBC3) ? SQL_C_TYPE_DATE : SQL_C_DATE; 599 600 case SQL_C_TIME: 601 case SQL_C_TYPE_TIME: 602 return (odbcver == SQL_OV_ODBC3) ? SQL_C_TYPE_TIME : SQL_C_TIME; 603 604 case SQL_C_TIMESTAMP: 605 case SQL_C_TYPE_TIMESTAMP: 606 return (odbcver == SQL_OV_ODBC3) ? SQL_C_TYPE_TIMESTAMP : SQL_C_TIMESTAMP; 607 } 608 609 return type; 610} 611 612 613SQLRETURN SQL_API 614SQLDescribeCol_Internal ( 615 SQLHSTMT hstmt, 616 SQLUSMALLINT icol, 617 SQLPOINTER szColName, 618 SQLSMALLINT cbColNameMax, 619 SQLSMALLINT * pcbColName, 620 SQLSMALLINT * pfSqlType, 621 SQLULEN * pcbColDef, 622 SQLSMALLINT * pibScale, 623 SQLSMALLINT * pfNullable, 624 SQLCHAR waMode) 625{ 626 STMT(pstmt, hstmt); 627 CONN (pdbc, pstmt->hdbc); 628 ENVR (penv, pdbc->henv); 629 GENV (genv, pdbc->genv); 630 HPROC hproc = SQL_NULL_HPROC; 631 SQLRETURN retcode = SQL_SUCCESS; 632 void * _ColName = NULL; 633 void * colNameOut = szColName; 634 sqlstcode_t sqlstat = en_00000; 635 636 /* check arguments */ 637 if (icol == 0) 638 { 639 sqlstat = en_S1002; 640 } 641 else if (cbColNameMax < 0) 642 { 643 sqlstat = en_S1090; 644 } 645 646 if (sqlstat != en_00000) 647 { 648 PUSHSQLERR (pstmt->herr, sqlstat); 649 650 return SQL_ERROR; 651 } 652#if (ODBCVER < 0x0300) 653 /* check state */ 654 if (pstmt->asyn_on == en_NullProc) 655 { 656 if (pstmt->state == en_stmt_allocated 657 || pstmt->state >= en_stmt_needdata) 658 { 659 sqlstat = en_S1010; 660 } 661 } 662 else if (pstmt->asyn_on != en_DescribeCol) 663 { 664 sqlstat = en_S1010; 665 } 666#endif 667 668 if (sqlstat != en_00000) 669 { 670 PUSHSQLERR (pstmt->herr, sqlstat); 671 672 return SQL_ERROR; 673 } 674 675 /* call driver */ 676 if (szColName != NULL && cbColNameMax > 0 && 677 ((penv->unicode_driver && waMode != 'W') || 678 (!penv->unicode_driver && waMode == 'W')) 679 ) 680 { 681 if (waMode != 'W') 682 { 683 /* ansi=>unicode*/ 684 if ((_ColName = _iodbcdm_alloc_param(pstmt, 0, 685 cbColNameMax * sizeof(wchar_t))) == NULL) 686 { 687 PUSHSQLERR (pstmt->herr, en_HY001); 688 return SQL_ERROR; 689 } 690 } 691 else 692 { 693 /* unicode=>ansi*/ 694 if ((_ColName = _iodbcdm_alloc_param(pstmt, 0, cbColNameMax)) == NULL) 695 { 696 PUSHSQLERR (pstmt->herr, en_HY001); 697 return SQL_ERROR; 698 } 699 } 700 colNameOut = _ColName; 701 } 702 703 /* call driver */ 704 CALL_UDRIVER(pstmt->hdbc, pstmt, retcode, hproc, penv->unicode_driver, 705 en_DescribeCol, ( 706 pstmt->dhstmt, 707 icol, 708 colNameOut, 709 cbColNameMax, 710 pcbColName, 711 pfSqlType, 712 pcbColDef, 713 pibScale, 714 pfNullable)); 715 716 if (hproc == SQL_NULL_HPROC) 717 { 718 _iodbcdm_FreeStmtParams(pstmt); 719 PUSHSQLERR (pstmt->herr, en_IM001); 720 return SQL_ERROR; 721 } 722 723 /* 724 * Convert sql type to ODBC version of application 725 */ 726 if (SQL_SUCCEEDED(retcode) && pfSqlType) 727 *pfSqlType = _iodbcdm_map_sql_type (*pfSqlType, genv->odbc_ver); 728 729 if (szColName 730 && SQL_SUCCEEDED (retcode) 731 && ((penv->unicode_driver && waMode != 'W') 732 || (!penv->unicode_driver && waMode == 'W'))) 733 { 734 if (waMode != 'W') 735 { 736 /* ansi<=unicode*/ 737 dm_StrCopyOut2_W2A ((SQLWCHAR *) colNameOut, (SQLCHAR *) szColName, cbColNameMax, NULL); 738 } 739 else 740 { 741 /* unicode<=ansi*/ 742 dm_StrCopyOut2_A2W ((SQLCHAR *) colNameOut, (SQLWCHAR *) szColName, cbColNameMax, NULL); 743 } 744 } 745 746 if (retcode != SQL_STILL_EXECUTING) 747 _iodbcdm_FreeStmtParams(pstmt); 748 749 /* state transition */ 750 if (pstmt->asyn_on == en_DescribeCol) 751 { 752 switch (retcode) 753 { 754 case SQL_SUCCESS: 755 case SQL_SUCCESS_WITH_INFO: 756 case SQL_ERROR: 757 pstmt->asyn_on = en_NullProc; 758 break; 759 760 default: 761 return retcode; 762 } 763 } 764 765 switch (pstmt->state) 766 { 767 case en_stmt_prepared: 768 case en_stmt_cursoropen: 769 case en_stmt_fetched: 770 case en_stmt_xfetched: 771 if (retcode == SQL_STILL_EXECUTING) 772 { 773 pstmt->asyn_on = en_DescribeCol; 774 } 775 break; 776 777 default: 778 break; 779 } 780 781 return retcode; 782} 783 784 785SQLRETURN SQL_API 786SQLDescribeCol (SQLHSTMT hstmt, 787 SQLUSMALLINT icol, 788 SQLCHAR * szColName, 789 SQLSMALLINT cbColNameMax, 790 SQLSMALLINT * pcbColName, 791 SQLSMALLINT * pfSqlType, 792 SQLULEN * pcbColDef, 793 SQLSMALLINT * pibScale, 794 SQLSMALLINT * pfNullable) 795{ 796 ENTER_STMT (hstmt, 797 trace_SQLDescribeCol (TRACE_ENTER, 798 hstmt, 799 icol, 800 szColName, cbColNameMax, pcbColName, 801 pfSqlType, 802 pcbColDef, 803 pibScale, 804 pfNullable)); 805 806 retcode = SQLDescribeCol_Internal ( 807 hstmt, 808 icol, 809 szColName, cbColNameMax, pcbColName, 810 pfSqlType, 811 pcbColDef, 812 pibScale, 813 pfNullable, 814 'A'); 815 816 LEAVE_STMT (hstmt, 817 trace_SQLDescribeCol (TRACE_LEAVE, 818 hstmt, 819 icol, 820 szColName, cbColNameMax, pcbColName, 821 pfSqlType, 822 pcbColDef, 823 pibScale, 824 pfNullable)); 825} 826 827 828#if ODBCVER >= 0x0300 829SQLRETURN SQL_API 830SQLDescribeColA (SQLHSTMT hstmt, 831 SQLUSMALLINT icol, 832 SQLCHAR * szColName, 833 SQLSMALLINT cbColNameMax, 834 SQLSMALLINT * pcbColName, 835 SQLSMALLINT * pfSqlType, 836 SQLULEN * pcbColDef, 837 SQLSMALLINT * pibScale, 838 SQLSMALLINT * pfNullable) 839{ 840 ENTER_STMT (hstmt, 841 trace_SQLDescribeCol (TRACE_ENTER, 842 hstmt, 843 icol, 844 szColName, cbColNameMax, pcbColName, 845 pfSqlType, 846 pcbColDef, 847 pibScale, 848 pfNullable)); 849 850 retcode = SQLDescribeCol_Internal ( 851 hstmt, 852 icol, 853 szColName, cbColNameMax, pcbColName, 854 pfSqlType, 855 pcbColDef, 856 pibScale, 857 pfNullable, 858 'A'); 859 860 LEAVE_STMT (hstmt, 861 trace_SQLDescribeCol (TRACE_LEAVE, 862 hstmt, 863 icol, 864 szColName, cbColNameMax, pcbColName, 865 pfSqlType, 866 pcbColDef, 867 pibScale, 868 pfNullable)); 869} 870 871 872SQLRETURN SQL_API 873SQLDescribeColW ( 874 SQLHSTMT hstmt, 875 SQLUSMALLINT icol, 876 SQLWCHAR * szColName, 877 SQLSMALLINT cbColNameMax, 878 SQLSMALLINT * pcbColName, 879 SQLSMALLINT * pfSqlType, 880 SQLULEN * pcbColDef, 881 SQLSMALLINT * pibScale, 882 SQLSMALLINT * pfNullable) 883{ 884 ENTER_STMT (hstmt, 885 trace_SQLDescribeColW (TRACE_ENTER, 886 hstmt, 887 icol, 888 szColName, cbColNameMax, pcbColName, 889 pfSqlType, 890 pcbColDef, 891 pibScale, 892 pfNullable)); 893 894 retcode = SQLDescribeCol_Internal ( 895 hstmt, 896 icol, 897 szColName, cbColNameMax, pcbColName, 898 pfSqlType, 899 pcbColDef, 900 pibScale, 901 pfNullable, 902 'W'); 903 904 LEAVE_STMT (hstmt, 905 trace_SQLDescribeColW (TRACE_LEAVE, 906 hstmt, 907 icol, 908 szColName, cbColNameMax, pcbColName, 909 pfSqlType, 910 pcbColDef, 911 pibScale, 912 pfNullable)); 913} 914#endif 915 916 917SQLRETURN SQL_API 918SQLColAttributes_Internal ( 919 SQLHSTMT hstmt, 920 SQLUSMALLINT icol, 921 SQLUSMALLINT fDescType, 922 SQLPOINTER rgbDesc, 923 SQLSMALLINT cbDescMax, 924 SQLSMALLINT * pcbDesc, 925 SQLLEN * pfDesc, 926 SQLCHAR waMode) 927{ 928 STMT(pstmt, hstmt); 929 CONN (pdbc, pstmt->hdbc); 930 ENVR (penv, pdbc->henv); 931 HPROC hproc2 = SQL_NULL_HPROC; 932 HPROC hproc3 = SQL_NULL_HPROC; 933 SQLRETURN retcode = SQL_SUCCESS; 934 void * _Desc = NULL; 935 void * descOut = rgbDesc; 936 sqlstcode_t sqlstat = en_00000; 937 SQLUSMALLINT new_attr = fDescType; 938 SQLUINTEGER odbc_ver = ((GENV_t *) pdbc->genv)->odbc_ver; 939 SQLUINTEGER dodbc_ver = ((ENV_t *) pdbc->henv)->dodbc_ver; 940 941 /* check arguments */ 942 if (icol == 0 && fDescType != SQL_COLUMN_COUNT) 943 { 944 sqlstat = en_S1002; 945 } 946 else if (cbDescMax < 0) 947 { 948 sqlstat = en_S1090; 949 } 950#if (ODBCVER < 0x0300) 951 else if ( /* fDescType < SQL_COLATT_OPT_MIN || *//* turnoff warning */ 952 (fDescType > SQL_COLATT_OPT_MAX 953 && fDescType < SQL_COLUMN_DRIVER_START)) 954 { 955 sqlstat = en_S1091; 956 } 957#endif /* ODBCVER < 0x0300 */ 958 959 if (sqlstat != en_00000) 960 { 961 PUSHSQLERR (pstmt->herr, sqlstat); 962 963 return SQL_ERROR; 964 } 965 966 /* check state */ 967 if (pstmt->asyn_on == en_NullProc) 968 { 969 if (pstmt->state == en_stmt_allocated 970 || pstmt->state >= en_stmt_needdata) 971 { 972 sqlstat = en_S1010; 973 } 974 } 975 else if (pstmt->asyn_on != en_ColAttributes) 976 { 977 sqlstat = en_S1010; 978 } 979 980 if (sqlstat != en_00000) 981 { 982 PUSHSQLERR (pstmt->herr, sqlstat); 983 984 return SQL_ERROR; 985 } 986 987 /* call driver */ 988 if (rgbDesc != NULL && cbDescMax > 0 && 989 ((penv->unicode_driver && waMode != 'W') || 990 (!penv->unicode_driver && waMode == 'W'))) 991 { 992 switch(fDescType) 993 { 994 case SQL_COLUMN_QUALIFIER_NAME: 995 case SQL_COLUMN_NAME: 996 case SQL_COLUMN_LABEL: 997 case SQL_COLUMN_OWNER_NAME: 998 case SQL_COLUMN_TABLE_NAME: 999 case SQL_COLUMN_TYPE_NAME: 1000 1001 if (waMode != 'W') 1002 { 1003 /* ansi=>unicode*/ 1004 cbDescMax *= sizeof(wchar_t); 1005 if ((_Desc = _iodbcdm_alloc_param(pstmt, 0, cbDescMax)) == NULL) 1006 { 1007 PUSHSQLERR (pstmt->herr, en_HY001); 1008 return SQL_ERROR; 1009 } 1010 } 1011 else 1012 { 1013 /* unicode=>ansi*/ 1014 cbDescMax /= sizeof(wchar_t); 1015 if ((_Desc = _iodbcdm_alloc_param(pstmt, 0, cbDescMax)) == NULL) 1016 { 1017 PUSHSQLERR (pstmt->herr, en_HY001); 1018 return SQL_ERROR; 1019 } 1020 } 1021 descOut = _Desc; 1022 break; 1023 } 1024 } 1025 1026#if (ODBCVER >= 0x0300) 1027 switch (new_attr) 1028 { 1029 case SQL_COLUMN_NAME: new_attr = SQL_DESC_NAME; break; 1030 case SQL_COLUMN_NULLABLE: new_attr = SQL_DESC_NULLABLE; break; 1031 case SQL_COLUMN_COUNT: new_attr = SQL_DESC_COUNT; break; 1032 } 1033#endif 1034 1035 if (penv->unicode_driver) 1036 { 1037 hproc2 = _iodbcdm_getproc (pdbc, en_ColAttributesW); 1038#if (ODBCVER >= 0x0300) 1039 hproc3 = _iodbcdm_getproc (pdbc, en_ColAttributeW); 1040#endif 1041 1042 if (odbc_ver == SQL_OV_ODBC2 && 1043 ( dodbc_ver == SQL_OV_ODBC2 1044 || (dodbc_ver == SQL_OV_ODBC3 && hproc2 != SQL_NULL_HPROC))) 1045 hproc3 = SQL_NULL_HPROC; 1046 1047#if (ODBCVER >= 0x0300) 1048 if (hproc3 != SQL_NULL_HPROC) 1049 { 1050 CALL_DRIVER (pstmt->hdbc, pstmt, retcode, hproc3, ( 1051 pstmt->dhstmt, 1052 icol, 1053 new_attr, 1054 descOut, 1055 cbDescMax, 1056 pcbDesc, 1057 pfDesc)); 1058 } 1059 else 1060#endif 1061 { 1062 if (hproc2 == SQL_NULL_HPROC) 1063 { 1064 _iodbcdm_FreeStmtParams(pstmt); 1065 PUSHSQLERR (pstmt->herr, en_IM001); 1066 return SQL_ERROR; 1067 } 1068 1069 CALL_DRIVER (pstmt->hdbc, pstmt, retcode, hproc2, ( 1070 pstmt->dhstmt, 1071 icol, 1072 fDescType, 1073 descOut, 1074 cbDescMax, 1075 pcbDesc, 1076 pfDesc)); 1077 } 1078 } 1079 else 1080 { 1081 /* SQL_XXX */ 1082 /* SQL_XXX_A */ 1083 hproc2 = _iodbcdm_getproc (pdbc, en_ColAttributes); 1084 if (hproc2 == SQL_NULL_HPROC) 1085 hproc2 = _iodbcdm_getproc (pdbc, en_ColAttributesA); 1086#if (ODBCVER >= 0x0300) 1087 hproc3 = _iodbcdm_getproc (pdbc, en_ColAttribute); 1088 if (hproc3 == SQL_NULL_HPROC) 1089 hproc3 = _iodbcdm_getproc (pdbc, en_ColAttributeA); 1090#endif 1091 1092 if (odbc_ver == SQL_OV_ODBC2 && 1093 ( dodbc_ver == SQL_OV_ODBC2 1094 || (dodbc_ver == SQL_OV_ODBC3 && hproc2 != SQL_NULL_HPROC))) 1095 hproc3 = SQL_NULL_HPROC; 1096 1097#if (ODBCVER >= 0x0300) 1098 if (hproc3 != SQL_NULL_HPROC) 1099 { 1100 CALL_DRIVER (pstmt->hdbc, pstmt, retcode, hproc3, ( 1101 pstmt->dhstmt, 1102 icol, 1103 new_attr, 1104 descOut, 1105 cbDescMax, 1106 pcbDesc, 1107 pfDesc)); 1108 } 1109 else 1110#endif 1111 { 1112 if (hproc2 == SQL_NULL_HPROC) 1113 { 1114 _iodbcdm_FreeStmtParams(pstmt); 1115 PUSHSQLERR (pstmt->herr, en_IM001); 1116 return SQL_ERROR; 1117 } 1118 1119 CALL_DRIVER (pstmt->hdbc, pstmt, retcode, hproc2, ( 1120 pstmt->dhstmt, 1121 icol, 1122 fDescType, 1123 descOut, 1124 cbDescMax, 1125 pcbDesc, 1126 pfDesc)); 1127 } 1128 } 1129 1130 if (rgbDesc 1131 && SQL_SUCCEEDED (retcode) 1132 && ((penv->unicode_driver && waMode != 'W') 1133 || (!penv->unicode_driver && waMode == 'W'))) 1134 { 1135 switch(fDescType) 1136 { 1137 case SQL_COLUMN_QUALIFIER_NAME: 1138 case SQL_COLUMN_NAME: 1139 case SQL_COLUMN_LABEL: 1140 case SQL_COLUMN_OWNER_NAME: 1141 case SQL_COLUMN_TABLE_NAME: 1142 case SQL_COLUMN_TYPE_NAME: 1143 if (waMode != 'W') 1144 { 1145 /* ansi<=unicode*/ 1146 dm_StrCopyOut2_W2A ((SQLWCHAR *) descOut, (SQLCHAR *) rgbDesc, cbDescMax / sizeof(wchar_t), pcbDesc); 1147 } 1148 else 1149 { 1150 /* unicode<=ansi*/ 1151 dm_StrCopyOut2_A2W ((SQLCHAR *) descOut, (SQLWCHAR *) rgbDesc, cbDescMax, pcbDesc); 1152 if (pcbDesc) 1153 *pcbDesc = *pcbDesc * sizeof(wchar_t); 1154 } 1155 } 1156 } 1157 1158 if (retcode != SQL_STILL_EXECUTING) 1159 _iodbcdm_FreeStmtParams(pstmt); 1160 1161 /* state transition */ 1162 if (pstmt->asyn_on == en_ColAttributes) 1163 { 1164 switch (retcode) 1165 { 1166 case SQL_SUCCESS: 1167 case SQL_SUCCESS_WITH_INFO: 1168 case SQL_ERROR: 1169 pstmt->asyn_on = en_NullProc; 1170 break; 1171 1172 default: 1173 return retcode; 1174 } 1175 } 1176 1177 switch (pstmt->state) 1178 { 1179 case en_stmt_prepared: 1180 case en_stmt_cursoropen: 1181 case en_stmt_fetched: 1182 case en_stmt_xfetched: 1183 if (retcode == SQL_STILL_EXECUTING) 1184 { 1185 pstmt->asyn_on = en_ColAttributes; 1186 } 1187 break; 1188 1189 default: 1190 break; 1191 } 1192 1193 return retcode; 1194} 1195 1196 1197RETCODE SQL_API 1198SQLColAttributes ( 1199 SQLHSTMT statementHandle, 1200 SQLUSMALLINT icol, 1201 SQLUSMALLINT fDescType, 1202 SQLPOINTER rgbDesc, 1203 SQLSMALLINT cbDescMax, 1204 SQLSMALLINT * pcbDesc, 1205 SQLLEN * pfDesc) 1206{ 1207 ENTER_STMT (statementHandle, 1208 trace_SQLColAttributes (TRACE_ENTER, 1209 statementHandle, 1210 icol, 1211 fDescType, 1212 rgbDesc, cbDescMax, pcbDesc, 1213 pfDesc)); 1214 1215 retcode = SQLColAttributes_Internal ( 1216 statementHandle, 1217 icol, 1218 fDescType, 1219 rgbDesc, cbDescMax, pcbDesc, 1220 pfDesc, 1221 'A'); 1222 1223 LEAVE_STMT (statementHandle, 1224 trace_SQLColAttributes (TRACE_LEAVE, 1225 statementHandle, 1226 icol, 1227 fDescType, 1228 rgbDesc, cbDescMax, pcbDesc, 1229 pfDesc)); 1230} 1231 1232 1233#if ODBCVER >= 0x0300 1234RETCODE SQL_API 1235SQLColAttributesA ( 1236 SQLHSTMT statementHandle, 1237 SQLUSMALLINT icol, 1238 SQLUSMALLINT fDescType, 1239 SQLPOINTER rgbDesc, 1240 SQLSMALLINT cbDescMax, 1241 SQLSMALLINT * pcbDesc, 1242 SQLLEN * pfDesc) 1243{ 1244 ENTER_STMT (statementHandle, 1245 trace_SQLColAttributes (TRACE_ENTER, 1246 statementHandle, 1247 icol, 1248 fDescType, 1249 rgbDesc, cbDescMax, pcbDesc, 1250 pfDesc)); 1251 1252 retcode = SQLColAttributes_Internal ( 1253 statementHandle, 1254 icol, 1255 fDescType, 1256 rgbDesc, cbDescMax, pcbDesc, 1257 pfDesc, 1258 'A'); 1259 1260 LEAVE_STMT (statementHandle, 1261 trace_SQLColAttributes (TRACE_LEAVE, 1262 statementHandle, 1263 icol, 1264 fDescType, 1265 rgbDesc, cbDescMax, pcbDesc, 1266 pfDesc)); 1267} 1268 1269 1270RETCODE SQL_API 1271SQLColAttributesW ( 1272 SQLHSTMT statementHandle, 1273 SQLUSMALLINT icol, 1274 SQLUSMALLINT fDescType, 1275 SQLPOINTER rgbDesc, 1276 SQLSMALLINT cbDescMax, 1277 SQLSMALLINT * pcbDesc, 1278 SQLLEN * pfDesc) 1279{ 1280 ENTER_STMT (statementHandle, 1281 trace_SQLColAttributesW (TRACE_ENTER, 1282 statementHandle, 1283 icol, 1284 fDescType, 1285 rgbDesc, cbDescMax, pcbDesc, 1286 pfDesc)); 1287 1288 retcode = SQLColAttributes_Internal ( 1289 statementHandle, 1290 icol, 1291 fDescType, 1292 rgbDesc, cbDescMax, pcbDesc, 1293 pfDesc, 1294 'W'); 1295 1296 LEAVE_STMT (statementHandle, 1297 trace_SQLColAttributesW (TRACE_LEAVE, 1298 statementHandle, 1299 icol, 1300 fDescType, 1301 rgbDesc, cbDescMax, pcbDesc, 1302 pfDesc)); 1303} 1304#endif 1305