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