1 /*
2  *  hdbc.c
3  *
4  *  $Id$
5  *
6  *  Data source connect 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 #include <sqlucode.h>
84 #include <iodbcext.h>
85 
86 #include "unicode.h"
87 
88 #include "dlproc.h"
89 
90 #include "herr.h"
91 #include "henv.h"
92 #include "hdbc.h"
93 #include "hstmt.h"
94 
95 #include "itrace.h"
96 #include <stdio.h>
97 
98 
99 extern SQLRETURN _iodbcdm_driverunload (HDBC hdbc, int ver);
100 
101 static SQLRETURN
_iodbcdm_drvopt_store(SQLHDBC hdbc,SQLUSMALLINT fOption,SQLULEN vParam,SQLCHAR waMode)102 _iodbcdm_drvopt_store (SQLHDBC hdbc, SQLUSMALLINT fOption, SQLULEN vParam,
103 	SQLCHAR waMode)
104 {
105   CONN (pdbc, hdbc);
106   DRVOPT *popt;
107 
108   /*
109    *  Check if this option is already registered
110    */
111   for (popt = pdbc->drvopt; popt != NULL; popt = popt->next)
112     {
113       if (popt->Option == fOption)
114 	break;
115     }
116 
117   /*
118    *  New option
119    */
120   if (popt == NULL)
121     {
122       if ((popt = (DRVOPT *) MEM_ALLOC (sizeof (DRVOPT))) == NULL)
123 	return SQL_ERROR;
124 
125       popt->Option = fOption;
126       popt->next = pdbc->drvopt;
127       pdbc->drvopt = popt;
128     }
129 
130   /*
131    *  Store the value
132    */
133   popt->Param = vParam;
134   popt->waMode = waMode;
135 
136   return SQL_SUCCESS;
137 }
138 
139 
140 static SQLRETURN
_iodbcdm_drvopt_free(SQLHDBC hdbc)141 _iodbcdm_drvopt_free (SQLHDBC hdbc)
142 {
143   CONN (pdbc, hdbc);
144   DRVOPT *popt;
145 
146   popt = pdbc->drvopt;
147   while (popt != NULL)
148     {
149       DRVOPT *tmp = popt->next;
150       free (popt);
151       popt = tmp;
152     }
153   pdbc->drvopt = NULL;
154 
155   return SQL_SUCCESS;
156 }
157 
158 
159 SQLRETURN
SQLAllocConnect_Internal(SQLHENV henv,SQLHDBC * phdbc)160 SQLAllocConnect_Internal (
161     SQLHENV henv,
162     SQLHDBC * phdbc)
163 {
164   GENV (genv, henv);
165   CONN (pdbc, NULL);
166 
167   if (phdbc == NULL)
168     {
169       PUSHSQLERR (genv->herr, en_S1009);
170       return SQL_ERROR;
171     }
172 
173   pdbc = (DBC_t *) MEM_ALLOC (sizeof (DBC_t));
174 
175   if (pdbc == NULL)
176     {
177       *phdbc = SQL_NULL_HDBC;
178 
179       PUSHSQLERR (genv->herr, en_S1001);
180       return SQL_ERROR;
181     }
182   pdbc->rc = 0;
183 
184   /*
185    *  Initialize this handle
186    */
187   pdbc->type = SQL_HANDLE_DBC;
188 
189   /* insert this dbc entry into the link list */
190   pdbc->next = (DBC_t *) genv->hdbc;
191   genv->hdbc = pdbc;
192 #if (ODBCVER >= 0x0300)
193   if (genv->odbc_ver == 0)
194     genv->odbc_ver = SQL_OV_ODBC2;
195   pdbc->hdesc = NULL;
196 
197   pdbc->cp_pdbc = NULL;
198   pdbc->cp_in_use = FALSE;
199   pdbc->cp_timeout = 0;
200   pdbc->cp_expiry_time = 0;
201   pdbc->cp_retry_wait = 0;
202   pdbc->cp_probe = NULL;
203   pdbc->cp_dsn = NULL;
204   pdbc->cp_uid = NULL;
205   pdbc->cp_pwd = NULL;
206   pdbc->cp_connstr = NULL;
207 #endif
208   pdbc->genv = genv;
209   pdbc->conv = genv->conv;
210 
211   pdbc->henv = SQL_NULL_HENV;
212   pdbc->hstmt = SQL_NULL_HSTMT;
213   pdbc->herr = SQL_NULL_HERR;
214   pdbc->dhdbc = SQL_NULL_HDBC;
215   pdbc->state = en_dbc_allocated;
216   pdbc->drvopt = NULL;
217   pdbc->dbc_cip = 0;
218   pdbc->err_rec = 0;
219 
220   /* set connect options to default values */
221   pdbc->access_mode = SQL_MODE_DEFAULT;
222   pdbc->autocommit = SQL_AUTOCOMMIT_DEFAULT;
223   pdbc->current_qualifier = NULL;
224   pdbc->login_timeout = 0UL;
225   pdbc->odbc_cursors = SQL_CUR_DEFAULT;
226   pdbc->packet_size = 0UL;
227   pdbc->quiet_mode = (UDWORD) NULL;
228   pdbc->txn_isolation = SQL_TXN_READ_UNCOMMITTED;
229   pdbc->cb_commit = (SWORD) SQL_CB_DELETE;
230   pdbc->cb_rollback = (SWORD) SQL_CB_DELETE;
231 
232   *phdbc = (SQLHDBC) pdbc;
233 
234   return SQL_SUCCESS;
235 }
236 
237 
238 SQLRETURN SQL_API
SQLAllocConnect(SQLHENV henv,SQLHDBC * phdbc)239 SQLAllocConnect (SQLHENV henv, SQLHDBC * phdbc)
240 {
241   GENV (genv, henv);
242   SQLRETURN retcode = SQL_SUCCESS;
243 
244   ODBC_LOCK ();
245   if (!IS_VALID_HENV (genv))
246     {
247       ODBC_UNLOCK ();
248       return SQL_INVALID_HANDLE;
249     }
250   CLEAR_ERRORS (genv);
251 
252   TRACE (trace_SQLAllocConnect (TRACE_ENTER, henv, phdbc));
253 
254   retcode = SQLAllocConnect_Internal (henv, phdbc);
255 
256   TRACE (trace_SQLAllocConnect (TRACE_LEAVE, henv, phdbc));
257 
258   ODBC_UNLOCK ();
259 
260   return SQL_SUCCESS;
261 }
262 
263 
264 SQLRETURN
SQLFreeConnect_Internal(SQLHDBC hdbc,int ver)265 SQLFreeConnect_Internal (SQLHDBC hdbc, int ver)
266 {
267   CONN (pdbc, hdbc);
268   GENV (genv, pdbc->genv);
269   CONN (tpdbc, NULL);
270 
271   /* check state */
272   if (pdbc->state != en_dbc_allocated)
273     {
274       PUSHSQLERR (pdbc->herr, en_S1010);
275       return SQL_ERROR;
276     }
277 
278   for (tpdbc = (DBC_t *) genv->hdbc; tpdbc != NULL; tpdbc = tpdbc->next)
279     {
280       if (pdbc == tpdbc)
281 	{
282 	  genv->hdbc = pdbc->next;
283 	  break;
284 	}
285 
286       if (pdbc == tpdbc->next)
287 	{
288 	  tpdbc->next = pdbc->next;
289 	  break;
290 	}
291     }
292 
293   /* free this dbc */
294   _iodbcdm_driverunload (pdbc, 3);
295 
296   /* free driver connect options */
297   _iodbcdm_drvopt_free (pdbc);
298 
299   /* free probe */
300   if (pdbc->cp_probe)
301     MEM_FREE (pdbc->cp_probe);
302 
303   /*
304    *  Invalidate this handle
305    */
306   pdbc->type = 0;
307 
308   return SQL_SUCCESS;
309 }
310 
311 
312 SQLRETURN SQL_API
SQLFreeConnect(SQLHDBC hdbc)313 SQLFreeConnect (SQLHDBC hdbc)
314 {
315   ENTER_HDBC (hdbc, 1,
316     trace_SQLFreeConnect (TRACE_ENTER, hdbc));
317 
318   retcode = SQLFreeConnect_Internal (hdbc, 2);
319 
320   LEAVE_HDBC (hdbc, 1,
321     trace_SQLFreeConnect (TRACE_LEAVE, hdbc);
322     MEM_FREE(hdbc);
323   );
324 }
325 
326 
327 SQLRETURN
_iodbcdm_SetConnectOption(SQLHDBC hdbc,SQLUSMALLINT fOption,SQLULEN vParam,SQLCHAR waMode)328 _iodbcdm_SetConnectOption (
329   SQLHDBC		  hdbc,
330   SQLUSMALLINT		  fOption,
331   SQLULEN		  vParam,
332   SQLCHAR		  waMode)
333 {
334   CONN (pdbc, hdbc);
335   ENVR (penv, pdbc->henv);
336   STMT (pstmt, NULL);
337   HPROC hproc2 = SQL_NULL_HPROC;
338   HPROC hproc3 = SQL_NULL_HPROC;
339   sqlstcode_t sqlstat = en_00000;
340   SQLRETURN retcode = SQL_SUCCESS;
341   SQLUINTEGER odbc_ver;
342   SQLUINTEGER dodbc_ver;
343   CONV_DIRECT conv_direct = CD_NONE;
344   DM_CONV *conv = &pdbc->conv;
345 
346   odbc_ver = ((GENV_t *) pdbc->genv)->odbc_ver;
347   dodbc_ver = (penv != SQL_NULL_HENV) ? penv->dodbc_ver : odbc_ver;
348 
349 #if (ODBCVER < 0x0300)
350   /* check option */
351   if (fOption < SQL_CONN_OPT_MIN ||
352       (fOption > SQL_CONN_OPT_MAX && fOption < SQL_CONNECT_OPT_DRVR_START))
353     {
354       PUSHSQLERR (pdbc->herr, en_S1092);
355 
356       return SQL_ERROR;
357     }
358 #endif
359 
360   /* check state of connection handle */
361   switch (pdbc->state)
362     {
363     case en_dbc_allocated:
364       if (fOption == SQL_TRANSLATE_DLL || fOption == SQL_TRANSLATE_OPTION)
365 	{
366 	  /* This two options are only meaningful
367 	   * for specified driver. So, has to be
368 	   * set after a driver has been loaded.
369 	   */
370 	  sqlstat = en_08003;
371 	  break;
372 	}
373 
374       /*
375        *  An option only meaningful for the driver is passed before the
376        *  driver was actually loaded. We save it here and pass it onto
377        *  the driver at a later stage.
378        */
379       if (fOption >= SQL_CONNECT_OPT_DRVR_START && pdbc->henv == SQL_NULL_HENV)
380         _iodbcdm_drvopt_store (hdbc, fOption, vParam, waMode);
381 
382       break;
383 
384     case en_dbc_needdata:
385       sqlstat = en_S1010;
386       break;
387 
388     case en_dbc_connected:
389     case en_dbc_hstmt:
390       if (fOption == SQL_ODBC_CURSORS)
391 	{
392 	  sqlstat = en_08002;
393 	}
394       break;
395 
396     default:
397       break;
398     }
399 
400   /* check state of statement handle(s) */
401   for (pstmt = (STMT_t *) pdbc->hstmt;
402       pstmt != NULL && sqlstat == en_00000;
403       pstmt = (STMT_t *) pstmt->next)
404     {
405       if (pstmt->state >= en_stmt_needdata || pstmt->asyn_on != en_NullProc)
406 	{
407 	  sqlstat = en_S1010;
408 	}
409     }
410 
411   if (sqlstat != en_00000)
412     {
413       PUSHSQLERR (pdbc->herr, sqlstat);
414 
415       return SQL_ERROR;
416     }
417 
418 #if (ODBCVER >= 0x0300)
419   if (fOption == SQL_OPT_TRACE || fOption == SQL_ATTR_TRACE)
420 #else
421   if (fOption == SQL_OPT_TRACE)
422 #endif
423     /* tracing flag can be set before and after connect
424      * and only meaningful for driver manager(actually
425      * there is only one tracing file under one global
426      * environment).
427      */
428     {
429       switch ((SQLUINTEGER)vParam)
430 	{
431 	case SQL_OPT_TRACE_ON:
432 	  trace_start ();
433 	  break;
434 
435 	case SQL_OPT_TRACE_OFF:
436 	  trace_stop ();
437 	  break;
438 
439 	default:
440 	  PUSHSQLERR (pdbc->herr, en_HY024);
441 	  return SQL_ERROR;
442 	}
443 
444       if (sqlstat != en_00000)
445 	{
446 	  PUSHSQLERR (pdbc->herr, sqlstat);
447 	}
448 
449       return retcode;
450     }
451 
452 #if (ODBCVER >= 0x0300)
453   if (fOption == SQL_OPT_TRACEFILE || fOption == SQL_ATTR_TRACEFILE)
454 #else
455   if (fOption == SQL_OPT_TRACEFILE)
456 #endif
457     /* Tracing file can be set before and after connect
458      * and only meaningful for driver manager.
459      */
460     {
461       SQLCHAR *_vParam;
462       SQLCHAR *tmp = NULL;
463 
464       if (((char *)vParam) == NULL
465           || (waMode != 'W' && ((char *) vParam)[0] == '\0')
466           || (waMode == 'W' && DM_GetWCharAt(conv, (void *)vParam, 0) == L'\0' ))
467 	{
468 	  PUSHSQLERR (pdbc->herr, en_S1009);
469 	  return SQL_ERROR;
470 	}
471 
472       _vParam = (SQLCHAR *)vParam;
473       if (waMode == 'W')
474         {
475           if ((_vParam = tmp = DM_WtoU8(conv, (void *)vParam, SQL_NTS)) == NULL)
476 	    {
477               PUSHSQLERR (pdbc->herr, en_S1001);
478               return SQL_ERROR;
479             }
480         }
481 
482       if (ODBCSharedTraceFlag)
483 	{
484 	  PUSHSQLERR (pdbc->herr, en_IM013);
485 	  return SQL_ERROR;
486 	}
487 
488       trace_set_filename ((char *) _vParam);
489       MEM_FREE (tmp);
490       return SQL_SUCCESS;
491     }
492 
493   if (pdbc->state != en_dbc_allocated)
494     {
495       /* If already connected, then, driver's odbc call
496        * will be invoked. Otherwise, we only save the options
497        * and delay the setting process until the connection
498        * been established.
499        */
500      void * _vParam = NULL;
501 
502      if (penv->unicode_driver && waMode != 'W')
503        conv_direct = CD_A2W;
504      else if (!penv->unicode_driver && waMode == 'W')
505        conv_direct = CD_W2A;
506      else if (waMode == 'W' && conv->dm_cp!=conv->drv_cp)
507        conv_direct = CD_W2W;
508 
509      switch (fOption)
510        {
511        case SQL_ATTR_TRACEFILE:
512        case SQL_CURRENT_QUALIFIER:
513        case SQL_TRANSLATE_DLL:
514        case SQL_APPLICATION_NAME:
515        case SQL_COPT_SS_ENLIST_IN_DTC:
516        case SQL_COPT_SS_PERF_QUERY_LOG:
517        case SQL_COPT_SS_PERF_DATA_LOG:
518        case SQL_CURRENT_SCHEMA:
519          if (conv_direct != CD_NONE)
520            {
521              _vParam = conv_text_m2d (conv, (void *)vParam, SQL_NTS, conv_direct);
522              vParam = (SQLULEN)_vParam;
523            }
524          break;
525        }
526 
527      if (penv->unicode_driver)
528        {
529          /* SQL_XXX_W */
530 #if (ODBCVER >= 0x0300)
531          hproc3 = _iodbcdm_getproc (pdbc, en_SetConnectAttrW);
532 #endif
533          hproc2 = _iodbcdm_getproc (pdbc, en_SetConnectOptionW);
534        }
535      else
536        {
537          /* SQL_XXX */
538          /* SQL_XXX_A */
539 #if (ODBCVER >= 0x0300)
540          hproc3 = _iodbcdm_getproc (pdbc, en_SetConnectAttr);
541 	 if (hproc3 == SQL_NULL_HPROC)
542 	   hproc3 = _iodbcdm_getproc (pdbc, en_SetConnectAttrA);
543 #endif
544          hproc2 = _iodbcdm_getproc (pdbc, en_SetConnectOption);
545 	 if (hproc2 == SQL_NULL_HPROC)
546 	   hproc2 = _iodbcdm_getproc (pdbc, en_SetConnectOptionA);
547        }
548 
549       if (odbc_ver == SQL_OV_ODBC2 && (dodbc_ver == SQL_OV_ODBC2
550 	      || (dodbc_ver == SQL_OV_ODBC3 && hproc2 != SQL_NULL_HPROC)))
551 	hproc3 = SQL_NULL_HPROC;
552 
553 #if (ODBCVER >= 0x0300)
554       if (hproc3 != SQL_NULL_HPROC)
555 	{
556 	  switch (fOption)
557 	    {
558 	      /* integer attributes */
559 	    case SQL_ATTR_ACCESS_MODE:
560 	    case SQL_ATTR_AUTOCOMMIT:
561 	    case SQL_ATTR_LOGIN_TIMEOUT:
562 	    case SQL_ATTR_ODBC_CURSORS:
563 	    case SQL_ATTR_PACKET_SIZE:
564 	    case SQL_ATTR_QUIET_MODE:
565 	    case SQL_ATTR_TRANSLATE_OPTION:
566 	    case SQL_ATTR_TXN_ISOLATION:
567 	      CALL_DRIVER (hdbc, pdbc, retcode, hproc3,
568 		  (pdbc->dhdbc, fOption, vParam, 0));
569 	      break;
570 
571 	      /* ODBC3 defined options */
572 	    case SQL_ATTR_ASYNC_ENABLE:
573 	    case SQL_ATTR_AUTO_IPD:
574 	    case SQL_ATTR_CONNECTION_DEAD:
575 	    case SQL_ATTR_CONNECTION_TIMEOUT:
576 	    case SQL_ATTR_METADATA_ID:
577 	      PUSHSQLERR (pdbc->herr, en_IM001);
578 	      MEM_FREE(_vParam);
579 	      return SQL_ERROR;
580 
581 	    default:		/* string & driver defined */
582 
583 	      CALL_DRIVER (hdbc, pdbc, retcode, hproc3,
584 		  (pdbc->dhdbc, fOption, vParam, SQL_NTS));
585 	    }
586 	}
587       else
588 #endif
589 	{
590 	  if (hproc2 == SQL_NULL_HPROC)
591 	    {
592 	      PUSHSQLERR (pdbc->herr, en_IM001);
593 	      MEM_FREE(_vParam);
594 	      return SQL_ERROR;
595 	    }
596 
597 	  CALL_DRIVER (hdbc, pdbc, retcode, hproc2,
598 	      (pdbc->dhdbc, fOption, vParam));
599 	}
600 
601       MEM_FREE(_vParam);
602       if (!SQL_SUCCEEDED (retcode))
603 	{
604 	  return retcode;
605 	}
606     }
607 
608   /*
609    * Now, either driver's odbc call was successful or
610    * driver has not been loaded yet. In the first case, we
611    * need flip flag for(such as access_mode, autocommit, ...)
612    * for our finit state machine. While in the second case,
613    * we need save option values(such as current_qualifier, ...)
614    * for delayed setting. So, ...
615    */
616 
617   /* No matter what state we are(i.e. allocated or connected, ..)
618    * we need to flip the flag.
619    */
620   switch (fOption)
621     {
622     case SQL_ACCESS_MODE:
623       pdbc->access_mode = vParam;
624       break;
625 
626     case SQL_AUTOCOMMIT:
627       pdbc->autocommit = vParam;
628       break;
629     }
630 
631   /* state transition */
632   if (pdbc->state != en_dbc_allocated)
633     {
634       return retcode;
635     }
636 
637   /* Only 'allocated' state is possible here, and we need to
638    * save the options for delayed setting.
639    */
640   switch (fOption)
641     {
642     case SQL_CURRENT_QUALIFIER:
643       if (pdbc->current_qualifier != NULL)
644 	{
645 	  MEM_FREE (pdbc->current_qualifier);
646 	}
647 
648       if (vParam == 0UL)
649 	{
650 	  pdbc->current_qualifier = NULL;
651 	  break;
652 	}
653 
654       if (waMode != 'W')
655         pdbc->current_qualifier = (wchar_t *) MEM_ALLOC (STRLEN (vParam) + 1);
656       else
657         pdbc->current_qualifier = (wchar_t *) MEM_ALLOC((DM_WCSLEN (conv, (void *)vParam) + 1)
658 		* DM_WCHARSIZE(conv));
659 
660       if (pdbc->current_qualifier == NULL)
661 	{
662 	  PUSHSQLERR (pdbc->herr, en_S1001);
663 	  return SQL_ERROR;
664 	}
665 
666       if (waMode != 'W')
667         STRCPY ((char *)pdbc->current_qualifier, vParam);
668       else
669         DM_WCSCPY (conv, pdbc->current_qualifier, (void *)vParam);
670 
671       pdbc->current_qualifier_WA = waMode;
672       break;
673 
674     case SQL_LOGIN_TIMEOUT:
675       pdbc->login_timeout = vParam;
676       break;
677 
678     case SQL_ODBC_CURSORS:
679       pdbc->odbc_cursors = vParam;
680       break;
681 
682     case SQL_PACKET_SIZE:
683       pdbc->packet_size = vParam;
684       break;
685 
686     case SQL_QUIET_MODE:
687       pdbc->quiet_mode = vParam;
688       break;
689 
690     case SQL_TXN_ISOLATION:
691       pdbc->txn_isolation = vParam;
692       break;
693 
694     default:
695       /* Since we didn't save the option value for delayed
696        * setting, we should raise an error here.
697        */
698       break;
699     }
700 
701   return retcode;
702 }
703 
704 
705 SQLRETURN SQL_API
SQLSetConnectOption(SQLHDBC hdbc,SQLUSMALLINT fOption,SQLULEN vParam)706 SQLSetConnectOption (
707   SQLHDBC		  hdbc,
708   SQLUSMALLINT		  fOption,
709   SQLULEN		  vParam)
710 {
711   ENTER_HDBC (hdbc, 0,
712     trace_SQLSetConnectOption (TRACE_ENTER, hdbc, fOption, vParam));
713 
714   retcode = _iodbcdm_SetConnectOption (hdbc, fOption, vParam, 'A');
715 
716   LEAVE_HDBC (hdbc, 0,
717     trace_SQLSetConnectOption (TRACE_LEAVE, hdbc, fOption, vParam));
718 }
719 
720 
721 #if ODBCVER >= 0x0300
722 SQLRETURN SQL_API
SQLSetConnectOptionA(SQLHDBC hdbc,SQLUSMALLINT fOption,SQLULEN vParam)723 SQLSetConnectOptionA (
724   SQLHDBC		  hdbc,
725   SQLUSMALLINT		  fOption,
726   SQLULEN		  vParam)
727 {
728   ENTER_HDBC (hdbc, 0,
729     trace_SQLSetConnectOption (TRACE_ENTER, hdbc, fOption, vParam));
730 
731   retcode = _iodbcdm_SetConnectOption (hdbc, fOption, vParam, 'A');
732 
733   LEAVE_HDBC (hdbc, 0,
734     trace_SQLSetConnectOption (TRACE_LEAVE, hdbc, fOption, vParam));
735 }
736 
737 
738 SQLRETURN SQL_API
SQLSetConnectOptionW(SQLHDBC hdbc,SQLUSMALLINT fOption,SQLULEN vParam)739 SQLSetConnectOptionW (
740   SQLHDBC		  hdbc,
741   SQLUSMALLINT		  fOption,
742   SQLULEN		  vParam)
743 {
744   ENTER_HDBC (hdbc, 0,
745     trace_SQLSetConnectOptionW (TRACE_ENTER, hdbc, fOption, vParam));
746 
747   retcode = _iodbcdm_SetConnectOption (hdbc, fOption, vParam, 'W');
748 
749   LEAVE_HDBC (hdbc, 0,
750     trace_SQLSetConnectOptionW (TRACE_LEAVE, hdbc, fOption, vParam));
751 }
752 #endif
753 
754 
755 SQLRETURN SQL_API
_iodbcdm_GetConnectOption(SQLHDBC hdbc,SQLUSMALLINT fOption,SQLPOINTER pvParam,SQLCHAR waMode)756 _iodbcdm_GetConnectOption (
757     SQLHDBC hdbc,
758     SQLUSMALLINT fOption,
759     SQLPOINTER pvParam,
760     SQLCHAR waMode)
761 {
762   CONN (pdbc, hdbc);
763   ENVR (penv, pdbc->henv);
764   HPROC hproc2 = SQL_NULL_HPROC;
765   HPROC hproc3 = SQL_NULL_HPROC;
766   sqlstcode_t sqlstat = en_00000;
767   SQLRETURN retcode = SQL_SUCCESS;
768   SQLUINTEGER odbc_ver;
769   SQLUINTEGER dodbc_ver;
770   CONV_DIRECT conv_direct = CD_NONE;
771   DM_CONV *conv = &pdbc->conv;
772 
773   odbc_ver = ((GENV_t *) pdbc->genv)->odbc_ver;
774   dodbc_ver = (penv != SQL_NULL_HENV) ? penv->dodbc_ver : odbc_ver;
775 
776 #if (ODBCVER < 0x0300)
777   /* check option */
778   if (fOption < SQL_CONN_OPT_MIN ||
779       (fOption > SQL_CONN_OPT_MAX && fOption < SQL_CONNECT_OPT_DRVR_START))
780     {
781       PUSHSQLERR (pdbc->herr, en_S1092);
782 
783       return SQL_ERROR;
784     }
785 #endif
786 
787   if (penv != SQL_NULL_HENV)
788     {
789       if (penv->unicode_driver && waMode != 'W')
790         conv_direct = CD_A2W;
791       else if (!penv->unicode_driver && waMode == 'W')
792         conv_direct = CD_W2A;
793       else if (waMode == 'W' && conv->dm_cp != conv->drv_cp)
794         conv_direct = CD_W2W;
795     }
796 
797   /* check state */
798   switch (pdbc->state)
799     {
800     case en_dbc_allocated:
801       if (fOption != SQL_ACCESS_MODE
802 	  && fOption != SQL_AUTOCOMMIT
803 	  && fOption != SQL_LOGIN_TIMEOUT
804 	  && fOption != SQL_OPT_TRACE
805 	  && fOption != SQL_OPT_TRACEFILE)
806 	{
807 	  sqlstat = en_08003;
808 	}
809       /* MS ODBC SDK document only
810        * allows SQL_ACCESS_MODE
811        * and SQL_AUTOCOMMIT in this
812        * dbc state. We allow another
813        * two options, because they
814        * are only meaningful for driver
815        * manager.
816        */
817       break;
818 
819     case en_dbc_needdata:
820       sqlstat = en_S1010;
821       break;
822 
823     default:
824       break;
825     }
826 
827   if (sqlstat != en_00000)
828     {
829       PUSHSQLERR (pdbc->herr, sqlstat);
830       return SQL_ERROR;
831     }
832 
833   /* Tracing and tracing file options are only
834    * meaningful for driver manager
835    */
836 #if (ODBCVER >= 0x0300)
837   if (fOption == SQL_OPT_TRACE || fOption == SQL_ATTR_TRACE)
838 #else
839   if (fOption == SQL_OPT_TRACE)
840 #endif
841     {
842       if (ODBCSharedTraceFlag)
843 	*((UDWORD *) pvParam) = (UDWORD) SQL_OPT_TRACE_ON;
844       else
845 	*((UDWORD *) pvParam) = (UDWORD) SQL_OPT_TRACE_OFF;
846 
847       return SQL_SUCCESS;
848     }
849 
850 #if (ODBCVER >= 0x0300)
851   if (fOption == SQL_OPT_TRACEFILE || fOption == SQL_ATTR_TRACEFILE)
852 #else
853   if (fOption == SQL_OPT_TRACEFILE)
854 #endif
855     {
856       char *fname;
857 
858       fname = trace_get_filename ();	/* UTF8 format */
859 
860       if (waMode != 'W')
861         {
862            STRCPY (pvParam, fname);
863         }
864       else
865         {
866            DM_strcpy_U8toW (conv, pvParam, (SQLCHAR *)fname);
867         }
868 
869       free (fname);
870 
871       return SQL_SUCCESS;
872     }
873 
874   if (pdbc->state != en_dbc_allocated)
875     /* if already connected, we will invoke driver's function */
876     {
877 
878       void * _Param = NULL;
879       void * paramOut = pvParam;
880 
881       switch (fOption)
882         {
883         case SQL_CURRENT_QUALIFIER:
884         case SQL_TRANSLATE_DLL:
885 
886           if (conv_direct != CD_NONE)
887             {
888               if ((_Param = malloc(SQL_MAX_OPTION_STRING_LENGTH * WCHAR_MAXSIZE)) == NULL)
889 	        {
890                   PUSHSQLERR (pdbc->herr, en_HY001);
891                   return SQL_ERROR;
892                 }
893               paramOut = _Param;
894             }
895           break;
896         }
897 
898 
899      if (penv->unicode_driver)
900        {
901          /* SQL_XXX_W */
902 #if (ODBCVER >= 0x0300)
903          hproc3 = _iodbcdm_getproc (pdbc, en_GetConnectAttrW);
904 #endif
905          hproc2 = _iodbcdm_getproc (pdbc, en_GetConnectOptionW);
906        }
907      else
908        {
909          /* SQL_XXX */
910          /* SQL_XXX_A */
911 #if (ODBCVER >= 0x0300)
912          hproc3 = _iodbcdm_getproc (pdbc, en_GetConnectAttr);
913 	 if (hproc3 == SQL_NULL_HPROC)
914            hproc3 = _iodbcdm_getproc (pdbc, en_GetConnectAttrA);
915 #endif
916          hproc2 = _iodbcdm_getproc (pdbc, en_GetConnectOption);
917 	 if (hproc2 == SQL_NULL_HPROC)
918            hproc2 = _iodbcdm_getproc (pdbc, en_GetConnectOptionA);
919        }
920 
921       if (odbc_ver == SQL_OV_ODBC2 && (dodbc_ver == SQL_OV_ODBC2
922 	      || (dodbc_ver == SQL_OV_ODBC3 && hproc2 != SQL_NULL_HPROC)))
923 	hproc3 = SQL_NULL_HPROC;
924 
925 #if (ODBCVER >= 0x0300)
926       if (hproc3 != SQL_NULL_HPROC)
927 	{
928 	  switch (fOption)
929 	    {
930 	      /* integer attributes */
931 	    case SQL_ATTR_ACCESS_MODE:
932 	    case SQL_ATTR_AUTOCOMMIT:
933 	    case SQL_ATTR_LOGIN_TIMEOUT:
934 	    case SQL_ATTR_ODBC_CURSORS:
935 	    case SQL_ATTR_PACKET_SIZE:
936 	    case SQL_ATTR_QUIET_MODE:
937 	    case SQL_ATTR_TRANSLATE_OPTION:
938 	    case SQL_ATTR_TXN_ISOLATION:
939 	      CALL_DRIVER (hdbc, pdbc, retcode, hproc3,
940 		  (pdbc->dhdbc, fOption, paramOut, 0, NULL));
941 	      break;
942 
943 	      /* ODBC3 defined options */
944 	    case SQL_ATTR_ASYNC_ENABLE:
945 	    case SQL_ATTR_AUTO_IPD:
946 	    case SQL_ATTR_CONNECTION_DEAD:
947 	    case SQL_ATTR_CONNECTION_TIMEOUT:
948 	    case SQL_ATTR_METADATA_ID:
949 	      PUSHSQLERR (pdbc->herr, en_IM001);
950 	      MEM_FREE(_Param);
951 	      return SQL_ERROR;
952 
953 	    default:		/* string & driver defined */
954 
955 	      CALL_DRIVER (hdbc, pdbc, retcode, hproc3,
956 		  (pdbc->dhdbc, fOption, paramOut, SQL_MAX_OPTION_STRING_LENGTH, NULL));
957 
958 	    }
959 	}
960       else
961 #endif
962 	{
963 	  if (hproc2 == SQL_NULL_HPROC)
964 	    {
965 	      PUSHSQLERR (pdbc->herr, en_IM001);
966               MEM_FREE(_Param);
967 	      return SQL_ERROR;
968 	    }
969 
970 	  CALL_DRIVER (hdbc, pdbc, retcode, hproc2,
971 	      (pdbc->dhdbc, fOption, paramOut));
972 	}
973 
974 
975       if (pvParam && conv_direct != CD_NONE && SQL_SUCCEEDED (retcode))
976         {
977           size_t sizeMax = SQL_MAX_OPTION_STRING_LENGTH;
978           if (conv->dm_cp != CP_UTF8)
979             sizeMax *= DM_WCHARSIZE(conv);
980 
981           switch (fOption)
982             {
983             case SQL_ATTR_TRACEFILE:
984             case SQL_CURRENT_QUALIFIER:
985             case SQL_TRANSLATE_DLL:
986               if (conv_direct == CD_A2W)
987                 {
988                 /* ansi<=unicode*/
989                   dm_StrCopyOut2_W2A_d2m (conv, paramOut, (SQLCHAR *)pvParam,
990 			SQL_MAX_OPTION_STRING_LENGTH, NULL, NULL);
991                 }
992               else if (conv_direct == CD_W2A)
993                 {
994                 /* unicode<=ansi*/
995                   dm_StrCopyOut2_A2W_d2m (conv, (SQLCHAR *)paramOut, pvParam,
996 			sizeMax, NULL, NULL);
997                 }
998               else if (conv_direct == CD_W2W)
999                 {
1000                 /* unicode<=unicode*/
1001                   dm_StrCopyOut2_W2W_d2m (conv, paramOut, pvParam,
1002 			sizeMax, NULL, NULL);
1003                 }
1004               break;
1005             }
1006         }
1007 
1008       MEM_FREE(_Param);
1009       return retcode;
1010     }
1011 
1012   /* We needn't to handle options which are not allowed
1013    * to be *get* at a allocated dbc state(and two tracing
1014    * options which has been handled and returned). Thus,
1015    * there are only two possible cases.
1016    */
1017   switch (fOption)
1018     {
1019     case SQL_ACCESS_MODE:
1020       *((UDWORD *) pvParam) = pdbc->access_mode;
1021       break;
1022 
1023     case SQL_AUTOCOMMIT:
1024       *((UDWORD *) pvParam) = pdbc->autocommit;
1025       break;
1026 
1027     case SQL_LOGIN_TIMEOUT:
1028       *((UDWORD *) pvParam) = pdbc->login_timeout;
1029       break;
1030 
1031     default:
1032       break;
1033     }
1034 
1035   return SQL_SUCCESS;
1036 }
1037 
1038 
1039 SQLRETURN SQL_API
SQLGetConnectOption(SQLHDBC hdbc,SQLUSMALLINT fOption,SQLPOINTER pvParam)1040 SQLGetConnectOption (SQLHDBC hdbc,
1041     SQLUSMALLINT fOption,
1042     SQLPOINTER pvParam)
1043 {
1044   ENTER_HDBC (hdbc, 0,
1045     trace_SQLGetConnectOption (TRACE_ENTER, hdbc, fOption, pvParam));
1046 
1047   retcode = _iodbcdm_GetConnectOption (hdbc, fOption, pvParam, 'A');
1048 
1049   LEAVE_HDBC (hdbc, 0,
1050     trace_SQLGetConnectOption (TRACE_LEAVE, hdbc, fOption, pvParam));
1051 }
1052 
1053 
1054 #if ODBCVER >= 0x0300
1055 SQLRETURN SQL_API
SQLGetConnectOptionA(SQLHDBC hdbc,SQLUSMALLINT fOption,SQLPOINTER pvParam)1056 SQLGetConnectOptionA (
1057   SQLHDBC		  hdbc,
1058   SQLUSMALLINT		  fOption,
1059   SQLPOINTER		  pvParam)
1060 {
1061   ENTER_HDBC (hdbc, 0,
1062     trace_SQLGetConnectOption (TRACE_ENTER, hdbc, fOption, pvParam));
1063 
1064   retcode = _iodbcdm_GetConnectOption (hdbc, fOption, pvParam, 'A');
1065 
1066   LEAVE_HDBC (hdbc, 0,
1067     trace_SQLGetConnectOption (TRACE_LEAVE, hdbc, fOption, pvParam));
1068 }
1069 
1070 
1071 SQLRETURN SQL_API
SQLGetConnectOptionW(SQLHDBC hdbc,SQLUSMALLINT fOption,SQLPOINTER pvParam)1072 SQLGetConnectOptionW (
1073   SQLHDBC		  hdbc,
1074   SQLUSMALLINT		  fOption,
1075   SQLPOINTER		  pvParam)
1076 {
1077   ENTER_HDBC (hdbc, 0,
1078     trace_SQLGetConnectOptionW (TRACE_ENTER, hdbc, fOption, pvParam));
1079 
1080   retcode = _iodbcdm_GetConnectOption (hdbc, fOption, pvParam, 'W');
1081 
1082   LEAVE_HDBC (hdbc, 0,
1083     trace_SQLGetConnectOptionW (TRACE_LEAVE, hdbc, fOption, pvParam));
1084 }
1085 #endif
1086 
1087 
1088 static SQLRETURN
_iodbcdm_transact(HDBC hdbc,UWORD fType)1089 _iodbcdm_transact (
1090     HDBC hdbc,
1091     UWORD fType)
1092 {
1093   CONN (pdbc, hdbc);
1094   ENVR (penv, pdbc->henv);
1095   STMT (pstmt, NULL);
1096   HPROC hproc2 = SQL_NULL_HPROC;
1097   HPROC hproc3 = SQL_NULL_HPROC;
1098   SQLRETURN retcode;
1099   SQLUINTEGER odbc_ver;
1100   SQLUINTEGER dodbc_ver;
1101 
1102   odbc_ver = ((GENV_t *) pdbc->genv)->odbc_ver;
1103   dodbc_ver = (penv != SQL_NULL_HENV) ? penv->dodbc_ver : odbc_ver;
1104 
1105   /* check state */
1106   switch (pdbc->state)
1107     {
1108     case en_dbc_allocated:
1109     case en_dbc_needdata:
1110       PUSHSQLERR (pdbc->herr, en_08003);
1111       return SQL_ERROR;
1112 
1113     case en_dbc_connected:
1114       return SQL_SUCCESS;
1115 
1116     case en_dbc_hstmt:
1117     default:
1118       break;
1119     }
1120 
1121   for (pstmt = (STMT_t *) (pdbc->hstmt); pstmt != NULL; pstmt = pstmt->next)
1122     {
1123       if (pstmt->state >= en_stmt_needdata || pstmt->asyn_on != en_NullProc)
1124 	{
1125 	  PUSHSQLERR (pdbc->herr, en_S1010);
1126 
1127 	  return SQL_ERROR;
1128 	}
1129     }
1130 
1131 
1132   hproc2 = _iodbcdm_getproc (pdbc, en_Transact);
1133 #if (ODBCVER >= 0x300)
1134   hproc3 = _iodbcdm_getproc (pdbc, en_EndTran);
1135 #endif
1136 
1137   if (odbc_ver == SQL_OV_ODBC2 &&
1138       (dodbc_ver == SQL_OV_ODBC2
1139 	  || (dodbc_ver == SQL_OV_ODBC3 && hproc2 != SQL_NULL_HPROC)))
1140     hproc3 = SQL_NULL_HPROC;
1141 
1142 
1143 #if (ODBCVER >= 0x300)
1144   if (hproc3 != SQL_NULL_HPROC)
1145     {
1146       CALL_DRIVER (hdbc, pdbc, retcode, hproc3,
1147 	  (SQL_HANDLE_DBC, pdbc->dhdbc, fType));
1148     }
1149   else
1150 #endif
1151     {
1152       if (hproc2 == SQL_NULL_HPROC)
1153         {
1154           PUSHSQLERR (pdbc->herr, en_IM001);
1155           return SQL_ERROR;
1156         }
1157       CALL_DRIVER (hdbc, pdbc, retcode, hproc2,
1158 	  (SQL_NULL_HENV, pdbc->dhdbc, fType));
1159     }
1160 
1161 
1162   /* state transition */
1163   if (!SQL_SUCCEEDED (retcode))
1164     {
1165       return retcode;
1166     }
1167 
1168   pdbc->state = en_dbc_hstmt;
1169 
1170   for (pstmt = (STMT_t *) (pdbc->hstmt); pstmt != NULL; pstmt = pstmt->next)
1171     {
1172       switch (pstmt->state)
1173 	{
1174 	case en_stmt_prepared:
1175 	  if (pdbc->cb_commit == SQL_CB_DELETE
1176 	      || pdbc->cb_rollback == SQL_CB_DELETE)
1177 	    {
1178 	      pstmt->state = en_stmt_allocated;
1179 	      pstmt->prep_state = 0;
1180 	      break;
1181 	    }
1182 	  break;
1183 
1184 	case en_stmt_executed_with_info:
1185 	case en_stmt_executed:
1186 	case en_stmt_cursoropen:
1187 	case en_stmt_fetched:
1188 	case en_stmt_xfetched:
1189 	  if (!pstmt->prep_state
1190 	      && pdbc->cb_commit != SQL_CB_PRESERVE
1191 	      && pdbc->cb_rollback != SQL_CB_PRESERVE)
1192 	    {
1193 	      pstmt->state = en_stmt_allocated;
1194 	      pstmt->prep_state = 0;
1195 	      pstmt->cursor_state = en_stmt_cursor_no;
1196 	      break;
1197 	    }
1198 
1199 	  if (pstmt->prep_state)
1200 	    {
1201 	      if (pdbc->cb_commit == SQL_CB_DELETE
1202 		  || pdbc->cb_rollback == SQL_CB_DELETE)
1203 		{
1204 		  pstmt->state = en_stmt_allocated;
1205 		  pstmt->prep_state = 0;
1206 		  pstmt->cursor_state = en_stmt_cursor_no;
1207 		  break;
1208 		}
1209 
1210 	      if (pdbc->cb_commit == SQL_CB_CLOSE
1211 		  || pdbc->cb_rollback == SQL_CB_CLOSE)
1212 		{
1213 		  pstmt->state = en_stmt_prepared;
1214 		  pstmt->cursor_state = en_stmt_cursor_no;
1215 		  break;
1216 		}
1217 	      break;
1218 	    }
1219 	  break;
1220 
1221 	default:
1222 	  break;
1223 	}
1224     }
1225 
1226   return retcode;
1227 }
1228 
1229 
1230 SQLRETURN
SQLTransact_Internal(SQLHENV henv,SQLHDBC hdbc,SQLUSMALLINT fType)1231 SQLTransact_Internal (
1232     SQLHENV henv,
1233     SQLHDBC hdbc,
1234     SQLUSMALLINT fType)
1235 {
1236   GENV (genv, henv);
1237   CONN (pdbc, hdbc);
1238   HERR herr;
1239   SQLRETURN retcode = SQL_SUCCESS;
1240 
1241   if (IS_VALID_HDBC (pdbc))
1242     {
1243       CLEAR_ERRORS (pdbc);
1244       herr = pdbc->herr;
1245     }
1246   else if (IS_VALID_HENV (genv))
1247     {
1248       CLEAR_ERRORS (genv);
1249       herr = genv->herr;
1250     }
1251   else
1252     {
1253       return SQL_INVALID_HANDLE;
1254     }
1255 
1256   /* check argument */
1257   if (fType != SQL_COMMIT && fType != SQL_ROLLBACK)
1258     {
1259 /*      SQLHENV handle = IS_VALID_HDBC (pdbc) ? ((SQLHENV) pdbc) : genv;*/
1260       PUSHSQLERR (herr, en_S1012);
1261       return SQL_ERROR;
1262     }
1263 
1264   if (hdbc != SQL_NULL_HDBC)
1265     {
1266       retcode = _iodbcdm_transact (pdbc, fType);
1267     }
1268   else
1269     {
1270       for (pdbc = (DBC_t *) (genv->hdbc); pdbc != NULL; pdbc = pdbc->next)
1271 	{
1272 	  retcode |= _iodbcdm_transact (pdbc, fType);
1273 	}
1274     }
1275 
1276   if (!SQL_SUCCEEDED (retcode))
1277     {
1278       /* fail on one of the connection */
1279       return SQL_ERROR;
1280     }
1281 
1282   return retcode;
1283 }
1284 
1285 
1286 SQLRETURN SQL_API
SQLTransact(SQLHENV henv,SQLHDBC hdbc,SQLUSMALLINT fType)1287 SQLTransact (
1288   SQLHENV		  henv,
1289   SQLHDBC		  hdbc,
1290   SQLUSMALLINT		  fType)
1291 {
1292   SQLRETURN retcode = SQL_SUCCESS;
1293 
1294   ODBC_LOCK ();
1295   TRACE (trace_SQLTransact (TRACE_ENTER, henv, hdbc, fType));
1296 
1297   retcode = SQLTransact_Internal (henv, hdbc, fType);
1298 
1299   TRACE (trace_SQLTransact (TRACE_LEAVE, henv, hdbc, fType));
1300   ODBC_UNLOCK ();
1301 
1302   return retcode;
1303 }
1304