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
43RETCODE SQL_API
44SQLPrepare (
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
169RETCODE SQL_API
170SQLSetCursorName (
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
255RETCODE SQL_API
256SQLBindParameter (
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
374RETCODE SQL_API
375SQLParamOptions (
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
419RETCODE SQL_API
420SQLSetScrollOptions (
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
504RETCODE SQL_API
505SQLSetParam (
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