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