1/* 2 * execute.c 3 * 4 * $Id: execute.c,v 1.24 2006/12/11 14:21:48 source Exp $ 5 * 6 * Invoke a query 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#include <henv.h> 91#include <hdbc.h> 92#include <hstmt.h> 93 94#include <itrace.h> 95 96void 97_iodbcdm_do_cursoropen (STMT_t * pstmt) 98{ 99 SQLRETURN retcode; 100 SWORD ncol; 101 102 pstmt->state = en_stmt_executed; 103 104 retcode = _iodbcdm_NumResultCols ((SQLHSTMT) pstmt, &ncol); 105 106 if (SQL_SUCCEEDED (retcode)) 107 { 108 if (ncol) 109 { 110 pstmt->state = en_stmt_cursoropen; 111 pstmt->cursor_state = en_stmt_cursor_opened; 112 } 113 else 114 { 115 pstmt->state = en_stmt_executed; 116 pstmt->cursor_state = en_stmt_cursor_no; 117 } 118 } 119} 120 121 122static SQLRETURN 123SQLExecute_Internal (SQLHSTMT hstmt) 124{ 125 STMT (pstmt, hstmt); 126 HPROC hproc = SQL_NULL_HPROC; 127 SQLRETURN retcode; 128 sqlstcode_t sqlstat = en_00000; 129 130 /* check state */ 131 if (pstmt->asyn_on == en_NullProc) 132 { 133 switch (pstmt->state) 134 { 135 case en_stmt_allocated: 136 sqlstat = en_S1010; 137 break; 138 139 case en_stmt_executed_with_info: 140 case en_stmt_executed: 141 if (!pstmt->prep_state) 142 { 143 sqlstat = en_S1010; 144 } 145 break; 146 147 case en_stmt_cursoropen: 148 if (!pstmt->prep_state) 149 { 150 sqlstat = en_S1010; 151 } 152 break; 153 154 case en_stmt_fetched: 155 case en_stmt_xfetched: 156 if (!pstmt->prep_state) 157 { 158 sqlstat = en_S1010; 159 } 160 else 161 { 162 sqlstat = en_24000; 163 } 164 break; 165 166 case en_stmt_needdata: 167 case en_stmt_mustput: 168 case en_stmt_canput: 169 sqlstat = en_S1010; 170 break; 171 172 default: 173 break; 174 } 175 } 176 else if (pstmt->asyn_on != en_Execute) 177 { 178 sqlstat = en_S1010; 179 } 180 181 if (sqlstat == en_00000) 182 { 183 hproc = _iodbcdm_getproc (pstmt->hdbc, en_Execute); 184 185 if (hproc == SQL_NULL_HPROC) 186 { 187 sqlstat = en_IM001; 188 } 189 } 190 191 if (sqlstat != en_00000) 192 { 193 PUSHSQLERR (pstmt->herr, sqlstat); 194 195 return SQL_ERROR; 196 } 197 198 CALL_DRIVER (pstmt->hdbc, pstmt, retcode, hproc, (pstmt->dhstmt)); 199 200 /* stmt state transition */ 201 if (pstmt->asyn_on == en_Execute) 202 { 203 switch (retcode) 204 { 205 case SQL_SUCCESS: 206 case SQL_SUCCESS_WITH_INFO: 207 case SQL_NEED_DATA: 208 case SQL_ERROR: 209 pstmt->asyn_on = en_NullProc; 210 break; 211 212 case SQL_STILL_EXECUTING: 213 default: 214 return retcode; 215 } 216 } 217 218 switch (pstmt->state) 219 { 220 case en_stmt_prepared: 221 switch (retcode) 222 { 223 case SQL_SUCCESS: 224 _iodbcdm_do_cursoropen (pstmt); 225 break; 226 227 case SQL_SUCCESS_WITH_INFO: 228 pstmt->state = en_stmt_executed_with_info; 229 break; 230 231 case SQL_NEED_DATA: 232 pstmt->state = en_stmt_needdata; 233 pstmt->need_on = en_Execute; 234 break; 235 236 case SQL_STILL_EXECUTING: 237 pstmt->asyn_on = en_Execute; 238 break; 239 240 default: 241 break; 242 } 243 break; 244 245 case en_stmt_executed: 246 switch (retcode) 247 { 248 case SQL_ERROR: 249 pstmt->state = en_stmt_prepared; 250 pstmt->cursor_state = en_stmt_cursor_no; 251 break; 252 253 case SQL_NEED_DATA: 254 pstmt->state = en_stmt_needdata; 255 pstmt->need_on = en_Execute; 256 break; 257 258 case SQL_STILL_EXECUTING: 259 pstmt->asyn_on = en_Execute; 260 break; 261 262 default: 263 break; 264 } 265 break; 266 267 default: 268 break; 269 } 270 271 return retcode; 272} 273 274 275SQLRETURN SQL_API 276SQLExecute (SQLHSTMT hstmt) 277{ 278 ENTER_STMT (hstmt, 279 trace_SQLExecute (TRACE_ENTER, hstmt)); 280 281 retcode = SQLExecute_Internal (hstmt); 282 283 LEAVE_STMT (hstmt, 284 trace_SQLExecute (TRACE_LEAVE, hstmt)); 285} 286 287 288SQLRETURN SQL_API 289SQLExecDirect_Internal (SQLHSTMT hstmt, 290 SQLPOINTER szSqlStr, 291 SQLINTEGER cbSqlStr, 292 SQLCHAR waMode) 293{ 294 STMT (pstmt, hstmt); 295 CONN (pdbc, pstmt->hdbc); 296 ENVR (penv, pdbc->henv); 297 HPROC hproc = SQL_NULL_HPROC; 298 SQLRETURN retcode = SQL_SUCCESS; 299 sqlstcode_t sqlstat = en_00000; 300 void * _SqlStr = NULL; 301 302 /* check arguments */ 303 if (szSqlStr == NULL) 304 { 305 sqlstat = en_S1009; 306 } 307 else if (cbSqlStr < 0 && cbSqlStr != SQL_NTS) 308 { 309 sqlstat = en_S1090; 310 } 311 312 if (sqlstat != en_00000) 313 { 314 PUSHSQLERR (pstmt->herr, sqlstat); 315 316 return SQL_ERROR; 317 } 318 319 /* check state */ 320 if (pstmt->asyn_on == en_NullProc) 321 { 322 switch (pstmt->state) 323 { 324 case en_stmt_fetched: 325 case en_stmt_xfetched: 326 sqlstat = en_24000; 327 break; 328 329 case en_stmt_needdata: 330 case en_stmt_mustput: 331 case en_stmt_canput: 332 sqlstat = en_S1010; 333 break; 334 335 default: 336 break; 337 } 338 } 339 else if (pstmt->asyn_on != en_ExecDirect) 340 { 341 sqlstat = en_S1010; 342 } 343 344 if (sqlstat != en_00000) 345 { 346 PUSHSQLERR (pstmt->herr, sqlstat); 347 348 return SQL_ERROR; 349 } 350 351 if ((penv->unicode_driver && waMode != 'W') 352 || (!penv->unicode_driver && waMode == 'W')) 353 { 354 if (waMode != 'W') 355 { 356 /* ansi=>unicode*/ 357 _SqlStr = _iodbcdm_conv_param_A2W(pstmt, 0, (SQLCHAR *) szSqlStr, cbSqlStr); 358 } 359 else 360 { 361 /* unicode=>ansi*/ 362 _SqlStr = _iodbcdm_conv_param_W2A(pstmt, 0, (SQLWCHAR *) szSqlStr, cbSqlStr); 363 } 364 szSqlStr = _SqlStr; 365 cbSqlStr = SQL_NTS; 366 } 367 368 CALL_UDRIVER(pstmt->hdbc, pstmt, retcode, hproc, penv->unicode_driver, 369 en_ExecDirect, ( 370 pstmt->dhstmt, 371 szSqlStr, 372 cbSqlStr)); 373 374 if (hproc == SQL_NULL_HPROC) 375 { 376 _iodbcdm_FreeStmtParams(pstmt); 377 PUSHSQLERR (pstmt->herr, en_IM001); 378 return SQL_ERROR; 379 } 380 381 if (retcode != SQL_STILL_EXECUTING) 382 _iodbcdm_FreeStmtParams(pstmt); 383 384 /* stmt state transition */ 385 if (pstmt->asyn_on == en_ExecDirect) 386 { 387 switch (retcode) 388 { 389 case SQL_SUCCESS: 390 case SQL_SUCCESS_WITH_INFO: 391 case SQL_NEED_DATA: 392 case SQL_ERROR: 393 pstmt->asyn_on = en_NullProc; 394 break; 395 396 case SQL_STILL_EXECUTING: 397 default: 398 return retcode; 399 } 400 } 401 402 if (pstmt->state <= en_stmt_executed) 403 { 404 switch (retcode) 405 { 406 case SQL_SUCCESS: 407 _iodbcdm_do_cursoropen (pstmt); 408 pstmt->prep_state = 1; 409 break; 410 411 case SQL_SUCCESS_WITH_INFO: 412 pstmt->state = en_stmt_executed_with_info; 413 pstmt->prep_state = 1; 414 break; 415 416 case SQL_NEED_DATA: 417 pstmt->state = en_stmt_needdata; 418 pstmt->need_on = en_ExecDirect; 419 break; 420 421 case SQL_STILL_EXECUTING: 422 pstmt->asyn_on = en_ExecDirect; 423 break; 424 425 case SQL_ERROR: 426 pstmt->state = en_stmt_allocated; 427 pstmt->cursor_state = en_stmt_cursor_no; 428 pstmt->prep_state = 0; 429 break; 430 431 default: 432 break; 433 } 434 } 435 436 return retcode; 437} 438 439 440SQLRETURN SQL_API 441SQLExecDirect (SQLHSTMT hstmt, SQLCHAR * szSqlStr, SQLINTEGER cbSqlStr) 442{ 443 ENTER_STMT (hstmt, 444 trace_SQLExecDirect (TRACE_ENTER, hstmt, szSqlStr, cbSqlStr)); 445 446 retcode = SQLExecDirect_Internal(hstmt, szSqlStr, cbSqlStr, 'A'); 447 448 LEAVE_STMT (hstmt, 449 trace_SQLExecDirect (TRACE_LEAVE, hstmt, szSqlStr, cbSqlStr)); 450} 451 452 453#if ODBCVER >= 0x0300 454SQLRETURN SQL_API 455SQLExecDirectA (SQLHSTMT hstmt, SQLCHAR * szSqlStr, SQLINTEGER cbSqlStr) 456{ 457 ENTER_STMT (hstmt, 458 trace_SQLExecDirect (TRACE_ENTER, hstmt, szSqlStr, cbSqlStr)); 459 460 retcode = SQLExecDirect_Internal(hstmt, szSqlStr, cbSqlStr, 'A'); 461 462 LEAVE_STMT (hstmt, 463 trace_SQLExecDirect (TRACE_LEAVE, hstmt, szSqlStr, cbSqlStr)); 464} 465 466 467SQLRETURN SQL_API 468SQLExecDirectW (SQLHSTMT hstmt, SQLWCHAR * szSqlStr, SQLINTEGER cbSqlStr) 469{ 470 ENTER_STMT (hstmt, 471 trace_SQLExecDirectW (TRACE_ENTER, hstmt, szSqlStr, cbSqlStr)); 472 473 retcode = SQLExecDirect_Internal(hstmt, szSqlStr, cbSqlStr, 'W'); 474 475 LEAVE_STMT (hstmt, 476 trace_SQLExecDirectW (TRACE_LEAVE, hstmt, szSqlStr, cbSqlStr)); 477} 478#endif 479 480 481static SQLRETURN 482SQLPutData_Internal ( 483 SQLHSTMT hstmt, 484 SQLPOINTER rgbValue, 485 SQLLEN cbValue) 486{ 487 STMT (pstmt, hstmt); 488 HPROC hproc; 489 SQLRETURN retcode; 490 491 /* check argument value */ 492 if (rgbValue == NULL && 493 (cbValue != SQL_DEFAULT_PARAM && cbValue != SQL_NULL_DATA)) 494 { 495 PUSHSQLERR (pstmt->herr, en_S1009); 496 497 return SQL_ERROR; 498 } 499 500 /* check state */ 501 if (pstmt->asyn_on == en_NullProc) 502 { 503 if (pstmt->state <= en_stmt_xfetched) 504 { 505 PUSHSQLERR (pstmt->herr, en_S1010); 506 507 return SQL_ERROR; 508 } 509 } 510 else if (pstmt->asyn_on != en_PutData) 511 { 512 PUSHSQLERR (pstmt->herr, en_S1010); 513 514 return SQL_ERROR; 515 } 516 517 /* call driver */ 518 hproc = _iodbcdm_getproc (pstmt->hdbc, en_PutData); 519 520 if (hproc == SQL_NULL_HPROC) 521 { 522 PUSHSQLERR (pstmt->herr, en_IM001); 523 524 return SQL_ERROR; 525 } 526 527 CALL_DRIVER (pstmt->hdbc, pstmt, retcode, hproc, 528 (pstmt->dhstmt, rgbValue, cbValue)); 529 530 /* state transition */ 531 if (pstmt->asyn_on == en_PutData) 532 { 533 switch (retcode) 534 { 535 case SQL_SUCCESS: 536 case SQL_SUCCESS_WITH_INFO: 537 case SQL_ERROR: 538 pstmt->asyn_on = en_NullProc; 539 break; 540 541 case SQL_STILL_EXECUTING: 542 default: 543 return retcode; 544 } 545 } 546 547 /* must in mustput or canput states */ 548 switch (retcode) 549 { 550 case SQL_SUCCESS: 551 case SQL_SUCCESS_WITH_INFO: 552 pstmt->state = en_stmt_canput; 553 break; 554 555 case SQL_ERROR: 556 switch (pstmt->need_on) 557 { 558 case en_ExecDirect: 559 pstmt->state = en_stmt_allocated; 560 pstmt->need_on = en_NullProc; 561 break; 562 563 case en_Execute: 564 if (pstmt->prep_state) 565 { 566 pstmt->state = en_stmt_prepared; 567 pstmt->need_on = en_NullProc; 568 } 569 break; 570 571 case en_SetPos: 572 /* Is this possible ???? */ 573 pstmt->state = en_stmt_xfetched; 574 break; 575 576 default: 577 break; 578 } 579 break; 580 581 case SQL_STILL_EXECUTING: 582 pstmt->asyn_on = en_PutData; 583 break; 584 585 default: 586 break; 587 } 588 589 return retcode; 590} 591 592 593SQLRETURN SQL_API 594SQLPutData ( 595 SQLHSTMT hstmt, 596 SQLPOINTER rgbValue, 597 SQLLEN cbValue) 598{ 599 ENTER_STMT (hstmt, 600 trace_SQLPutData (TRACE_ENTER, hstmt, rgbValue, cbValue)); 601 602 retcode = SQLPutData_Internal (hstmt, rgbValue, cbValue); 603 604 LEAVE_STMT (hstmt, 605 trace_SQLPutData (TRACE_LEAVE, hstmt, rgbValue, cbValue)); 606} 607 608 609static SQLRETURN 610SQLParamData_Internal (SQLHSTMT hstmt, SQLPOINTER * prgbValue) 611{ 612 STMT (pstmt, hstmt); 613 HPROC hproc; 614 SQLRETURN retcode; 615 616 /* check argument */ 617 618 /* check state */ 619 if (pstmt->asyn_on == en_NullProc) 620 { 621 if (pstmt->state <= en_stmt_xfetched) 622 { 623 PUSHSQLERR (pstmt->herr, en_S1010); 624 625 return SQL_ERROR; 626 } 627 } 628 else if (pstmt->asyn_on != en_ParamData) 629 { 630 PUSHSQLERR (pstmt->herr, en_S1010); 631 632 return SQL_ERROR; 633 } 634 635 /* call driver */ 636 hproc = _iodbcdm_getproc (pstmt->hdbc, en_ParamData); 637 638 if (hproc == SQL_NULL_HPROC) 639 { 640 PUSHSQLERR (pstmt->herr, en_IM001); 641 642 return SQL_ERROR; 643 } 644 645 CALL_DRIVER (pstmt->hdbc, pstmt, retcode, hproc, (pstmt->dhstmt, prgbValue)); 646 647 /* state transition */ 648 if (pstmt->asyn_on == en_ParamData) 649 { 650 switch (retcode) 651 { 652 case SQL_SUCCESS: 653 case SQL_SUCCESS_WITH_INFO: 654 case SQL_ERROR: 655 pstmt->asyn_on = en_NullProc; 656 break; 657 658 case SQL_STILL_EXECUTING: 659 default: 660 return retcode; 661 } 662 } 663 664 if (pstmt->state < en_stmt_needdata) 665 { 666 return retcode; 667 } 668 669 switch (retcode) 670 { 671 case SQL_ERROR: 672 switch (pstmt->need_on) 673 { 674 case en_ExecDirect: 675 pstmt->state = en_stmt_allocated; 676 break; 677 678 case en_Execute: 679 pstmt->state = en_stmt_prepared; 680 break; 681 682 case en_SetPos: 683 pstmt->state = en_stmt_xfetched; 684 pstmt->cursor_state = en_stmt_cursor_xfetched; 685 break; 686 687 default: 688 break; 689 } 690 pstmt->need_on = en_NullProc; 691 break; 692 693 case SQL_SUCCESS: 694 case SQL_SUCCESS_WITH_INFO: 695 switch (pstmt->state) 696 { 697 case en_stmt_needdata: 698 pstmt->state = en_stmt_mustput; 699 break; 700 701 case en_stmt_canput: 702 switch (pstmt->need_on) 703 { 704 case en_SetPos: 705 pstmt->state = en_stmt_xfetched; 706 pstmt->cursor_state = en_stmt_cursor_xfetched; 707 break; 708 709 case en_ExecDirect: 710 case en_Execute: 711 _iodbcdm_do_cursoropen (pstmt); 712 break; 713 714 default: 715 break; 716 } 717 break; 718 719 default: 720 break; 721 } 722 pstmt->need_on = en_NullProc; 723 break; 724 725 case SQL_NEED_DATA: 726 pstmt->state = en_stmt_mustput; 727 break; 728 729 default: 730 break; 731 } 732 733 return retcode; 734} 735 736 737SQLRETURN SQL_API 738SQLParamData (SQLHSTMT hstmt, SQLPOINTER * prgbValue) 739{ 740 ENTER_STMT (hstmt, 741 trace_SQLParamData (TRACE_ENTER, hstmt, prgbValue)); 742 743 retcode = SQLParamData_Internal (hstmt, prgbValue); 744 745 LEAVE_STMT (hstmt, 746 trace_SQLParamData (TRACE_LEAVE, hstmt, prgbValue)); 747} 748 749 750static SQLRETURN 751SQLNumParams_Internal (SQLHSTMT hstmt, SQLSMALLINT * pcpar) 752{ 753 STMT (pstmt, hstmt); 754 HPROC hproc; 755 SQLRETURN retcode; 756 757 /* check argument */ 758 if (!pcpar) 759 { 760 return SQL_SUCCESS; 761 } 762 763 /* check state */ 764 if (pstmt->asyn_on == en_NullProc) 765 { 766 switch (pstmt->state) 767 { 768 case en_stmt_allocated: 769 case en_stmt_needdata: 770 case en_stmt_mustput: 771 case en_stmt_canput: 772 PUSHSQLERR (pstmt->herr, en_S1010); 773 return SQL_ERROR; 774 775 default: 776 break; 777 } 778 } 779 else if (pstmt->asyn_on != en_NumParams) 780 { 781 PUSHSQLERR (pstmt->herr, en_S1010); 782 783 return SQL_ERROR; 784 } 785 786 /* call driver */ 787 hproc = _iodbcdm_getproc (pstmt->hdbc, en_NumParams); 788 789 if (hproc == SQL_NULL_HPROC) 790 { 791 PUSHSQLERR (pstmt->herr, en_IM001); 792 793 return SQL_ERROR; 794 } 795 796 CALL_DRIVER (pstmt->hdbc, pstmt, retcode, hproc, (pstmt->dhstmt, pcpar)); 797 798 /* state transition */ 799 if (pstmt->asyn_on == en_NumParams) 800 { 801 switch (retcode) 802 { 803 case SQL_SUCCESS: 804 case SQL_SUCCESS_WITH_INFO: 805 case SQL_ERROR: 806 break; 807 808 default: 809 return retcode; 810 } 811 } 812 813 if (retcode == SQL_STILL_EXECUTING) 814 { 815 pstmt->asyn_on = en_NumParams; 816 } 817 818 return retcode; 819} 820 821 822SQLRETURN SQL_API 823SQLNumParams (SQLHSTMT hstmt, SQLSMALLINT * pcpar) 824{ 825 ENTER_STMT (hstmt, 826 trace_SQLNumParams (TRACE_ENTER, hstmt, pcpar)); 827 828 retcode = SQLNumParams_Internal (hstmt, pcpar); 829 830 LEAVE_STMT (hstmt, 831 trace_SQLNumParams (TRACE_LEAVE, hstmt, pcpar)); 832} 833 834 835static SQLRETURN 836SQLDescribeParam_Internal ( 837 SQLHSTMT hstmt, 838 SQLUSMALLINT ipar, 839 SQLSMALLINT * pfSqlType, 840 SQLULEN * pcbColDef, 841 SQLSMALLINT * pibScale, 842 SQLSMALLINT * pfNullable) 843{ 844 STMT (pstmt, hstmt); 845 CONN (pdbc, pstmt->hdbc); 846 GENV (genv, pdbc->genv); 847 848 HPROC hproc; 849 SQLRETURN retcode; 850 851 /* check argument */ 852 if (ipar == 0) 853 { 854 PUSHSQLERR (pstmt->herr, en_S1093); 855 856 return SQL_ERROR; 857 } 858 859 /* check state */ 860 if (pstmt->asyn_on == en_NullProc) 861 { 862 switch (pstmt->state) 863 { 864 case en_stmt_allocated: 865 case en_stmt_needdata: 866 case en_stmt_mustput: 867 case en_stmt_canput: 868 PUSHSQLERR (pstmt->herr, en_S1010); 869 return SQL_ERROR; 870 871 default: 872 break; 873 } 874 } 875 else if (pstmt->asyn_on != en_DescribeParam) 876 { 877 PUSHSQLERR (pstmt->herr, en_S1010); 878 879 return SQL_ERROR; 880 } 881 882 /* call driver */ 883 hproc = _iodbcdm_getproc (pstmt->hdbc, en_DescribeParam); 884 885 if (hproc == SQL_NULL_HPROC) 886 { 887 PUSHSQLERR (pstmt->herr, en_IM001); 888 889 return SQL_ERROR; 890 } 891 892 CALL_DRIVER (pstmt->hdbc, pstmt, retcode, hproc, 893 (pstmt->dhstmt, ipar, pfSqlType, pcbColDef, pibScale, pfNullable)); 894 895 /* 896 * Convert sql type to ODBC version of application 897 */ 898 if (SQL_SUCCEEDED(retcode) && pfSqlType) 899 *pfSqlType = _iodbcdm_map_sql_type (*pfSqlType, genv->odbc_ver); 900 901 902 /* state transition */ 903 if (pstmt->asyn_on == en_DescribeParam) 904 { 905 switch (retcode) 906 { 907 case SQL_SUCCESS: 908 case SQL_SUCCESS_WITH_INFO: 909 case SQL_ERROR: 910 break; 911 912 default: 913 return retcode; 914 } 915 } 916 917 if (retcode == SQL_STILL_EXECUTING) 918 { 919 pstmt->asyn_on = en_DescribeParam; 920 } 921 922 return retcode; 923} 924 925 926SQLRETURN SQL_API 927SQLDescribeParam ( 928 SQLHSTMT hstmt, 929 SQLUSMALLINT ipar, 930 SQLSMALLINT * pfSqlType, 931 SQLULEN * pcbColDef, 932 SQLSMALLINT * pibScale, 933 SQLSMALLINT * pfNullable) 934{ 935 ENTER_STMT (hstmt, 936 trace_SQLDescribeParam (TRACE_ENTER, 937 hstmt, ipar, pfSqlType, 938 pcbColDef, pibScale, pfNullable)); 939 940 retcode = SQLDescribeParam_Internal ( hstmt, ipar, pfSqlType, 941 pcbColDef, pibScale, pfNullable); 942 943 LEAVE_STMT (hstmt, 944 trace_SQLDescribeParam (TRACE_LEAVE, 945 hstmt, ipar, pfSqlType, 946 pcbColDef, pibScale, pfNullable)); 947} 948