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 
41 static void
do_cursoropen(STMT_t FAR * pstmt)42 do_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 
67 RETCODE SQL_API
SQLExecute(HSTMT hstmt)68 SQLExecute (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 
224 RETCODE SQL_API
SQLExecDirect(HSTMT hstmt,UCHAR FAR * szSqlStr,SDWORD cbSqlStr)225 SQLExecDirect (
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 
353 RETCODE SQL_API
SQLPutData(HSTMT hstmt,PTR rgbValue,SDWORD cbValue)354 SQLPutData (
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 
470 RETCODE SQL_API
SQLParamData(HSTMT hstmt,PTR FAR * prgbValue)471 SQLParamData (
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 
609 RETCODE SQL_API
SQLNumParams(HSTMT hstmt,SWORD FAR * pcpar)610 SQLNumParams (
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 
685 RETCODE SQL_API
SQLDescribeParam(HSTMT hstmt,UWORD ipar,SWORD FAR * pfSqlType,UDWORD FAR * pcbColDef,SWORD FAR * pibScale,SWORD FAR * pfNullable)686 SQLDescribeParam (
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