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