6  *  Data source connect object management functions 
   8  *  The iODBC driver manager. 
  10  *  Copyright (C) 1995 by Ke Jin <kejin@empress.com>  
  12  *  This library is free software; you can redistribute it and/or 
  13  *  modify it under the terms of the GNU Library General Public 
  14  *  License as published by the Free Software Foundation; either 
  15  *  version 2 of the License, or (at your option) any later version. 
  17  *  This library is distributed in the hope that it will be useful, 
  18  *  but WITHOUT ANY WARRANTY; without even the implied warranty of 
  19  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
  20  *  Library General Public License for more details. 
  22  *  You should have received a copy of the GNU Library General Public 
  23  *  License along with this library; if not, write to the Free 
  24  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  42 extern  RETCODE 
_iodbcdm_driverunload(); 
  50   GENV_t FAR 
*genv 
= (GENV_t FAR 
*) henv
; 
  53 #if (ODBCVER >= 0x0300) 
  54   if (henv 
== SQL_NULL_HENV 
|| genv
->type 
!= SQL_HANDLE_ENV
) 
  56   if (henv 
== SQL_NULL_HENV
) 
  60       return SQL_INVALID_HANDLE
; 
  65       PUSHSQLERR (genv
->herr
, en_S1009
); 
  70   pdbc 
= (DBC_t FAR 
*) MEM_ALLOC (sizeof (DBC_t
)); 
  74       *phdbc 
= SQL_NULL_HDBC
; 
  76       PUSHSQLERR (genv
->herr
, en_S1001
); 
  81 #if (ODBCVER >= 0x0300) 
  82   pdbc
->type 
= SQL_HANDLE_DBC
; 
  85   /* insert this dbc entry into the link list */ 
  86   pdbc
->next 
= genv
->hdbc
; 
  90   pdbc
->henv 
= SQL_NULL_HENV
; 
  91   pdbc
->hstmt 
= SQL_NULL_HSTMT
; 
  92   pdbc
->herr 
= SQL_NULL_HERR
; 
  93   pdbc
->dhdbc 
= SQL_NULL_HDBC
; 
  94   pdbc
->state 
= en_dbc_allocated
; 
  99   /* set connect options to default values */ 
 100   pdbc
->access_mode 
= SQL_MODE_DEFAULT
; 
 101   pdbc
->autocommit 
= SQL_AUTOCOMMIT_DEFAULT
; 
 102   pdbc
->current_qualifier 
= NULL
; 
 103   pdbc
->login_timeout 
= 0UL; 
 104   pdbc
->odbc_cursors 
= SQL_CUR_DEFAULT
; 
 105   pdbc
->packet_size 
= 0UL; 
 106   pdbc
->quiet_mode 
= (UDWORD
) NULL
; 
 107   pdbc
->txn_isolation 
= SQL_TXN_READ_UNCOMMITTED
; 
 108   pdbc
->cb_commit 
= (SWORD
) SQL_CB_DELETE
; 
 109   pdbc
->cb_rollback 
= (SWORD
) SQL_CB_DELETE
; 
 111   *phdbc 
= (HDBC
) pdbc
; 
 118 SQLFreeConnect (HDBC hdbc
) 
 121   DBC_t FAR 
*pdbc 
= (DBC_t FAR 
*) hdbc
; 
 124   if (hdbc 
== SQL_NULL_HDBC
) 
 126       return SQL_INVALID_HANDLE
; 
 130   if (pdbc
->state 
!= en_dbc_allocated
) 
 132       PUSHSQLERR (pdbc
->herr
, en_S1010
); 
 137   genv 
