1 /*
2  *  prepare.c
3  *
4  *  $Id: prepare.c 2613 1999-06-01 15:32:12Z VZ $
5  *
6  *  Prepare 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 #include        <unistd.h>
42 
43 RETCODE SQL_API
SQLPrepare(HSTMT hstmt,UCHAR FAR * szSqlStr,SDWORD cbSqlStr)44 SQLPrepare (
45     HSTMT hstmt,
46     UCHAR FAR * szSqlStr,
47     SDWORD cbSqlStr)
48 {
49   STMT_t FAR *pstmt = (STMT_t *) hstmt;
50 
51   HPROC hproc = SQL_NULL_HPROC;
52   RETCODE retcode = SQL_SUCCESS;
53   int sqlstat = en_00000;
54 
55   if (hstmt == SQL_NULL_HSTMT || pstmt->hdbc == SQL_NULL_HDBC)
56     {
57       return SQL_INVALID_HANDLE;
58     }
59 
60   /* check state */
61   if (pstmt->asyn_on == en_NullProc)
62     {
63       /* not on asyn state */
64       switch (pstmt->state)
65 	 {
66 	 case en_stmt_fetched:
67 	 case en_stmt_xfetched:
68 	   sqlstat = en_24000;
69 	   break;
70 
71 	 case en_stmt_needdata:
72 	 case en_stmt_mustput:
73 	 case en_stmt_canput:
74 	   sqlstat = en_S1010;
75 	   break;
76 
77 	 default:
78 	   break;
79 	 }
80     }
81   else if (pstmt->asyn_on != en_Prepare)
82     {
83       /* asyn on other */
84       sqlstat = en_S1010;
85     }
86 
87   if (sqlstat != en_00000)
88     {
89       PUSHSQLERR (pstmt->herr, sqlstat);
90 
91       return SQL_ERROR;
92     }
93 
94   if (szSqlStr == NULL)
95     {
96       PUSHSQLERR (pstmt->herr, en_S1009);
97 
98       return SQL_ERROR;
99     }
100 
101   if (cbSqlStr < 0 && cbSqlStr != SQL_NTS)
102     {
103       PUSHSQLERR (pstmt->herr, en_S1090);
104 
105       return SQL_ERROR;
106     }
107 
108   hproc = _iodbcdm_getproc (pstmt->hdbc, en_Prepare);
109 
110   if (hproc == SQL_NULL_HPROC)
111     {
112       PUSHSQLERR (pstmt->herr, en_IM001);
113       return SQL_ERROR;
114     }
115 
116   CALL_DRIVER (pstmt->hdbc, retcode, hproc, en_Prepare,
117     (pstmt->dhstmt, szSqlStr, cbSqlStr))
118 
119   /* stmt state transition */
120   if (pstmt->asyn_on == en_Prepare)
121     {
122       switch (retcode)
123 	 {
124 	 case SQL_SUCCESS:
125 	 case SQL_SUCCESS_WITH_INFO:
126 	 case SQL_ERROR:
127 	   pstmt->asyn_on = en_NullProc;
128 	   return retcode;
129 
130 	 case SQL_STILL_EXECUTING:
131 	 default:
132 	   return retcode;
133 	 }
134     }
135 
136   switch (retcode)
137      {
138      case SQL_STILL_EXECUTING:
139        pstmt->asyn_on = en_Prepare;
140        break;
141 
142      case SQL_SUCCESS:
143      case SQL_SUCCESS_WITH_INFO:
144        pstmt->state = en_stmt_prepared;
145        pstmt->prep_state = 1;
146        break;
147 
148      case SQL_ERROR:
149        switch (pstmt->state)
150 	  {
151 	  case en_stmt_prepared:
152 	  case en_stmt_executed:
153 	    pstmt->state = en_stmt_allocated;
154 	    pstmt->prep_state = 0;
155 	    break;
156 
157 	  default:
158 	    break;
159 	  }
160 
161      default:
162        break;
163      }
164 
165   return retcode;
166 }
167 
168 
169 RETCODE SQL_API
SQLSetCursorName(HSTMT hstmt,UCHAR FAR * szCursor,SWORD cbCursor)170 SQLSetCursorName (
171     HSTMT hstmt,
172     UCHAR FAR * szCursor,
173     SWORD cbCursor)
174 {
175   STMT_t FAR *pstmt = (STMT_t *) hstmt;
176   HPROC hproc = SQL_NULL_HPROC;
177 
178   RETCODE retcode = SQL_SUCCESS;
179   int sqlstat = en_00000;
180 
181   if (hstmt == SQL_NULL_HSTMT || pstmt->hdbc == SQL_NULL_HDBC)
182     {
183       return SQL_INVALID_HANDLE;
184     }
185 
186   if (szCursor == NULL)
187     {
188       PUSHSQLERR (pstmt->herr, en_S1009);
189 
190       return SQL_ERROR;
191     }
192 
193   if (cbCursor < 0 && cbCursor != SQL_NTS)
194     {
195       PUSHSQLERR (pstmt->herr, en_S1090);
196 
197       return SQL_ERROR;
198     }
199 
200   /* check state */
201   if (pstmt->asyn_on != en_NullProc)
202     {
203       sqlstat = en_S1010;
204     }
205   else
206     {
207       switch (pstmt->state)
208 	 {
209 	 case en_stmt_executed:
210 	 case en_stmt_cursoropen:
211 	 case en_stmt_fetched:
212 	 case en_stmt_xfetched:
213 	   sqlstat = en_24000;
214 	   break;
215 
216 	 case en_stmt_needdata:
217 	 case en_stmt_mustput:
218 	 case en_stmt_canput:
219 	   sqlstat = en_S1010;
220 	   break;
221 
222 	 default:
223 	   break;
224 	 }
225     }
226 
227   if (sqlstat != en_00000)
228     {
229       PUSHSQLERR (pstmt->herr, sqlstat);
230 
231       return SQL_ERROR;
232     }
233 
234   hproc = _iodbcdm_getproc (pstmt->hdbc, en_SetCursorName);
235 
236   if (hproc == SQL_NULL_HPROC)
237     {
238       PUSHSQLERR (pstmt->herr, en_IM001);
239 
240       return SQL_ERROR;
241     }
242 
243   CALL_DRIVER (pstmt->hdbc, retcode, hproc, en_SetCursorName,
244     (pstmt->dhstmt, szCursor, cbCursor))
245 
246   if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)
247     {
248       pstmt->cursor_state = en_stmt_cursor_named;
249     }
250 
251   return retcode;
252 }
253 
254 
255 RETCODE SQL_API
SQLBindParameter(HSTMT hstmt,UWORD ipar,SWORD fParamType,SWORD fCType,SWORD fSqlType,UDWORD cbColDef,SWORD ibScale,PTR rgbValue,SDWORD cbValueMax,SDWORD FAR * pcbValue)256 SQLBindParameter (
257     HSTMT hstmt,
258     UWORD ipar,
259     SWORD fParamType,
260     SWORD fCType,
261     SWORD fSqlType,
262     UDWORD cbColDef,
263     SWORD ibScale,
264     PTR rgbValue,
265     SDWORD cbValueMax,
266     SDWORD FAR * pcbValue)
267 {
268   STMT_t FAR *pstmt = (STMT_t FAR *) hstmt;
269   HPROC hproc = SQL_NULL_HPROC;
270 
271   int sqlstat = en_00000;
272   RETCODE retcode = SQL_SUCCESS;
273 
274   if (hstmt == SQL_NULL_HSTMT || pstmt->hdbc == SQL_NULL_HDBC)
275     {
276       return SQL_INVALID_HANDLE;
277     }
278 
279   /* check param */
280   if (fSqlType > SQL_TYPE_MAX ||
281 	(fSqlType < SQL_TYPE_MIN && fSqlType > SQL_TYPE_DRIVER_START))
282     /* Note: SQL_TYPE_DRIVER_START is a nagtive number
283      * So, we use ">" */
284     {
285       sqlstat = en_S1004;
286     }
287   else if (ipar < 1)
288     {
289       sqlstat = en_S1093;
290     }
291   else if ((rgbValue == NULL && pcbValue == NULL)
292       && fParamType != SQL_PARAM_OUTPUT)
293     {
294       sqlstat = en_S1009;
295       /* This means, I allow output to nowhere
296        * (i.e. * junk output result). But I can't
297        * allow input from nowhere.
298        */
299     }
300 /**********
301 	else if( cbValueMax < 0L && cbValueMax != SQL_SETPARAM_VALUE_MAX )
302 	{
303 		sqlstat = en_S1090;
304 	}
305 **********/
306   else if (fParamType != SQL_PARAM_INPUT
307 	&& fParamType != SQL_PARAM_OUTPUT
308       && fParamType != SQL_PARAM_INPUT_OUTPUT)
309     {
310       sqlstat = en_S1105;
311     }
312   else
313     {
314       switch (fCType)
315 	 {
316 	 case SQL_C_DEFAULT:
317 	 case SQL_C_CHAR:
318 	 case SQL_C_BINARY:
319 	 case SQL_C_BIT:
320 	 case SQL_C_TINYINT:
321 	 case SQL_C_STINYINT:
322 	 case SQL_C_UTINYINT:
323 	 case SQL_C_SHORT:
324 	 case SQL_C_SSHORT:
325 	 case SQL_C_USHORT:
326 	 case SQL_C_LONG:
327 	 case SQL_C_SLONG:
328 	 case SQL_C_ULONG:
329 	 case SQL_C_FLOAT:
330 	 case SQL_C_DOUBLE:
331 	 case SQL_C_DATE:
332 	 case SQL_C_TIME:
333 	 case SQL_C_TIMESTAMP:
334 	   break;
335 
336 	 default:
337 	   sqlstat = en_S1003;
338 	   break;
339 	 }
340     }
341 
342   if (sqlstat != en_00000)
343     {
344       PUSHSQLERR (pstmt->herr, sqlstat);
345 
346       return SQL_ERROR;
347     }
348 
349   /* check state */
350   if (pstmt->state >= en_stmt_needdata || pstmt->asyn_on != en_NullProc)
351     {
352       PUSHSQLERR (pstmt->herr, en_S1010);
353 
354       retcode = SQL_ERROR;
355     }
356 
357   hproc = _iodbcdm_getproc (pstmt->hdbc, en_BindParameter);
358 
359   if (hproc == SQL_NULL_HPROC)
360     {
361       PUSHSQLERR (pstmt->herr, en_IM001);
362 
363       return SQL_ERROR;
364     }
365 
366   CALL_DRIVER (pstmt->hdbc, retcode, hproc, en_BindParameter,
367     (pstmt->dhstmt, ipar, fParamType, fCType, fSqlType, cbColDef,
368       ibScale, rgbValue, cbValueMax, pcbValue))
369 
370   return retcode;
371 }
372 
373 
374 RETCODE SQL_API
SQLParamOptions(HSTMT hstmt,UDWORD crow,UDWORD FAR * pirow)375 SQLParamOptions (
376     HSTMT hstmt,
377     UDWORD crow,
378     UDWORD FAR * pirow)
379 {
380   STMT_t FAR *pstmt = (STMT_t FAR *) hstmt;
381   HPROC hproc;
382   RETCODE retcode;
383 
384   if (hstmt == SQL_NULL_HSTMT || pstmt->hdbc == SQL_NULL_HDBC)
385     {
386       return SQL_INVALID_HANDLE;
387     }
388 
389   if (crow == (UDWORD) 0UL)
390     {
391       PUSHSQLERR (pstmt->herr, en_S1107);
392 
393       return SQL_ERROR;
394     }
395 
396   if (pstmt->state >= en_stmt_needdata || pstmt->asyn_on != en_NullProc)
397     {
398       PUSHSQLERR (pstmt->herr, en_S1010);
399 
400       return SQL_ERROR;
401     }
402 
403   hproc = _iodbcdm_getproc (pstmt->hdbc, en_ParamOptions);
404 
405   if (hproc == SQL_NULL_HPROC)
406     {
407       PUSHSQLERR (pstmt->herr, en_IM001);
408 
409       return SQL_ERROR;
410     }
411 
412   CALL_DRIVER (pstmt->hdbc, retcode, hproc, en_ParamOptions,
413     (pstmt->dhstmt, crow, pirow))
414 
415   return retcode;
416 }
417 
418 
419 RETCODE SQL_API
SQLSetScrollOptions(HSTMT hstmt,UWORD fConcurrency,SDWORD crowKeyset,UWORD crowRowset)420 SQLSetScrollOptions (
421     HSTMT hstmt,
422     UWORD fConcurrency,
423     SDWORD crowKeyset,
424     UWORD crowRowset)
425 {
426   STMT_t FAR *pstmt = (STMT_t FAR *) hstmt;
427   HPROC hproc;
428   int sqlstat = en_00000;
429   RETCODE retcode;
430 
431   if (hstmt == SQL_NULL_HSTMT || pstmt->hdbc == SQL_NULL_HDBC)
432     {
433       return SQL_INVALID_HANDLE;
434     }
435 
436   for (;;)
437     {
438       if (crowRowset == (UWORD) 0)
439 	{
440 	  sqlstat = en_S1107;
441 	  break;
442 	}
443 
444       if (crowKeyset > (SDWORD) 0L && crowKeyset < (SDWORD) crowRowset)
445 	{
446 	  sqlstat = en_S1107;
447 	  break;
448 	}
449 
450       if (crowKeyset < 1)
451 	{
452 	  if (crowKeyset != SQL_SCROLL_FORWARD_ONLY
453 	      && crowKeyset != SQL_SCROLL_STATIC
454 	      && crowKeyset != SQL_SCROLL_KEYSET_DRIVEN
455 	      && crowKeyset != SQL_SCROLL_DYNAMIC)
456 	    {
457 	      sqlstat = en_S1107;
458 	      break;
459 	    }
460 	}
461 
462       if (fConcurrency != SQL_CONCUR_READ_ONLY
463 	  && fConcurrency != SQL_CONCUR_LOCK
464 	  && fConcurrency != SQL_CONCUR_ROWVER
465 	  && fConcurrency != SQL_CONCUR_VALUES)
466 	{
467 	  sqlstat = en_S1108;
468 	  break;
469 	}
470 
471       if (pstmt->state != en_stmt_allocated)
472 	{
473 	  sqlstat = en_S1010;
474 	  break;
475 	}
476 
477       hproc = _iodbcdm_getproc (pstmt->hdbc, en_SetScrollOptions);
478 
479       if (hproc == SQL_NULL_HPROC)
480 	{
481 	  sqlstat = en_IM001;
482 	  break;
483 	}
484 
485       sqlstat = en_00000;
486       if (1)			/* turn off solaris warning message */
487 	break;
488     }
489 
490   if (sqlstat != en_00000)
491     {
492       PUSHSQLERR (pstmt->herr, sqlstat);
493 
494       return SQL_ERROR;
495     }
496 
497   CALL_DRIVER (pstmt->hdbc, retcode, hproc, en_SetScrollOptions,
498     (pstmt->dhstmt, fConcurrency, crowKeyset, crowRowset))
499 
500   return retcode;
501 }
502 
503 
504 RETCODE SQL_API
SQLSetParam(HSTMT hstmt,UWORD ipar,SWORD fCType,SWORD fSqlType,UDWORD cbColDef,SWORD ibScale,PTR rgbValue,SDWORD FAR * pcbValue)505 SQLSetParam (
506     HSTMT hstmt,
507     UWORD ipar,
508     SWORD fCType,
509     SWORD fSqlType,
510     UDWORD cbColDef,
511     SWORD ibScale,
512     PTR rgbValue,
513     SDWORD FAR * pcbValue)
514 {
515   return SQLBindParameter (hstmt,
516       ipar,
517       (SWORD) SQL_PARAM_INPUT_OUTPUT,
518       fCType,
519       fSqlType,
520       cbColDef,
521       ibScale,
522       rgbValue,
523       SQL_SETPARAM_VALUE_MAX,
524       pcbValue);
525 }
526