1/* 2 * fetch.c 3 * 4 * $Id: fetch.c,v 1.24 2006/12/11 14:21:48 source Exp $ 5 * 6 * Fetch 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 79#include <iodbc.h> 80 81#include <sql.h> 82#include <sqlext.h> 83#include <sqlucode.h> 84 85#include <dlproc.h> 86 87#include <herr.h> 88#include <henv.h> 89#include <hdbc.h> 90#include <hstmt.h> 91 92#include <itrace.h> 93#include <unicode.h> 94 95SQLRETURN 96SQLFetch_Internal (SQLHSTMT hstmt) 97{ 98 STMT (pstmt, hstmt); 99 HPROC hproc = SQL_NULL_HPROC; 100 SQLRETURN retcode = SQL_SUCCESS; 101 102 /* check state */ 103 if (pstmt->asyn_on == en_NullProc) 104 { 105 switch (pstmt->state) 106 { 107 case en_stmt_allocated: 108 case en_stmt_prepared: 109 case en_stmt_xfetched: 110 case en_stmt_needdata: 111 case en_stmt_mustput: 112 case en_stmt_canput: 113 PUSHSQLERR (pstmt->herr, en_S1010); 114 return SQL_ERROR; 115 116 case en_stmt_executed_with_info: 117 _iodbcdm_do_cursoropen (pstmt); 118 break; 119 120 default: 121 break; 122 } 123 } 124 else if (pstmt->asyn_on != en_Fetch) 125 { 126 PUSHSQLERR (pstmt->herr, en_S1010); 127 return SQL_ERROR; 128 } 129 130#if (ODBCVER >= 0x0300) 131 if (((ENV_t *) ((DBC_t *) pstmt->hdbc)->henv)->dodbc_ver == SQL_OV_ODBC2 132 && ((GENV_t *) ((DBC_t *) pstmt->hdbc)->genv)->odbc_ver == SQL_OV_ODBC3) 133 { 134 /* 135 * Try to map SQLFetch to SQLExtendedFetch for ODBC3 app calling 136 * ODBC2 driver 137 * 138 * The rows_status_ptr must not be null because the SQLExtendedFetch 139 * requires it 140 */ 141 hproc = _iodbcdm_getproc (pstmt->hdbc, en_ExtendedFetch); 142 143 if (hproc) 144 { 145 CALL_DRIVER (pstmt->hdbc, pstmt, retcode, hproc, 146 (pstmt->dhstmt, SQL_FETCH_NEXT, 0, pstmt->rows_fetched_ptr, 147 pstmt->row_status_ptr)); 148 } 149 } 150#endif 151 if (hproc == SQL_NULL_HPROC) 152 { 153 hproc = _iodbcdm_getproc (pstmt->hdbc, en_Fetch); 154 155 if (hproc == SQL_NULL_HPROC) 156 { 157 PUSHSQLERR (pstmt->herr, en_IM001); 158 return SQL_ERROR; 159 } 160 161 CALL_DRIVER (pstmt->hdbc, pstmt, retcode, hproc, 162 (pstmt->dhstmt)); 163 } 164 165 /* state transition */ 166 if (pstmt->asyn_on == en_Fetch) 167 { 168 switch (retcode) 169 { 170 case SQL_SUCCESS: 171 case SQL_SUCCESS_WITH_INFO: 172 case SQL_NO_DATA_FOUND: 173 case SQL_ERROR: 174 pstmt->asyn_on = en_NullProc; 175 break; 176 177 case SQL_STILL_EXECUTING: 178 default: 179 return retcode; 180 } 181 } 182 183 switch (pstmt->state) 184 { 185 case en_stmt_cursoropen: 186 case en_stmt_fetched: 187 switch (retcode) 188 { 189 case SQL_SUCCESS: 190 case SQL_SUCCESS_WITH_INFO: 191 pstmt->state = en_stmt_fetched; 192 pstmt->cursor_state = en_stmt_cursor_fetched; 193 break; 194 195 case SQL_NO_DATA_FOUND: 196 if (pstmt->prep_state) 197 { 198 pstmt->state = en_stmt_fetched; 199 } 200 else 201 { 202 pstmt->state = en_stmt_allocated; 203 } 204 pstmt->cursor_state = en_stmt_cursor_no; 205 break; 206 207 case SQL_STILL_EXECUTING: 208 pstmt->asyn_on = en_Fetch; 209 break; 210 211 default: 212 break; 213 } 214 break; 215 216 default: 217 break; 218 } 219 220 return retcode; 221} 222 223 224SQLRETURN SQL_API 225SQLFetch (SQLHSTMT hstmt) 226{ 227 ENTER_STMT (hstmt, 228 trace_SQLFetch (TRACE_ENTER, hstmt)); 229 230 retcode = SQLFetch_Internal (hstmt); 231 232 if (SQL_SUCCEEDED (retcode)) 233 _iodbcdm_ConvBindData (pstmt); 234 235 LEAVE_STMT (hstmt, 236 trace_SQLFetch (TRACE_LEAVE, hstmt)); 237} 238 239 240SQLRETURN SQL_API 241_iodbcdm_ExtendedFetch ( 242 SQLHSTMT hstmt, 243 SQLUSMALLINT fFetchType, 244 SQLLEN irow, 245 SQLULEN * pcrow, 246 SQLUSMALLINT * rgfRowStatus) 247{ 248 STMT (pstmt, hstmt); 249 HPROC hproc = SQL_NULL_HPROC; 250 SQLRETURN retcode; 251 252 /* check fetch type */ 253 if (fFetchType < SQL_FETCH_NEXT || fFetchType > SQL_FETCH_BOOKMARK) 254 { 255 /* Unlike MS driver manager(i.e. DM), 256 * we don't check driver's ODBC version 257 * against SQL_FETCH_RESUME (only 1.0) 258 * and SQL_FETCH_BOOKMARK (only 2.0). 259 */ 260 PUSHSQLERR (pstmt->herr, en_S1106); 261 262 return SQL_ERROR; 263 } 264 265 /* check state */ 266 if (pstmt->asyn_on == en_NullProc) 267 { 268 switch (pstmt->state) 269 { 270 case en_stmt_allocated: 271 case en_stmt_prepared: 272 case en_stmt_fetched: 273 case en_stmt_needdata: 274 case en_stmt_mustput: 275 case en_stmt_canput: 276 PUSHSQLERR (pstmt->herr, en_S1010); 277 return SQL_ERROR; 278 279 default: 280 break; 281 } 282 } 283 else if (pstmt->asyn_on != en_ExtendedFetch) 284 { 285 PUSHSQLERR (pstmt->herr, en_S1010); 286 return SQL_ERROR; 287 } 288 289 if (fFetchType == SQL_FETCH_NEXT || 290 fFetchType == SQL_FETCH_PRIOR || 291 fFetchType == SQL_FETCH_FIRST || fFetchType == SQL_FETCH_LAST) 292 { 293 irow = 0; 294 } 295 296 hproc = _iodbcdm_getproc (pstmt->hdbc, en_ExtendedFetch); 297 298 if (hproc == SQL_NULL_HPROC) 299 { 300 PUSHSQLERR (pstmt->herr, en_IM001); 301 302 return SQL_ERROR; 303 } 304 305 CALL_DRIVER (pstmt->hdbc, pstmt, retcode, hproc, 306 (pstmt->dhstmt, fFetchType, irow, pcrow, rgfRowStatus)); 307 308 /* state transition */ 309 if (pstmt->asyn_on == en_ExtendedFetch) 310 { 311 switch (retcode) 312 { 313 case SQL_SUCCESS: 314 case SQL_SUCCESS_WITH_INFO: 315 case SQL_NO_DATA_FOUND: 316 case SQL_ERROR: 317 pstmt->asyn_on = en_NullProc; 318 break; 319 320 case SQL_STILL_EXECUTING: 321 default: 322 return retcode; 323 } 324 } 325 326 switch (pstmt->state) 327 { 328 case en_stmt_cursoropen: 329 case en_stmt_xfetched: 330 switch (retcode) 331 { 332 case SQL_SUCCESS: 333 case SQL_SUCCESS_WITH_INFO: 334 case SQL_NO_DATA_FOUND: 335 pstmt->state = en_stmt_xfetched; 336 pstmt->cursor_state = en_stmt_cursor_xfetched; 337 break; 338 339 case SQL_STILL_EXECUTING: 340 pstmt->asyn_on = en_ExtendedFetch; 341 break; 342 343 default: 344 break; 345 } 346 break; 347 348 default: 349 break; 350 } 351 352 return retcode; 353} 354 355 356SQLRETURN SQL_API 357SQLExtendedFetch ( 358 SQLHSTMT hstmt, 359 SQLUSMALLINT fFetchType, 360 SQLLEN irow, 361 SQLULEN * pcrow, 362 SQLUSMALLINT * rgfRowStatus) 363{ 364 ENTER_STMT (hstmt, 365 trace_SQLExtendedFetch (TRACE_ENTER, 366 hstmt, fFetchType, irow, pcrow, rgfRowStatus)); 367 368 retcode = 369 _iodbcdm_ExtendedFetch (hstmt, fFetchType, irow, pcrow, rgfRowStatus); 370 371 if (SQL_SUCCEEDED (retcode)) 372 _iodbcdm_ConvBindData (pstmt); 373 374 LEAVE_STMT (hstmt, 375 trace_SQLExtendedFetch (TRACE_LEAVE, 376 hstmt, fFetchType, irow, pcrow, rgfRowStatus)); 377} 378 379 380static SQLRETURN 381SQLGetData_Internal ( 382 SQLHSTMT hstmt, 383 SQLUSMALLINT icol, 384 SQLSMALLINT fCType, 385 SQLPOINTER rgbValue, 386 SQLLEN cbValueMax, 387 SQLLEN * pcbValue) 388{ 389 STMT (pstmt, hstmt); 390 CONN (pdbc, pstmt->hdbc); 391 ENVR (penv, pdbc->henv); 392 HPROC hproc; 393 SQLRETURN retcode = SQL_SUCCESS; 394 sqlstcode_t sqlstat = en_00000; 395 SQLSMALLINT nCType; 396 397 /* check argument */ 398 if (rgbValue == NULL) 399 { 400 sqlstat = en_S1009; 401 } 402 else if (cbValueMax < 0) 403 { 404 sqlstat = en_S1090; 405 } 406 else 407 { 408 switch (fCType) 409 { 410 case SQL_C_DEFAULT: 411 case SQL_C_BINARY: 412 case SQL_C_BIT: 413 case SQL_C_CHAR: 414 case SQL_C_DATE: 415 case SQL_C_DOUBLE: 416 case SQL_C_FLOAT: 417 case SQL_C_LONG: 418 case SQL_C_SHORT: 419 case SQL_C_SLONG: 420 case SQL_C_SSHORT: 421 case SQL_C_STINYINT: 422 case SQL_C_TIME: 423 case SQL_C_TIMESTAMP: 424 case SQL_C_TINYINT: 425 case SQL_C_ULONG: 426 case SQL_C_USHORT: 427 case SQL_C_UTINYINT: 428#if (ODBCVER >= 0x0300) 429 case SQL_C_GUID: 430 case SQL_C_INTERVAL_DAY: 431 case SQL_C_INTERVAL_DAY_TO_HOUR: 432 case SQL_C_INTERVAL_DAY_TO_MINUTE: 433 case SQL_C_INTERVAL_DAY_TO_SECOND: 434 case SQL_C_INTERVAL_HOUR: 435 case SQL_C_INTERVAL_HOUR_TO_MINUTE: 436 case SQL_C_INTERVAL_HOUR_TO_SECOND: 437 case SQL_C_INTERVAL_MINUTE: 438 case SQL_C_INTERVAL_MINUTE_TO_SECOND: 439 case SQL_C_INTERVAL_MONTH: 440 case SQL_C_INTERVAL_SECOND: 441 case SQL_C_INTERVAL_YEAR: 442 case SQL_C_INTERVAL_YEAR_TO_MONTH: 443 case SQL_C_NUMERIC: 444 case SQL_C_SBIGINT: 445 case SQL_C_TYPE_DATE: 446 case SQL_C_TYPE_TIME: 447 case SQL_C_TYPE_TIMESTAMP: 448 case SQL_C_UBIGINT: 449 case SQL_C_WCHAR: 450#endif 451 break; 452 453 default: 454 sqlstat = en_S1003; 455 break; 456 } 457 } 458 459 if (sqlstat != en_00000) 460 { 461 PUSHSQLERR (pstmt->herr, sqlstat); 462 463 return SQL_ERROR; 464 } 465 466 /* check state */ 467 if (pstmt->asyn_on == en_NullProc) 468 { 469 switch (pstmt->state) 470 { 471 case en_stmt_allocated: 472 case en_stmt_prepared: 473 case en_stmt_needdata: 474 case en_stmt_mustput: 475 case en_stmt_canput: 476 sqlstat = en_S1010; 477 break; 478 479 case en_stmt_executed_with_info: 480 case en_stmt_executed: 481 case en_stmt_cursoropen: 482 sqlstat = en_24000; 483 break; 484 485 default: 486 break; 487 } 488 } 489 else if (pstmt->asyn_on != en_GetData) 490 { 491 sqlstat = en_S1010; 492 } 493 494 if (sqlstat != en_00000) 495 { 496 PUSHSQLERR (pstmt->herr, sqlstat); 497 498 return SQL_ERROR; 499 } 500 501 502 /* 503 * Convert C type to ODBC version of driver 504 */ 505 nCType = _iodbcdm_map_c_type (fCType, penv->dodbc_ver); 506 507 if (!penv->unicode_driver && nCType == SQL_C_WCHAR) 508 { 509 nCType = SQL_C_CHAR; 510 cbValueMax /= sizeof(wchar_t); 511 } 512 513 514 /* call driver */ 515 hproc = _iodbcdm_getproc (pstmt->hdbc, en_GetData); 516 517 if (hproc == SQL_NULL_HPROC) 518 { 519 PUSHSQLERR (pstmt->herr, en_IM001); 520 return SQL_ERROR; 521 } 522 523 CALL_DRIVER (pstmt->hdbc, pstmt, retcode, hproc, 524 (pstmt->dhstmt, icol, nCType, rgbValue, cbValueMax, pcbValue)); 525 526 /* state transition */ 527 if (pstmt->asyn_on == en_GetData) 528 { 529 switch (retcode) 530 { 531 case SQL_SUCCESS: 532 case SQL_SUCCESS_WITH_INFO: 533 case SQL_NO_DATA_FOUND: 534 case SQL_ERROR: 535 pstmt->asyn_on = en_NullProc; 536 break; 537 538 case SQL_STILL_EXECUTING: 539 default: 540 return retcode; 541 } 542 } 543 544 switch (pstmt->state) 545 { 546 case en_stmt_fetched: 547 case en_stmt_xfetched: 548 if (retcode == SQL_STILL_EXECUTING) 549 { 550 pstmt->asyn_on = en_GetData; 551 break; 552 } 553 break; 554 555 default: 556 break; 557 } 558 559 if (!penv->unicode_driver && fCType == SQL_C_WCHAR) 560 { 561 wchar_t *buf = dm_SQL_A2W((SQLCHAR *) rgbValue, SQL_NTS); 562 563 if (buf != NULL) 564 WCSCPY(rgbValue, buf); 565 566 MEM_FREE(buf); 567 if (pcbValue) 568 *pcbValue *= sizeof(wchar_t); 569 } 570 571 return retcode; 572} 573 574 575SQLRETURN SQL_API 576SQLGetData ( 577 SQLHSTMT hstmt, 578 SQLUSMALLINT icol, 579 SQLSMALLINT fCType, 580 SQLPOINTER rgbValue, 581 SQLLEN cbValueMax, 582 SQLLEN * pcbValue) 583{ 584 ENTER_STMT (hstmt, 585 trace_SQLGetData (TRACE_ENTER, 586 hstmt, 587 icol, 588 fCType, 589 rgbValue, cbValueMax, pcbValue)); 590 591 retcode = SQLGetData_Internal ( 592 hstmt, 593 icol, 594 fCType, 595 rgbValue, cbValueMax, pcbValue); 596 597 LEAVE_STMT (hstmt, 598 trace_SQLGetData (TRACE_LEAVE, 599 hstmt, 600 icol, 601 fCType, 602 rgbValue, cbValueMax, pcbValue)); 603} 604 605 606static SQLRETURN 607SQLMoreResults_Internal (SQLHSTMT hstmt) 608{ 609 STMT (pstmt, hstmt); 610 HPROC hproc; 611 SQLRETURN retcode; 612 613 /* check state */ 614 if (pstmt->asyn_on == en_NullProc) 615 { 616 switch (pstmt->state) 617 { 618#if 0 619 case en_stmt_allocated: 620 case en_stmt_prepared: 621 return SQL_NO_DATA_FOUND; 622#endif 623 624 case en_stmt_needdata: 625 case en_stmt_mustput: 626 case en_stmt_canput: 627 PUSHSQLERR (pstmt->herr, en_S1010); 628 return SQL_ERROR; 629 630 default: 631 break; 632 } 633 } 634 else if (pstmt->asyn_on != en_MoreResults) 635 { 636 PUSHSQLERR (pstmt->herr, en_S1010); 637 638 return SQL_ERROR; 639 } 640 641 /* call driver */ 642 hproc = _iodbcdm_getproc (pstmt->hdbc, en_MoreResults); 643 644 if (hproc == SQL_NULL_HPROC) 645 { 646 PUSHSQLERR (pstmt->herr, en_IM001); 647 648 return SQL_ERROR; 649 } 650 651 CALL_DRIVER (pstmt->hdbc, pstmt, retcode, hproc, 652 (pstmt->dhstmt)); 653 654 /* state transition */ 655 if (pstmt->asyn_on == en_MoreResults) 656 { 657 switch (retcode) 658 { 659 case SQL_SUCCESS: 660 case SQL_SUCCESS_WITH_INFO: 661 case SQL_NO_DATA_FOUND: 662 case SQL_ERROR: 663 pstmt->asyn_on = en_NullProc; 664 break; 665 666 case SQL_STILL_EXECUTING: 667 default: 668 return retcode; 669 } 670 } 671 672 switch (pstmt->state) 673 { 674 case en_stmt_allocated: 675 case en_stmt_prepared: 676 /* driver should return SQL_NO_DATA_FOUND */ 677 if (pstmt->prep_state) 678 { 679 pstmt->state = en_stmt_cursoropen; 680 } 681 else 682 { 683 pstmt->state = en_stmt_prepared; 684 } 685 break; 686 687 case en_stmt_executed_with_info: 688 _iodbcdm_do_cursoropen (pstmt); 689 /* FALL THROUGH */ 690 691 case en_stmt_executed: 692 if (retcode == SQL_NO_DATA_FOUND) 693 { 694 if (pstmt->prep_state) 695 { 696 pstmt->state = en_stmt_prepared; 697 } 698 else 699 { 700 pstmt->state = en_stmt_cursoropen; 701 } 702 } 703 else if (retcode == SQL_STILL_EXECUTING) 704 { 705 pstmt->asyn_on = en_MoreResults; 706 } 707 break; 708 709 case en_stmt_cursoropen: 710 case en_stmt_fetched: 711 case en_stmt_xfetched: 712 if (retcode == SQL_SUCCESS) 713 { 714 break; 715 } 716 else if (retcode == SQL_NO_DATA_FOUND) 717 { 718 if (pstmt->prep_state) 719 { 720 pstmt->state = en_stmt_prepared; 721 } 722 else 723 { 724 pstmt->state = en_stmt_allocated; 725 } 726 } 727 else if (retcode == SQL_STILL_EXECUTING) 728 { 729 pstmt->asyn_on = en_MoreResults; 730 } 731 break; 732 733 default: 734 break; 735 } 736 737 return retcode; 738} 739 740 741SQLRETURN SQL_API 742SQLMoreResults (SQLHSTMT hstmt) 743{ 744 ENTER_STMT (hstmt, 745 trace_SQLMoreResults (TRACE_ENTER, hstmt)); 746 747 retcode = SQLMoreResults_Internal (hstmt); 748 749 LEAVE_STMT (hstmt, 750 trace_SQLMoreResults (TRACE_LEAVE, hstmt)); 751} 752 753 754SQLRETURN SQL_API 755_iodbcdm_SetPos ( 756 SQLHSTMT hstmt, 757 SQLSETPOSIROW irow, 758 SQLUSMALLINT fOption, 759 SQLUSMALLINT fLock) 760{ 761 STMT (pstmt, hstmt); 762 HPROC hproc; 763 SQLRETURN retcode; 764 sqlstcode_t sqlstat = en_00000; 765 766 /* check argument value */ 767 if (fOption > SQL_ADD || fLock > SQL_LOCK_UNLOCK) 768 { 769 PUSHSQLERR (pstmt->herr, en_S1009); 770 return SQL_ERROR; 771 } 772 773 /* check state */ 774 if (pstmt->asyn_on == en_NullProc) 775 { 776 switch (pstmt->state) 777 { 778 case en_stmt_allocated: 779 case en_stmt_prepared: 780 case en_stmt_needdata: 781 case en_stmt_mustput: 782 case en_stmt_canput: 783 sqlstat = en_S1010; 784 break; 785 786 case en_stmt_executed_with_info: 787 case en_stmt_executed: 788 case en_stmt_cursoropen: 789 sqlstat = en_24000; 790 break; 791 792 default: 793 break; 794 } 795 } 796 else if (pstmt->asyn_on != en_SetPos) 797 { 798 sqlstat = en_S1010; 799 } 800 801 if (sqlstat != en_00000) 802 { 803 PUSHSQLERR (pstmt->herr, sqlstat); 804 805 return SQL_ERROR; 806 } 807 808 /* call driver */ 809 hproc = _iodbcdm_getproc (pstmt->hdbc, en_SetPos); 810 811 if (hproc == SQL_NULL_HPROC) 812 { 813 PUSHSQLERR (pstmt->herr, en_IM001); 814 815 return SQL_ERROR; 816 } 817 818 CALL_DRIVER (pstmt->hdbc, pstmt, retcode, hproc, 819 (pstmt->dhstmt, irow, fOption, fLock)); 820 821 /* state transition */ 822 if (pstmt->asyn_on == en_SetPos) 823 { 824 switch (retcode) 825 { 826 case SQL_SUCCESS: 827 case SQL_SUCCESS_WITH_INFO: 828 case SQL_NEED_DATA: 829 case SQL_ERROR: 830 pstmt->asyn_on = en_NullProc; 831 break; 832 833 case SQL_STILL_EXECUTING: 834 default: 835 return retcode; 836 } 837 } 838 839 /* now, the only possible init state is 'xfetched' */ 840 switch (retcode) 841 { 842 case SQL_SUCCESS: 843 case SQL_SUCCESS_WITH_INFO: 844 break; 845 846 case SQL_NEED_DATA: 847 pstmt->state = en_stmt_needdata; 848 pstmt->need_on = en_SetPos; 849 break; 850 851 case SQL_STILL_EXECUTING: 852 pstmt->asyn_on = en_SetPos; 853 break; 854 855 default: 856 break; 857 } 858 859 return retcode; 860} 861 862 863SQLRETURN SQL_API 864SQLSetPos ( 865 SQLHSTMT hstmt, 866 SQLSETPOSIROW irow, 867 SQLUSMALLINT fOption, 868 SQLUSMALLINT fLock) 869{ 870 ENTER_STMT (hstmt, 871 trace_SQLSetPos (TRACE_ENTER, 872 hstmt, irow, fOption, fLock)); 873 874 retcode = _iodbcdm_SetPos (hstmt, irow, fOption, fLock); 875 876 LEAVE_STMT (hstmt, 877 trace_SQLSetPos (TRACE_LEAVE, 878 hstmt, irow, fOption, fLock)); 879} 880