1/* 2 * hstmt.c 3 * 4 * $Id: hstmt.c 2613 1999-06-01 15:32:12Z VZ $ 5 * 6 * Query statement object management functions 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 42SQLAllocStmt ( 43 HDBC hdbc, 44 HSTMT FAR * phstmt) 45{ 46 DBC_t FAR *pdbc = (DBC_t FAR *) hdbc; 47 STMT_t FAR *pstmt = NULL; 48 HPROC hproc = SQL_NULL_HPROC; 49 RETCODE retcode = SQL_SUCCESS; 50 51#if (ODBCVER >= 0x0300) 52 if (hdbc == SQL_NULL_HDBC || pdbc->type != SQL_HANDLE_DBC) 53#else 54 if (hdbc == SQL_NULL_HDBC) 55#endif 56 { 57 return SQL_INVALID_HANDLE; 58 } 59 60 if (phstmt == NULL) 61 { 62 PUSHSQLERR (pdbc->herr, en_S1009); 63 64 return SQL_ERROR; 65 } 66 67 /* check state */ 68 switch (pdbc->state) 69 { 70 case en_dbc_connected: 71 case en_dbc_hstmt: 72 break; 73 74 case en_dbc_allocated: 75 case en_dbc_needdata: 76 PUSHSQLERR (pdbc->herr, en_08003); 77 *phstmt = SQL_NULL_HSTMT; 78 return SQL_ERROR; 79 80 default: 81 return SQL_INVALID_HANDLE; 82 } 83 84 pstmt = (STMT_t FAR *) MEM_ALLOC (sizeof (STMT_t)); 85 86 if (pstmt == NULL) 87 { 88 PUSHSQLERR (pdbc->herr, en_S1001); 89 *phstmt = SQL_NULL_HSTMT; 90 91 return SQL_ERROR; 92 } 93 94#if (ODBCVER >= 0x0300) 95 pstmt->type = SQL_HANDLE_STMT; 96#endif 97 98 /* initiate the object */ 99 pstmt->herr = SQL_NULL_HERR; 100 pstmt->hdbc = hdbc; 101 pstmt->state = en_stmt_allocated; 102 pstmt->cursor_state = en_stmt_cursor_no; 103 pstmt->prep_state = 0; 104 pstmt->asyn_on = en_NullProc; 105 pstmt->need_on = en_NullProc; 106 107 /* call driver's function */ 108 109#if (ODBCVER >= 0x0300) 110 hproc = _iodbcdm_getproc (hdbc, en_AllocHandle); 111 112 if (hproc) 113 { 114 CALL_DRIVER (pstmt->hdbc, hdbc, retcode, hproc, en_AllocHandle, 115 (SQL_HANDLE_STMT, pdbc->dhdbc, &(pstmt->dhstmt))) 116 } 117 else 118#endif 119 120 { 121 hproc = _iodbcdm_getproc (hdbc, en_AllocStmt); 122 123 if (hproc == SQL_NULL_HPROC) 124 { 125 PUSHSQLERR (pstmt->herr, en_IM001); 126 *phstmt = SQL_NULL_HSTMT; 127 MEM_FREE (pstmt); 128 129 return SQL_ERROR; 130 } 131 132 CALL_DRIVER (hdbc, retcode, hproc, en_AllocStmt, 133 (pdbc->dhdbc, &(pstmt->dhstmt))) 134 } 135 136 if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO) 137 { 138 *phstmt = SQL_NULL_HSTMT; 139 MEM_FREE (pstmt); 140 141 return retcode; 142 } 143 144 /* insert into list */ 145 pstmt->next = pdbc->hstmt; 146 pdbc->hstmt = pstmt; 147 148 *phstmt = (HSTMT) pstmt; 149 150 /* state transition */ 151 pdbc->state = en_dbc_hstmt; 152 153 return SQL_SUCCESS; 154} 155 156 157RETCODE 158_iodbcdm_dropstmt (HSTMT hstmt) 159{ 160 STMT_t FAR *pstmt = (STMT_t FAR *) hstmt; 161 STMT_t FAR *tpstmt; 162 DBC_t FAR *pdbc; 163 164 if (hstmt == SQL_NULL_HSTMT) 165 { 166 return SQL_INVALID_HANDLE; 167 } 168 169 pdbc = (DBC_t FAR *) (pstmt->hdbc); 170 171 for (tpstmt = (STMT_t FAR *) pdbc->hstmt; 172 tpstmt != NULL; 173 tpstmt = tpstmt->next) 174 { 175 if (tpstmt == pstmt) 176 { 177 pdbc->hstmt = (HSTMT) pstmt->next; 178 break; 179 } 180 181 if (tpstmt->next == pstmt) 182 { 183 tpstmt->next = pstmt->next; 184 break; 185 } 186 } 187 188 if (tpstmt == NULL) 189 { 190 return SQL_INVALID_HANDLE; 191 } 192 193 _iodbcdm_freesqlerrlist (pstmt->herr); 194 MEM_FREE (hstmt); 195 196 return SQL_SUCCESS; 197} 198 199 200RETCODE SQL_API 201SQLFreeStmt ( 202 HSTMT hstmt, 203 UWORD fOption) 204{ 205 STMT_t FAR *pstmt = (STMT_t FAR *) hstmt; 206 STMT_t FAR *tpstmt; 207 DBC_t FAR *pdbc; 208 209 HPROC hproc = SQL_NULL_HPROC; 210 RETCODE retcode; 211 212 if (hstmt == SQL_NULL_HSTMT || pstmt->hdbc == SQL_NULL_HDBC) 213 { 214 return SQL_INVALID_HANDLE; 215 } 216 217 pdbc = (DBC_t FAR *) (pstmt->hdbc); 218 219 /* check option */ 220 switch (fOption) 221 { 222 case SQL_DROP: 223 case SQL_CLOSE: 224 case SQL_UNBIND: 225 case SQL_RESET_PARAMS: 226 break; 227 228 default: 229 PUSHSQLERR (pstmt->herr, en_S1092); 230 return SQL_ERROR; 231 } 232 233 /* check state */ 234 if (pstmt->state >= en_stmt_needdata || pstmt->asyn_on != en_NullProc) 235 { 236 PUSHSQLERR (pstmt->herr, en_S1010); 237 238 return SQL_ERROR; 239 } 240 241 hproc = SQL_NULL_HPROC; 242 243#if (ODBCVER >= 0x0300) 244 if (fOption == SQL_DROP) 245 { 246 hproc = _iodbcdm_getproc (pstmt->hdbc, en_FreeHandle); 247 248 if (hproc) 249 { 250 CALL_DRIVER (pstmt->hdbc, retcode, hproc, en_FreeHandle, 251 (SQL_HANDLE_STMT, pstmt->dhstmt)) 252 } 253 } 254#endif 255 256 if (hproc == SQL_NULL_HPROC) 257 { 258 hproc = _iodbcdm_getproc (pstmt->hdbc, en_FreeStmt); 259 260 if (hproc == SQL_NULL_HPROC) 261 { 262 PUSHSQLERR (pstmt->herr, en_IM001); 263 264 return SQL_ERROR; 265 } 266 267 CALL_DRIVER (pstmt->hdbc, retcode, hproc, en_FreeStmt, 268 (pstmt->dhstmt, fOption)) 269 } 270 271 if (retcode != SQL_SUCCESS 272 && retcode != SQL_SUCCESS_WITH_INFO) 273 { 274 return retcode; 275 } 276 277 /* state transition */ 278 switch (fOption) 279 { 280 case SQL_DROP: 281 /* delet this object (ignore return) */ 282 _iodbcdm_dropstmt (hstmt); 283 break; 284 285 case SQL_CLOSE: 286 pstmt->cursor_state = en_stmt_cursor_no; 287 /* This means cursor name set by 288 * SQLSetCursorName() call will also 289 * be erased. 290 */ 291 292 switch (pstmt->state) 293 { 294 case en_stmt_allocated: 295 case en_stmt_prepared: 296 break; 297 298 case en_stmt_executed: 299 case en_stmt_cursoropen: 300 case en_stmt_fetched: 301 case en_stmt_xfetched: 302 if (pstmt->prep_state) 303 { 304 pstmt->state = 305 en_stmt_prepared; 306 } 307 else 308 { 309 pstmt->state = 310 en_stmt_allocated; 311 } 312 break; 313 314 default: 315 break; 316 } 317 break; 318 319 case SQL_UNBIND: 320 case SQL_RESET_PARAMS: 321 default: 322 break; 323 } 324 325 return retcode; 326} 327 328 329RETCODE SQL_API 330SQLSetStmtOption ( 331 HSTMT hstmt, 332 UWORD fOption, 333 UDWORD vParam) 334{ 335 STMT_t FAR *pstmt = (STMT_t FAR *) hstmt; 336 HPROC hproc; 337 int sqlstat = en_00000; 338 RETCODE retcode; 339 340 if (hstmt == SQL_NULL_HSTMT || pstmt->hdbc == SQL_NULL_HDBC) 341 { 342 return SQL_INVALID_HANDLE; 343 } 344 345 /* check option */ 346 if ( /* fOption < SQL_STMT_OPT_MIN || */ 347 fOption > SQL_STMT_OPT_MAX) 348 { 349 PUSHSQLERR (pstmt->herr, en_S1092); 350 351 return SQL_ERROR; 352 } 353 354 if (fOption == SQL_CONCURRENCY 355 || fOption == SQL_CURSOR_TYPE 356 || fOption == SQL_SIMULATE_CURSOR 357 || fOption == SQL_USE_BOOKMARKS) 358 { 359 if (pstmt->asyn_on != en_NullProc) 360 { 361 if (pstmt->prep_state) 362 { 363 sqlstat = en_S1011; 364 } 365 } 366 else 367 { 368 switch (pstmt->state) 369 { 370 case en_stmt_prepared: 371 sqlstat = en_S1011; 372 break; 373 374 case en_stmt_executed: 375 case en_stmt_cursoropen: 376 case en_stmt_fetched: 377 case en_stmt_xfetched: 378 sqlstat = en_24000; 379 break; 380 381 case en_stmt_needdata: 382 case en_stmt_mustput: 383 case en_stmt_canput: 384 if (pstmt->prep_state) 385 { 386 sqlstat = en_S1011; 387 } 388 break; 389 390 default: 391 break; 392 } 393 } 394 } 395 else 396 { 397 if (pstmt->asyn_on != en_NullProc) 398 { 399 if (!pstmt->prep_state) 400 { 401 sqlstat = en_S1010; 402 } 403 } 404 else 405 { 406 if (pstmt->state >= en_stmt_needdata) 407 { 408 sqlstat = en_S1010; 409 } 410 } 411 } 412 413 if (sqlstat != en_00000) 414 { 415 PUSHSQLERR (pstmt->herr, sqlstat); 416 417 return SQL_ERROR; 418 } 419 420 hproc = _iodbcdm_getproc (pstmt->hdbc, en_SetStmtOption); 421 422 if (hproc == SQL_NULL_HPROC) 423 { 424 PUSHSQLERR (pstmt->herr, en_IM001); 425 426 return SQL_ERROR; 427 } 428 429 CALL_DRIVER (pstmt->hdbc, retcode, hproc, en_SetStmtOption, 430 (pstmt->dhstmt, fOption, vParam)) 431 432 return retcode; 433} 434 435 436RETCODE SQL_API 437SQLGetStmtOption ( 438 HSTMT hstmt, 439 UWORD fOption, 440 PTR pvParam) 441{ 442 STMT_t FAR *pstmt = (STMT_t *) hstmt; 443 HPROC hproc; 444 int sqlstat = en_00000; 445 RETCODE retcode; 446 447 if (hstmt == SQL_NULL_HSTMT || pstmt->hdbc == SQL_NULL_HDBC) 448 { 449 return SQL_INVALID_HANDLE; 450 } 451 452 /* check option */ 453 if ( /* fOption < SQL_STMT_OPT_MIN || */ 454 fOption > SQL_STMT_OPT_MAX) 455 { 456 PUSHSQLERR (pstmt->herr, en_S1092); 457 458 return SQL_ERROR; 459 } 460 461 /* check state */ 462 if (pstmt->state >= en_stmt_needdata 463 || pstmt->asyn_on != en_NullProc) 464 { 465 sqlstat = en_S1010; 466 } 467 else 468 { 469 switch (pstmt->state) 470 { 471 case en_stmt_allocated: 472 case en_stmt_prepared: 473 case en_stmt_executed: 474 case en_stmt_cursoropen: 475 if (fOption == SQL_ROW_NUMBER || fOption == SQL_GET_BOOKMARK) 476 { 477 sqlstat = en_24000; 478 } 479 break; 480 481 default: 482 break; 483 } 484 } 485 486 if (sqlstat != en_00000) 487 { 488 PUSHSQLERR (pstmt->herr, sqlstat); 489 490 return SQL_ERROR; 491 } 492 493 hproc = _iodbcdm_getproc (pstmt->hdbc, en_GetStmtOption); 494 495 if (hproc == SQL_NULL_HPROC) 496 { 497 PUSHSQLERR (pstmt->herr, en_IM001); 498 return SQL_ERROR; 499 } 500 501 CALL_DRIVER (pstmt->hdbc, retcode, hproc, en_GetStmtOption, 502 (pstmt->dhstmt, fOption, pvParam)) 503 504 return retcode; 505} 506 507 508RETCODE SQL_API 509SQLCancel (HSTMT hstmt) 510{ 511 STMT_t FAR *pstmt = (STMT_t FAR *) hstmt; 512 HPROC hproc; 513 RETCODE retcode; 514 515 if (hstmt == SQL_NULL_HSTMT || pstmt->hdbc == SQL_NULL_HDBC) 516 { 517 return SQL_INVALID_HANDLE; 518 } 519 520 /* check argument */ 521 /* check state */ 522 523 /* call driver */ 524 hproc = _iodbcdm_getproc (pstmt->hdbc, en_Cancel); 525 526 if (hproc == SQL_NULL_HPROC) 527 { 528 PUSHSQLERR (pstmt->herr, en_IM001); 529 530 return SQL_ERROR; 531 } 532 533 CALL_DRIVER (pstmt->hdbc, retcode, hproc, en_Cancel, 534 (pstmt->dhstmt)) 535 536 /* state transition */ 537 if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO) 538 { 539 return retcode; 540 } 541 542 switch (pstmt->state) 543 { 544 case en_stmt_allocated: 545 case en_stmt_prepared: 546 break; 547 548 case en_stmt_executed: 549 if (pstmt->prep_state) 550 { 551 pstmt->state = en_stmt_prepared; 552 } 553 else 554 { 555 pstmt->state = en_stmt_allocated; 556 } 557 break; 558 559 case en_stmt_cursoropen: 560 case en_stmt_fetched: 561 case en_stmt_xfetched: 562 if (pstmt->prep_state) 563 { 564 pstmt->state = en_stmt_prepared; 565 } 566 else 567 { 568 pstmt->state = en_stmt_allocated; 569 } 570 break; 571 572 case en_stmt_needdata: 573 case en_stmt_mustput: 574 case en_stmt_canput: 575 switch (pstmt->need_on) 576 { 577 case en_ExecDirect: 578 pstmt->state = en_stmt_allocated; 579 break; 580 581 case en_Execute: 582 pstmt->state = en_stmt_prepared; 583 break; 584 585 case en_SetPos: 586 pstmt->state = en_stmt_xfetched; 587 break; 588 589 default: 590 break; 591 } 592 pstmt->need_on = en_NullProc; 593 break; 594 595 default: 596 break; 597 } 598 599 return retcode; 600} 601