1/* 2 * fetch.c 3 * 4 * $Id: fetch.c 2613 1999-06-01 15:32:12Z VZ $ 5 * 6 * Fetch query result 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 41RETCODE SQL_API 42SQLFetch (HSTMT hstmt) 43{ 44 STMT_t FAR *pstmt = (STMT_t FAR *) hstmt; 45 HPROC hproc = SQL_NULL_HPROC; 46 RETCODE retcode; 47 48 if (hstmt == SQL_NULL_HSTMT || pstmt->hdbc == SQL_NULL_HDBC) 49 { 50 return SQL_INVALID_HANDLE; 51 } 52 53 /* check state */ 54 if (pstmt->asyn_on == en_NullProc) 55 { 56 switch (pstmt->state) 57 { 58 case en_stmt_allocated: 59 case en_stmt_prepared: 60 case en_stmt_xfetched: 61 case en_stmt_needdata: 62 case en_stmt_mustput: 63 case en_stmt_canput: 64 PUSHSQLERR (pstmt->herr, en_S1010); 65 return SQL_ERROR; 66 67 default: 68 break; 69 } 70 } 71 else if (pstmt->asyn_on != en_Fetch) 72 { 73 PUSHSQLERR (pstmt->herr, en_S1010); 74 return SQL_ERROR; 75 } 76 77 hproc = _iodbcdm_getproc (pstmt->hdbc, en_Fetch); 78 79 if (hproc == SQL_NULL_HPROC) 80 { 81 PUSHSQLERR (pstmt->herr, en_IM001); 82 83 return SQL_ERROR; 84 } 85 86 CALL_DRIVER (pstmt->hdbc, retcode, hproc, en_Fetch, 87 (pstmt->dhstmt)) 88 89 /* state transition */ 90 if (pstmt->asyn_on == en_Fetch) 91 { 92 switch (retcode) 93 { 94 case SQL_SUCCESS: 95 case SQL_SUCCESS_WITH_INFO: 96 case SQL_NO_DATA_FOUND: 97 case SQL_ERROR: 98 pstmt->asyn_on = en_NullProc; 99 break; 100 101 case SQL_STILL_EXECUTING: 102 default: 103 return retcode; 104 } 105 } 106 107 switch (pstmt->state) 108 { 109 case en_stmt_cursoropen: 110 case en_stmt_fetched: 111 switch (retcode) 112 { 113 case SQL_SUCCESS: 114 case SQL_SUCCESS_WITH_INFO: 115 pstmt->state = en_stmt_fetched; 116 pstmt->cursor_state = en_stmt_cursor_fetched; 117 break; 118 119 case SQL_NO_DATA_FOUND: 120 if (pstmt->prep_state) 121 { 122 pstmt->state = en_stmt_prepared; 123 } 124 else 125 { 126 127 pstmt->state = en_stmt_allocated; 128 } 129 pstmt->cursor_state = en_stmt_cursor_no; 130 break; 131 132 case SQL_STILL_EXECUTING: 133 pstmt->asyn_on = en_Fetch; 134 break; 135 136 default: 137 break; 138 } 139 break; 140 141 default: 142 break; 143 } 144 145 return retcode; 146} 147 148 149RETCODE SQL_API 150SQLExtendedFetch ( 151 HSTMT hstmt, 152 UWORD fFetchType, 153 SDWORD irow, 154 UDWORD FAR * pcrow, 155 UWORD FAR * rgfRowStatus) 156{ 157 STMT_t FAR *pstmt = (STMT_t FAR *) hstmt; 158 HPROC hproc = SQL_NULL_HPROC; 159 RETCODE retcode; 160 161 if (hstmt == SQL_NULL_HSTMT || pstmt->hdbc == SQL_NULL_HDBC) 162 { 163 return SQL_INVALID_HANDLE; 164 } 165 166 /* check fetch type */ 167 if (fFetchType < SQL_FETCH_NEXT || fFetchType > SQL_FETCH_BOOKMARK) 168 { 169 /* Unlike MS driver manager(i.e. DM), 170 * we don't check driver's ODBC version 171 * against SQL_FETCH_RESUME (only 1.0) 172 * and SQL_FETCH_BOOKMARK (only 2.0). 173 */ 174 PUSHSQLERR (pstmt->herr, en_S1106); 175 176 return SQL_ERROR; 177 } 178 179 /* check state */ 180 if (pstmt->asyn_on == en_NullProc) 181 { 182 switch (pstmt->state) 183 { 184 case en_stmt_allocated: 185 case en_stmt_prepared: 186 case en_stmt_fetched: 187 case en_stmt_needdata: 188 case en_stmt_mustput: 189 case en_stmt_canput: 190 PUSHSQLERR (pstmt->herr, en_S1010); 191 return SQL_ERROR; 192 193 default: 194 break; 195 } 196 } 197 else if (pstmt->asyn_on != en_ExtendedFetch) 198 { 199 PUSHSQLERR (pstmt->herr, en_S1010); 200 return SQL_ERROR; 201 } 202 203 hproc = _iodbcdm_getproc (pstmt->hdbc, en_ExtendedFetch); 204 205 if (hproc == SQL_NULL_HPROC) 206 { 207 PUSHSQLERR (pstmt->herr, en_IM001); 208 209 return SQL_ERROR; 210 } 211 212 CALL_DRIVER (pstmt->hdbc, retcode, hproc, en_ExtendedFetch, 213 (pstmt->dhstmt, fFetchType, irow, pcrow, rgfRowStatus)) 214 215 /* state transition */ 216 if (pstmt->asyn_on == en_ExtendedFetch) 217 { 218 switch (retcode) 219 { 220 case SQL_SUCCESS: 221 case SQL_SUCCESS_WITH_INFO: 222 case SQL_NO_DATA_FOUND: 223 case SQL_ERROR: 224 pstmt->asyn_on = en_NullProc; 225 break; 226 227 case SQL_STILL_EXECUTING: 228 default: 229 return retcode; 230 } 231 } 232 233 switch (pstmt->state) 234 { 235 case en_stmt_cursoropen: 236 case en_stmt_xfetched: 237 switch (retcode) 238 { 239 case SQL_SUCCESS: 240 case SQL_SUCCESS_WITH_INFO: 241 case SQL_NO_DATA_FOUND: 242 pstmt->state = en_stmt_xfetched; 243 pstmt->cursor_state = en_stmt_cursor_xfetched; 244 break; 245 246 case SQL_STILL_EXECUTING: 247 pstmt->asyn_on = en_ExtendedFetch; 248 break; 249 250 default: 251 break; 252 } 253 break; 254 255 default: 256 break; 257 } 258 259 return retcode; 260} 261 262 263RETCODE SQL_API 264SQLGetData ( 265 HSTMT hstmt, 266 UWORD icol, 267 SWORD fCType, 268 PTR rgbValue, 269 SDWORD cbValueMax, 270 SDWORD FAR * pcbValue) 271{ 272 STMT_t FAR *pstmt = (STMT_t FAR *) hstmt; 273 HPROC hproc; 274 RETCODE retcode; 275 int sqlstat = en_00000; 276 277 if (hstmt == SQL_NULL_HSTMT || pstmt->hdbc == SQL_NULL_HDBC) 278 { 279 return SQL_INVALID_HANDLE; 280 } 281 282 /* check argument */ 283 if (rgbValue == NULL) 284 { 285 sqlstat = en_S1009; 286 } 287 else if (cbValueMax < 0) 288 { 289 sqlstat = en_S1090; 290 } 291 else 292 { 293 switch (fCType) 294 { 295 case SQL_C_DEFAULT: 296 case SQL_C_CHAR: 297 case SQL_C_BINARY: 298 case SQL_C_BIT: 299 case SQL_C_TINYINT: 300 case SQL_C_STINYINT: 301 case SQL_C_UTINYINT: 302 case SQL_C_SHORT: 303 case SQL_C_SSHORT: 304 case SQL_C_USHORT: 305 case SQL_C_LONG: 306 case SQL_C_SLONG: 307 case SQL_C_ULONG: 308 case SQL_C_FLOAT: 309 case SQL_C_DOUBLE: 310 case SQL_C_DATE: 311 case SQL_C_TIME: 312 case SQL_C_TIMESTAMP: 313 break; 314 315 default: 316 sqlstat = en_S1003; 317 break; 318 } 319 } 320 321 if (sqlstat != en_00000) 322 { 323 PUSHSQLERR (pstmt->herr, sqlstat); 324 325 return SQL_ERROR; 326 } 327 328 /* check state */ 329 if (pstmt->asyn_on == en_NullProc) 330 { 331 switch (pstmt->state) 332 { 333 case en_stmt_allocated: 334 case en_stmt_prepared: 335 case en_stmt_needdata: 336 case en_stmt_mustput: 337 case en_stmt_canput: 338 sqlstat = en_S1010; 339 break; 340 341 case en_stmt_executed: 342 case en_stmt_cursoropen: 343 sqlstat = en_24000; 344 break; 345 346 default: 347 break; 348 } 349 } 350 else if (pstmt->asyn_on != en_GetData) 351 { 352 sqlstat = en_S1010; 353 } 354 355 if (sqlstat != en_00000) 356 { 357 PUSHSQLERR (pstmt->herr, sqlstat); 358 359 return SQL_ERROR; 360 } 361 362 /* call driver */ 363 hproc = _iodbcdm_getproc (pstmt->hdbc, en_GetData); 364 365 if (hproc == SQL_NULL_HPROC) 366 { 367 PUSHSQLERR (pstmt->herr, en_IM001); 368 369 return SQL_ERROR; 370 } 371 372 CALL_DRIVER (pstmt->hdbc, retcode, hproc, en_GetData, 373 (pstmt->dhstmt, icol, fCType, rgbValue, cbValueMax, pcbValue)) 374 375 /* state transition */ 376 if (pstmt->asyn_on == en_GetData) 377 { 378 switch (retcode) 379 { 380 case SQL_SUCCESS: 381 case SQL_SUCCESS_WITH_INFO: 382 case SQL_NO_DATA_FOUND: 383 case SQL_ERROR: 384 pstmt->asyn_on = en_NullProc; 385 break; 386 387 case SQL_STILL_EXECUTING: 388 default: 389 return retcode; 390 } 391 } 392 393 switch (pstmt->state) 394 { 395 case en_stmt_fetched: 396 case en_stmt_xfetched: 397 if (retcode == SQL_STILL_EXECUTING) 398 { 399 pstmt->asyn_on = en_GetData; 400 break; 401 } 402 break; 403 404 default: 405 break; 406 } 407 408 return retcode; 409} 410 411 412RETCODE SQL_API 413SQLMoreResults (HSTMT hstmt) 414{ 415 STMT_t FAR *pstmt = (STMT_t FAR *) hstmt; 416 HPROC hproc; 417 RETCODE retcode; 418 419 if (hstmt == SQL_NULL_HSTMT 420 || pstmt->hdbc == SQL_NULL_HDBC) 421 { 422 return SQL_INVALID_HANDLE; 423 } 424 425 /* check state */ 426 if (pstmt->asyn_on == en_NullProc) 427 { 428 switch (pstmt->state) 429 { 430 case en_stmt_allocated: 431 case en_stmt_prepared: 432 return SQL_NO_DATA_FOUND; 433 434 case en_stmt_needdata: 435 case en_stmt_mustput: 436 case en_stmt_canput: 437 PUSHSQLERR (pstmt->herr, en_S1010); 438 return SQL_ERROR; 439 440 default: 441 break; 442 } 443 } 444 else if (pstmt->asyn_on != en_MoreResults) 445 { 446 PUSHSQLERR (pstmt->herr, en_S1010); 447 448 return SQL_ERROR; 449 } 450 451 /* call driver */ 452 hproc = _iodbcdm_getproc (pstmt->hdbc, en_MoreResults); 453 454 if (hproc == SQL_NULL_HPROC) 455 { 456 PUSHSQLERR (pstmt->herr, en_IM001); 457 458 return SQL_ERROR; 459 } 460 461 CALL_DRIVER (pstmt->hdbc, retcode, hproc, en_MoreResults, 462 (pstmt->dhstmt)) 463 464 /* state transition */ 465 if (pstmt->asyn_on == en_MoreResults) 466 { 467 switch (retcode) 468 { 469 case SQL_SUCCESS: 470 case SQL_SUCCESS_WITH_INFO: 471 case SQL_NO_DATA_FOUND: 472 case SQL_ERROR: 473 pstmt->asyn_on = en_NullProc; 474 break; 475 476 case SQL_STILL_EXECUTING: 477 default: 478 return retcode; 479 } 480 } 481 482 switch (pstmt->state) 483 { 484 case en_stmt_allocated: 485 case en_stmt_prepared: 486 /* driver should return SQL_NO_DATA_FOUND */ 487 break; 488 489 case en_stmt_executed: 490 if (retcode == SQL_NO_DATA_FOUND) 491 { 492 if (pstmt->prep_state) 493 { 494 pstmt->state = en_stmt_prepared; 495 } 496 else 497 { 498 pstmt->state = en_stmt_allocated; 499 } 500 } 501 else if (retcode == SQL_STILL_EXECUTING) 502 { 503 pstmt->asyn_on = en_MoreResults; 504 } 505 break; 506 507 case en_stmt_cursoropen: 508 case en_stmt_fetched: 509 case en_stmt_xfetched: 510 if (retcode == SQL_SUCCESS) 511 { 512 break; 513 } 514 else if (retcode == SQL_NO_DATA_FOUND) 515 { 516 if (pstmt->prep_state) 517 { 518 pstmt->state = en_stmt_prepared; 519 } 520 else 521 { 522 pstmt->state = en_stmt_allocated; 523 } 524 } 525 else if (retcode == SQL_STILL_EXECUTING) 526 { 527 pstmt->asyn_on = en_MoreResults; 528 } 529 break; 530 531 default: 532 break; 533 } 534 535 return retcode; 536} 537 538 539RETCODE SQL_API 540SQLSetPos ( 541 HSTMT hstmt, 542 UWORD irow, 543 UWORD fOption, 544 UWORD fLock) 545{ 546 STMT_t FAR *pstmt = (STMT_t FAR *) hstmt; 547 HPROC hproc; 548 RETCODE retcode; 549 int sqlstat = en_00000; 550 551 if (hstmt == SQL_NULL_HSTMT || pstmt->hdbc == SQL_NULL_HDBC) 552 { 553 return SQL_INVALID_HANDLE; 554 } 555 556 /* check argument value */ 557 if (fOption > SQL_ADD || fLock > SQL_LOCK_UNLOCK) 558 { 559 PUSHSQLERR (pstmt->herr, en_S1009); 560 } 561 562 /* check state */ 563 if (pstmt->asyn_on == en_NullProc) 564 { 565 switch (pstmt->state) 566 { 567 case en_stmt_allocated: 568 case en_stmt_prepared: 569 case en_stmt_fetched: 570 case en_stmt_needdata: 571 case en_stmt_mustput: 572 case en_stmt_canput: 573 sqlstat = en_S1010; 574 break; 575 576 case en_stmt_executed: 577 case en_stmt_cursoropen: 578 sqlstat = en_24000; 579 break; 580 581 default: 582 break; 583 } 584 } 585 else if (pstmt->asyn_on != en_SetPos) 586 { 587 sqlstat = en_S1010; 588 } 589 590 if (sqlstat != en_00000) 591 { 592 PUSHSQLERR (pstmt->herr, sqlstat); 593 594 return SQL_ERROR; 595 } 596 597 /* call driver */ 598 hproc = _iodbcdm_getproc (pstmt->hdbc, en_SetPos); 599 600 if (hproc == SQL_NULL_HPROC) 601 { 602 PUSHSQLERR (pstmt->herr, en_IM001); 603 604 return SQL_ERROR; 605 } 606 607 CALL_DRIVER (pstmt->hdbc, retcode, hproc, en_SetPos, 608 (pstmt->dhstmt, irow, fOption, fLock)) 609 610 /* state transition */ 611 if (pstmt->asyn_on == en_SetPos) 612 { 613 switch (retcode) 614 { 615 case SQL_SUCCESS: 616 case SQL_SUCCESS_WITH_INFO: 617 case SQL_NEED_DATA: 618 case SQL_ERROR: 619 pstmt->asyn_on = en_NullProc; 620 break; 621 622 case SQL_STILL_EXECUTING: 623 default: 624 return retcode; 625 } 626 } 627 628 /* now, the only possible init state is 'xfetched' */ 629 switch (retcode) 630 { 631 case SQL_SUCCESS: 632 case SQL_SUCCESS_WITH_INFO: 633 break; 634 635 case SQL_NEED_DATA: 636 pstmt->state = en_stmt_needdata; 637 pstmt->need_on = en_SetPos; 638 break; 639 640 case SQL_STILL_EXECUTING: 641 pstmt->asyn_on = en_SetPos; 642 break; 643 644 default: 645 break; 646 } 647 648 return retcode; 649} 650