]> git.saurik.com Git - wxWidgets.git/blob - src/iodbc/hstmt.c
fix for bug 1371386, with some minor mods and cleanup
[wxWidgets.git] / src / iodbc / hstmt.c
1 /*
2 * hstmt.c
3 *
4 * $Id$
5 *
6 * Query statement object management functions
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 RETCODE SQL_API
42 SQLAllocStmt (
43 HDBC hdbc,
44 HSTMT FAR * phstmt)
45 {
46 DBC_t FAR *pdbc = (DBC_t FAR *) hdbc;
47 STMT_t FAR *pstmt = NULL;
48 HPROC hproc = SQL_NULL_HPROC;
49 RETCODE retcode = SQL_SUCCESS;
50
51 #if (ODBCVER >= 0x0300)
52 if (hdbc == SQL_NULL_HDBC || pdbc->type != SQL_HANDLE_DBC)
53 #else
54 if (hdbc == SQL_NULL_HDBC)
55 #endif
56 {
57 return SQL_INVALID_HANDLE;
58 }
59
60 if (phstmt == NULL)
61 {
62 PUSHSQLERR (pdbc->herr, en_S1009);
63
64 return SQL_ERROR;
65 }
66
67 /* check state */
68 switch (pdbc->state)
69 {
70 case en_dbc_connected:
71 case en_dbc_hstmt:
72 break;
73
74 case en_dbc_allocated:
75 case en_dbc_needdata:
76 PUSHSQLERR (pdbc->herr, en_08003);
77 *phstmt = SQL_NULL_HSTMT;
78 return SQL_ERROR;
79
80 default:
81 return SQL_INVALID_HANDLE;
82 }
83
84 pstmt = (STMT_t FAR *) MEM_ALLOC (sizeof (STMT_t));
85
86 if (pstmt == NULL)
87 {
88 PUSHSQLERR (pdbc->herr, en_S1001);
89 *phstmt = SQL_NULL_HSTMT;
90
91 return SQL_ERROR;
92 }
93
94 #if (ODBCVER >= 0x0300)
95 pstmt->type = SQL_HANDLE_STMT;
96 #endif
97
98 /* initiate the object */
99 pstmt->herr = SQL_NULL_HERR;
100 pstmt->hdbc = hdbc;
101 pstmt->state = en_stmt_allocated;
102 pstmt->cursor_state = en_stmt_cursor_no;
103 pstmt->prep_state = 0;
104 pstmt->asyn_on = en_NullProc;
105 pstmt->need_on = en_NullProc;
106
107 /* call driver's function */
108
109 #if (ODBCVER >= 0x0300)
110 hproc = _iodbcdm_getproc (hdbc, en_AllocHandle);
111
112 if (hproc)
113 {
114 CALL_DRIVER (pstmt->hdbc, hdbc, retcode, hproc, en_AllocHandle,
115 (SQL_HANDLE_STMT, pdbc->dhdbc, &(pstmt->dhstmt)))
116 }
117 else
118 #endif
119
120 {
121 hproc = _iodbcdm_getproc (hdbc, en_AllocStmt);
122
123 if (hproc == SQL_NULL_HPROC)
124 {
125 PUSHSQLERR (pstmt->herr, en_IM001);
126 *phstmt = SQL_NULL_HSTMT;
127 MEM_FREE (pstmt);
128
129 return SQL_ERROR;
130 }
131
132 CALL_DRIVER (hdbc, retcode, hproc, en_AllocStmt,
133 (pdbc->dhdbc, &(pstmt->dhstmt)))
134 }
135
136 if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
137 {
138 *phstmt = SQL_NULL_HSTMT;
139 MEM_FREE (pstmt);
140
141 return retcode;
142 }
143
144 /* insert into list */
145 pstmt->next = pdbc->hstmt;
146 pdbc->hstmt = pstmt;
147
148 *phstmt = (HSTMT) pstmt;
149
150 /* state transition */
151 pdbc->state = en_dbc_hstmt;
152
153 return SQL_SUCCESS;
154 }
155
156
157 RETCODE
158 _iodbcdm_dropstmt (HSTMT hstmt)
159 {
160 STMT_t FAR *pstmt = (STMT_t FAR *) hstmt;
161 STMT_t FAR *tpstmt;
162 DBC_t FAR *pdbc;
163
164 if (hstmt == SQL_NULL_HSTMT)
165 {
166 return SQL_INVALID_HANDLE;
167 }
168
169 pdbc = (DBC_t FAR *) (pstmt->hdbc);
170
171 for (tpstmt = (STMT_t FAR *) pdbc->hstmt;
172 tpstmt != NULL;
173 tpstmt = tpstmt->next)
174 {
175 if (tpstmt == pstmt)
176 {
177 pdbc->hstmt = (HSTMT) pstmt->next;
178 break;
179 }
180
181 if (tpstmt->next == pstmt)
182 {
183 tpstmt->next = pstmt->next;
184 break;
185 }
186 }
187
188 if (tpstmt == NULL)
189 {
190 return SQL_INVALID_HANDLE;
191 }
192
193 _iodbcdm_freesqlerrlist (pstmt->herr);
194 MEM_FREE (hstmt);
195
196 return SQL_SUCCESS;
197 }
198
199
200 RETCODE SQL_API
201 SQLFreeStmt (
202 HSTMT hstmt,
203 UWORD fOption)
204 {
205 STMT_t FAR *pstmt = (STMT_t FAR *) hstmt;
206 STMT_t FAR *tpstmt;
207 DBC_t FAR *pdbc;
208
209 HPROC hproc = SQL_NULL_HPROC;
210 RETCODE retcode;
211
212 if (hstmt == SQL_NULL_HSTMT || pstmt->hdbc == SQL_NULL_HDBC)
213 {
214 return SQL_INVALID_HANDLE;
215 }
216
217 pdbc = (DBC_t FAR *) (pstmt->hdbc);
218
219 /* check option */
220 switch (fOption)
221 {
222 case SQL_DROP:
223 case SQL_CLOSE:
224 case SQL_UNBIND:
225 case SQL_RESET_PARAMS:
226 break;
227
228 default:
229 PUSHSQLERR (pstmt->herr, en_S1092);
230 return SQL_ERROR;
231 }
232
233 /* check state */
234 if (pstmt->state >= en_stmt_needdata || pstmt->asyn_on != en_NullProc)
235 {
236 PUSHSQLERR (pstmt->herr, en_S1010);
237
238 return SQL_ERROR;
239 }
240
241 hproc = SQL_NULL_HPROC;
242
243 #if (ODBCVER >= 0x0300)
244 if (fOption == SQL_DROP)
245 {
246 hproc = _iodbcdm_getproc (pstmt->hdbc, en_FreeHandle);
247
248 if (hproc)
249 {
250 CALL_DRIVER (pstmt->hdbc, retcode, hproc, en_FreeHandle,
251 (SQL_HANDLE_STMT, pstmt->dhstmt))
252 }
253 }
254 #endif
255
256 if (hproc == SQL_NULL_HPROC)
257 {
258 hproc = _iodbcdm_getproc (pstmt->hdbc, en_FreeStmt);
259
260 if (hproc == SQL_NULL_HPROC)
261 {
262 PUSHSQLERR (pstmt->herr, en_IM001);
263
264 return SQL_ERROR;
265 }
266
267 CALL_DRIVER (pstmt->hdbc, retcode, hproc, en_FreeStmt,
268 (pstmt->dhstmt, fOption))
269 }
270
271 if (retcode != SQL_SUCCESS
272 && retcode != SQL_SUCCESS_WITH_INFO)
273 {
274 return retcode;
275 }
276
277 /* state transition */
278 switch (fOption)
279 {
280 case SQL_DROP:
281 /* delet this object (ignore return) */
282 _iodbcdm_dropstmt (hstmt);
283 break;
284
285 case SQL_CLOSE:
286 pstmt->cursor_state = en_stmt_cursor_no;
287 /* This means cursor name set by
288 * SQLSetCursorName() call will also
289 * be erased.
290 */
291
292 switch (pstmt->state)
293 {
294 case en_stmt_allocated:
295 case en_stmt_prepared:
296 break;
297
298 case en_stmt_executed:
299 case en_stmt_cursoropen:
300 case en_stmt_fetched:
301 case en_stmt_xfetched:
302 if (pstmt->prep_state)
303 {
304 pstmt->state =
305 en_stmt_prepared;
306 }
307 else
308 {
309 pstmt->state =
310 en_stmt_allocated;
311 }
312 break;
313
314 default:
315 break;
316 }
317 break;
318
319 case SQL_UNBIND:
320 case SQL_RESET_PARAMS:
321 default:
322 break;
323 }
324
325 return retcode;
326 }
327
328
329 RETCODE SQL_API
330 SQLSetStmtOption (
331 HSTMT hstmt,
332 UWORD fOption,
333 UDWORD vParam)
334 {
335 STMT_t FAR *pstmt = (STMT_t FAR *) hstmt;
336 HPROC hproc;
337 int sqlstat = en_00000;
338 RETCODE retcode;
339
340 if (hstmt == SQL_NULL_HSTMT || pstmt->hdbc == SQL_NULL_HDBC)
341 {
342 return SQL_INVALID_HANDLE;
343 }
344
345 /* check option */
346 if ( /* fOption < SQL_STMT_OPT_MIN || */
347 fOption > SQL_STMT_OPT_MAX)
348 {
349 PUSHSQLERR (pstmt->herr, en_S1092);
350
351 return SQL_ERROR;
352 }
353
354 if (fOption == SQL_CONCURRENCY
355 || fOption == SQL_CURSOR_TYPE
356 || fOption == SQL_SIMULATE_CURSOR
357 || fOption == SQL_USE_BOOKMARKS)
358 {
359 if (pstmt->asyn_on != en_NullProc)
360 {
361 if (pstmt->prep_state)
362 {
363 sqlstat = en_S1011;
364 }
365 }
366 else
367 {
368 switch (pstmt->state)
369 {
370 case en_stmt_prepared:
371 sqlstat = en_S1011;
372 break;
373
374 case en_stmt_executed:
375 case en_stmt_cursoropen:
376 case en_stmt_fetched:
377 case en_stmt_xfetched:
378 sqlstat = en_24000;
379 break;
380
381 case en_stmt_needdata:
382 case en_stmt_mustput:
383 case en_stmt_canput:
384 if (pstmt->prep_state)
385 {
386 sqlstat = en_S1011;
387 }
388 break;
389
390 default:
391 break;
392 }
393 }
394 }
395 else
396 {
397 if (pstmt->asyn_on != en_NullProc)
398 {
399 if (!pstmt->prep_state)
400 {
401 sqlstat = en_S1010;
402 }
403 }
404 else
405 {
406 if (pstmt->state >= en_stmt_needdata)
407 {
408 sqlstat = en_S1010;
409 }
410 }
411 }
412
413 if (sqlstat != en_00000)
414 {
415 PUSHSQLERR (pstmt->herr, sqlstat);
416
417 return SQL_ERROR;
418 }
419
420 hproc = _iodbcdm_getproc (pstmt->hdbc, en_SetStmtOption);
421
422 if (hproc == SQL_NULL_HPROC)
423 {
424 PUSHSQLERR (pstmt->herr, en_IM001);
425
426 return SQL_ERROR;
427 }
428
429 CALL_DRIVER (pstmt->hdbc, retcode, hproc, en_SetStmtOption,
430 (pstmt->dhstmt, fOption, vParam))
431
432 return retcode;
433 }
434
435
436 RETCODE SQL_API
437 SQLGetStmtOption (
438 HSTMT hstmt,
439 UWORD fOption,
440 PTR pvParam)
441 {
442 STMT_t FAR *pstmt = (STMT_t *) hstmt;
443 HPROC hproc;
444 int sqlstat = en_00000;
445 RETCODE retcode;
446
447 if (hstmt == SQL_NULL_HSTMT || pstmt->hdbc == SQL_NULL_HDBC)
448 {
449 return SQL_INVALID_HANDLE;
450 }
451
452 /* check option */
453 if ( /* fOption < SQL_STMT_OPT_MIN || */
454 fOption > SQL_STMT_OPT_MAX)
455 {
456 PUSHSQLERR (pstmt->herr, en_S1092);
457
458 return SQL_ERROR;
459 }
460
461 /* check state */
462 if (pstmt->state >= en_stmt_needdata
463 || pstmt->asyn_on != en_NullProc)
464 {
465 sqlstat = en_S1010;
466 }
467 else
468 {
469 switch (pstmt->state)
470 {
471 case en_stmt_allocated:
472 case en_stmt_prepared:
473 case en_stmt_executed:
474 case en_stmt_cursoropen:
475 if (fOption == SQL_ROW_NUMBER || fOption == SQL_GET_BOOKMARK)
476 {
477 sqlstat = en_24000;
478 }
479 break;
480
481 default:
482 break;
483 }
484 }
485
486 if (sqlstat != en_00000)
487 {
488 PUSHSQLERR (pstmt->herr, sqlstat);
489
490 return SQL_ERROR;
491 }
492
493 hproc = _iodbcdm_getproc (pstmt->hdbc, en_GetStmtOption);
494
495 if (hproc == SQL_NULL_HPROC)
496 {
497 PUSHSQLERR (pstmt->herr, en_IM001);
498 return SQL_ERROR;
499 }
500
501 CALL_DRIVER (pstmt->hdbc, retcode, hproc, en_GetStmtOption,
502 (pstmt->dhstmt, fOption, pvParam))
503
504 return retcode;
505 }
506
507
508 RETCODE SQL_API
509 SQLCancel (HSTMT hstmt)
510 {
511 STMT_t FAR *pstmt = (STMT_t FAR *) hstmt;
512 HPROC hproc;
513 RETCODE retcode;
514
515 if (hstmt == SQL_NULL_HSTMT || pstmt->hdbc == SQL_NULL_HDBC)
516 {
517 return SQL_INVALID_HANDLE;
518 }
519
520 /* check argument */
521 /* check state */
522
523 /* call driver */
524 hproc = _iodbcdm_getproc (pstmt->hdbc, en_Cancel);
525
526 if (hproc == SQL_NULL_HPROC)
527 {
528 PUSHSQLERR (pstmt->herr, en_IM001);
529
530 return SQL_ERROR;
531 }
532
533 CALL_DRIVER (pstmt->hdbc, retcode, hproc, en_Cancel,
534 (pstmt->dhstmt))
535
536 /* state transition */
537 if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
538 {
539 return retcode;
540 }
541
542 switch (pstmt->state)
543 {
544 case en_stmt_allocated:
545 case en_stmt_prepared:
546 break;
547
548 case en_stmt_executed:
549 if (pstmt->prep_state)
550 {
551 pstmt->state = en_stmt_prepared;
552 }
553 else
554 {
555 pstmt->state = en_stmt_allocated;
556 }
557 break;
558
559 case en_stmt_cursoropen:
560 case en_stmt_fetched:
561 case en_stmt_xfetched:
562 if (pstmt->prep_state)
563 {
564 pstmt->state = en_stmt_prepared;
565 }
566 else
567 {
568 pstmt->state = en_stmt_allocated;
569 }
570 break;
571
572 case en_stmt_needdata:
573 case en_stmt_mustput:
574 case en_stmt_canput:
575 switch (pstmt->need_on)
576 {
577 case en_ExecDirect:
578 pstmt->state = en_stmt_allocated;
579 break;
580
581 case en_Execute:
582 pstmt->state = en_stmt_prepared;
583 break;
584
585 case en_SetPos:
586 pstmt->state = en_stmt_xfetched;
587 break;
588
589 default:
590 break;
591 }
592 pstmt->need_on = en_NullProc;
593 break;
594
595 default:
596 break;
597 }
598
599 return retcode;
600 }