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 Ke Jin <kejin@empress.com>
11 * Copyright (C) 1996-2021 OpenLink Software <iodbc@openlinksw.com>
12 * All Rights Reserved.
13 *
14 * This software is released under the terms of either of the following
15 * licenses:
16 *
17 * - GNU Library General Public License (see LICENSE.LGPL)
18 * - The BSD License (see LICENSE.BSD).
19 *
20 * Note that the only valid version of the LGPL license as far as this
21 * project is concerned is the original GNU Library General Public License
22 * Version 2, dated June 1991.
23 *
24 * While not mandated by the BSD license, any patches you make to the
25 * iODBC source code may be contributed back into the iODBC project
26 * at your discretion. Contributions will benefit the Open Source and
27 * Data Access community as a whole. Submissions may be made at:
28 *
29 * http://www.iodbc.org
30 *
31 *
32 * GNU Library Generic Public License Version 2
33 * ============================================
34 * This library is free software; you can redistribute it and/or
35 * modify it under the terms of the GNU Library General Public
36 * License as published by the Free Software Foundation; only
37 * Version 2 of the License dated June 1991.
38 *
39 * This library is distributed in the hope that it will be useful,
40 * but WITHOUT ANY WARRANTY; without even the implied warranty of
41 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
42 * Library General Public License for more details.
43 *
44 * You should have received a copy of the GNU Library General Public
45 * License along with this library; if not, write to the Free
46 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
47 *
48 *
49 * The BSD License
50 * ===============
51 * Redistribution and use in source and binary forms, with or without
52 * modification, are permitted provided that the following conditions
53 * are met:
54 *
55 * 1. Redistributions of source code must retain the above copyright
56 * notice, this list of conditions and the following disclaimer.
57 * 2. Redistributions in binary form must reproduce the above copyright
58 * notice, this list of conditions and the following disclaimer in
59 * the documentation and/or other materials provided with the
60 * distribution.
61 * 3. Neither the name of OpenLink Software Inc. nor the names of its
62 * contributors may be used to endorse or promote products derived
63 * from this software without specific prior written permission.
64 *
65 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
66 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
67 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
68 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OPENLINK OR
69 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
70 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
71 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
72 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
73 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
74 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
75 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
76 */
77
78
79 #include <iodbc.h>
80
81 #include <sql.h>
82 #include <sqlext.h>
83
84 #include "unicode.h"
85
86 #include "dlproc.h"
87
88 #include "herr.h"
89 #if (ODBCVER >= 0x0300)
90 #include "hdesc.h"
91 #endif
92 #include "henv.h"
93 #include "hdbc.h"
94 #include "hstmt.h"
95
96 #include "itrace.h"
97
98 #if (ODBCVER >= 0x300)
99 static const SQLINTEGER desc_attrs[4] =
100 {
101 SQL_ATTR_APP_ROW_DESC,
102 SQL_ATTR_APP_PARAM_DESC,
103 SQL_ATTR_IMP_ROW_DESC,
104 SQL_ATTR_IMP_PARAM_DESC
105 };
106 #endif
107
108 #define XFREE(V) if (V) { free(V); V = NULL; }
109
110 SQLRETURN
SQLAllocStmt_Internal(SQLHDBC hdbc,SQLHSTMT * phstmt)111 SQLAllocStmt_Internal (
112 SQLHDBC hdbc,
113 SQLHSTMT * phstmt)
114 {
115 CONN (pdbc, hdbc);
116 STMT (pstmt, NULL);
117 HPROC hproc2 = SQL_NULL_HPROC;
118 HPROC hproc3 = SQL_NULL_HPROC;
119 SQLRETURN retcode = SQL_SUCCESS;
120 int i;
121 SQLUINTEGER odbc_ver = ((GENV_t *) pdbc->genv)->odbc_ver;
122 SQLUINTEGER dodbc_ver = ((ENV_t *) pdbc->henv)->dodbc_ver;
123
124 if (phstmt == NULL)
125 {
126 PUSHSQLERR (pdbc->herr, en_S1009);
127 return SQL_ERROR;
128 }
129
130 /* check state */
131 switch (pdbc->state)
132 {
133 case en_dbc_connected:
134 case en_dbc_hstmt:
135 break;
136
137 case en_dbc_allocated:
138 case en_dbc_needdata:
139 PUSHSQLERR (pdbc->herr, en_08003);
140 *phstmt = SQL_NULL_HSTMT;
141
142 return SQL_ERROR;
143
144 default:
145 return SQL_INVALID_HANDLE;
146 }
147
148 pstmt = (STMT_t *) MEM_ALLOC (sizeof (STMT_t));
149
150 if (pstmt == NULL)
151 {
152 PUSHSQLERR (pdbc->herr, en_S1001);
153 *phstmt = SQL_NULL_HSTMT;
154
155 return SQL_ERROR;
156 }
157 pstmt->rc = 0;
158
159 /*
160 * Initialize this handle
161 */
162 pstmt->type = SQL_HANDLE_STMT;
163
164 /* initiate the object */
165 pstmt->herr = SQL_NULL_HERR;
166 pstmt->hdbc = (HSTMT) hdbc;
167 pstmt->state = en_stmt_allocated;
168 pstmt->cursor_state = en_stmt_cursor_no;
169 pstmt->prep_state = 0;
170 pstmt->asyn_on = en_NullProc;
171 pstmt->need_on = en_NullProc;
172 pstmt->stmt_cip = 0;
173 pstmt->err_rec = 0;
174
175 memset (pstmt->vars, 0, sizeof (VAR_t) * STMT_VARS_MAX);
176 pstmt->vars_inserted = 0;
177
178 /* call driver's function */
179 pstmt->rowset_size = 1;
180 pstmt->row_bind_type = SQL_BIND_BY_COLUMN;
181 pstmt->row_bind_offset = 0;
182 pstmt->param_bind_type = SQL_PARAM_BIND_BY_COLUMN;
183 pstmt->param_bind_offset = 0;
184 pstmt->st_pbinding = NULL;
185
186 pstmt->st_pparam = NULL;
187 pstmt->st_nparam = 0;
188
189 pstmt->params_buf = NULL;
190 pstmt->rows_buf = NULL;
191 pstmt->conv_param_bind_type = SQL_PARAM_BIND_BY_COLUMN;
192 pstmt->conv_row_bind_type = SQL_BIND_BY_COLUMN;
193
194 #if (ODBCVER >= 0x0300)
195 pstmt->row_array_size = 1;
196 pstmt->fetch_bookmark_ptr = NULL;
197 pstmt->params_processed_ptr = NULL;
198 pstmt->paramset_size = 0;
199 pstmt->rows_fetched_ptr = NULL;
200 if (dodbc_ver == SQL_OV_ODBC2 && odbc_ver == SQL_OV_ODBC3)
201 { /* if it's a odbc3 app calling odbc2 driver */
202 pstmt->row_status_ptr =
203 MEM_ALLOC (sizeof (SQLUINTEGER) * pstmt->row_array_size);
204 if (!pstmt->row_status_ptr)
205 {
206 PUSHSQLERR (pstmt->herr, en_HY001);
207 *phstmt = SQL_NULL_HSTMT;
208 pstmt->type = 0;
209 MEM_FREE (pstmt);
210 return SQL_ERROR;
211 }
212 pstmt->row_status_allocated = SQL_TRUE;
213 }
214 else
215 {
216 pstmt->row_status_ptr = NULL;
217 pstmt->row_status_allocated = SQL_FALSE;
218 }
219 #endif
220
221 hproc2 = _iodbcdm_getproc (pdbc, en_AllocStmt);
222 #if (ODBCVER >= 0x0300)
223 hproc3 = _iodbcdm_getproc (pdbc, en_AllocHandle);
224 #endif
225
226 if (odbc_ver == SQL_OV_ODBC2 &&
227 ( dodbc_ver == SQL_OV_ODBC2
228 || (dodbc_ver == SQL_OV_ODBC3 && hproc2 != SQL_NULL_HPROC)))
229 hproc3 = SQL_NULL_HPROC;
230
231 #if (ODBCVER >= 0x0300)
232 if (hproc3)
233 {
234 CALL_DRIVER (pstmt->hdbc, pdbc, retcode, hproc3,
235 (SQL_HANDLE_STMT, pdbc->dhdbc, &(pstmt->dhstmt)));
236 }
237 else
238 #endif
239 {
240 if (hproc2 == SQL_NULL_HPROC)
241 {
242 PUSHSQLERR (pstmt->herr, en_IM001);
243 *phstmt = SQL_NULL_HSTMT;
244 pstmt->type = 0;
245 MEM_FREE (pstmt);
246
247 return SQL_ERROR;
248 }
249
250 CALL_DRIVER (hdbc, pdbc, retcode, hproc2,
251 (pdbc->dhdbc, &(pstmt->dhstmt)));
252 }
253
254 if (!SQL_SUCCEEDED (retcode))
255 {
256 *phstmt = SQL_NULL_HSTMT;
257 pstmt->type = 0;
258 MEM_FREE (pstmt);
259
260 return retcode;
261 }
262
263 #if (ODBCVER >= 0x0300)
264 /* get the descriptors */
265 memset (&pstmt->imp_desc, 0, sizeof (pstmt->imp_desc));
266 memset (&pstmt->desc, 0, sizeof (pstmt->desc));
267
268 if (dodbc_ver == SQL_OV_ODBC2)
269 {
270 /*
271 * this is an ODBC2 driver - so alloc dummy implicit desc handles
272 * (dhdesc = NULL)
273 */
274 for (i = 0; i < 4; i++)
275 {
276 pstmt->imp_desc[i] = (DESC_t *) MEM_ALLOC (sizeof (DESC_t));
277 if (pstmt->imp_desc[i] == NULL)
278 {
279 PUSHSQLERR (pdbc->herr, en_HY001);
280
281 goto alloc_stmt_failed;
282 }
283 memset (pstmt->imp_desc[i], 0, sizeof (DESC_t));
284 pstmt->imp_desc[i]->type = SQL_HANDLE_DESC;
285 pstmt->imp_desc[i]->hstmt = pstmt;
286 pstmt->imp_desc[i]->dhdesc = NULL;
287 pstmt->imp_desc[i]->hdbc = hdbc;
288 pstmt->imp_desc[i]->herr = NULL;
289 }
290 }
291 else
292 { /* the ODBC3 driver */
293 if (((ENV_t *) pdbc->henv)->unicode_driver)
294 hproc3 = _iodbcdm_getproc (pdbc, en_GetStmtAttrW);
295 else
296 {
297 hproc3 = _iodbcdm_getproc (pdbc, en_GetStmtAttr);
298 if (hproc3 == SQL_NULL_HPROC)
299 hproc3 = _iodbcdm_getproc (pdbc, en_GetStmtAttrA);
300 }
301
302 if (hproc3 == SQL_NULL_HPROC)
303 { /* with no GetStmtAttr ! */
304 PUSHSQLERR (pdbc->herr, en_HYC00);
305 goto alloc_stmt_failed;
306 }
307 else
308 { /* get the implicit descriptors */
309 RETCODE rc1;
310
311 for (i = 0; i < 4; i++)
312 {
313 int desc_type = 0;
314
315 switch (i)
316 {
317 case APP_ROW_DESC:
318 desc_type = SQL_ATTR_APP_ROW_DESC;
319 break;
320 case APP_PARAM_DESC:
321 desc_type = SQL_ATTR_APP_PARAM_DESC;
322 break;
323 case IMP_ROW_DESC:
324 desc_type = SQL_ATTR_IMP_ROW_DESC;
325 break;
326 case IMP_PARAM_DESC:
327 desc_type = SQL_ATTR_IMP_PARAM_DESC;
328 break;
329 }
330
331 pstmt->imp_desc[i] = (DESC_t *) MEM_ALLOC (sizeof (DESC_t));
332 if (pstmt->imp_desc[i] == NULL)
333 { /* memory allocation error */
334 PUSHSQLERR (pdbc->herr, en_HY001);
335
336 goto alloc_stmt_failed;
337 }
338 memset (pstmt->imp_desc[i], 0, sizeof (DESC_t));
339 pstmt->imp_desc[i]->type = SQL_HANDLE_DESC;
340 pstmt->imp_desc[i]->hdbc = hdbc;
341 pstmt->imp_desc[i]->hstmt = *phstmt;
342 pstmt->imp_desc[i]->herr = NULL;
343 CALL_DRIVER (hdbc, pstmt, rc1, hproc3,
344 (pstmt->dhstmt, desc_type, &pstmt->imp_desc[i]->dhdesc, 0,
345 NULL));
346 if (rc1 != SQL_SUCCESS && rc1 != SQL_SUCCESS_WITH_INFO)
347 { /* no descriptor returned from the driver */
348 pdbc->rc = SQL_ERROR;
349
350 goto alloc_stmt_failed;
351 }
352 }
353 }
354 }
355 #endif
356
357 /* insert into list */
358 pstmt->next = (STMT_t *) pdbc->hstmt;
359 pdbc->hstmt = pstmt;
360
361 *phstmt = (SQLHSTMT) pstmt;
362
363 /* state transition */
364 pdbc->state = en_dbc_hstmt;
365
366 return SQL_SUCCESS;
367
368 /*
369 * If statement allocation has failed, we need to make sure the driver
370 * handle is also destroyed
371 */
372 alloc_stmt_failed:
373
374 /*
375 * Deallocate any descriptors
376 */
377 for (i = 0; i < 4; i++)
378 {
379 if (pstmt->imp_desc[i])
380 {
381 pstmt->imp_desc[i]->type = 0;
382 MEM_FREE (pstmt->imp_desc[i]);
383 }
384 }
385
386 /*
387 * Tell the driver to remove the statement handle
388 */
389 hproc2 = SQL_NULL_HPROC;
390 hproc3 = SQL_NULL_HPROC;
391
392 hproc2 = _iodbcdm_getproc (pstmt->hdbc, en_FreeStmt);
393 #if (ODBCVER >= 0x0300)
394 hproc3 = _iodbcdm_getproc (pstmt->hdbc, en_FreeHandle);
395 #endif
396
397 if (odbc_ver == SQL_OV_ODBC2 &&
398 ( dodbc_ver == SQL_OV_ODBC2
399 || (dodbc_ver == SQL_OV_ODBC3 && hproc2 != SQL_NULL_HPROC)))
400 hproc3 = SQL_NULL_HPROC;
401
402 #if (ODBCVER >= 0x0300)
403 if (hproc3 != SQL_NULL_HPROC)
404 {
405 CALL_DRIVER (pstmt->hdbc, pstmt, retcode, hproc3,
406 (SQL_HANDLE_STMT, pstmt->dhstmt));
407 }
408 else
409 #endif
410 {
411 if (hproc2 == SQL_NULL_HPROC)
412 {
413 PUSHSQLERR (pdbc->herr, en_IM001);
414 return SQL_ERROR;
415 }
416
417 CALL_DRIVER (pstmt->hdbc, pstmt, retcode, hproc2,
418 (pstmt->dhstmt, SQL_DROP));
419 }
420
421 /*
422 * Invalidate and free the statement handle
423 */
424 pstmt->type = 0;
425 MEM_FREE (pstmt);
426
427 return SQL_ERROR;
428 }
429
430
431 SQLRETURN SQL_API
SQLAllocStmt(SQLHDBC hdbc,SQLHSTMT * phstmt)432 SQLAllocStmt (
433 SQLHDBC hdbc,
434 SQLHSTMT * phstmt)
435 {
436 ENTER_HDBC (hdbc, 1,
437 trace_SQLAllocStmt (TRACE_ENTER, hdbc, phstmt));
438
439 retcode = SQLAllocStmt_Internal (hdbc, phstmt);
440
441 LEAVE_HDBC (hdbc, 1,
442 trace_SQLAllocStmt (TRACE_LEAVE, hdbc, phstmt));
443 }
444
445
446 SQLRETURN
_iodbcdm_dropstmt(HSTMT hstmt)447 _iodbcdm_dropstmt (HSTMT hstmt)
448 {
449 STMT (pstmt, hstmt);
450 STMT (tpstmt, NULL);
451 CONN (pdbc, NULL);
452
453 if (!IS_VALID_HSTMT (pstmt))
454 {
455 return SQL_INVALID_HANDLE;
456 }
457 CLEAR_ERRORS (pstmt);
458
459 pdbc = (DBC_t *) (pstmt->hdbc);
460
461 for (tpstmt = (STMT_t *) pdbc->hstmt;
462 tpstmt != NULL;
463 tpstmt = tpstmt->next)
464 {
465 if (tpstmt == pstmt)
466 {
467 pdbc->hstmt = (HSTMT) pstmt->next;
468 break;
469 }
470
471 if (tpstmt->next == pstmt)
472 {
473 tpstmt->next = pstmt->next;
474 break;
475 }
476 }
477
478 if (tpstmt == NULL)
479 {
480 return SQL_INVALID_HANDLE;
481 }
482
483 #if (ODBCVER >= 0x0300)
484 if (pstmt->row_status_allocated == SQL_TRUE && pstmt->row_status_ptr)
485 MEM_FREE(pstmt->row_status_ptr);
486
487 /* drop the implicit descriptors */
488 if (pstmt->imp_desc[0])
489 {
490 int i;
491 for (i = 0; i < 4; i++)
492 {
493 _iodbcdm_freesqlerrlist (pstmt->imp_desc[i]->herr);
494 pstmt->imp_desc[i]->type = 0;
495 MEM_FREE(pstmt->imp_desc[i]);
496 }
497 }
498 #endif
499
500 MEM_FREE(pstmt->params_buf);
501 MEM_FREE(pstmt->rows_buf);
502
503 if (pstmt->vars_inserted > 0)
504 _iodbcdm_FreeStmtVars(pstmt);
505
506 _iodbcdm_FreeStmtParams(pstmt);
507
508 /*
509 * Invalidate this handle
510 */
511 pstmt->type = 0;
512
513 MEM_FREE (pstmt);
514
515 return SQL_SUCCESS;
516 }
517
518
519 SQLRETURN
SQLFreeStmt_Internal(SQLHSTMT hstmt,SQLUSMALLINT fOption)520 SQLFreeStmt_Internal (
521 SQLHSTMT hstmt,
522 SQLUSMALLINT fOption)
523 {
524 STMT (pstmt, hstmt);
525 CONN (pdbc, pstmt->hdbc);
526 HPROC hproc2 = SQL_NULL_HPROC;
527 HPROC hproc3 = SQL_NULL_HPROC;
528 SQLRETURN retcode = SQL_SUCCESS;
529 SQLUINTEGER odbc_ver = ((GENV_t *) pdbc->genv)->odbc_ver;
530 SQLUINTEGER dodbc_ver = ((ENV_t *) pdbc->henv)->dodbc_ver;
531
532 /* check option */
533 switch (fOption)
534 {
535 case SQL_DROP:
536 case SQL_CLOSE:
537 case SQL_UNBIND:
538 case SQL_RESET_PARAMS:
539 break;
540
541 default:
542 PUSHSQLERR (pstmt->herr, en_S1092);
543 return SQL_ERROR;
544 }
545
546 /* check state */
547 if (pstmt->state >= en_stmt_needdata || pstmt->asyn_on != en_NullProc)
548 {
549 PUSHSQLERR (pstmt->herr, en_S1010);
550 return SQL_ERROR;
551 }
552
553
554 hproc2 = _iodbcdm_getproc (pstmt->hdbc, en_FreeStmt);
555 #if (ODBCVER >= 0x0300)
556 hproc3 = _iodbcdm_getproc (pstmt->hdbc, en_FreeHandle);
557 #endif
558
559 if (odbc_ver == SQL_OV_ODBC2 &&
560 ( dodbc_ver == SQL_OV_ODBC2
561 || (dodbc_ver == SQL_OV_ODBC3 && hproc2 != SQL_NULL_HPROC)))
562 hproc3 = SQL_NULL_HPROC;
563
564 #if (ODBCVER >= 0x0300)
565 if (fOption == SQL_DROP && hproc3 != SQL_NULL_HPROC)
566 {
567 CALL_DRIVER (pstmt->hdbc, pstmt, retcode, hproc3,
568 (SQL_HANDLE_STMT, pstmt->dhstmt));
569 }
570 #endif
571 else
572 {
573 if (hproc2 == SQL_NULL_HPROC)
574 {
575 PUSHSQLERR (pstmt->herr, en_IM001);
576 return SQL_ERROR;
577 }
578
579 CALL_DRIVER (pstmt->hdbc, pstmt, retcode, hproc2,
580 (pstmt->dhstmt, fOption));
581 }
582
583 if (!SQL_SUCCEEDED (retcode))
584 {
585 return retcode;
586 }
587
588 /* state transition */
589 switch (fOption)
590 {
591 case SQL_DROP:
592 /* delete this object (ignore return) */
593 _iodbcdm_RemoveBind (pstmt);
594 _iodbcdm_FreeStmtParams(pstmt);
595 #if 0
596 _iodbcdm_dropstmt (pstmt); /* Delayed until last moment */
597 #endif
598 break;
599
600 case SQL_CLOSE:
601 pstmt->cursor_state = en_stmt_cursor_no;
602 /* This means cursor name set by
603 * SQLSetCursorName() call will also
604 * be erased.
605 */
606
607 switch (pstmt->state)
608 {
609 case en_stmt_allocated:
610 case en_stmt_prepared:
611 break;
612
613 case en_stmt_executed_with_info:
614 case en_stmt_executed:
615 case en_stmt_cursoropen:
616 case en_stmt_fetched:
617 case en_stmt_xfetched:
618 if (pstmt->prep_state)
619 {
620 pstmt->state = en_stmt_prepared;
621 }
622 else
623 {
624 pstmt->state = en_stmt_allocated;
625 }
626 break;
627
628 default:
629 break;
630 }
631 break;
632
633 case SQL_UNBIND:
634 _iodbcdm_RemoveBind (pstmt);
635 break;
636 case SQL_RESET_PARAMS:
637 _iodbcdm_FreeStmtParams(pstmt);
638 break;
639 default:
640 break;
641 }
642
643 return retcode;
644 }
645
646
647 SQLRETURN SQL_API
SQLFreeStmt(SQLHSTMT hstmt,SQLUSMALLINT fOption)648 SQLFreeStmt (
649 SQLHSTMT hstmt,
650 SQLUSMALLINT fOption)
651 {
652 ENTER_STMT (hstmt,
653 trace_SQLFreeStmt (TRACE_ENTER, hstmt, fOption));
654
655 retcode = SQLFreeStmt_Internal (hstmt, fOption);
656
657 LEAVE_STMT (hstmt,
658 trace_SQLFreeStmt (TRACE_LEAVE, hstmt, fOption);
659 if (fOption == SQL_DROP)
660 _iodbcdm_dropstmt (hstmt);
661 );
662 }
663
664
665 static SQLRETURN
SQLSetStmtOption_Internal(SQLHSTMT hstmt,SQLUSMALLINT fOption,SQLUINTEGER vParam)666 SQLSetStmtOption_Internal (
667 SQLHSTMT hstmt,
668 SQLUSMALLINT fOption,
669 SQLUINTEGER vParam)
670 {
671 STMT (pstmt, hstmt);
672 HPROC hproc2 = SQL_NULL_HPROC;
673 HPROC hproc3 = SQL_NULL_HPROC;
674 sqlstcode_t sqlstat = en_00000;
675 SQLRETURN retcode;
676 CONN (pdbc, pstmt->hdbc);
677 SQLUINTEGER odbc_ver = ((GENV_t *) pdbc->genv)->odbc_ver;
678 SQLUINTEGER dodbc_ver = ((ENV_t *) pdbc->henv)->dodbc_ver;
679
680 #if (ODBCVER < 0x0300)
681 /* check option */
682 if ( /* fOption < SQL_STMT_OPT_MIN || */
683 fOption > SQL_STMT_OPT_MAX)
684 {
685 PUSHSQLERR (pstmt->herr, en_S1092);
686 return SQL_ERROR;
687 }
688 #endif /* ODBCVER < 0x0300 */
689
690 if (fOption == SQL_CONCURRENCY
691 || fOption == SQL_CURSOR_TYPE
692 || fOption == SQL_SIMULATE_CURSOR
693 || fOption == SQL_USE_BOOKMARKS)
694 {
695 if (pstmt->asyn_on != en_NullProc)
696 {
697 if (pstmt->prep_state)
698 {
699 sqlstat = en_S1011;
700 }
701 }
702 else
703 {
704 switch (pstmt->state)
705 {
706 case en_stmt_prepared:
707 sqlstat = en_S1011;
708 break;
709
710 case en_stmt_executed_with_info:
711 case en_stmt_executed:
712 case en_stmt_cursoropen:
713 case en_stmt_fetched:
714 case en_stmt_xfetched:
715 sqlstat = en_24000;
716 break;
717
718 case en_stmt_needdata:
719 case en_stmt_mustput:
720 case en_stmt_canput:
721 if (pstmt->prep_state)
722 {
723 sqlstat = en_S1011;
724 }
725 break;
726
727 default:
728 break;
729 }
730 }
731 }
732 else
733 {
734 if (pstmt->asyn_on != en_NullProc)
735 {
736 if (!pstmt->prep_state)
737 {
738 sqlstat = en_S1010;
739 }
740 }
741 else
742 {
743 if (pstmt->state >= en_stmt_needdata)
744 {
745 sqlstat = en_S1010;
746 }
747 }
748 }
749
750 if (sqlstat != en_00000)
751 {
752 PUSHSQLERR (pstmt->herr, sqlstat);
753
754 return SQL_ERROR;
755 }
756
757
758 hproc2 = _iodbcdm_getproc (pstmt->hdbc, en_SetStmtOption);
759 #if (ODBCVER >= 0x0300)
760 hproc3 = _iodbcdm_getproc (pstmt->hdbc, en_SetStmtAttr);
761 #endif
762
763 if (odbc_ver == SQL_OV_ODBC2 &&
764 ( dodbc_ver == SQL_OV_ODBC2
765 || (dodbc_ver == SQL_OV_ODBC3 && hproc2 != SQL_NULL_HPROC)))
766 hproc3 = SQL_NULL_HPROC;
767
768 #if (ODBCVER >= 0x0300)
769 if (hproc3 != SQL_NULL_HPROC)
770 {
771 switch ((int)fOption)
772 {
773 /* ODBC integer attributes */
774 case SQL_ATTR_ASYNC_ENABLE:
775 case SQL_ATTR_CONCURRENCY:
776 case SQL_ATTR_CURSOR_TYPE:
777 case SQL_ATTR_KEYSET_SIZE:
778 case SQL_ATTR_MAX_LENGTH:
779 case SQL_ATTR_MAX_ROWS:
780 case SQL_ATTR_NOSCAN:
781 case SQL_ATTR_QUERY_TIMEOUT:
782 case SQL_ATTR_RETRIEVE_DATA:
783 case SQL_ATTR_ROW_BIND_TYPE:
784 case SQL_ATTR_ROW_NUMBER:
785 case SQL_ATTR_SIMULATE_CURSOR:
786 case SQL_ATTR_USE_BOOKMARKS:
787 CALL_DRIVER (pstmt->hdbc, pstmt, retcode, hproc3,
788 (pstmt->dhstmt, fOption, vParam, 0));
789 break;
790
791 /* ODBC3 attributes */
792 case SQL_ATTR_APP_PARAM_DESC:
793 case SQL_ATTR_APP_ROW_DESC:
794 case SQL_ATTR_CURSOR_SCROLLABLE:
795 case SQL_ATTR_CURSOR_SENSITIVITY:
796 case SQL_ATTR_ENABLE_AUTO_IPD:
797 case SQL_ATTR_FETCH_BOOKMARK_PTR:
798 case SQL_ATTR_IMP_PARAM_DESC:
799 case SQL_ATTR_IMP_ROW_DESC:
800 case SQL_ATTR_METADATA_ID:
801 case SQL_ATTR_PARAM_BIND_OFFSET_PTR:
802 case SQL_ATTR_PARAM_BIND_TYPE:
803 case SQL_ATTR_PARAM_STATUS_PTR:
804 case SQL_ATTR_PARAMS_PROCESSED_PTR:
805 case SQL_ATTR_PARAMSET_SIZE:
806 case SQL_ATTR_ROW_ARRAY_SIZE:
807 case SQL_ATTR_ROW_BIND_OFFSET_PTR:
808 case SQL_ATTR_ROW_OPERATION_PTR:
809 case SQL_ATTR_ROW_STATUS_PTR:
810 case SQL_ATTR_ROWS_FETCHED_PTR:
811 PUSHSQLERR (pstmt->herr, en_IM001);
812 return SQL_ERROR;
813
814 default:
815 CALL_DRIVER (pstmt->hdbc, pstmt, retcode, hproc3,
816 (pstmt->dhstmt, fOption, vParam, SQL_NTS));
817 }
818 }
819 else
820 #endif
821 {
822 if (hproc2 == SQL_NULL_HPROC)
823 {
824 PUSHSQLERR (pstmt->herr, en_IM001);
825 return SQL_ERROR;
826 }
827
828 CALL_DRIVER (pstmt->hdbc, pstmt, retcode, hproc2,
829 (pstmt->dhstmt, fOption, vParam));
830 }
831
832 if (SQL_SUCCEEDED (retcode))
833 {
834 if (fOption == SQL_ROWSET_SIZE || fOption == SQL_ATTR_ROW_ARRAY_SIZE)
835 {
836 pstmt->rowset_size = vParam;
837 if (retcode == SQL_SUCCESS_WITH_INFO)
838 {
839 SQLUINTEGER data;
840 if (SQLGetStmtOption_Internal (hstmt, SQL_ROWSET_SIZE, &data)
841 == SQL_SUCCESS)
842 pstmt->rowset_size = data;
843 }
844 }
845 if (fOption == SQL_BIND_TYPE)
846 pstmt->row_bind_type = vParam;
847 }
848 return retcode;
849 }
850
851
852 SQLRETURN SQL_API
SQLSetStmtOption(SQLHSTMT hstmt,SQLUSMALLINT fOption,SQLULEN vParam)853 SQLSetStmtOption (
854 SQLHSTMT hstmt,
855 SQLUSMALLINT fOption,
856 SQLULEN vParam)
857 {
858 ENTER_STMT (hstmt,
859 trace_SQLSetStmtOption (TRACE_ENTER, hstmt, fOption, vParam));
860
861 retcode = SQLSetStmtOption_Internal (hstmt, fOption, vParam);
862
863 LEAVE_STMT (hstmt,
864 trace_SQLSetStmtOption (TRACE_LEAVE, hstmt, fOption, vParam));
865 }
866
867
868 #if ODBCVER >= 0x0300
869 SQLRETURN SQL_API
SQLSetStmtOptionA(SQLHSTMT hstmt,SQLUSMALLINT fOption,SQLULEN vParam)870 SQLSetStmtOptionA (
871 SQLHSTMT hstmt,
872 SQLUSMALLINT fOption,
873 SQLULEN vParam)
874 {
875 ENTER_STMT (hstmt,
876 trace_SQLSetStmtOption (TRACE_ENTER, hstmt, fOption, vParam));
877
878 retcode = SQLSetStmtOption_Internal (hstmt, fOption, vParam);
879
880 LEAVE_STMT (hstmt,
881 trace_SQLSetStmtOption (TRACE_LEAVE, hstmt, fOption, vParam));
882 }
883 #endif
884
885
886 SQLRETURN
SQLGetStmtOption_Internal(SQLHSTMT hstmt,SQLUSMALLINT fOption,SQLPOINTER pvParam)887 SQLGetStmtOption_Internal (
888 SQLHSTMT hstmt,
889 SQLUSMALLINT fOption,
890 SQLPOINTER pvParam)
891 {
892 STMT (pstmt, hstmt);
893 HPROC hproc2 = SQL_NULL_HPROC;
894 HPROC hproc3 = SQL_NULL_HPROC;
895 sqlstcode_t sqlstat = en_00000;
896 SQLRETURN retcode;
897 CONN (pdbc, pstmt->hdbc);
898 SQLUINTEGER odbc_ver = ((GENV_t *) pdbc->genv)->odbc_ver;
899 SQLUINTEGER dodbc_ver = ((ENV_t *) pdbc->henv)->dodbc_ver;
900
901
902 #if (ODBCVER < 0x0300)
903 /* check option */
904 if ( /* fOption < SQL_STMT_OPT_MIN || */
905 fOption > SQL_STMT_OPT_MAX)
906 {
907 PUSHSQLERR (pstmt->herr, en_S1092);
908 return SQL_ERROR;
909 }
910 #endif /* ODBCVER < 0x0300 */
911
912 /* check state */
913 if (pstmt->state >= en_stmt_needdata || pstmt->asyn_on != en_NullProc)
914 {
915 sqlstat = en_S1010;
916 }
917 else
918 {
919 switch (pstmt->state)
920 {
921 case en_stmt_allocated:
922 case en_stmt_prepared:
923 case en_stmt_executed_with_info:
924 case en_stmt_executed:
925 case en_stmt_cursoropen:
926 if (fOption == SQL_ROW_NUMBER || fOption == SQL_GET_BOOKMARK)
927 {
928 sqlstat = en_24000;
929 }
930 break;
931
932 default:
933 break;
934 }
935 }
936
937 if (sqlstat != en_00000)
938 {
939 PUSHSQLERR (pstmt->herr, sqlstat);
940
941 return SQL_ERROR;
942 }
943
944 hproc2 = _iodbcdm_getproc (pstmt->hdbc, en_GetStmtOption);
945 #if (ODBCVER >= 0x0300)
946 hproc3 = _iodbcdm_getproc (pstmt->hdbc, en_GetStmtAttr);
947 #endif
948
949 if (odbc_ver == SQL_OV_ODBC2 &&
950 ( dodbc_ver == SQL_OV_ODBC2
951 || (dodbc_ver == SQL_OV_ODBC3 && hproc2 != SQL_NULL_HPROC)))
952 hproc3 = SQL_NULL_HPROC;
953
954 #if (ODBCVER >= 0x0300)
955 if (hproc3 != SQL_NULL_HPROC)
956 {
957 switch ((int)fOption)
958 {
959 /* ODBC integer attributes */
960 case SQL_ATTR_ASYNC_ENABLE:
961 case SQL_ATTR_CONCURRENCY:
962 case SQL_ATTR_CURSOR_TYPE:
963 case SQL_ATTR_KEYSET_SIZE:
964 case SQL_ATTR_MAX_LENGTH:
965 case SQL_ATTR_MAX_ROWS:
966 case SQL_ATTR_NOSCAN:
967 case SQL_ATTR_QUERY_TIMEOUT:
968 case SQL_ATTR_RETRIEVE_DATA:
969 case SQL_ATTR_ROW_BIND_TYPE:
970 case SQL_ATTR_ROW_NUMBER:
971 case SQL_ATTR_SIMULATE_CURSOR:
972 case SQL_ATTR_USE_BOOKMARKS:
973 CALL_DRIVER (pstmt->hdbc, pstmt, retcode, hproc3,
974 (pstmt->dhstmt, fOption, pvParam, 0, NULL));
975 break;
976
977 /* ODBC3 attributes */
978 case SQL_ATTR_APP_PARAM_DESC:
979 case SQL_ATTR_APP_ROW_DESC:
980 case SQL_ATTR_CURSOR_SCROLLABLE:
981 case SQL_ATTR_CURSOR_SENSITIVITY:
982 case SQL_ATTR_ENABLE_AUTO_IPD:
983 case SQL_ATTR_FETCH_BOOKMARK_PTR:
984 case SQL_ATTR_IMP_PARAM_DESC:
985 case SQL_ATTR_IMP_ROW_DESC:
986 case SQL_ATTR_METADATA_ID:
987 case SQL_ATTR_PARAM_BIND_OFFSET_PTR:
988 case SQL_ATTR_PARAM_BIND_TYPE:
989 case SQL_ATTR_PARAM_STATUS_PTR:
990 case SQL_ATTR_PARAMS_PROCESSED_PTR:
991 case SQL_ATTR_PARAMSET_SIZE:
992 case SQL_ATTR_ROW_ARRAY_SIZE:
993 case SQL_ATTR_ROW_BIND_OFFSET_PTR:
994 case SQL_ATTR_ROW_OPERATION_PTR:
995 case SQL_ATTR_ROW_STATUS_PTR:
996 case SQL_ATTR_ROWS_FETCHED_PTR:
997 PUSHSQLERR (pstmt->herr, en_IM001);
998 return SQL_ERROR;
999
1000 default:
1001 CALL_DRIVER (pstmt->hdbc, pstmt, retcode, hproc3,
1002 (pstmt->dhstmt, fOption, pvParam, SQL_MAX_OPTION_STRING_LENGTH,
1003 NULL));
1004 break;
1005 }
1006 }
1007 else
1008 #endif
1009 {
1010 if (hproc2 == SQL_NULL_HPROC)
1011 {
1012 PUSHSQLERR (pstmt->herr, en_IM001);
1013 return SQL_ERROR;
1014 }
1015 CALL_DRIVER (pstmt->hdbc, pstmt, retcode, hproc2,
1016 (pstmt->dhstmt, fOption, pvParam));
1017 }
1018 return retcode;
1019 }
1020
1021
1022 SQLRETURN SQL_API
SQLGetStmtOption(SQLHSTMT hstmt,SQLUSMALLINT fOption,SQLPOINTER pvParam)1023 SQLGetStmtOption (
1024 SQLHSTMT hstmt,
1025 SQLUSMALLINT fOption,
1026 SQLPOINTER pvParam)
1027 {
1028 ENTER_STMT (hstmt,
1029 trace_SQLGetStmtOption (TRACE_ENTER, hstmt, fOption, pvParam));
1030
1031 retcode = SQLGetStmtOption_Internal (hstmt, fOption, pvParam);
1032
1033 LEAVE_STMT (hstmt,
1034 trace_SQLGetStmtOption (TRACE_LEAVE, hstmt, fOption, pvParam));
1035 }
1036
1037
1038 #if ODBCVER >= 0x0300
1039 SQLRETURN SQL_API
SQLGetStmtOptionA(SQLHSTMT hstmt,SQLUSMALLINT fOption,SQLPOINTER pvParam)1040 SQLGetStmtOptionA (
1041 SQLHSTMT hstmt,
1042 SQLUSMALLINT fOption,
1043 SQLPOINTER pvParam)
1044 {
1045 ENTER_STMT (hstmt,
1046 trace_SQLGetStmtOption (TRACE_ENTER, hstmt, fOption, pvParam));
1047
1048 retcode = SQLGetStmtOption_Internal (hstmt, fOption, pvParam);
1049
1050 LEAVE_STMT (hstmt,
1051 trace_SQLGetStmtOption (TRACE_LEAVE, hstmt, fOption, pvParam));
1052 }
1053 #endif
1054
1055
1056 static SQLRETURN
SQLCancel_Internal(SQLHSTMT hstmt,int stmt_cip)1057 SQLCancel_Internal (SQLHSTMT hstmt, int stmt_cip)
1058 {
1059 STMT (pstmt, hstmt);
1060 HPROC hproc;
1061 SQLRETURN retcode;
1062
1063
1064 /* check argument */
1065 /* check state */
1066
1067 /* call driver */
1068 hproc = _iodbcdm_getproc (pstmt->hdbc, en_Cancel);
1069
1070 if (hproc == SQL_NULL_HPROC)
1071 {
1072 PUSHSQLERR (pstmt->herr, en_IM001);
1073
1074 return SQL_ERROR;
1075 }
1076
1077 CALL_DRIVER (pstmt->hdbc, pstmt, retcode, hproc, (pstmt->dhstmt));
1078
1079 /* state transition */
1080 if (!SQL_SUCCEEDED (retcode))
1081 {
1082 return retcode;
1083 }
1084
1085 if (stmt_cip == 0)
1086 {
1087 ODBC_LOCK();
1088
1089 switch (pstmt->state)
1090 {
1091 case en_stmt_allocated:
1092 case en_stmt_prepared:
1093 break;
1094
1095 case en_stmt_executed_with_info:
1096 case en_stmt_executed:
1097 if (pstmt->prep_state)
1098 {
1099 pstmt->state = en_stmt_prepared;
1100 }
1101 else
1102 {
1103 pstmt->state = en_stmt_allocated;
1104 }
1105 break;
1106
1107 case en_stmt_cursoropen:
1108 case en_stmt_fetched:
1109 case en_stmt_xfetched:
1110 if (pstmt->prep_state)
1111 {
1112 pstmt->state = en_stmt_prepared;
1113 }
1114 else
1115 {
1116 pstmt->state = en_stmt_allocated;
1117 }
1118 break;
1119
1120 case en_stmt_needdata:
1121 case en_stmt_mustput:
1122 case en_stmt_canput:
1123 switch (pstmt->need_on)
1124 {
1125 case en_ExecDirect:
1126 pstmt->state = en_stmt_allocated;
1127 break;
1128
1129 case en_Execute:
1130 pstmt->state = en_stmt_prepared;
1131 break;
1132
1133 case en_SetPos:
1134 pstmt->state = en_stmt_xfetched;
1135 break;
1136
1137 default:
1138 break;
1139 }
1140 pstmt->need_on = en_NullProc;
1141 break;
1142
1143 default:
1144 break;
1145 }
1146
1147 ODBC_UNLOCK();
1148 }
1149
1150 return retcode;
1151 }
1152
1153
1154 SQLRETURN SQL_API
SQLCancel(SQLHSTMT hstmt)1155 SQLCancel (SQLHSTMT hstmt)
1156 {
1157 ENTER_STMT_CANCEL (hstmt,
1158 trace_SQLCancel (TRACE_ENTER, hstmt));
1159
1160 retcode = SQLCancel_Internal (hstmt, stmt_cip);
1161
1162 LEAVE_STMT_CANCEL (hstmt,
1163 trace_SQLCancel (TRACE_LEAVE, hstmt));
1164 }
1165
1166
1167 void
_iodbcdm_FreeStmtVars(STMT_t * pstmt)1168 _iodbcdm_FreeStmtVars(STMT_t *pstmt)
1169 {
1170 int i;
1171 VAR_t *p;
1172
1173 for(i= 0; i < STMT_VARS_MAX; i++)
1174 {
1175 p = &pstmt->vars[i];
1176 if (p->data)
1177 {
1178 free(p->data);
1179 p->data = NULL;
1180 }
1181 p->length = 0;
1182 }
1183 pstmt->vars_inserted = 0;
1184 }
1185
1186
1187 void
_iodbcdm_FreeStmtParams(STMT_t * pstmt)1188 _iodbcdm_FreeStmtParams(STMT_t *pstmt)
1189 {
1190 PPARM pparm;
1191 int i, maxpar;
1192
1193 if (pstmt->st_pparam)
1194 {
1195 maxpar = pstmt->st_nparam;
1196 pparm = pstmt->st_pparam;
1197 for (i = 0; i < maxpar; i++, pparm++)
1198 {
1199 if (pparm->pm_tmp)
1200 {
1201 free(pparm->pm_tmp);
1202 pparm->pm_tmp = NULL;
1203 }
1204 if (pparm->pm_tmp_Ind)
1205 {
1206 free(pparm->pm_tmp_Ind);
1207 pparm->pm_tmp_Ind = NULL;
1208 }
1209 }
1210 free (pstmt->st_pparam);
1211 pstmt->st_pparam = NULL;
1212 }
1213
1214 pstmt->st_nparam = 0;
1215 }
1216
1217
1218 void *
_iodbcdm_alloc_var(STMT_t * pstmt,int i,int size)1219 _iodbcdm_alloc_var(STMT_t *pstmt, int i, int size)
1220 {
1221 VAR_t *var;
1222
1223 if (i > STMT_VARS_MAX - 1)
1224 return NULL;
1225
1226 var = &pstmt->vars[i];
1227 pstmt->vars_inserted = 1;
1228
1229 if (size == 0)
1230 {
1231 MEM_FREE(var->data);
1232 var->data = NULL;
1233 var->length = 0;
1234 return NULL;
1235 }
1236
1237 if (var->data == NULL || var->length < size)
1238 {
1239 MEM_FREE(var->data);
1240 var->length = 0;
1241 if ((var->data = MEM_ALLOC(size)) != NULL)
1242 var->length = size;
1243 }
1244
1245 return var->data;
1246 }
1247
1248
1249 /** DM => DRV**/
1250 void *
_iodbcdm_conv_var(STMT_t * pstmt,int i,void * pData,int pDataLength,CONV_DIRECT direct)1251 _iodbcdm_conv_var(STMT_t *pstmt, int i, void *pData, int pDataLength,
1252 CONV_DIRECT direct)
1253 {
1254 VAR_t *var;
1255 size_t size;
1256 int count_alloc = 0;
1257 CONN (pdbc, pstmt->hdbc);
1258 ENVR (penv, pdbc->henv);
1259 DM_CONV *conv = &pdbc->conv;
1260 IODBC_CHARSET m_charset = (conv) ? conv->dm_cp : CP_DEF;
1261 IODBC_CHARSET d_charset = (conv) ? conv->drv_cp : CP_DEF;
1262
1263 if (i > STMT_VARS_MAX - 1 || direct == CD_NONE)
1264 return NULL;
1265
1266 var = &pstmt->vars[i];
1267 pstmt->vars_inserted = 1;
1268
1269 if (pData == NULL)
1270 {
1271 MEM_FREE(var->data);
1272 var->data = NULL;
1273 var->length = 0;
1274 return NULL;
1275 }
1276
1277
1278 if (pDataLength == SQL_NTS)
1279 {
1280 if (direct == CD_W2A || direct == CD_W2W)
1281 size = DM_WCSLEN(conv, pData);
1282 else
1283 size = strlen((char *) pData);
1284 }
1285 else
1286 size = pDataLength;
1287
1288 if (direct == CD_W2A )
1289 count_alloc = size * MB_CUR_MAX + 1;
1290 else
1291 count_alloc = (size + 1) * DRV_WCHARSIZE_ALLOC(conv);
1292
1293 if (var->data == NULL || var->length < count_alloc)
1294 {
1295 MEM_FREE(var->data);
1296 var->length = 0;
1297 if ((var->data = MEM_ALLOC(count_alloc)) != NULL)
1298 var->length = count_alloc;
1299 }
1300
1301 if (direct == CD_A2W)
1302 {
1303 size = dm_conv_A2W((char *)pData, pDataLength, var->data,
1304 count_alloc - DRV_WCHARSIZE(conv), d_charset);
1305 if (d_charset == CP_UTF8)
1306 *(char*)(var->data + size) = 0;
1307 else
1308 DRV_SetWCharAt(conv, var->data, size/DRV_WCHARSIZE(conv), 0);
1309 }
1310 else if (direct == CD_W2A)
1311 {
1312 size = dm_conv_W2A(pData, pDataLength, (char *)var->data, count_alloc - 1,
1313 m_charset);
1314 ((char*)var->data)[size] = '\0';
1315 }
1316 else /* CD_W2W*/
1317 {
1318 size = dm_conv_W2W(pData, pDataLength, (char *)var->data,
1319 count_alloc - DRV_WCHARSIZE(conv), m_charset, d_charset);
1320 if (d_charset == CP_UTF8)
1321 *(char*)(var->data + size) = 0;
1322 else
1323 DRV_SetWCharAt(conv, var->data, size/DRV_WCHARSIZE(conv), 0);
1324 }
1325
1326 return (void *) var->data;
1327
1328 }
1329
1330
1331 SQLRETURN
_iodbcdm_BindColumn(STMT_t * pstmt,BIND_t * pbind)1332 _iodbcdm_BindColumn (STMT_t *pstmt, BIND_t *pbind)
1333 {
1334 PBLST pblst;
1335 PBLST prev;
1336
1337 /*
1338 * Initialize the cell
1339 */
1340 if ((pblst = (PBLST) calloc (1, sizeof (TBLST))) == NULL)
1341 {
1342 return SQL_ERROR;
1343 }
1344 pblst->bl_bind = *pbind;
1345
1346 /*
1347 * First on the list?
1348 */
1349 if (pstmt->st_pbinding == NULL)
1350 {
1351 pstmt->st_pbinding = pblst;
1352 return SQL_SUCCESS;
1353 }
1354
1355 for (prev = pstmt->st_pbinding; ; prev = prev->bl_nextBind)
1356 {
1357 /*
1358 * Column already on the linked list?
1359 */
1360 if (prev->bl_bind.bn_col == pbind->bn_col)
1361 {
1362 prev->bl_bind = *pbind;
1363 MEM_FREE (pblst);
1364 return SQL_SUCCESS;
1365 }
1366 if (prev->bl_nextBind == NULL)
1367 break;
1368 }
1369 prev->bl_nextBind = pblst;
1370
1371 return SQL_SUCCESS;
1372 }
1373
1374
1375 /*
1376 * Remove a binding from the linked list
1377 */
1378 int
_iodbcdm_UnBindColumn(STMT_t * pstmt,BIND_t * pbind)1379 _iodbcdm_UnBindColumn (STMT_t *pstmt, BIND_t *pbind)
1380 {
1381 PBLST pNewNextBind;
1382 PBLST *pBindHistory;
1383
1384 /*
1385 * Anything on the list? No? Nothing to do.
1386 */
1387 if (pstmt->st_pbinding == NULL)
1388 return 0;
1389
1390 for (pBindHistory = &pstmt->st_pbinding; (*pBindHistory);
1391 pBindHistory = &(*pBindHistory)->bl_nextBind)
1392 {
1393 /*
1394 * Column already on the linked list?
1395 */
1396 if ((*pBindHistory)->bl_bind.bn_col == pbind->bn_col)
1397 {
1398 pNewNextBind = (*pBindHistory)->bl_nextBind;
1399 free (*pBindHistory);
1400 (*pBindHistory) = pNewNextBind;
1401 return 0;
1402 }
1403 }
1404 return 0;
1405 }
1406
1407
1408 /*
1409 * Remove all bindings
1410 */
1411 void
_iodbcdm_RemoveBind(STMT_t * pstmt)1412 _iodbcdm_RemoveBind (STMT_t *pstmt)
1413 {
1414 BIND_t *col;
1415 PBLST pblst, pnext;
1416
1417 if (pstmt->st_pbinding)
1418 {
1419 for (pblst = pstmt->st_pbinding; pblst; pblst = pnext)
1420 {
1421 col = &(pblst->bl_bind);
1422
1423 MEM_FREE(col->bn_tmp);
1424 MEM_FREE(col->bn_tmp_Ind);
1425
1426 pnext = pblst->bl_nextBind;
1427 free (pblst);
1428 }
1429 pstmt->st_pbinding = NULL;
1430 }
1431 }
1432
1433
1434
1435 static void
_iodbcdm_bindConv_A2W_d2m(char * data,SQLLEN * pInd,UDWORD size,DM_CONV * conv)1436 _iodbcdm_bindConv_A2W_d2m(char *data, SQLLEN *pInd, UDWORD size, DM_CONV *conv)
1437 {
1438 if (*pInd != SQL_NULL_DATA)
1439 {
1440 int count = 0;
1441 char *buf = calloc(size + 1, sizeof(char));
1442
1443 if (buf != NULL)
1444 {
1445 memcpy(buf, data, size);
1446 dm_StrCopyOut2_A2W_d2m (conv, (SQLCHAR *)buf, data, size, NULL, &count);
1447 MEM_FREE(buf);
1448 }
1449
1450 if (pInd && *pInd != SQL_NTS)
1451 *pInd =(SQLLEN)count;
1452 }
1453 }
1454
1455 static void
_iodbcdm_bindConv_W2A_m2d(char * data,SQLLEN * pInd,UDWORD size,DM_CONV * conv)1456 _iodbcdm_bindConv_W2A_m2d(char *data, SQLLEN *pInd, UDWORD size, DM_CONV *conv)
1457 {
1458 if (*pInd != SQL_NULL_DATA)
1459 {
1460 int count = 0;
1461 char *buf = calloc(size + 1, sizeof(char));
1462
1463 if (buf != NULL)
1464 {
1465 memcpy(buf, data, size);
1466 dm_StrCopyOut2_W2A_m2d (conv, buf, (SQLCHAR *)data, size, NULL, &count);
1467 MEM_FREE(buf);
1468 }
1469
1470 if (pInd && *pInd != SQL_NTS)
1471 *pInd =(SQLLEN)count;
1472 }
1473 }
1474
1475
1476 static void
_iodbcdm_bindConv_W2W_d2m(char * data,SQLLEN * pInd,UDWORD size,DM_CONV * conv)1477 _iodbcdm_bindConv_W2W_d2m(char *data, SQLLEN *pInd, UDWORD size, DM_CONV *conv)
1478 {
1479 if (*pInd != SQL_NULL_DATA)
1480 {
1481 int count = 0;
1482 char *buf = calloc(size + WCHAR_MAXSIZE, sizeof(char));
1483
1484 if (buf != NULL)
1485 {
1486 memcpy(buf, data, size);
1487 dm_StrCopyOut2_W2W_d2m (conv, buf, data, size, NULL, &count);
1488 MEM_FREE(buf);
1489 }
1490
1491 if (pInd && *pInd != SQL_NTS)
1492 *pInd =(SQLLEN)count;
1493 }
1494 }
1495
1496 static void
_iodbcdm_bindConv_W2W_m2d(char * data,SQLLEN * pInd,UDWORD size,DM_CONV * conv)1497 _iodbcdm_bindConv_W2W_m2d(char *data, SQLLEN *pInd, UDWORD size, DM_CONV *conv)
1498 {
1499 if (*pInd != SQL_NULL_DATA)
1500 {
1501 int count = 0;
1502 char *buf = calloc(size + WCHAR_MAXSIZE, sizeof(char));
1503
1504 if (buf != NULL)
1505 {
1506 memcpy(buf, data, size);
1507 dm_StrCopyOut2_W2W_m2d (conv, buf, data, size, NULL, &count);
1508 MEM_FREE(buf);
1509 }
1510
1511 if (pInd && *pInd != SQL_NTS)
1512 *pInd =(SQLLEN)count;
1513 }
1514 }
1515
1516
1517 static SQLLEN
GetColSize(BIND_t * col)1518 GetColSize (BIND_t *col)
1519 {
1520 SQLLEN elementSize;
1521
1522
1523 if (col->bn_type == SQL_C_CHAR
1524 || col->bn_type == SQL_C_BINARY
1525 || col->bn_type == SQL_C_WCHAR)
1526 {
1527 elementSize = col->bn_size;
1528 }
1529 else /* fixed length types */
1530 {
1531 elementSize = _iodbcdm_OdbcCTypeSize(col->bn_type);
1532 }
1533
1534 return elementSize;
1535 }
1536
1537
1538 /** drv => dm **/
1539 void
_iodbcdm_ConvBindData(STMT_t * pstmt)1540 _iodbcdm_ConvBindData (STMT_t *pstmt)
1541 {
1542 PBLST ptr;
1543 BIND_t *col;
1544 UDWORD i, size, row_size;
1545 CONN (pdbc, pstmt->hdbc);
1546 ENVR (penv, pdbc->henv);
1547 DM_CONV *conv = &pdbc->conv;
1548 IODBC_CHARSET m_charset = CP_DEF;
1549 IODBC_CHARSET d_charset = CP_DEF;
1550 SQLULEN cRows = pstmt->rowset_size;
1551 SQLUINTEGER bindOffset = pstmt->row_bind_offset;
1552
1553 /*
1554 * Anything on the list? No? Nothing to do.
1555 */
1556 if (pstmt->st_pbinding == NULL)
1557 return ;
1558
1559 if (cRows == 0)
1560 cRows = 1;
1561
1562 if (conv)
1563 {
1564 m_charset = conv ? conv->dm_cp: CP_DEF;
1565 d_charset = conv ? conv->drv_cp: CP_DEF;
1566 }
1567
1568 for (ptr = pstmt->st_pbinding; ptr; ptr = ptr->bl_nextBind)
1569 {
1570 col = &(ptr->bl_bind);
1571
1572 for (i = 0; i < cRows; i++)
1573 {
1574 void *val_dm = NULL;
1575 void *val_drv = NULL;
1576 SQLLEN *pInd_dm = NULL;
1577 SQLLEN *pInd_drv = NULL;
1578 SQLLEN len;
1579 size = GetColSize(col);
1580
1581 if (pstmt->row_bind_type == SQL_BIND_BY_COLUMN)
1582 {
1583 if (col->bn_pInd)
1584 pInd_dm = &((SQLLEN*)((char*)col->bn_pInd + bindOffset))[i];
1585 val_dm = (char *) col->bn_data + i * size + bindOffset;
1586
1587 if (col->rebinded)
1588 {
1589 pInd_drv = &((SQLLEN*)col->bn_conv_pInd)[i];
1590 val_drv = (char *) col->bn_conv_data + i * col->bn_conv_size;
1591 }
1592 }
1593 else /* row-wise binding */
1594 {
1595 row_size = pstmt->row_bind_type;
1596 if (col->bn_pInd)
1597 pInd_dm = (SQLLEN *) ((char *) col->bn_pInd
1598 + i * row_size + bindOffset);
1599
1600 val_dm = (char *) col->bn_data + i * row_size + bindOffset;
1601
1602 if (col->rebinded)
1603 {
1604 pInd_drv = (SQLLEN *) ((char *) col->bn_conv_pInd
1605 + i * pstmt->conv_row_bind_type);
1606 val_drv = (char *) col->bn_conv_data
1607 + i * pstmt->conv_row_bind_type;
1608 }
1609 }
1610
1611
1612 if (col->rebinded)
1613 {
1614 if (*pInd_drv != SQL_NULL_DATA)
1615 {
1616 if (col->bn_type==SQL_C_WCHAR)
1617 {
1618 len = (SQLLEN)*pInd_drv;
1619
1620 len = dm_conv_W2W(val_drv, len, val_dm, size,
1621 d_charset, m_charset);
1622 if (m_charset == CP_UTF8)
1623 *(char*)(val_dm + len) = 0;
1624 else
1625 DM_SetWCharAt(conv, val_dm, len/DM_WCHARSIZE(conv), 0);
1626
1627 if (pInd_dm)
1628 *pInd_dm = (*pInd_drv != SQL_NTS)? len: SQL_NTS;
1629 }
1630 else
1631 {
1632 memcpy(val_dm, val_drv, size);
1633 if (pInd_dm)
1634 *pInd_dm = *pInd_drv;
1635 }
1636 }
1637 else
1638 {
1639 if (pInd_dm)
1640 *pInd_dm = *pInd_drv;
1641 }
1642 }
1643 else
1644 {
1645 if (col->direct == CD_A2W)
1646 _iodbcdm_bindConv_A2W_d2m(val_dm, pInd_dm, size, conv);
1647 else if (col->direct == CD_W2W)
1648 _iodbcdm_bindConv_W2W_d2m(val_dm, pInd_dm, size, conv);
1649 }
1650 }
1651 }
1652 }
1653
1654
1655
1656 /** dm => drv **/
1657 void
_iodbcdm_ConvBindData_m2d(STMT_t * pstmt)1658 _iodbcdm_ConvBindData_m2d (STMT_t *pstmt)
1659 {
1660 PBLST ptr;
1661 BIND_t *col;
1662 UDWORD i, size, row_size;
1663 CONN (pdbc, pstmt->hdbc);
1664 ENVR (penv, pdbc->henv);
1665 DM_CONV *conv = &pdbc->conv;
1666 IODBC_CHARSET m_charset = CP_DEF;
1667 IODBC_CHARSET d_charset = CP_DEF;
1668 SQLULEN cRows = pstmt->rowset_size;
1669 SQLUINTEGER bindOffset = pstmt->row_bind_offset;
1670
1671 /*
1672 * Anything on the list? No? Nothing to do.
1673 */
1674 if (pstmt->st_pbinding == NULL)
1675 return ;
1676
1677 if (cRows == 0)
1678 cRows = 1;
1679
1680 if (conv)
1681 {
1682 m_charset = conv ? conv->dm_cp: CP_DEF;
1683 d_charset = conv ? conv->drv_cp: CP_DEF;
1684 }
1685
1686 for (ptr = pstmt->st_pbinding; ptr; ptr = ptr->bl_nextBind)
1687 {
1688 col = &(ptr->bl_bind);
1689
1690 for (i = 0; i < cRows; i++)
1691 {
1692 void *val_dm = NULL;
1693 void *val_drv = NULL;
1694 SQLLEN *pInd_dm = NULL;
1695 SQLLEN *pInd_drv = NULL;
1696 SQLLEN len;
1697 size = GetColSize(col);
1698
1699 if (pstmt->row_bind_type == SQL_BIND_BY_COLUMN)
1700 {
1701 if (col->bn_pInd)
1702 pInd_dm = &((SQLLEN*)((char*)col->bn_pInd + bindOffset))[i];
1703 val_dm = (char *) col->bn_data + i * size + bindOffset;
1704
1705 if (col->rebinded)
1706 {
1707 pInd_drv = &((SQLLEN*)col->bn_conv_pInd)[i];
1708 val_drv = (char *) col->bn_conv_data + i * col->bn_conv_size;
1709 }
1710 }
1711 else /* row-wise binding */
1712 {
1713 row_size = pstmt->row_bind_type;
1714 if (col->bn_pInd)
1715 pInd_dm = (SQLLEN *) ((char *) col->bn_pInd
1716 + i * row_size + bindOffset);
1717
1718 val_dm = (char *) col->bn_data + i * row_size + bindOffset;
1719
1720 if (col->rebinded)
1721 {
1722 pInd_drv = (SQLLEN *) ((char *) col->bn_conv_pInd
1723 + i * pstmt->conv_row_bind_type);
1724 val_drv = (char *) col->bn_conv_data
1725 + i * pstmt->conv_row_bind_type;
1726 }
1727 }
1728
1729
1730 if (col->rebinded)
1731 {
1732 if (*pInd_dm != SQL_NULL_DATA)
1733 {
1734 if (col->bn_type==SQL_C_WCHAR)
1735 {
1736 len = (SQLLEN)*pInd_dm;
1737 size = size/DM_WCHARSIZE(conv)*DRV_WCHARSIZE(conv);
1738
1739 len = dm_conv_W2W(val_dm, len, val_drv, size,
1740 m_charset, d_charset);
1741 if (d_charset == CP_UTF8)
1742 *(char*)(val_dm + len) = 0;
1743 else
1744 DRV_SetWCharAt(conv, val_drv, len/DRV_WCHARSIZE(conv), 0);
1745
1746 if (pInd_dm)
1747 *pInd_drv = (*pInd_dm != SQL_NTS)? len: SQL_NTS;
1748 }
1749 else
1750 {
1751 memcpy(val_drv, val_dm, size);
1752 if (pInd_dm)
1753 *pInd_drv = *pInd_dm;
1754 }
1755 }
1756 else
1757 {
1758 if (pInd_dm)
1759 *pInd_drv = *pInd_dm;
1760 }
1761 }
1762 else /* convert on place */
1763 {
1764 if (col->direct == CD_A2W)
1765 _iodbcdm_bindConv_W2A_m2d(val_dm, pInd_dm, size, conv);
1766 else if (col->direct == CD_W2W)
1767 _iodbcdm_bindConv_W2W_m2d(val_dm, pInd_dm, size, conv);
1768 }
1769 }
1770 }
1771 }
1772
1773
1774
1775 static SQLRETURN
_ReBindCol(STMT_t * pstmt,BIND_t * col)1776 _ReBindCol (STMT_t *pstmt, BIND_t *col)
1777 {
1778 HPROC hproc = SQL_NULL_HPROC;
1779 SQLRETURN retcode = SQL_SUCCESS;
1780
1781 hproc = _iodbcdm_getproc (pstmt->hdbc, en_BindCol);
1782 if (hproc == SQL_NULL_HPROC)
1783 {
1784 PUSHSQLERR (pstmt->herr, en_IM001);
1785 return SQL_ERROR;
1786 }
1787
1788 CALL_DRIVER (pstmt->hdbc, pstmt, retcode, hproc,
1789 (pstmt->dhstmt, col->bn_col, col->bn_type, col->bn_conv_data,
1790 col->bn_conv_size, col->bn_conv_pInd));
1791
1792 return retcode;
1793 }
1794
1795
1796 SQLRETURN
_iodbcdm_FixColBindData(STMT_t * pstmt)1797 _iodbcdm_FixColBindData (STMT_t *pstmt)
1798 {
1799 PBLST ptr;
1800 BIND_t *col;
1801 CONN (pdbc, pstmt->hdbc);
1802 ENVR (penv, pdbc->henv);
1803 SQLUINTEGER odbc_ver = ((GENV_t *) pdbc->genv)->odbc_ver;
1804 SQLUINTEGER dodbc_ver = ((ENV_t *) pdbc->henv)->dodbc_ver;
1805 DM_CONV *conv = &pdbc->conv;
1806 IODBC_CHARSET m_charset = CP_DEF;
1807 IODBC_CHARSET d_charset = CP_DEF;
1808 BOOL needRebind = FALSE;
1809 SQLLEN sz_mult = 1;
1810 SQLULEN cRows = pstmt->rowset_size;
1811 HPROC hproc2 = SQL_NULL_HPROC;
1812 HPROC hproc3 = SQL_NULL_HPROC;
1813 SQLRETURN retcode = SQL_SUCCESS;
1814
1815
1816 /*
1817 * Anything on the list? No? Nothing to do.
1818 */
1819 if (pstmt->st_pbinding == NULL)
1820 return SQL_SUCCESS;
1821
1822 if (cRows == 0)
1823 cRows = 1;
1824
1825 if (conv)
1826 {
1827 m_charset = conv ? conv->dm_cp: CP_DEF;
1828 d_charset = conv ? conv->drv_cp: CP_DEF;
1829
1830 if (m_charset==CP_UTF16 && d_charset==CP_UCS4)
1831 sz_mult = 2;
1832 else if (m_charset==CP_UTF8 && d_charset==CP_UCS4)
1833 sz_mult = 4;
1834 else if (m_charset==CP_UTF8 && d_charset==CP_UTF16)
1835 sz_mult = 2;
1836 else
1837 sz_mult = 1;
1838 }
1839
1840 if (penv->unicode_driver)
1841 {
1842 if (conv==NULL || (conv && conv->dm_cp == conv->drv_cp))
1843 {
1844 needRebind = FALSE;
1845 }
1846 else if ((m_charset==CP_UTF16 && d_charset==CP_UCS4)
1847 ||(m_charset==CP_UTF8 && d_charset==CP_UTF16)
1848 ||(m_charset==CP_UTF8 && d_charset==CP_UCS4))
1849 {
1850 /* check if we need rebind columns */
1851 for (ptr = pstmt->st_pbinding; ptr; ptr = ptr->bl_nextBind)
1852 {
1853 col = &(ptr->bl_bind);
1854 if (col->bn_type==SQL_C_WCHAR && col->direct==CD_W2W)
1855 {
1856 needRebind = TRUE;
1857 break;
1858 }
1859 }
1860 }
1861 }
1862
1863 if (needRebind)
1864 {
1865 SQLULEN new_size = 0;
1866 void *buf = NULL;
1867
1868 if (pstmt->row_bind_type == SQL_BIND_BY_COLUMN)
1869 {
1870 for (ptr = pstmt->st_pbinding; ptr; ptr = ptr->bl_nextBind)
1871 {
1872 col = &(ptr->bl_bind);
1873
1874 XFREE(col->bn_tmp);
1875 XFREE(col->bn_tmp_Ind);
1876
1877 col->bn_conv_size = GetColSize(col);
1878 if (col->bn_type==SQL_C_WCHAR)
1879 col->bn_conv_size *= sz_mult;
1880
1881 new_size = cRows * col->bn_conv_size;
1882 buf = calloc(new_size, sizeof(char));
1883 if (!buf)
1884 {
1885 PUSHSQLERR (pstmt->herr, en_HY001);
1886 return SQL_ERROR;
1887 }
1888 col->bn_tmp = col->bn_conv_data = buf;
1889
1890 buf = calloc(cRows, sizeof(SQLLEN));
1891 if (!buf)
1892 {
1893 PUSHSQLERR (pstmt->herr, en_HY001);
1894 return SQL_ERROR;
1895 }
1896 col->bn_tmp_Ind = col->bn_conv_pInd = (SQLLEN*)buf;
1897
1898 retcode = _ReBindCol(pstmt, col);
1899 if (!SQL_SUCCEEDED (retcode))
1900 return retcode;
1901 col->rebinded = TRUE;
1902
1903 }
1904
1905 }
1906 else /* row-wise bind*/
1907 {
1908
1909 /* calc new_size */
1910 for (ptr = pstmt->st_pbinding; ptr; ptr = ptr->bl_nextBind)
1911 {
1912 col = &(ptr->bl_bind);
1913 new_size += sizeof(SQLLEN);
1914
1915 col->bn_conv_size = GetColSize(col);
1916 if (col->bn_type==SQL_C_WCHAR)
1917 col->bn_conv_size *= sz_mult;
1918
1919 new_size += col->bn_conv_size;
1920 }
1921
1922 if (pstmt->rows_buf)
1923 {
1924 free(pstmt->rows_buf);
1925 pstmt->rows_buf = NULL;
1926 }
1927
1928 buf = calloc((new_size*cRows), sizeof(char));
1929 if (!buf)
1930 {
1931 PUSHSQLERR (pstmt->herr, en_HY001);
1932 return SQL_ERROR;
1933 }
1934 pstmt->rows_buf = buf;
1935 pstmt->conv_row_bind_type = new_size;
1936
1937 /***** Set Bind_type in driver to new size *****/
1938 if (dodbc_ver == SQL_OV_ODBC3)
1939 {
1940 CALL_UDRIVER(pstmt->hdbc, pstmt, retcode, hproc3,
1941 penv->unicode_driver, en_SetStmtAttr, (pstmt->dhstmt,
1942 (SQLINTEGER)SQL_ATTR_ROW_BIND_TYPE,
1943 (SQLPOINTER)new_size, 0));
1944 if (hproc3 == SQL_NULL_HPROC)
1945 {
1946 PUSHSQLERR (pstmt->herr, en_IM001);
1947 return SQL_ERROR;
1948 }
1949 }
1950 else
1951 {
1952 hproc2 = _iodbcdm_getproc (pstmt->hdbc, en_SetStmtOption);
1953 if (hproc2 == SQL_NULL_HPROC)
1954 hproc2 = _iodbcdm_getproc (pstmt->hdbc, en_SetStmtOptionA);
1955
1956 if (hproc2 == SQL_NULL_HPROC)
1957 {
1958 PUSHSQLERR (pstmt->herr, en_IM001);
1959 return SQL_ERROR;
1960 }
1961
1962 CALL_DRIVER (pstmt->hdbc, pstmt, retcode, hproc2,
1963 (pstmt->dhstmt,
1964 (SQLUSMALLINT)SQL_BIND_TYPE,
1965 (SQLUINTEGER)new_size));
1966
1967 }
1968 if (!SQL_SUCCEEDED (retcode))
1969 return retcode;
1970
1971 /* rebind parameters */
1972 buf = pstmt->rows_buf;
1973 for (ptr = pstmt->st_pbinding; ptr; ptr = ptr->bl_nextBind)
1974 {
1975 col = &(ptr->bl_bind);
1976
1977 col->bn_conv_data = buf;
1978 buf += col->bn_conv_size;
1979
1980 col->bn_conv_pInd = (SQLLEN*)buf;
1981 buf += sizeof(SQLLEN);
1982
1983 retcode = _ReBindCol(pstmt, col);
1984 if (!SQL_SUCCEEDED (retcode))
1985 return retcode;
1986 col->rebinded = TRUE;
1987 }
1988 }
1989
1990
1991 /***** Set ColSet offset *****/
1992 if (dodbc_ver == SQL_OV_ODBC3)
1993 {
1994 CALL_UDRIVER(pstmt->hdbc, pstmt, retcode, hproc3,
1995 penv->unicode_driver, en_SetStmtAttr, (pstmt->dhstmt,
1996 (SQLINTEGER)SQL_ATTR_ROW_BIND_OFFSET_PTR,
1997 (SQLPOINTER)0, 0));
1998 if (hproc3 == SQL_NULL_HPROC)
1999 {
2000 PUSHSQLERR (pstmt->herr, en_IM001);
2001 return SQL_ERROR;
2002 }
2003 }
2004 #if 0
2005 if (!SQL_SUCCEEDED (retcode))
2006 return retcode;
2007 #endif
2008 }
2009
2010 return SQL_SUCCESS;
2011 }
2012