= (GENV_t FAR 
*) pdbc
->genv
; 
 139   for (tpdbc 
= (DBC_t FAR 
*) genv
->hdbc
; 
 145           genv
->hdbc 
= pdbc
->next
; 
 149       if (pdbc 
== tpdbc
->next
) 
 151           tpdbc
->next 
= pdbc
->next
; 
 157   _iodbcdm_driverunload (pdbc
); 
 158   _iodbcdm_freesqlerrlist (pdbc
->herr
); 
 162       MEM_FREE (pdbc
->tfile
); 
 165   SQLSetConnectOption (pdbc
, SQL_OPT_TRACE
, SQL_OPT_TRACE_OFF
); 
 174 SQLSetConnectOption ( 
 179   DBC_t FAR 
*pdbc 
= (DBC_t FAR 
*) hdbc
; 
 181   HPROC hproc 
= SQL_NULL_HPROC
; 
 182   int sqlstat 
= en_00000
; 
 183   RETCODE retcode 
= SQL_SUCCESS
; 
 185   if (hdbc 
== SQL_NULL_HDBC
) 
 187       return SQL_INVALID_HANDLE
; 
 191   if (fOption 
< SQL_CONN_OPT_MIN 
||  
 192         (fOption 
> SQL_CONN_OPT_MAX 
&& fOption 
< SQL_CONNECT_OPT_DRVR_START
)) 
 194       PUSHSQLERR (pdbc
->herr
, en_S1092
); 
 199   /* check state of connection handle */ 
 202      case en_dbc_allocated
: 
 203        if (fOption 
== SQL_TRANSLATE_DLL 
|| fOption 
== SQL_TRANSLATE_OPTION
) 
 205            /* This two options are only meaningful 
 206             * for specified driver. So, has to be 
 207             * set after a dirver has been loaded. 
 213        if (fOption 
>= SQL_CONNECT_OPT_DRVR_START 
&& pdbc
->henv 
== SQL_NULL_HENV
) 
 214          /* An option only meaningful for drivers 
 215           * is passed before loading a driver. 
 216           * We classify this as an invalid option error. 
 217           * This is not documented by MS SDK guide. 
 225      case en_dbc_needdata
: 
 229      case en_dbc_connected
: 
 231        if (fOption 
== SQL_ODBC_CURSORS
) 
 241   /* check state of statement handle(s) */ 
 242   for (pstmt 
= (STMT_t FAR 
*) pdbc
->hstmt
; 
 243       pstmt 
!= NULL 
&& sqlstat 
== en_00000
; 
 244       pstmt 
= (STMT_t FAR 
*) pstmt
->next
) 
 246       if (pstmt
->state 
>= en_stmt_needdata 
|| pstmt
->asyn_on 
!= en_NullProc
) 
 252   if (sqlstat 
!= en_00000
) 
 254       PUSHSQLERR (pdbc
->herr
, sqlstat
); 
 259   if (fOption 
== SQL_OPT_TRACE
) 
 260     /* tracing flag can be set before and after connect  
 261      * and only meaningful for driver manager(actually 
 262      * there is only one tracing file under one global 
 268          case SQL_OPT_TRACE_ON
: 
 269            if (pdbc
->tfile 
== NULL
) 
 271                pdbc
->tfile 
= (char FAR 
*) MEM_ALLOC (1 + 
 272                    STRLEN (SQL_OPT_TRACE_FILE_DEFAULT
)); 
 274                if (pdbc
->tfile 
== NULL
) 
 276                    PUSHSQLERR (pdbc
->herr
, en_S1001
); 
 281                STRCPY (pdbc
->tfile
, SQL_OPT_TRACE_FILE_DEFAULT
); 
 284            if (pdbc
->tstm 
== NULL
) 
 287 #if     defined(stderr) && defined(stdout) 
 288                if (STREQ (pdbc
->tfile
, "stderr")) 
 292                else if (STREQ (pdbc
->tfile
, "stdout")) 
 301                        = fopen (pdbc
->tfile
, "a+"); 
 318          case SQL_OPT_TRACE_OFF
: 
 319            if (pdbc
->trace 
&& pdbc
->tstm
) 
 322 #if     defined(stderr) && defined(stdout) 
 323                if (stderr 
!= (FILE FAR 
*) (pdbc
->tstm
) 
 324                    && stdout 
!= (FILE FAR 
*) (pdbc
->tstm
)) 
 336            PUSHSQLERR (pdbc
->herr
, en_S1009
); 
 340       if (sqlstat 
!= en_00000
) 
 342           PUSHSQLERR (pdbc
->herr
, sqlstat
); 
 348   if (fOption 
== SQL_OPT_TRACEFILE
) 
 349     /* Tracing file can be set before and after connect  
 350      * and only meaningful for driver manager.  
 353       if (vParam 
== 0UL || ((char FAR 
*) vParam
)[0] == 0) 
 355           PUSHSQLERR (pdbc
->herr
, en_S1009
); 
 360       if (pdbc
->tfile 
&& STREQ (pdbc
->tfile
, vParam
)) 
 367           PUSHSQLERR (pdbc
->herr
, en_IM014
); 
 374           MEM_FREE (pdbc
->tfile
); 
 377       pdbc
->tfile 
= (char FAR 
*) MEM_ALLOC (1 + STRLEN (vParam
)); 
 379       if (pdbc
->tfile 
== NULL
) 
 381           PUSHSQLERR (pdbc
->herr
, en_S1001
); 
 386       STRCPY (pdbc
->tfile
, vParam
); 
 391   if (pdbc
->state 
!= en_dbc_allocated
) 
 393       /* If already connected, then, driver's odbc call 
 394        * will be invoked. Otherwise, we only save the options 
 395        * and delay the setting process until the connection  
 398       hproc 
= _iodbcdm_getproc (hdbc
, en_SetConnectOption
); 
 400       if (hproc 
== SQL_NULL_HPROC
) 
 402           PUSHSQLERR (pdbc
->herr
, en_IM001
); 
 407       CALL_DRIVER (hdbc
, retcode
, hproc
, en_SetConnectOption
,  
 408         (pdbc
->dhdbc
, fOption
, vParam
)) 
 410       if (retcode 
!= SQL_SUCCESS 
&& retcode 
!= SQL_SUCCESS_WITH_INFO
) 
 417    * Now, either driver's odbc call was successed or 
 418    * driver has not been loaded yet. In the first case, we 
 419    * need flip flag for(such as access_mode, autocommit, ...) 
 420    * for our finit state machine. While in the second case,  
 421    * we need save option values(such as current_qualifier, ...) 
 422    * for delaied setting. So, ... 
 425   /* No matter what state we are(i.e. allocated or connected, ..) 
 426    * we need to flip the flag. 
 430      case SQL_ACCESS_MODE
: 
 431        pdbc
->access_mode 
= vParam
; 
 435        pdbc
->autocommit 
= vParam
; 
 439   /* state transition */ 
 440   if (pdbc
->state 
!= en_dbc_allocated
) 
 445   /* Only 'allocated' state is possible here, and we need to 
 446    * save the options for delaied setting. 
 450      case SQL_CURRENT_QUALIFIER
: 
 451        if (pdbc
->current_qualifier 
!= NULL
) 
 453            MEM_FREE (pdbc
->current_qualifier
); 
 458            pdbc
->current_qualifier 
= NULL
; 
 463        pdbc
->current_qualifier
 
 464            = (char FAR 
*) MEM_ALLOC ( 
 465            STRLEN (vParam
) + 1); 
 467        if (pdbc
->current_qualifier 
== NULL
) 
 469            PUSHSQLERR (pdbc
->herr
, en_S1001
); 
 473        STRCPY (pdbc
->current_qualifier
, vParam
); 
 476      case SQL_LOGIN_TIMEOUT
: 
 477        pdbc
->login_timeout 
= vParam
; 
 480      case SQL_ODBC_CURSORS
: 
 481        pdbc
->odbc_cursors 
= vParam
; 
 484      case SQL_PACKET_SIZE
: 
 485        pdbc
->packet_size 
= vParam
; 
 489        pdbc
->quiet_mode 
= vParam
; 
 492      case SQL_TXN_ISOLATION
: 
 493        pdbc
->txn_isolation 
= vParam
; 
 497        /* Since we didn't save the option value for delaied 
 498         * setting, we should raise an error here. 
 508 SQLGetConnectOption ( 
 513   DBC_t FAR 
*pdbc 
= (DBC_t FAR 
*) hdbc
; 
 514   int sqlstat 
= en_00000
; 
 515   HPROC hproc 
= SQL_NULL_HPROC
; 
 518   if (hdbc 
== SQL_NULL_HDBC
) 
 520       return SQL_INVALID_HANDLE
; 
 524   if (fOption 
< SQL_CONN_OPT_MIN 
||  
 525         (fOption 
> SQL_CONN_OPT_MAX 
&& fOption 
< SQL_CONNECT_OPT_DRVR_START
)) 
 527       PUSHSQLERR (pdbc
->herr
, en_S1092
); 
 535      case en_dbc_allocated
: 
 536        if (fOption 
!= SQL_ACCESS_MODE
 
 537            && fOption 
!= SQL_AUTOCOMMIT
 
 538            && fOption 
!= SQL_LOGIN_TIMEOUT
 
 539            && fOption 
!= SQL_OPT_TRACE
 
 540            && fOption 
!= SQL_OPT_TRACEFILE
) 
 544        /* MS ODBC SDK document only 
 545         * allows SQL_ACCESS_MODE 
 546         * and SQL_AUTOCOMMIT in this 
 547         * dbc state. We allow another  
 548         * two options, because they  
 549         * are only meaningful for driver  
 554      case en_dbc_needdata
: 
 562   if (sqlstat 
!= en_00000
) 
 564       PUSHSQLERR (pdbc
->herr
, sqlstat
); 
 569   /* Tracing and tracing file options are only  
 570    * meaningful for driver manager 
 572   if (fOption 
== SQL_OPT_TRACE
) 
 575         *((UDWORD 
*) pvParam
) = (UDWORD
) SQL_OPT_TRACE_ON
; 
 577         *((UDWORD 
*) pvParam
) = (UDWORD
) SQL_OPT_TRACE_OFF
; 
 582   if (fOption 
== SQL_OPT_TRACEFILE
) 
 584       STRCPY (pvParam
, pdbc
->tfile
); 
 589   if (pdbc
->state 
!= en_dbc_allocated
) 
 590     /* if already connected, we will invoke driver's function */ 
 592       hproc 
= _iodbcdm_getproc (hdbc
, en_GetConnectOption
); 
 594       if (hproc 
== SQL_NULL_HPROC
) 
 596           PUSHSQLERR (pdbc
->herr
, en_IM001
); 
 601       CALL_DRIVER (hdbc
, retcode
, hproc
, en_GetConnectOption
, 
 602         (pdbc
->dhdbc
, fOption
, pvParam
)) 
 607   /* We needn't to handle options which are not allowed  
 608    * to be *get* at a allocated dbc state(and two tracing 
 609    * options which has been handled and returned). Thus,  
 610    * there are only two possible cases.  
 614      case SQL_ACCESS_MODE
: 
 615        *((UDWORD 
*) pvParam
) = pdbc
->access_mode
; 
 619        *((UDWORD 
*) pvParam
) = pdbc
->autocommit
; 
 622      case SQL_LOGIN_TIMEOUT
: 
 623        *((UDWORD 
*) pvParam
) = pdbc
->login_timeout
; 
 639   DBC_t FAR 
*pdbc 
= (DBC_t FAR 
*) hdbc
; 
 647      case en_dbc_allocated
: 
 648      case en_dbc_needdata
: 
 649        PUSHSQLERR (pdbc
->herr
, en_08003
); 
 652      case en_dbc_connected
: 
 660   for (pstmt 
= (STMT_t FAR 
*) (pdbc
->hstmt
); 
 664       if (pstmt
->state 
>= en_stmt_needdata
 
 665           || pstmt
->asyn_on 
!= en_NullProc
) 
 667           PUSHSQLERR (pdbc
->herr
, en_S1010
); 
 673   hproc 
= _iodbcdm_getproc (hdbc
, en_Transact
); 
 675   if (hproc 
== SQL_NULL_HPROC
) 
 677       PUSHSQLERR (pdbc
->herr
, en_IM001
); 
 682   CALL_DRIVER (hdbc
, retcode
, hproc
, en_Transact
, 
 683     (SQL_NULL_HENV
, pdbc
->dhdbc
, fType
)) 
 685   /* state transition */ 
 686   if (retcode 
!= SQL_SUCCESS 
&& retcode 
!= SQL_SUCCESS_WITH_INFO
) 
 691   pdbc
->state 
= en_dbc_hstmt
; 
 693   for (pstmt 
= (STMT_t FAR 
*) (pdbc
->hstmt
); 
 697       switch (pstmt
->state
) 
 699          case en_stmt_prepared
: 
 700            if (pdbc
->cb_commit 
== SQL_CB_DELETE
 
 701                || pdbc
->cb_rollback 
== SQL_CB_DELETE
) 
 703                pstmt
->state 
= en_stmt_allocated
; 
 704                pstmt
->prep_state 
= 0; 
 709          case en_stmt_executed
: 
 710          case en_stmt_cursoropen
: 
 711          case en_stmt_fetched
: 
 712          case en_stmt_xfetched
: 
 713            if (!pstmt
->prep_state
 
 714                && pdbc
->cb_commit 
!= SQL_CB_PRESERVE
 
 715                && pdbc
->cb_rollback 
!= SQL_CB_PRESERVE
) 
 717                pstmt
->state 
= en_stmt_allocated
; 
 718                pstmt
->prep_state 
= 0; 
 719                pstmt
->cursor_state 
= en_stmt_cursor_no
; 
 723            if (pstmt
->prep_state
) 
 725                if (pdbc
->cb_commit 
== SQL_CB_DELETE
 
 726                    || pdbc
->cb_rollback 
== SQL_CB_DELETE
) 
 728                    pstmt
->state 
= en_stmt_allocated
; 
 729                    pstmt
->prep_state 
= 0; 
 730                    pstmt
->cursor_state 
= en_stmt_cursor_no
; 
 734                if (pdbc
->cb_commit 
== SQL_CB_CLOSE
 
 735                    || pdbc
->cb_rollback 
== SQL_CB_CLOSE
) 
 762   GENV_t FAR 
*genv 
= (GENV_t FAR 
*) henv
; 
 763   DBC_t FAR 
*pdbc 
= (DBC_t FAR 
*) hdbc
; 
 767   if (hdbc 
!= SQL_NULL_HDBC
) 
 771   else if (henv 
!= SQL_NULL_HENV
) 
 777       return SQL_INVALID_HANDLE
; 
 781   if (fType 
!= SQL_COMMIT
 
 782       && fType 
!= SQL_ROLLBACK
) 
 784       PUSHSQLERR (herr
, en_S1012
); 
 789   if (hdbc 
!= SQL_NULL_HDBC
) 
 791       retcode 
= _iodbcdm_transact (hdbc
, fType
); 
 795       for (pdbc 
= (DBC_t FAR 
*) (genv
->hdbc
); 
 799           retcode 
|= _iodbcdm_transact (hdbc
, fType
); 
 803   if (retcode 
!= SQL_SUCCESS
 
 804       && retcode 
!= SQL_SUCCESS_WITH_INFO
) 
 806       /* fail on one of the connection */