1/* 2 * execute.c 3 * 4 * $Id: execute.c 2613 1999-06-01 15:32:12Z VZ $ 5 * 6 * Invoke a query 7 * 8 * The iODBC driver manager. 9 * 10 * Copyright (C) 1995 by Ke Jin <kejin@empress.com> 11 * 12 * This library is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU Library General Public 14 * License as published by the Free Software Foundation; either 15 * version 2 of the License, or (at your option) any later version. 16 * 17 * This library is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 * Library General Public License for more details. 21 * 22 * You should have received a copy of the GNU Library General Public 23 * License along with this library; if not, write to the Free 24 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 25 */ 26 27#include "config.h" 28 29#include "isql.h" 30#include "isqlext.h" 31 32#include "dlproc.h" 33 34#include "herr.h" 35#include "henv.h" 36#include "hdbc.h" 37#include "hstmt.h" 38 39#include "itrace.h" 40 41static void 42do_cursoropen (STMT_t FAR * pstmt) 43{ 44 RETCODE retcode; 45 SWORD ncol; 46 47 pstmt->state = en_stmt_executed; 48 49 retcode = SQLNumResultCols (pstmt, &ncol); 50 51 if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) 52 { 53 if (ncol) 54 { 55 pstmt->state = en_stmt_cursoropen; 56 pstmt->cursor_state = en_stmt_cursor_opened; 57 } 58 else 59 { 60 pstmt->state = en_stmt_executed; 61 pstmt->cursor_state = en_stmt_cursor_no; 62 } 63 } 64} 65 66 67RETCODE SQL_API 68SQLExecute (HSTMT hstmt) 69{ 70 STMT_t FAR *pstmt = (STMT_t FAR *) hstmt; 71 HPROC hproc = SQL_NULL_HPROC; 72 RETCODE retcode; 73 74 int sqlstat = en_00000; 75 76 if (hstmt == SQL_NULL_HSTMT || pstmt->hdbc == SQL_NULL_HDBC) 77 { 78 return SQL_INVALID_HANDLE; 79 } 80 81 /* check state */ 82 if (pstmt->asyn_on == en_NullProc) 83 { 84 switch (pstmt->state) 85 { 86 case en_stmt_allocated: 87 sqlstat = en_S1010; 88 break; 89 90 case en_stmt_executed: 91 if (!pstmt->prep_state) 92 { 93 sqlstat = en_S1010; 94 } 95 break; 96 97 case en_stmt_cursoropen: 98 if (!pstmt->prep_state) 99 { 100 sqlstat = en_S1010; 101 } 102 break; 103 104 case en_stmt_fetched: 105 case en_stmt_xfetched: 106 if (!pstmt->prep_state) 107 { 108 sqlstat = en_S1010; 109 } 110 else 111 { 112 sqlstat = en_24000; 113 } 114 break; 115 116 case en_stmt_needdata: 117 case en_stmt_mustput: 118 case en_stmt_canput: 119 sqlstat = en_S1010; 120 break; 121 122 default: 123 break; 124 } 125 } 126 else if (pstmt->asyn_on != en_Execute) 127 { 128 sqlstat = en_S1010; 129 } 130 131 if (sqlstat == en_00000) 132 { 133 hproc = _iodbcdm_getproc (pstmt->hdbc, en_Execute); 134 135 if (hproc == SQL_NULL_HPROC) 136 { 137 sqlstat = en_IM001; 138 } 139 } 140 141 if (sqlstat != en_00000) 142 { 143 PUSHSQLERR (pstmt->herr, sqlstat); 144 145 return SQL_ERROR; 146 } 147 148 CALL_DRIVER (pstmt->hdbc, retcode, hproc, en_Execute, 149 (pstmt->dhstmt)) 150 151 /* stmt state transition */ 152 if (pstmt->asyn_on == en_Execute) 153 { 154 switch (retcode) 155 { 156 case SQL_SUCCESS: 157 case SQL_SUCCESS_WITH_INFO: 158 case SQL_NEED_DATA: 159 case SQL_ERROR: 160 pstmt->asyn_on = en_NullProc; 161 break; 162 163 case SQL_STILL_EXECUTING: 164 default: 165 return retcode; 166 } 167 } 168 169 switch (pstmt->state) 170 { 171 case en_stmt_prepared: 172 switch (retcode) 173 { 174 case SQL_SUCCESS: 175 case SQL_SUCCESS_WITH_INFO: 176 do_cursoropen (hstmt); 177 break; 178 179 case SQL_NEED_DATA: 180 pstmt->state = en_stmt_needdata; 181 pstmt->need_on = en_Execute; 182 break; 183 184 case SQL_STILL_EXECUTING: 185 pstmt->asyn_on = en_Execute; 186 break; 187 188 default: 189 break; 190 } 191 break; 192 193 case en_stmt_executed: 194 switch (retcode) 195 { 196 case SQL_ERROR: 197 pstmt->state = en_stmt_allocated; 198 pstmt->cursor_state = en_stmt_cursor_no; 199 pstmt->prep_state = 0; 200 break; 201 202 case SQL_NEED_DATA: 203 pstmt->state = en_stmt_needdata; 204 pstmt->need_on = en_Execute; 205 break; 206 207 case SQL_STILL_EXECUTING: 208 pstmt->asyn_on = en_Execute; 209 break; 210 211 default: 212 break; 213 } 214 break; 215 216 default: 217 break; 218 } 219 220 return retcode; 221} 222 223 224RETCODE SQL_API 225SQLExecDirect ( 226 HSTMT hstmt, 227 UCHAR FAR * szSqlStr, 228 SDWORD cbSqlStr) 229{ 230 STMT_t FAR *pstmt = (STMT_t FAR *) hstmt; 231 HPROC hproc = SQL_NULL_HPROC; 232 233 int sqlstat = en_00000; 234 RETCODE retcode = SQL_SUCCESS; 235 236 if (hstmt == SQL_NULL_HSTMT || pstmt->hdbc == SQL_NULL_HDBC) 237 { 238 return SQL_INVALID_HANDLE; 239 } 240 241 /* check arguments */ 242 if (szSqlStr == NULL) 243 { 244 sqlstat = en_S1009; 245 } 246 else if (cbSqlStr < 0 && cbSqlStr != SQL_NTS) 247 { 248 sqlstat = en_S1090; 249 } 250 251 if (sqlstat != en_00000) 252 { 253 PUSHSQLERR (pstmt->herr, sqlstat); 254 255 return SQL_ERROR; 256 } 257 258 /* check state */ 259 if (pstmt->asyn_on == en_NullProc) 260 { 261 switch (pstmt->state) 262 { 263 case en_stmt_fetched: 264 case en_stmt_xfetched: 265 sqlstat = en_24000; 266 break; 267 268 case en_stmt_needdata: 269 case en_stmt_mustput: 270 case en_stmt_canput: 271 sqlstat = en_S1010; 272 break; 273 274 default: 275 break; 276 } 277 } 278 else if (pstmt->asyn_on != en_ExecDirect) 279 { 280 sqlstat = en_S1010; 281 } 282 283 if (sqlstat != en_00000) 284 { 285 PUSHSQLERR (pstmt->herr, sqlstat); 286 287 return SQL_ERROR; 288 } 289 290 hproc = _iodbcdm_getproc (pstmt->hdbc, en_ExecDirect); 291 292 if (hproc == SQL_NULL_HPROC) 293 { 294 PUSHSQLERR (pstmt->herr, en_IM001); 295 296 return SQL_ERROR; 297 } 298 299 CALL_DRIVER (pstmt->hdbc, retcode, hproc, en_ExecDirect, 300 (pstmt->dhstmt, szSqlStr, cbSqlStr)) 301 302 /* stmt state transition */ 303 if (pstmt->asyn_on == en_ExecDirect) 304 { 305 switch (retcode) 306 { 307 case SQL_SUCCESS: 308 case SQL_SUCCESS_WITH_INFO: 309 case SQL_NEED_DATA: 310 case SQL_ERROR: 311 pstmt->asyn_on = en_NullProc; 312 break; 313 314 case SQL_STILL_EXECUTING: 315 default: 316 return retcode; 317 } 318 } 319 320 if (pstmt->state <= en_stmt_executed) 321 { 322 switch (retcode) 323 { 324 case SQL_SUCCESS: 325 case SQL_SUCCESS_WITH_INFO: 326 do_cursoropen (hstmt); 327 break; 328 329 case SQL_NEED_DATA: 330 pstmt->state = en_stmt_needdata; 331 pstmt->need_on = en_ExecDirect; 332 break; 333 334 case SQL_STILL_EXECUTING: 335 pstmt->asyn_on = en_ExecDirect; 336 break; 337 338 case SQL_ERROR: 339 pstmt->state = en_stmt_allocated; 340 pstmt->cursor_state = en_stmt_cursor_no; 341 pstmt->prep_state = 0; 342 break; 343 344 default: 345 break; 346 } 347 } 348 349 return retcode; 350} 351 352 353RETCODE SQL_API 354SQLPutData ( 355 HSTMT hstmt, 356 PTR rgbValue, 357 SDWORD cbValue) 358{ 359 STMT_t FAR *pstmt = (STMT_t FAR *) hstmt; 360 HPROC hproc; 361 RETCODE retcode; 362 363 if (hstmt == SQL_NULL_HSTMT || pstmt->hdbc == SQL_NULL_HDBC) 364 { 365 return SQL_INVALID_HANDLE; 366 } 367 368 /* check argument value */ 369 if (rgbValue == NULL && 370 (cbValue != SQL_DEFAULT_PARAM && cbValue != SQL_NULL_DATA)) 371 { 372 PUSHSQLERR (pstmt->herr, en_S1009); 373 374 return SQL_ERROR; 375 } 376 377 /* check state */ 378 if (pstmt->asyn_on == en_NullProc) 379 { 380 if (pstmt->state <= en_stmt_xfetched) 381 { 382 PUSHSQLERR (pstmt->herr, en_S1010); 383 384 return SQL_ERROR; 385 } 386 } 387 else if (pstmt->asyn_on != en_PutData) 388 { 389 PUSHSQLERR (pstmt->herr, en_S1010); 390 391 return SQL_ERROR; 392 } 393 394 /* call driver */ 395 hproc = _iodbcdm_getproc (pstmt->hdbc, en_PutData); 396 397 if (hproc == SQL_NULL_HPROC) 398 { 399 PUSHSQLERR (pstmt->herr, en_IM001); 400 401 return SQL_ERROR; 402 } 403 404 CALL_DRIVER (pstmt->hdbc, retcode, hproc, en_PutData, 405 (pstmt->dhstmt, rgbValue, cbValue)) 406 407 /* state transition */ 408 if (pstmt->asyn_on == en_PutData) 409 { 410 switch (retcode) 411 { 412 case SQL_SUCCESS: 413 case SQL_SUCCESS_WITH_INFO: 414 case SQL_ERROR: 415 pstmt->asyn_on = en_NullProc; 416 break; 417 418 case SQL_STILL_EXECUTING: 419 default: 420 return retcode; 421 } 422 } 423 424 /* must in mustput or canput states */ 425 switch (retcode) 426 { 427 case SQL_SUCCESS: 428 case SQL_SUCCESS_WITH_INFO: 429 pstmt->state = en_stmt_canput; 430 break; 431 432 case SQL_ERROR: 433 switch (pstmt->need_on) 434 { 435 case en_ExecDirect: 436 pstmt->state = en_stmt_allocated; 437 pstmt->need_on = en_NullProc; 438 break; 439 440 case en_Execute: 441 if (pstmt->prep_state) 442 { 443 pstmt->state = en_stmt_prepared; 444 pstmt->need_on = en_NullProc; 445 } 446 break; 447 448 case en_SetPos: 449 /* Is this possible ???? */ 450 pstmt->state = en_stmt_xfetched; 451 break; 452 453 default: 454 break; 455 } 456 break; 457 458 case SQL_STILL_EXECUTING: 459 pstmt->asyn_on = en_PutData; 460 break; 461 462 default: 463 break; 464 } 465 466 return retcode; 467} 468 469 470RETCODE SQL_API 471SQLParamData ( 472 HSTMT hstmt, 473 PTR FAR * prgbValue) 474{ 475 STMT_t FAR *pstmt = (STMT_t FAR *) hstmt; 476 HPROC hproc; 477 RETCODE retcode; 478 479 if (hstmt == SQL_NULL_HSTMT || pstmt->hdbc == SQL_NULL_HDBC) 480 { 481 return SQL_INVALID_HANDLE; 482 } 483 484 /* check argument */ 485 486 /* check state */ 487 if (pstmt->asyn_on == en_NullProc) 488 { 489 if (pstmt->state <= en_stmt_xfetched) 490 { 491 PUSHSQLERR (pstmt->herr, en_S1010); 492 493 return SQL_ERROR; 494 } 495 } 496 else if (pstmt->asyn_on != en_ParamData) 497 { 498 PUSHSQLERR (pstmt->herr, en_S1010); 499 500 return SQL_ERROR; 501 } 502 503 /* call driver */ 504 hproc = _iodbcdm_getproc (pstmt->hdbc, en_ParamData); 505 506 if (hproc == SQL_NULL_HPROC) 507 { 508 PUSHSQLERR (pstmt->herr, en_IM001); 509 510 return SQL_ERROR; 511 } 512 513 CALL_DRIVER (pstmt->hdbc, retcode, hproc, en_ParamData, 514 (pstmt->dhstmt, prgbValue)) 515 516 /* state transition */ 517 if (pstmt->asyn_on == en_ParamData) 518 { 519 switch (retcode) 520 { 521 case SQL_SUCCESS: 522 case SQL_SUCCESS_WITH_INFO: 523 case SQL_ERROR: 524 pstmt->asyn_on = en_NullProc; 525 break; 526 527 case SQL_STILL_EXECUTING: 528 default: 529 return retcode; 530 } 531 } 532 533 if (pstmt->state < en_stmt_needdata) 534 { 535 return retcode; 536 } 537 538 switch (retcode) 539 { 540 case SQL_ERROR: 541 switch (pstmt->need_on) 542 { 543 case en_ExecDirect: 544 pstmt->state = en_stmt_allocated; 545 break; 546 547 case en_Execute: 548 pstmt->state = en_stmt_prepared; 549 break; 550 551 case en_SetPos: 552 pstmt->state = en_stmt_xfetched; 553 pstmt->cursor_state 554 = en_stmt_cursor_xfetched; 555 break; 556 557 default: 558 break; 559 } 560 pstmt->need_on = en_NullProc; 561 break; 562 563 case SQL_SUCCESS: 564 case SQL_SUCCESS_WITH_INFO: 565 switch (pstmt->state) 566 { 567 case en_stmt_needdata: 568 pstmt->state = en_stmt_mustput; 569 break; 570 571 case en_stmt_canput: 572 switch (pstmt->need_on) 573 { 574 case en_SetPos: 575 pstmt->state 576 = en_stmt_xfetched; 577 pstmt->cursor_state 578 = en_stmt_cursor_xfetched; 579 break; 580 581 case en_ExecDirect: 582 case en_Execute: 583 do_cursoropen (hstmt); 584 break; 585 586 default: 587 break; 588 } 589 break; 590 591 default: 592 break; 593 } 594 pstmt->need_on = en_NullProc; 595 break; 596 597 case SQL_NEED_DATA: 598 pstmt->state = en_stmt_mustput; 599 break; 600 601 default: 602 break; 603 } 604 605 return retcode; 606} 607 608 609RETCODE SQL_API 610SQLNumParams ( 611 HSTMT hstmt, 612 SWORD FAR * pcpar) 613{ 614 STMT_t FAR *pstmt = (STMT_t FAR *) hstmt; 615 HPROC hproc; 616 RETCODE retcode; 617 618 if (hstmt == SQL_NULL_HSTMT || pstmt->hdbc == SQL_NULL_HDBC) 619 { 620 return SQL_INVALID_HANDLE; 621 } 622 623 /* check argument */ 624 625 /* check state */ 626 if (pstmt->asyn_on == en_NullProc) 627 { 628 switch (pstmt->state) 629 { 630 case en_stmt_allocated: 631 case en_stmt_needdata: 632 case en_stmt_mustput: 633 case en_stmt_canput: 634 PUSHSQLERR (pstmt->herr, en_S1010); 635 return SQL_ERROR; 636 637 default: 638 break; 639 } 640 } 641 else if (pstmt->asyn_on != en_NumParams) 642 { 643 PUSHSQLERR (pstmt->herr, en_S1010); 644 645 return SQL_ERROR; 646 } 647 648 /* call driver */ 649 hproc = _iodbcdm_getproc (pstmt->hdbc, en_NumParams); 650 651 if (hproc == SQL_NULL_HPROC) 652 { 653 PUSHSQLERR (pstmt->herr, en_IM001); 654 655 return SQL_ERROR; 656 } 657 658 CALL_DRIVER (pstmt->hdbc, retcode, hproc, en_NumParams, 659 (pstmt->dhstmt, pcpar)) 660 661 /* state transition */ 662 if (pstmt->asyn_on == en_NumParams) 663 { 664 switch (retcode) 665 { 666 case SQL_SUCCESS: 667 case SQL_SUCCESS_WITH_INFO: 668 case SQL_ERROR: 669 break; 670 671 default: 672 return retcode; 673 } 674 } 675 676 if (retcode == SQL_STILL_EXECUTING) 677 { 678 pstmt->asyn_on = en_NumParams; 679 } 680 681 return retcode; 682} 683 684 685RETCODE SQL_API 686SQLDescribeParam ( 687 HSTMT hstmt, 688 UWORD ipar, 689 SWORD FAR * pfSqlType, 690 UDWORD FAR * pcbColDef, 691 SWORD FAR * pibScale, 692 SWORD FAR * pfNullable) 693{ 694 STMT_t FAR *pstmt = (STMT_t FAR *) hstmt; 695 HPROC hproc; 696 RETCODE retcode; 697 698 if (hstmt == SQL_NULL_HSTMT || pstmt->hdbc == SQL_NULL_HDBC) 699 { 700 return SQL_INVALID_HANDLE; 701 } 702 703 /* check argument */ 704 if (ipar == 0) 705 { 706 PUSHSQLERR (pstmt->herr, en_S1093); 707 708 return SQL_ERROR; 709 } 710 711 /* check state */ 712 if (pstmt->asyn_on == en_NullProc) 713 { 714 switch (pstmt->state) 715 { 716 case en_stmt_allocated: 717 case en_stmt_needdata: 718 case en_stmt_mustput: 719 case en_stmt_canput: 720 PUSHSQLERR (pstmt->herr, en_S1010); 721 return SQL_ERROR; 722 723 default: 724 break; 725 } 726 } 727 else if (pstmt->asyn_on != en_DescribeParam) 728 { 729 PUSHSQLERR (pstmt->herr, en_S1010); 730 731 return SQL_ERROR; 732 } 733 734 /* call driver */ 735 hproc = _iodbcdm_getproc (pstmt->hdbc, en_DescribeParam); 736 737 if (hproc == SQL_NULL_HPROC) 738 { 739 PUSHSQLERR (pstmt->herr, en_IM001); 740 741 return SQL_ERROR; 742 } 743 744 CALL_DRIVER (pstmt->hdbc, retcode, hproc, en_DescribeParam, 745 (pstmt->dhstmt, ipar, pfSqlType, pcbColDef, pibScale, pfNullable)) 746 747 /* state transition */ 748 if (pstmt->asyn_on == en_DescribeParam) 749 { 750 switch (retcode) 751 { 752 case SQL_SUCCESS: 753 case SQL_SUCCESS_WITH_INFO: 754 case SQL_ERROR: 755 break; 756 757 default: 758 return retcode; 759 } 760 } 761 762 if (retcode == SQL_STILL_EXECUTING) 763 { 764 pstmt->asyn_on = en_DescribeParam; 765 } 766 767 return retcode; 768} 769