1/* 2 * prepare.c 3 * 4 * $Id: prepare.c,v 1.25 2006/12/11 14:21:48 source Exp $ 5 * 6 * Prepare 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 96SQLRETURN SQL_API 97SQLPrepare_Internal ( 98 SQLHSTMT hstmt, 99 SQLPOINTER szSqlStr, 100 SQLINTEGER cbSqlStr, 101 SQLCHAR waMode) 102{ 103 STMT (pstmt, hstmt); 104 CONN (pdbc, pstmt->hdbc); 105 ENVR (penv, pdbc->henv); 106 HPROC hproc = SQL_NULL_HPROC; 107 SQLRETURN retcode = SQL_SUCCESS; 108 sqlstcode_t sqlstat = en_00000; 109 void * _SqlStr = NULL; 110 111 /* check state */ 112 if (pstmt->asyn_on == en_NullProc) 113 { 114 /* not on asyn state */ 115 switch (pstmt->state) 116 { 117 case en_stmt_fetched: 118 case en_stmt_xfetched: 119 sqlstat = en_24000; 120 break; 121 122 case en_stmt_needdata: 123 case en_stmt_mustput: 124 case en_stmt_canput: 125 sqlstat = en_S1010; 126 break; 127 128 default: 129 break; 130 } 131 } 132 else if (pstmt->asyn_on != en_Prepare) 133 { 134 /* asyn on other */ 135 sqlstat = en_S1010; 136 } 137 138 if (sqlstat != en_00000) 139 { 140 PUSHSQLERR (pstmt->herr, sqlstat); 141 142 return SQL_ERROR; 143 } 144 145 if (szSqlStr == NULL) 146 { 147 PUSHSQLERR (pstmt->herr, en_S1009); 148 149 return SQL_ERROR; 150 } 151 152 if (cbSqlStr < 0 && cbSqlStr != SQL_NTS) 153 { 154 PUSHSQLERR (pstmt->herr, en_S1090); 155 156 return SQL_ERROR; 157 } 158 159 if ((penv->unicode_driver && waMode != 'W') 160 || (!penv->unicode_driver && waMode == 'W')) 161 { 162 if (waMode != 'W') 163 { 164 /* ansi=>unicode*/ 165 _SqlStr = _iodbcdm_conv_param_A2W(pstmt, 0, (SQLCHAR *) szSqlStr, cbSqlStr); 166 } 167 else 168 { 169 /* unicode=>ansi*/ 170 _SqlStr = _iodbcdm_conv_param_W2A(pstmt, 0, (SQLWCHAR *) szSqlStr, cbSqlStr); 171 } 172 szSqlStr = _SqlStr; 173 cbSqlStr = SQL_NTS; 174 } 175 176 CALL_UDRIVER(pstmt->hdbc, pstmt, retcode, hproc, penv->unicode_driver, 177 en_Prepare, ( 178 pstmt->dhstmt, 179 szSqlStr, 180 cbSqlStr)); 181 182 if (hproc == SQL_NULL_HPROC) 183 { 184 _iodbcdm_FreeStmtParams(pstmt); 185 PUSHSQLERR (pstmt->herr, en_IM001); 186 return SQL_ERROR; 187 } 188 189 if (retcode != SQL_STILL_EXECUTING) 190 _iodbcdm_FreeStmtParams(pstmt); 191 192 /* stmt state transition */ 193 if (pstmt->asyn_on == en_Prepare) 194 { 195 switch (retcode) 196 { 197 case SQL_SUCCESS: 198 case SQL_SUCCESS_WITH_INFO: 199 case SQL_ERROR: 200 pstmt->asyn_on = en_NullProc; 201 return retcode; 202 203 case SQL_STILL_EXECUTING: 204 default: 205 return retcode; 206 } 207 } 208 209 switch (retcode) 210 { 211 case SQL_STILL_EXECUTING: 212 pstmt->asyn_on = en_Prepare; 213 break; 214 215 case SQL_SUCCESS: 216 case SQL_SUCCESS_WITH_INFO: 217 pstmt->state = en_stmt_prepared; 218 pstmt->prep_state = 1; 219 break; 220 221 case SQL_ERROR: 222 switch (pstmt->state) 223 { 224 case en_stmt_prepared: 225 case en_stmt_executed_with_info: 226 case en_stmt_executed: 227 pstmt->state = en_stmt_allocated; 228 pstmt->prep_state = 0; 229 break; 230 231 default: 232 break; 233 } 234 235 default: 236 break; 237 } 238 239 return retcode; 240} 241 242 243SQLRETURN SQL_API 244SQLPrepare (SQLHSTMT hstmt, 245 SQLCHAR * szSqlStr, 246 SQLINTEGER cbSqlStr) 247{ 248 ENTER_STMT (hstmt, 249 trace_SQLPrepare (TRACE_ENTER, hstmt, szSqlStr, cbSqlStr)); 250 251 retcode = SQLPrepare_Internal(hstmt, szSqlStr, cbSqlStr, 'A'); 252 253 LEAVE_STMT (hstmt, 254 trace_SQLPrepare (TRACE_LEAVE, hstmt, szSqlStr, cbSqlStr)); 255} 256 257 258#if ODBCVER >= 0x0300 259SQLRETURN SQL_API 260SQLPrepareA (SQLHSTMT hstmt, 261 SQLCHAR * szSqlStr, 262 SQLINTEGER cbSqlStr) 263{ 264 ENTER_STMT (hstmt, 265 trace_SQLPrepare (TRACE_ENTER, hstmt, szSqlStr, cbSqlStr)); 266 267 retcode = SQLPrepare_Internal(hstmt, szSqlStr, cbSqlStr, 'A'); 268 269 LEAVE_STMT (hstmt, 270 trace_SQLPrepare (TRACE_LEAVE, hstmt, szSqlStr, cbSqlStr)); 271} 272 273 274SQLRETURN SQL_API 275SQLPrepareW (SQLHSTMT hstmt, 276 SQLWCHAR * szSqlStr, 277 SQLINTEGER cbSqlStr) 278{ 279 ENTER_STMT (hstmt, 280 trace_SQLPrepareW (TRACE_ENTER, hstmt, szSqlStr, cbSqlStr)); 281 282 retcode = SQLPrepare_Internal(hstmt, szSqlStr, cbSqlStr, 'W'); 283 284 LEAVE_STMT (hstmt, 285 trace_SQLPrepareW (TRACE_LEAVE, hstmt, szSqlStr, cbSqlStr)); 286} 287#endif 288 289 290SQLRETURN SQL_API 291SQLSetCursorName_Internal ( 292 SQLHSTMT hstmt, 293 SQLPOINTER szCursor, 294 SQLSMALLINT cbCursor, 295 SQLCHAR waMode) 296{ 297 STMT (pstmt, hstmt); 298 CONN (pdbc, pstmt->hdbc); 299 ENVR (penv, pdbc->henv); 300 HPROC hproc = SQL_NULL_HPROC; 301 SQLRETURN retcode = SQL_SUCCESS; 302 sqlstcode_t sqlstat = en_00000; 303 void * _Cursor = NULL; 304 305 if (szCursor == NULL) 306 { 307 PUSHSQLERR (pstmt->herr, en_S1009); 308 309 return SQL_ERROR; 310 } 311 312 if (cbCursor < 0 && cbCursor != SQL_NTS) 313 { 314 PUSHSQLERR (pstmt->herr, en_S1090); 315 316 return SQL_ERROR; 317 } 318 319 /* check state */ 320 if (pstmt->asyn_on != en_NullProc) 321 { 322 sqlstat = en_S1010; 323 } 324 else 325 { 326 switch (pstmt->state) 327 { 328 case en_stmt_executed_with_info: 329 case en_stmt_executed: 330 case en_stmt_cursoropen: 331 case en_stmt_fetched: 332 case en_stmt_xfetched: 333 sqlstat = en_24000; 334 break; 335 336 case en_stmt_needdata: 337 case en_stmt_mustput: 338 case en_stmt_canput: 339 sqlstat = en_S1010; 340 break; 341 342 default: 343 break; 344 } 345 } 346 347 if (sqlstat != en_00000) 348 { 349 PUSHSQLERR (pstmt->herr, sqlstat); 350 351 return SQL_ERROR; 352 } 353 354 if ((penv->unicode_driver && waMode != 'W') 355 || (!penv->unicode_driver && waMode == 'W')) 356 { 357 if (waMode != 'W') 358 { 359 /* ansi=>unicode*/ 360 _Cursor = dm_SQL_A2W ((SQLCHAR *) szCursor, cbCursor); 361 } 362 else 363 { 364 /* unicode=>ansi*/ 365 _Cursor = dm_SQL_W2A ((SQLWCHAR *) szCursor, cbCursor); 366 } 367 szCursor = _Cursor; 368 cbCursor = SQL_NTS; 369 } 370 371 CALL_UDRIVER(pstmt->hdbc, pstmt, retcode, hproc, penv->unicode_driver, 372 en_SetCursorName, ( 373 pstmt->dhstmt, 374 szCursor, 375 cbCursor)); 376 377 MEM_FREE(_Cursor); 378 379 if (hproc == SQL_NULL_HPROC) 380 { 381 PUSHSQLERR (pstmt->herr, en_IM001); 382 383 return SQL_ERROR; 384 } 385 386 if (SQL_SUCCEEDED (retcode)) 387 { 388 pstmt->cursor_state = en_stmt_cursor_named; 389 } 390 391 return retcode; 392} 393 394 395SQLRETURN SQL_API 396SQLSetCursorName ( 397 SQLHSTMT hstmt, 398 SQLCHAR * szCursor, 399 SQLSMALLINT cbCursor) 400{ 401 ENTER_STMT (hstmt, 402 trace_SQLSetCursorName (TRACE_ENTER, hstmt, szCursor, cbCursor)); 403 404 retcode = SQLSetCursorName_Internal(hstmt, szCursor, cbCursor, 'A'); 405 406 LEAVE_STMT (hstmt, 407 trace_SQLSetCursorName (TRACE_LEAVE, hstmt, szCursor, cbCursor)); 408} 409 410 411#if ODBCVER >= 0x0300 412SQLRETURN SQL_API 413SQLSetCursorNameA ( 414 SQLHSTMT hstmt, 415 SQLCHAR * szCursor, 416 SQLSMALLINT cbCursor) 417{ 418 ENTER_STMT (hstmt, 419 trace_SQLSetCursorName (TRACE_ENTER, hstmt, szCursor, cbCursor)); 420 421 retcode = SQLSetCursorName_Internal(hstmt, szCursor, cbCursor, 'A'); 422 423 LEAVE_STMT (hstmt, 424 trace_SQLSetCursorName (TRACE_LEAVE, hstmt, szCursor, cbCursor)); 425} 426 427 428SQLRETURN SQL_API 429SQLSetCursorNameW ( 430 SQLHSTMT hstmt, 431 SQLWCHAR * szCursor, 432 SQLSMALLINT cbCursor) 433{ 434 ENTER_STMT (hstmt, 435 trace_SQLSetCursorNameW (TRACE_ENTER, hstmt, szCursor, cbCursor)); 436 437 retcode = SQLSetCursorName_Internal(hstmt, szCursor, cbCursor, 'W'); 438 439 LEAVE_STMT (hstmt, 440 trace_SQLSetCursorNameW (TRACE_LEAVE, hstmt, szCursor, cbCursor)); 441} 442#endif 443 444 445static SQLRETURN 446SQLBindParameter_Internal ( 447 SQLHSTMT hstmt, 448 SQLUSMALLINT ipar, 449 SQLSMALLINT fParamType, 450 SQLSMALLINT fCType, 451 SQLSMALLINT fSqlType, 452 SQLULEN cbColDef, 453 SQLSMALLINT ibScale, 454 SQLPOINTER rgbValue, 455 SQLLEN cbValueMax, 456 SQLLEN * pcbValue) 457{ 458 STMT (pstmt, hstmt); 459 CONN (pdbc, pstmt->hdbc); 460 ENVR (penv, pdbc->henv); 461 HPROC hproc2 = SQL_NULL_HPROC; 462 HPROC hproc3 = SQL_NULL_HPROC; 463 SQLSMALLINT nCType; 464 SQLSMALLINT nSqlType; 465 sqlstcode_t sqlstat = en_00000; 466 SQLRETURN retcode = SQL_SUCCESS; 467 SQLUINTEGER odbc_ver = ((GENV_t *) pdbc->genv)->odbc_ver; 468 SQLUINTEGER dodbc_ver = ((ENV_t *) pdbc->henv)->dodbc_ver; 469 470 471#if (ODBCVER >= 0x0300) 472 if (0) 473#else 474 /* check param */ 475 if (fSqlType > SQL_TYPE_MAX || 476 (fSqlType < SQL_TYPE_MIN && fSqlType > SQL_TYPE_DRIVER_START)) 477 /* Note: SQL_TYPE_DRIVER_START is a negative number 478 * So, we use ">" */ 479#endif 480 { 481 sqlstat = en_S1004; 482 } 483 else if (ipar < 1) 484 { 485 sqlstat = en_S1093; 486 } 487 else if ((rgbValue == NULL && pcbValue == NULL) 488 && fParamType != SQL_PARAM_OUTPUT) 489 { 490 sqlstat = en_S1009; 491 /* This means, I allow output to nowhere 492 * (i.e. * junk output result). But I can't 493 * allow input from nowhere. 494 */ 495 } 496/********** 497 else if( cbValueMax < 0L && cbValueMax != SQL_SETPARAM_VALUE_MAX ) 498 { 499 sqlstat = en_S1090; 500 } 501**********/ 502 else if (fParamType != SQL_PARAM_INPUT 503 && fParamType != SQL_PARAM_OUTPUT 504 && fParamType != SQL_PARAM_INPUT_OUTPUT) 505 { 506 sqlstat = en_S1105; 507 } 508 else 509 { 510 switch (fCType) 511 { 512 case SQL_C_DEFAULT: 513 case SQL_C_BINARY: 514 case SQL_C_BIT: 515 case SQL_C_CHAR: 516 case SQL_C_DATE: 517 case SQL_C_DOUBLE: 518 case SQL_C_FLOAT: 519 case SQL_C_LONG: 520 case SQL_C_SHORT: 521 case SQL_C_SLONG: 522 case SQL_C_SSHORT: 523 case SQL_C_STINYINT: 524 case SQL_C_TIME: 525 case SQL_C_TIMESTAMP: 526 case SQL_C_TINYINT: 527 case SQL_C_ULONG: 528 case SQL_C_USHORT: 529 case SQL_C_UTINYINT: 530#if (ODBCVER >= 0x0300) 531 case SQL_C_GUID: 532 case SQL_C_INTERVAL_DAY: 533 case SQL_C_INTERVAL_DAY_TO_HOUR: 534 case SQL_C_INTERVAL_DAY_TO_MINUTE: 535 case SQL_C_INTERVAL_DAY_TO_SECOND: 536 case SQL_C_INTERVAL_HOUR: 537 case SQL_C_INTERVAL_HOUR_TO_MINUTE: 538 case SQL_C_INTERVAL_HOUR_TO_SECOND: 539 case SQL_C_INTERVAL_MINUTE: 540 case SQL_C_INTERVAL_MINUTE_TO_SECOND: 541 case SQL_C_INTERVAL_MONTH: 542 case SQL_C_INTERVAL_SECOND: 543 case SQL_C_INTERVAL_YEAR: 544 case SQL_C_INTERVAL_YEAR_TO_MONTH: 545 case SQL_C_NUMERIC: 546 case SQL_C_SBIGINT: 547 case SQL_C_TYPE_DATE: 548 case SQL_C_TYPE_TIME: 549 case SQL_C_TYPE_TIMESTAMP: 550 case SQL_C_UBIGINT: 551 case SQL_C_WCHAR: 552#endif 553 break; 554 555 default: 556 sqlstat = en_S1003; 557 break; 558 } 559 } 560 561 if (sqlstat != en_00000) 562 { 563 PUSHSQLERR (pstmt->herr, sqlstat); 564 565 return SQL_ERROR; 566 } 567 568 /* check state */ 569 if (pstmt->state >= en_stmt_needdata || pstmt->asyn_on != en_NullProc) 570 { 571 PUSHSQLERR (pstmt->herr, en_S1010); 572 573 retcode = SQL_ERROR; 574 } 575 576 /* 577 * Convert C type to ODBC version of driver 578 */ 579 nCType = _iodbcdm_map_c_type (fCType, penv->dodbc_ver); 580 581 /* 582 * Convert SQL type to ODBC version of driver 583 */ 584 nSqlType = _iodbcdm_map_sql_type (fSqlType, penv->dodbc_ver); 585 586 hproc2 = _iodbcdm_getproc (pstmt->hdbc, en_BindParameter); 587#if (ODBCVER >=0x0300) 588 hproc3 = _iodbcdm_getproc (pstmt->hdbc, en_BindParam); 589#endif 590 591 if (odbc_ver == SQL_OV_ODBC2 && 592 ( dodbc_ver == SQL_OV_ODBC2 593 || (dodbc_ver == SQL_OV_ODBC3 && hproc2 != SQL_NULL_HPROC))) 594 hproc3 = SQL_NULL_HPROC; 595 596#if (ODBCVER >=0x0300) 597 if (fParamType == SQL_PARAM_INPUT && hproc3 != SQL_NULL_HPROC) 598 { 599 CALL_DRIVER (pstmt->hdbc, pstmt, retcode, hproc3, 600 (pstmt->dhstmt, ipar, nCType, nSqlType, cbColDef, 601 ibScale, rgbValue, pcbValue)); 602 } 603 else 604#endif 605 { 606 if (hproc2 == SQL_NULL_HPROC) 607 { 608 PUSHSQLERR (pstmt->herr, en_IM001); 609 return SQL_ERROR; 610 } 611 CALL_DRIVER (pstmt->hdbc, pstmt, retcode, hproc2, 612 (pstmt->dhstmt, ipar, fParamType, nCType, nSqlType, cbColDef, 613 ibScale, rgbValue, cbValueMax, pcbValue)); 614 } 615 616 return retcode; 617} 618 619 620SQLRETURN SQL_API 621SQLBindParameter ( 622 SQLHSTMT hstmt, 623 SQLUSMALLINT ipar, 624 SQLSMALLINT fParamType, 625 SQLSMALLINT fCType, 626 SQLSMALLINT fSqlType, 627 SQLULEN cbColDef, 628 SQLSMALLINT ibScale, 629 SQLPOINTER rgbValue, 630 SQLLEN cbValueMax, 631 SQLLEN * pcbValue) 632{ 633 ENTER_STMT (hstmt, 634 trace_SQLBindParameter (TRACE_ENTER, 635 hstmt, ipar, fParamType, fCType, fSqlType, cbColDef, 636 ibScale, rgbValue, cbValueMax, pcbValue)); 637 638 retcode = SQLBindParameter_Internal ( 639 hstmt, ipar, fParamType, fCType, fSqlType, cbColDef, 640 ibScale, rgbValue, cbValueMax, pcbValue); 641 642 LEAVE_STMT (hstmt, 643 trace_SQLBindParameter (TRACE_LEAVE, 644 hstmt, ipar, fParamType, fCType, fSqlType, cbColDef, 645 ibScale, rgbValue, cbValueMax, pcbValue)); 646} 647 648 649static SQLRETURN 650SQLParamOptions_Internal ( 651 SQLHSTMT hstmt, 652 SQLULEN crow, 653 SQLULEN * pirow) 654{ 655 STMT (pstmt, hstmt); 656 HPROC hproc2 = SQL_NULL_HPROC; 657 HPROC hproc3 = SQL_NULL_HPROC; 658 SQLRETURN retcode; 659 CONN (pdbc, pstmt->hdbc); 660 SQLUINTEGER odbc_ver = ((GENV_t *) pdbc->genv)->odbc_ver; 661 SQLUINTEGER dodbc_ver = ((ENV_t *) pdbc->henv)->dodbc_ver; 662 663 if (crow == (SQLULEN) 0UL) 664 { 665 PUSHSQLERR (pstmt->herr, en_S1107); 666 667 return SQL_ERROR; 668 } 669 670 if (pstmt->state >= en_stmt_needdata || pstmt->asyn_on != en_NullProc) 671 { 672 PUSHSQLERR (pstmt->herr, en_S1010); 673 674 return SQL_ERROR; 675 } 676 677 678 hproc2 = _iodbcdm_getproc (pstmt->hdbc, en_ParamOptions); 679#if (ODBCVER >= 0x0300) 680 hproc3 = _iodbcdm_getproc (pstmt->hdbc, en_SetStmtAttr); 681#endif 682 683 if (odbc_ver == SQL_OV_ODBC2 && 684 ( dodbc_ver == SQL_OV_ODBC2 685 || (dodbc_ver == SQL_OV_ODBC3 && hproc2 != SQL_NULL_HPROC))) 686 hproc3 = SQL_NULL_HPROC; 687 688#if (ODBCVER >= 0x0300) 689 if (hproc3 != SQL_NULL_HPROC) 690 { 691 CALL_DRIVER (pstmt->hdbc, pstmt, retcode, hproc3, 692 (pstmt->dhstmt, SQL_ATTR_PARAMSET_SIZE, crow, 0)); 693 if (SQL_SUCCEEDED (retcode)) 694 { 695 CALL_DRIVER (pstmt->hdbc, pstmt, retcode, hproc3, 696 (pstmt->dhstmt, SQL_ATTR_PARAMS_PROCESSED_PTR, pirow, 0)); 697 } 698 } 699 else 700#endif 701 { 702 if (hproc2 == SQL_NULL_HPROC) 703 { 704 PUSHSQLERR (pstmt->herr, en_IM001); 705 return SQL_ERROR; 706 } 707 708 CALL_DRIVER (pstmt->hdbc, pstmt, retcode, hproc2, 709 (pstmt->dhstmt, crow, pirow)); 710 } 711 712 return retcode; 713} 714 715 716SQLRETURN SQL_API 717SQLParamOptions( 718 SQLHSTMT hstmt, 719 SQLULEN crow, 720 SQLULEN * pirow) 721{ 722 ENTER_STMT (hstmt, 723 trace_SQLParamOptions (TRACE_ENTER, hstmt, crow, pirow)); 724 725 retcode = SQLParamOptions_Internal (hstmt, crow, pirow); 726 727 LEAVE_STMT (hstmt, 728 trace_SQLParamOptions (TRACE_LEAVE, hstmt, crow, pirow)); 729} 730 731 732static SQLRETURN 733SQLSetScrollOptions_Internal ( 734 SQLHSTMT hstmt, 735 SQLUSMALLINT fConcurrency, 736 SQLLEN crowKeyset, 737 SQLUSMALLINT crowRowset) 738{ 739 STMT (pstmt, hstmt); 740 CONN (pdbc, pstmt->hdbc); 741 HPROC hproc = SQL_NULL_HPROC; 742 sqlstcode_t sqlstat = en_00000; 743 SQLRETURN retcode = SQL_SUCCESS; 744 SQLUINTEGER odbc_ver = ((GENV_t *) pdbc->genv)->odbc_ver; 745 SQLUINTEGER dodbc_ver = ((ENV_t *) pdbc->henv)->dodbc_ver; 746 747 for (;;) 748 { 749 if (crowRowset == (UWORD) 0) 750 { 751 sqlstat = en_S1107; 752 break; 753 } 754 755 if (crowKeyset > (SDWORD) 0L && crowKeyset < (SDWORD) crowRowset) 756 { 757 sqlstat = en_S1107; 758 break; 759 } 760 761 if (crowKeyset < 1) 762 { 763 if (crowKeyset != SQL_SCROLL_FORWARD_ONLY 764 && crowKeyset != SQL_SCROLL_STATIC 765 && crowKeyset != SQL_SCROLL_KEYSET_DRIVEN 766 && crowKeyset != SQL_SCROLL_DYNAMIC) 767 { 768 sqlstat = en_S1107; 769 break; 770 } 771 } 772 773 if (fConcurrency != SQL_CONCUR_READ_ONLY 774 && fConcurrency != SQL_CONCUR_LOCK 775 && fConcurrency != SQL_CONCUR_ROWVER 776 && fConcurrency != SQL_CONCUR_VALUES) 777 { 778 sqlstat = en_S1108; 779 break; 780 } 781 782#if (ODBCVER < 0x0300) 783 if (pstmt->state != en_stmt_allocated) 784 { 785 sqlstat = en_S1010; 786 break; 787 } 788#endif 789 790 hproc = _iodbcdm_getproc (pstmt->hdbc, en_SetScrollOptions); 791 792 if (dodbc_ver == SQL_OV_ODBC3 && odbc_ver == SQL_OV_ODBC3) 793 hproc = SQL_NULL_HPROC; 794 795 if (hproc != SQL_NULL_HPROC) 796 { 797 CALL_DRIVER (pstmt->hdbc, pstmt, retcode, hproc, 798 (pstmt->dhstmt, fConcurrency, crowKeyset, crowRowset)); 799 } 800 else 801 { 802#if (ODBCVER >= 0x0300) 803 SQLINTEGER InfoValue, InfoType, Value; 804 HPROC hproc1 = _iodbcdm_getproc (pstmt->hdbc, en_SetStmtAttr); 805 HPROC hproc2 = _iodbcdm_getproc (pstmt->hdbc, en_GetInfo); 806 807 if (hproc1 == SQL_NULL_HPROC || hproc2 == SQL_NULL_HPROC) 808 { 809 PUSHSQLERR (pstmt->herr, en_IM001); 810 return SQL_ERROR; 811 } 812 813 switch (crowKeyset) 814 { 815 case SQL_SCROLL_FORWARD_ONLY: 816 InfoType = SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2; 817 Value = SQL_CURSOR_FORWARD_ONLY; 818 break; 819 820 case SQL_SCROLL_STATIC: 821 InfoType = SQL_STATIC_CURSOR_ATTRIBUTES2; 822 Value = SQL_CURSOR_STATIC; 823 break; 824 825 case SQL_SCROLL_DYNAMIC: 826 InfoType = SQL_DYNAMIC_CURSOR_ATTRIBUTES2; 827 Value = SQL_CURSOR_DYNAMIC; 828 break; 829 830 case SQL_SCROLL_KEYSET_DRIVEN: 831 default: 832 InfoType = SQL_KEYSET_CURSOR_ATTRIBUTES2; 833 Value = SQL_CURSOR_KEYSET_DRIVEN; 834 break; 835 } 836 837 CALL_DRIVER (pstmt->hdbc, pdbc, retcode, hproc2, 838 (pdbc->dhdbc, InfoType, &InfoValue, 0, NULL)); 839 840 if (retcode != SQL_SUCCESS) 841 { 842 return retcode; 843 } 844 845 switch (fConcurrency) 846 { 847 case SQL_CONCUR_READ_ONLY: 848 if (!(InfoValue & SQL_CA2_READ_ONLY_CONCURRENCY)) 849 { 850 PUSHSQLERR (pstmt->herr, en_S1C00); 851 return SQL_ERROR; 852 } 853 break; 854 855 case SQL_CONCUR_LOCK: 856 if (!(InfoValue & SQL_CA2_LOCK_CONCURRENCY)) 857 { 858 PUSHSQLERR (pstmt->herr, en_S1C00); 859 return SQL_ERROR; 860 } 861 break; 862 863 case SQL_CONCUR_ROWVER: 864 if (!(InfoValue & SQL_CA2_OPT_ROWVER_CONCURRENCY)) 865 { 866 PUSHSQLERR (pstmt->herr, en_S1C00); 867 return SQL_ERROR; 868 } 869 break; 870 871 case SQL_CONCUR_VALUES: 872 if (!(InfoValue & SQL_CA2_OPT_VALUES_CONCURRENCY)) 873 { 874 PUSHSQLERR (pstmt->herr, en_S1C00); 875 return SQL_ERROR; 876 } 877 break; 878 } 879 880 CALL_DRIVER (pstmt->hdbc, pstmt, retcode, hproc1, 881 (pstmt->dhstmt, SQL_ATTR_CURSOR_TYPE, Value, 0)); 882 883 if (retcode != SQL_SUCCESS) 884 return retcode; 885 886 CALL_DRIVER (pstmt->hdbc, pstmt, retcode, hproc1, 887 (pstmt->dhstmt, SQL_ATTR_CONCURRENCY, fConcurrency, 0)); 888 889 if (retcode != SQL_SUCCESS) 890 return retcode; 891 892 if (crowKeyset > 0) 893 { 894 CALL_DRIVER (pstmt->hdbc, pstmt, retcode, hproc1, 895 (pstmt->dhstmt, SQL_ATTR_KEYSET_SIZE, crowKeyset, 0)); 896 897 if (retcode != SQL_SUCCESS) 898 return retcode; 899 } 900 901 CALL_DRIVER (pstmt->hdbc, pstmt, retcode, hproc1, 902 (pstmt->dhstmt, SQL_ROWSET_SIZE, crowRowset, 0)); 903 904 if (retcode != SQL_SUCCESS) 905 return retcode; 906#else 907 sqlstat = en_IM001; 908 break; 909#endif 910 } 911 912 sqlstat = en_00000; 913 if (1) /* turn off solaris warning message */ 914 break; 915 } 916 917 if (sqlstat != en_00000) 918 { 919 PUSHSQLERR (pstmt->herr, sqlstat); 920 921 return SQL_ERROR; 922 } 923 924 return retcode; 925} 926 927 928SQLRETURN SQL_API 929SQLSetScrollOptions ( 930 SQLHSTMT hstmt, 931 SQLUSMALLINT fConcurrency, 932 SQLLEN crowKeyset, 933 SQLUSMALLINT crowRowset) 934{ 935 ENTER_STMT (hstmt, 936 trace_SQLSetScrollOptions (TRACE_ENTER, 937 hstmt, 938 fConcurrency, 939 crowKeyset, 940 crowRowset)); 941 942 retcode = SQLSetScrollOptions_Internal ( 943 hstmt, 944 fConcurrency, 945 crowKeyset, 946 crowRowset); 947 948 LEAVE_STMT (hstmt, 949 trace_SQLSetScrollOptions (TRACE_LEAVE, 950 hstmt, 951 fConcurrency, 952 crowKeyset, 953 crowRowset)); 954} 955 956 957SQLRETURN SQL_API 958SQLSetParam ( 959 SQLHSTMT hstmt, 960 SQLUSMALLINT ipar, 961 SQLSMALLINT fCType, 962 SQLSMALLINT fSqlType, 963 SQLULEN cbColDef, 964 SQLSMALLINT ibScale, 965 SQLPOINTER rgbValue, 966 SQLLEN * pcbValue) 967{ 968 return SQLBindParameter (hstmt, 969 ipar, 970 (SWORD) SQL_PARAM_INPUT_OUTPUT, 971 fCType, 972 fSqlType, 973 cbColDef, 974 ibScale, 975 rgbValue, 976 SQL_SETPARAM_VALUE_MAX, 977 pcbValue); 978} 979