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
41static void
42do_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
67RETCODE SQL_API
68SQLExecute (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
224RETCODE SQL_API
225SQLExecDirect (
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
353RETCODE SQL_API
354SQLPutData (
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
470RETCODE SQL_API
471SQLParamData (
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
609RETCODE SQL_API
610SQLNumParams (
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
685RETCODE SQL_API
686SQLDescribeParam (
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