]> git.saurik.com Git - wxWidgets.git/blobdiff - src/iodbc/hdbc.c
OnExit() is called for modules which were initialized even if the init of
[wxWidgets.git] / src / iodbc / hdbc.c
index 710a9b558abbd0f149da60684502b0276b61e47d..1d47da84f53a4aa3c1034140f4f2ebc50597f6c9 100644 (file)
@@ -1,6 +1,6 @@
 /** data source connect object management functions
 
-    Copyright (C) 1995 by Ke Jin <kejin@empress.com> 
+    Copyright (C) 1995 by Ke Jin <kejin@empress.com>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
 #include       <../iodbc/itrace.h>
 #include       <stdio.h>
 
-RETCODE SQL_API        SQLAllocConnect( 
-                       HENV            henv,
-                       HDBC FAR*       phdbc )
+extern RETCODE _iodbcdm_driverunload();
+
+RETCODE SQL_API SQLAllocConnect(
+                        HENV            henv,
+                        HDBC FAR*       phdbc )
 {
-       GENV_t FAR*     genv = (GENV_t FAR*)henv;
-       DBC_t  FAR*     pdbc;
+        GENV_t FAR*     genv = (GENV_t FAR*)henv;
+        DBC_t  FAR*     pdbc;
 
 #if (ODBCVER >= 0x0300)
-       if( henv == SQL_NULL_HENV 
-        || genv->type != SQL_HANDLE_ENV )
+        if( henv == SQL_NULL_HENV
+         || genv->type != SQL_HANDLE_ENV )
 #else
-       if( henv == SQL_NULL_HENV )
+        if( henv == SQL_NULL_HENV )
 #endif
-       {
-               return SQL_INVALID_HANDLE;
-       }
+        {
+                return SQL_INVALID_HANDLE;
+        }
 
-       if( phdbc == NULL )
-       {
-               PUSHSQLERR ( genv->herr, en_S1009 );
+        if( phdbc == NULL )
+        {
+                PUSHSQLERR ( genv->herr, en_S1009 );
 
-               return SQL_ERROR;
-       }
+                return SQL_ERROR;
+        }
 
-       pdbc = (DBC_t FAR*)MEM_ALLOC (sizeof(DBC_t));
+        pdbc = (DBC_t FAR*)MEM_ALLOC (sizeof(DBC_t));
 
-       if( pdbc == NULL )
-       {
-               *phdbc = SQL_NULL_HDBC;
+        if( pdbc == NULL )
+        {
+                *phdbc = SQL_NULL_HDBC;
 
-               PUSHSQLERR ( genv->herr, en_S1001 );
+                PUSHSQLERR ( genv->herr, en_S1001 );
 
-               return SQL_ERROR;
-       }
+                return SQL_ERROR;
+        }
 
 #if (ODBCVER >= 0x0300)
-       pdbc->type = SQL_HANDLE_DBC;
+        pdbc->type = SQL_HANDLE_DBC;
 #endif
-       /* insert this dbc entry into the link list */
-       pdbc->next = genv->hdbc;
-       genv->hdbc = pdbc;
-       pdbc->genv = henv;              
-
-       pdbc->henv = SQL_NULL_HENV;     
-       pdbc->hstmt= SQL_NULL_HSTMT;
-       pdbc->herr = SQL_NULL_HERR;
-       pdbc->dhdbc= SQL_NULL_HDBC;     
-       pdbc->state= en_dbc_allocated;
-       pdbc->trace = 0;
-       pdbc->tstm  = NULL;
-       pdbc->tfile = NULL;
-
-       /* set connect options to default values */
-       pdbc->access_mode       = SQL_MODE_DEFAULT;
-       pdbc->autocommit        = SQL_AUTOCOMMIT_DEFAULT;
-       pdbc->current_qualifier = NULL;
-       pdbc->login_timeout     = 0UL;
-       pdbc->odbc_cursors      = SQL_CUR_DEFAULT;
-       pdbc->packet_size       = 0UL;
-       pdbc->quiet_mode        = (UDWORD)NULL;
-       pdbc->txn_isolation     = SQL_TXN_READ_UNCOMMITTED;
-       pdbc->cb_commit         = (SWORD)SQL_CB_DELETE;
-       pdbc->cb_rollback       = (SWORD)SQL_CB_DELETE;
-
-       *phdbc = (HDBC)pdbc;
-
-       return SQL_SUCCESS;
+        /* insert this dbc entry into the link list */
+        pdbc->next = genv->hdbc;
+        genv->hdbc = pdbc;
+        pdbc->genv = henv;
+
+        pdbc->henv = SQL_NULL_HENV;
+        pdbc->hstmt= SQL_NULL_HSTMT;
+        pdbc->herr = SQL_NULL_HERR;
+        pdbc->dhdbc= SQL_NULL_HDBC;
+        pdbc->state= en_dbc_allocated;
+        pdbc->trace = 0;
+        pdbc->tstm  = NULL;
+        pdbc->tfile = NULL;
+
+        /* set connect options to default values */
+        pdbc->access_mode       = SQL_MODE_DEFAULT;
+        pdbc->autocommit        = SQL_AUTOCOMMIT_DEFAULT;
+        pdbc->current_qualifier = NULL;
+        pdbc->login_timeout     = 0UL;
+        pdbc->odbc_cursors      = SQL_CUR_DEFAULT;
+        pdbc->packet_size       = 0UL;
+        pdbc->quiet_mode        = (UDWORD)NULL;
+        pdbc->txn_isolation     = SQL_TXN_READ_UNCOMMITTED;
+        pdbc->cb_commit         = (SWORD)SQL_CB_DELETE;
+        pdbc->cb_rollback       = (SWORD)SQL_CB_DELETE;
+
+        *phdbc = (HDBC)pdbc;
+
+        return SQL_SUCCESS;
 }
 
-RETCODE SQL_API        SQLFreeConnect( HDBC    hdbc )
+RETCODE SQL_API SQLFreeConnect( HDBC    hdbc )
 {
-       GENV_t FAR*     genv;
-       DBC_t  FAR*     pdbc = (DBC_t FAR*)hdbc;
-       DBC_t  FAR*     tpdbc;
-
-       if( hdbc == SQL_NULL_HDBC )
-       {
-               return SQL_INVALID_HANDLE;
-       }
-
-       /* check state */
-       if( pdbc->state != en_dbc_allocated ) 
-       {
-               PUSHSQLERR ( pdbc->herr, en_S1010 );
-
-               return SQL_ERROR;
-       }
-
-       genv = (GENV_t FAR*)pdbc->genv;
-
-       for( tpdbc  = (DBC_t FAR*)genv->hdbc;
-            tpdbc != NULL;
-            tpdbc  = tpdbc->next )
-       {
-               if( pdbc == tpdbc )
-               {
-                       genv->hdbc = pdbc->next;
-                       break;
-               }
-
-               if( pdbc == tpdbc->next )
-               {
-                       tpdbc->next = pdbc->next;
-                       break;
-               }
-       }
-
-       /* free this dbc */
-       _iodbcdm_driverunload(pdbc);
-       _iodbcdm_freesqlerrlist( pdbc->herr );
-
-       if( pdbc->tfile )
-       {
-               MEM_FREE( pdbc->tfile );
-       }
-
-       SQLSetConnectOption( pdbc, SQL_OPT_TRACE, SQL_OPT_TRACE_OFF);
-
-       MEM_FREE ( pdbc );
-
-       return SQL_SUCCESS;
+        GENV_t FAR*     genv;
+        DBC_t  FAR*     pdbc = (DBC_t FAR*)hdbc;
+        DBC_t  FAR*     tpdbc;
+
+        if( hdbc == SQL_NULL_HDBC )
+        {
+                return SQL_INVALID_HANDLE;
+        }
+
+        /* check state */
+        if( pdbc->state != en_dbc_allocated )
+        {
+                PUSHSQLERR ( pdbc->herr, en_S1010 );
+
+                return SQL_ERROR;
+        }
+
+        genv = (GENV_t FAR*)pdbc->genv;
+
+        for( tpdbc  = (DBC_t FAR*)genv->hdbc;
+             tpdbc != NULL;
+             tpdbc  = tpdbc->next )
+        {
+                if( pdbc == tpdbc )
+                {
+                        genv->hdbc = pdbc->next;
+                        break;
+                }
+
+                if( pdbc == tpdbc->next )
+                {
+                        tpdbc->next = pdbc->next;
+                        break;
+                }
+        }
+
+        /* free this dbc */
+        _iodbcdm_driverunload(pdbc);
+        _iodbcdm_freesqlerrlist( pdbc->herr );
+
+        if( pdbc->tfile )
+        {
+                MEM_FREE( pdbc->tfile );
+        }
+
+        SQLSetConnectOption( pdbc, SQL_OPT_TRACE, SQL_OPT_TRACE_OFF);
+
+        MEM_FREE ( pdbc );
+
+        return SQL_SUCCESS;
 }
 
-RETCODE SQL_API        SQLSetConnectOption(
-                       HDBC    hdbc,
-                       UWORD   fOption,
-                       UDWORD  vParam )
+RETCODE SQL_API SQLSetConnectOption(
+                        HDBC    hdbc,
+                        UWORD   fOption,
+                        UDWORD  vParam )
 {
-       GENV_t FAR*     genv;
-       DBC_t  FAR*     pdbc    = (DBC_t FAR*)hdbc;
-       STMT_t FAR*     pstmt;
-       HPROC           hproc   = SQL_NULL_HPROC;
-       int             sqlstat = en_00000;
-       RETCODE         retcode = SQL_SUCCESS;
-
-       if( hdbc == SQL_NULL_HDBC )
-       {
-               return SQL_INVALID_HANDLE;
-       }
-
-       /* check option */
-       if( fOption < SQL_CONN_OPT_MIN 
-        || ( fOption > SQL_CONN_OPT_MAX 
-          && fOption < SQL_CONNECT_OPT_DRVR_START ) )
-       {
-               PUSHSQLERR ( pdbc->herr, en_S1092 );
-
-               return SQL_ERROR;
-       }
-
-       /* check state of connection handle */
-       switch( pdbc->state )
-       {
-               case en_dbc_allocated:
-                       if( fOption == SQL_TRANSLATE_DLL
-                        || fOption == SQL_TRANSLATE_OPTION )
-                       {
-                               /* This two options are only meaningful
-                                * for specified driver. So, has to be
-                                * set after a dirver has been loaded.
-                                */
-                               sqlstat = en_08003;
-                               break;
-                       }
-
-                       if( fOption >= SQL_CONNECT_OPT_DRVR_START 
-                        && pdbc->henv == SQL_NULL_HENV )
-                       /* An option only meaningful for drivers
-                        * is passed before loading a driver.
-                        * We classify this as an invalid option error.
-                        * This is not documented by MS SDK guide.
-                        */
-                       {
-                               sqlstat = en_S1092;
-                               break;
-                       }
-                       break;
-
-               case en_dbc_needdata:
-                       sqlstat = en_S1010;
-                       break;
-
-               case en_dbc_connected:
-               case en_dbc_hstmt:
-                       if( fOption == SQL_ODBC_CURSORS )
-                       {
-                               sqlstat = en_08002;
-                       }
-                       break;
-
-               default:
-                       break;
-       }
-
-       /* check state of statement handle(s) */
-       for( pstmt  = (STMT_t FAR*)pdbc->hstmt;
-            pstmt != NULL && sqlstat == en_00000;
-            pstmt  = (STMT_t FAR*)pstmt->next )
-       {
-               if( pstmt->state >= en_stmt_needdata 
-                || pstmt->asyn_on != en_NullProc )
-               {
-                       sqlstat = en_S1010;
-               }
-       }
-
-       if( sqlstat != en_00000 )
-       {
-               PUSHSQLERR ( pdbc->herr, sqlstat );
-       
-               return SQL_ERROR;
-       }
-
-       if( fOption == SQL_OPT_TRACE )
-       /* tracing flag can be set before and after connect 
-        * and only meaningful for driver manager(actually
-        * there is only one tracing file under one global
-        * environment).
-        */
-       {
-               switch( vParam )
-               {
-                       case SQL_OPT_TRACE_ON: 
-                               if( pdbc->tfile == NULL )
-                               {
-                                       pdbc->tfile = (char FAR*)MEM_ALLOC( 1 +
-                                               STRLEN(SQL_OPT_TRACE_FILE_DEFAULT) );
-
-                                       if( pdbc->tfile == NULL )
-                                       {
-                                               PUSHSQLERR( pdbc->herr, en_S1001 );
-
-                                               return SQL_ERROR;
-                                       }
-
-                                       STRCPY( pdbc->tfile, SQL_OPT_TRACE_FILE_DEFAULT );
-                               }
-
-                               if( pdbc->tstm == NULL )
-                               {
-#if    defined(stderr) && defined(stdout)
-                                       if(STREQ( pdbc->tfile, "stderr"))
-                                       {
-                                               pdbc->tstm = stderr;
-                                       }
-                                       else
-                                       if(STREQ(pdbc->tfile, "stdout"))
-                                       {
-                                               pdbc->tstm = stdout;
-                                       }
-                                       else
-#endif 
-                                       {
-                                               pdbc->tstm 
-                                                       = fopen(pdbc->tfile, "a+"); 
-                                       }
-
-                                       if(pdbc->tstm )
-                                       {
-                                               pdbc->trace = 1;
-                                       }
-                                       else
-                                       {
-                                               pdbc->trace = 0;
-
-                                               sqlstat = en_IM013;
-                                               retcode = SQL_ERROR;
-                                       }
-                               }
-                               break;
-
-                       case SQL_OPT_TRACE_OFF:
-                               if( pdbc->trace && pdbc->tstm )
-                               {
-#if    defined(stderr) && defined(stdout)
-                                       if( stderr != (FILE FAR*)(pdbc->tstm)
-                                        && stdout != (FILE FAR*)(pdbc->tstm) )
+        GENV_t FAR*     genv;
+        DBC_t  FAR*     pdbc    = (DBC_t FAR*)hdbc;
+        STMT_t FAR*     pstmt;
+        HPROC           hproc   = SQL_NULL_HPROC;
+        int             sqlstat = en_00000;
+        RETCODE         retcode = SQL_SUCCESS;
+
+        if( hdbc == SQL_NULL_HDBC )
+        {
+                return SQL_INVALID_HANDLE;
+        }
+
+        /* check option */
+        if( fOption < SQL_CONN_OPT_MIN
+         || ( fOption > SQL_CONN_OPT_MAX
+           && fOption < SQL_CONNECT_OPT_DRVR_START ) )
+        {
+                PUSHSQLERR ( pdbc->herr, en_S1092 );
+
+                return SQL_ERROR;
+        }
+
+        /* check state of connection handle */
+        switch( pdbc->state )
+        {
+                case en_dbc_allocated:
+                        if( fOption == SQL_TRANSLATE_DLL
+                         || fOption == SQL_TRANSLATE_OPTION )
+                        {
+                                /* This two options are only meaningful
+                                 * for specified driver. So, has to be
+                                 * set after a dirver has been loaded.
+                                 */
+                                sqlstat = en_08003;
+                                break;
+                        }
+
+                        if( fOption >= SQL_CONNECT_OPT_DRVR_START
+                         && pdbc->henv == SQL_NULL_HENV )
+                        /* An option only meaningful for drivers
+                         * is passed before loading a driver.
+                         * We classify this as an invalid option error.
+                         * This is not documented by MS SDK guide.
+                         */
+                        {
+                                sqlstat = en_S1092;
+                                break;
+                        }
+                        break;
+
+                case en_dbc_needdata:
+                        sqlstat = en_S1010;
+                        break;
+
+                case en_dbc_connected:
+                case en_dbc_hstmt:
+                        if( fOption == SQL_ODBC_CURSORS )
+                        {
+                                sqlstat = en_08002;
+                        }
+                        break;
+
+                default:
+                        break;
+        }
+
+        /* check state of statement handle(s) */
+        for( pstmt  = (STMT_t FAR*)pdbc->hstmt;
+             pstmt != NULL && sqlstat == en_00000;
+             pstmt  = (STMT_t FAR*)pstmt->next )
+        {
+                if( pstmt->state >= en_stmt_needdata
+                 || pstmt->asyn_on != en_NullProc )
+                {
+                        sqlstat = en_S1010;
+                }
+        }
+
+        if( sqlstat != en_00000 )
+        {
+                PUSHSQLERR ( pdbc->herr, sqlstat );
+
+                return SQL_ERROR;
+        }
+
+        if( fOption == SQL_OPT_TRACE )
+        /* tracing flag can be set before and after connect
+         * and only meaningful for driver manager(actually
+         * there is only one tracing file under one global
+         * environment).
+         */
+        {
+                switch( vParam )
+                {
+                        case SQL_OPT_TRACE_ON:
+                                if( pdbc->tfile == NULL )
+                                {
+                                        pdbc->tfile = (char FAR*)MEM_ALLOC( 1 +
+                                                STRLEN(SQL_OPT_TRACE_FILE_DEFAULT) );
+
+                                        if( pdbc->tfile == NULL )
+                                        {
+                                                PUSHSQLERR( pdbc->herr, en_S1001 );
+
+                                                return SQL_ERROR;
+                                        }
+
+                                        STRCPY( pdbc->tfile, SQL_OPT_TRACE_FILE_DEFAULT );
+                                }
+
+                                if( pdbc->tstm == NULL )
+                                {
+#if     defined(stderr) && defined(stdout)
+                                        if(STREQ( pdbc->tfile, "stderr"))
+                                        {
+                                                pdbc->tstm = stderr;
+                                        }
+                                        else
+                                        if(STREQ(pdbc->tfile, "stdout"))
+                                        {
+                                                pdbc->tstm = stdout;
+                                        }
+                                        else
+#endif
+                                        {
+                                                pdbc->tstm
+                                                        = fopen(pdbc->tfile, "a+");
+                                        }
+
+                                        if(pdbc->tstm )
+                                        {
+                                                pdbc->trace = 1;
+                                        }
+                                        else
+                                        {
+                                                pdbc->trace = 0;
+
+                                                sqlstat = en_IM013;
+                                                retcode = SQL_ERROR;
+                                        }
+                                }
+                                break;
+
+                        case SQL_OPT_TRACE_OFF:
+                                if( pdbc->trace && pdbc->tstm )
+                                {
+#if     defined(stderr) && defined(stdout)
+                                        if( stderr != (FILE FAR*)(pdbc->tstm)
+                                         && stdout != (FILE FAR*)(pdbc->tstm) )
 #endif
-                                       {
-                                               fclose(pdbc->tstm);
-                                       }
-                               }
-                               pdbc->tstm = NULL;
-                               pdbc->trace = 0;  
-                               break;
-
-                       default:
-                               PUSHSQLERR (pdbc->herr, en_S1009);
-                               retcode = SQL_ERROR;
-               }
-
-               if( sqlstat != en_00000 )
-               {
-                       PUSHSQLERR ( pdbc->herr, sqlstat );
-               }
-
-               return retcode;
-       }
-
-       if( fOption == SQL_OPT_TRACEFILE )
-       /* Tracing file can be set before and after connect 
-        * and only meaningful for driver manager. 
-        */
-       {
-               if( vParam == 0UL 
-                || ((char FAR*)vParam)[0] == 0 )
-               {
-                       PUSHSQLERR ( pdbc->herr, en_S1009 );
-
-                       return SQL_ERROR;
-               }
-
-               if( pdbc->tfile && STREQ (pdbc->tfile, vParam) )
-               {
-                       return SQL_SUCCESS;
-               }
-
-               if( pdbc->trace )
-               {
-                       PUSHSQLERR ( pdbc->herr, en_IM014 );
-
-                       return SQL_ERROR;
-               }
-
-               if( pdbc->tfile )
-               {
-                       MEM_FREE( pdbc->tfile );
-               }
-
-               pdbc->tfile = (char FAR*)MEM_ALLOC( 1 + STRLEN( vParam ) );
-
-               if( pdbc->tfile == NULL )
-               {
-                       PUSHSQLERR( pdbc->herr, en_S1001 );
-
-                       return SQL_ERROR;
-               }
-
-               STRCPY ( pdbc->tfile, vParam );
-
-               return SQL_SUCCESS;
-       }
-
-       if( pdbc->state != en_dbc_allocated )
-       {
-               /* If already connected, then, driver's odbc call
-                * will be invoked. Otherwise, we only save the options
-                * and delay the setting process until the connection 
-                * been established.  
-                */
-               hproc = _iodbcdm_getproc( hdbc, en_SetConnectOption );
-
-               if( hproc == SQL_NULL_HPROC )
-               {
-                       PUSHSQLERR ( pdbc->herr, en_IM001 );
-               
-                       return SQL_ERROR;
-               }
-
-               CALL_DRIVER ( hdbc, retcode, hproc, en_SetConnectOption, (
-                               pdbc->dhdbc, fOption, vParam ) )
+                                        {
+                                                fclose(pdbc->tstm);
+                                        }
+                                }
+                                pdbc->tstm = NULL;
+                                pdbc->trace = 0;
+                                break;
+
+                        default:
+                                PUSHSQLERR (pdbc->herr, en_S1009);
+                                retcode = SQL_ERROR;
+                }
+
+                if( sqlstat != en_00000 )
+                {
+                        PUSHSQLERR ( pdbc->herr, sqlstat );
+                }
+
+                return retcode;
+        }
+
+        if( fOption == SQL_OPT_TRACEFILE )
+        /* Tracing file can be set before and after connect
+         * and only meaningful for driver manager.
+         */
+        {
+                if( vParam == 0UL
+                 || ((char FAR*)vParam)[0] == 0 )
+                {
+                        PUSHSQLERR ( pdbc->herr, en_S1009 );
+
+                        return SQL_ERROR;
+                }
+
+                if( pdbc->tfile && STREQ (pdbc->tfile, vParam) )
+                {
+                        return SQL_SUCCESS;
+                }
+
+                if( pdbc->trace )
+                {
+                        PUSHSQLERR ( pdbc->herr, en_IM014 );
+
+                        return SQL_ERROR;
+                }
+
+                if( pdbc->tfile )
+                {
+                        MEM_FREE( pdbc->tfile );
+                }
+
+                pdbc->tfile = (char FAR*)MEM_ALLOC( 1 + STRLEN( vParam ) );
+
+                if( pdbc->tfile == NULL )
+                {
+                        PUSHSQLERR( pdbc->herr, en_S1001 );
+
+                        return SQL_ERROR;
+                }
+
+                STRCPY ( pdbc->tfile, vParam );
+
+                return SQL_SUCCESS;
+        }
+
+        if( pdbc->state != en_dbc_allocated )
+        {
+                /* If already connected, then, driver's odbc call
+                 * will be invoked. Otherwise, we only save the options
+                 * and delay the setting process until the connection
+                 * been established.
+                 */
+                hproc = _iodbcdm_getproc( hdbc, en_SetConnectOption );
+
+                if( hproc == SQL_NULL_HPROC )
+                {
+                        PUSHSQLERR ( pdbc->herr, en_IM001 );
+
+                        return SQL_ERROR;
+                }
+
+                CALL_DRIVER ( hdbc, retcode, hproc, en_SetConnectOption, (
+                                pdbc->dhdbc, fOption, vParam ) )
 
 #if 0
-               retcode = hproc( pdbc->dhdbc, fOption, vParam);
+                retcode = hproc( pdbc->dhdbc, fOption, vParam);
 #endif
 
-               if( retcode != SQL_SUCCESS
-                && retcode != SQL_SUCCESS_WITH_INFO )
-               {
-                       return retcode;
-               }
-       }
-
-       /* 
-        * Now, either driver's odbc call was successed or
-        * driver has not been loaded yet. In the first case, we
-        * need flip flag for(such as access_mode, autocommit, ...)
-        * for our finit state machine. While in the second case, 
-        * we need save option values(such as current_qualifier, ...)
-        * for delaied setting. So, ...
-        */
-
-       /* No matter what state we are(i.e. allocated or connected, ..)
-        * we need to flip the flag.
-        */
-       switch( fOption )
-       {
-               case SQL_ACCESS_MODE:
-                       pdbc->access_mode = vParam;
-                       break;
-
-               case SQL_AUTOCOMMIT:
-                       pdbc->autocommit  = vParam;
-                       break;
-       }
-
-       /* state transition */
-       if( pdbc->state != en_dbc_allocated )
-       {
-               return retcode;
-       }
-
-       /* Only 'allocated' state is possible here, and we need to
-        * save the options for delaied setting.
-        */
-       switch( fOption )
-       {
-               case SQL_CURRENT_QUALIFIER:
-                       if( pdbc->current_qualifier != NULL )
-                       {
-                               MEM_FREE ( pdbc->current_qualifier );
-                       }
-
-                       if( vParam == 0UL )
-                       {
-                               pdbc->current_qualifier = NULL;
-
-                               break;
-                       }
-
-                       pdbc->current_qualifier 
-                               = (char FAR*)MEM_ALLOC ( 
-                               STRLEN (vParam) + 1 );
-
-                       if( pdbc->current_qualifier == NULL )
-                       {
-                               PUSHSQLERR ( pdbc->herr, en_S1001 );
-                               return SQL_ERROR;
-                       }
-
-                       STRCPY ( pdbc->current_qualifier, vParam );
-                       break;
-
-               case SQL_LOGIN_TIMEOUT:
-                       pdbc->login_timeout = vParam;
-                       break;
-
-               case SQL_ODBC_CURSORS:
-                       pdbc->odbc_cursors = vParam;
-                       break;
-
-               case SQL_PACKET_SIZE:
-                       pdbc->packet_size = vParam;
-                       break;
-
-               case SQL_QUIET_MODE:
-                       pdbc->quiet_mode = vParam;
-                       break;
-
-               case SQL_TXN_ISOLATION:
-                       pdbc->txn_isolation = vParam;
-                       break;
-
-               default:
-                       /* Since we didn't save the option value for delaied
-                        * setting, we should raise an error here.
-                        */
-                       break;
-       }
-
-       return retcode;
+                if( retcode != SQL_SUCCESS
+                 && retcode != SQL_SUCCESS_WITH_INFO )
+                {
+                        return retcode;
+                }
+        }
+
+        /*
+         * Now, either driver's odbc call was successed or
+         * driver has not been loaded yet. In the first case, we
+         * need flip flag for(such as access_mode, autocommit, ...)
+         * for our finit state machine. While in the second case,
+         * we need save option values(such as current_qualifier, ...)
+         * for delaied setting. So, ...
+         */
+
+        /* No matter what state we are(i.e. allocated or connected, ..)
+         * we need to flip the flag.
+         */
+        switch( fOption )
+        {
+                case SQL_ACCESS_MODE:
+                        pdbc->access_mode = vParam;
+                        break;
+
+                case SQL_AUTOCOMMIT:
+                        pdbc->autocommit  = vParam;
+                        break;
+        }
+
+        /* state transition */
+        if( pdbc->state != en_dbc_allocated )
+        {
+                return retcode;
+        }
+
+        /* Only 'allocated' state is possible here, and we need to
+         * save the options for delaied setting.
+         */
+        switch( fOption )
+        {
+                case SQL_CURRENT_QUALIFIER:
+                        if( pdbc->current_qualifier != NULL )
+                        {
+                                MEM_FREE ( pdbc->current_qualifier );
+                        }
+
+                        if( vParam == 0UL )
+                        {
+                                pdbc->current_qualifier = NULL;
+
+                                break;
+                        }
+
+                        pdbc->current_qualifier
+                                = (char FAR*)MEM_ALLOC (
+                                STRLEN (vParam) + 1 );
+
+                        if( pdbc->current_qualifier == NULL )
+                        {
+                                PUSHSQLERR ( pdbc->herr, en_S1001 );
+                                return SQL_ERROR;
+                        }
+
+                        STRCPY ( pdbc->current_qualifier, vParam );
+                        break;
+
+                case SQL_LOGIN_TIMEOUT:
+                        pdbc->login_timeout = vParam;
+                        break;
+
+                case SQL_ODBC_CURSORS:
+                        pdbc->odbc_cursors = vParam;
+                        break;
+
+                case SQL_PACKET_SIZE:
+                        pdbc->packet_size = vParam;
+                        break;
+
+                case SQL_QUIET_MODE:
+                        pdbc->quiet_mode = vParam;
+                        break;
+
+                case SQL_TXN_ISOLATION:
+                        pdbc->txn_isolation = vParam;
+                        break;
+
+                default:
+                        /* Since we didn't save the option value for delaied
+                         * setting, we should raise an error here.
+                         */
+                        break;
+        }
+
+        return retcode;
 }
 
-RETCODE SQL_API        SQLGetConnectOption(
-                       HDBC    hdbc,
-                       UWORD   fOption,
-                       PTR     pvParam )
+RETCODE SQL_API SQLGetConnectOption(
+                        HDBC    hdbc,
+                        UWORD   fOption,
+                        PTR     pvParam )
 {
-       GENV_t FAR*     genv;
-       DBC_t  FAR*     pdbc = (DBC_t FAR*)hdbc;
-       int             sqlstat = en_00000;
-       HPROC           hproc   = SQL_NULL_HPROC;
-       RETCODE         retcode;
-
-       if( hdbc == SQL_NULL_HDBC )
-       {
-               return SQL_INVALID_HANDLE;
-       }
-
-       /* check option */
-       if( fOption < SQL_CONN_OPT_MIN 
-        || ( fOption > SQL_CONN_OPT_MAX 
-          && fOption < SQL_CONNECT_OPT_DRVR_START ) )
-       {
-               PUSHSQLERR ( pdbc->herr, en_S1092 );
-
-               return SQL_ERROR;
-       }
-
-       /* check state */
-       switch( pdbc->state )
-       {
-               case en_dbc_allocated:
-                       if( fOption != SQL_ACCESS_MODE
-                        && fOption != SQL_AUTOCOMMIT 
-                        && fOption != SQL_LOGIN_TIMEOUT
-                        && fOption != SQL_OPT_TRACE
-                        && fOption != SQL_OPT_TRACEFILE )
-                       {
-                               sqlstat = en_08003;
-                       }
-                       /* MS ODBC SDK document only
-                        * allows SQL_ACCESS_MODE
-                        * and SQL_AUTOCOMMIT in this
-                        * dbc state. We allow another 
-                        * two options, because they 
-                        * are only meaningful for driver 
-                        * manager.  
-                        */
-                       break;
-
-               case en_dbc_needdata:
-                       sqlstat = en_S1010;
-                       break;
-
-               default:
-                       break;
-       }
-
-       if( sqlstat != en_00000 )
-       {
-               PUSHSQLERR ( pdbc->herr, sqlstat );
-
-               return SQL_ERROR;
-       }
-
-       /* Tracing and tracing file options are only 
-        * meaningful for driver manager
-        */
-       if( fOption == SQL_OPT_TRACE )
-       {
-               if( pdbc->trace )
-                       *((UDWORD*)pvParam) = (UDWORD)SQL_OPT_TRACE_ON;
-               else    
-                       *((UDWORD*)pvParam) = (UDWORD)SQL_OPT_TRACE_OFF;
-
-               return SQL_SUCCESS;
-       }
-
-       if( fOption == SQL_OPT_TRACEFILE )
-       {
-               STRCPY (pvParam, pdbc->tfile );
-
-               return SQL_ERROR;
-       }
-
-       if( pdbc->state !=  en_dbc_allocated )
-       /* if already connected, we will invoke driver's function */
-       {
-               hproc = _iodbcdm_getproc( hdbc, en_GetConnectOption );
-
-               if( hproc == SQL_NULL_HPROC )
-               {
-                       PUSHSQLERR( pdbc->herr, en_IM001 );
-               
-                       return SQL_ERROR;
-               }
-
-               CALL_DRIVER ( hdbc, retcode, hproc, en_GetConnectOption, (
-                       pdbc->dhdbc, fOption, pvParam ) )
+        GENV_t FAR*     genv;
+        DBC_t  FAR*     pdbc = (DBC_t FAR*)hdbc;
+        int             sqlstat = en_00000;
+        HPROC           hproc   = SQL_NULL_HPROC;
+        RETCODE         retcode;
+
+        if( hdbc == SQL_NULL_HDBC )
+        {
+                return SQL_INVALID_HANDLE;
+        }
+
+        /* check option */
+        if( fOption < SQL_CONN_OPT_MIN
+         || ( fOption > SQL_CONN_OPT_MAX
+           && fOption < SQL_CONNECT_OPT_DRVR_START ) )
+        {
+                PUSHSQLERR ( pdbc->herr, en_S1092 );
+
+                return SQL_ERROR;
+        }
+
+        /* check state */
+        switch( pdbc->state )
+        {
+                case en_dbc_allocated:
+                        if( fOption != SQL_ACCESS_MODE
+                         && fOption != SQL_AUTOCOMMIT
+                         && fOption != SQL_LOGIN_TIMEOUT
+                         && fOption != SQL_OPT_TRACE
+                         && fOption != SQL_OPT_TRACEFILE )
+                        {
+                                sqlstat = en_08003;
+                        }
+                        /* MS ODBC SDK document only
+                         * allows SQL_ACCESS_MODE
+                         * and SQL_AUTOCOMMIT in this
+                         * dbc state. We allow another
+                         * two options, because they
+                         * are only meaningful for driver
+                         * manager.
+                         */
+                        break;
+
+                case en_dbc_needdata:
+                        sqlstat = en_S1010;
+                        break;
+
+                default:
+                        break;
+        }
+
+        if( sqlstat != en_00000 )
+        {
+                PUSHSQLERR ( pdbc->herr, sqlstat );
+
+                return SQL_ERROR;
+        }
+
+        /* Tracing and tracing file options are only
+         * meaningful for driver manager
+         */
+        if( fOption == SQL_OPT_TRACE )
+        {
+                if( pdbc->trace )
+                        *((UDWORD*)pvParam) = (UDWORD)SQL_OPT_TRACE_ON;
+                else
+                        *((UDWORD*)pvParam) = (UDWORD)SQL_OPT_TRACE_OFF;
+
+                return SQL_SUCCESS;
+        }
+
+        if( fOption == SQL_OPT_TRACEFILE )
+        {
+                STRCPY (pvParam, pdbc->tfile );
+
+                return SQL_ERROR;
+        }
+
+        if( pdbc->state !=  en_dbc_allocated )
+        /* if already connected, we will invoke driver's function */
+        {
+                hproc = _iodbcdm_getproc( hdbc, en_GetConnectOption );
+
+                if( hproc == SQL_NULL_HPROC )
+                {
+                        PUSHSQLERR( pdbc->herr, en_IM001 );
+
+                        return SQL_ERROR;
+                }
+
+                CALL_DRIVER ( hdbc, retcode, hproc, en_GetConnectOption, (
+                        pdbc->dhdbc, fOption, pvParam ) )
 
 #if 0
-               retcode = hproc(pdbc->dhdbc, fOption, pvParam);
+                retcode = hproc(pdbc->dhdbc, fOption, pvParam);
 #endif
-               
-               return retcode;
-       }
-
-       /* We needn't to handle options which are not allowed 
-        * to be *get* at a allocated dbc state(and two tracing
-        * options which has been handled and returned). Thus, 
-        * there are only two possible cases. 
-        */
-       switch( fOption )
-       {
-               case SQL_ACCESS_MODE:
-                       *((UDWORD*)pvParam) = pdbc->access_mode;
-                       break;
-
-               case SQL_AUTOCOMMIT:
-                       *((UDWORD*)pvParam) = pdbc->autocommit;
-                       break;
-
-               case SQL_LOGIN_TIMEOUT:
-                       *((UDWORD*)pvParam) = pdbc->login_timeout;
-                       break;
-
-               default:
-                       break;
-       }
-
-       return SQL_SUCCESS;
+
+                return retcode;
+        }
+
+        /* We needn't to handle options which are not allowed
+         * to be *get* at a allocated dbc state(and two tracing
+         * options which has been handled and returned). Thus,
+         * there are only two possible cases.
+         */
+        switch( fOption )
+        {
+                case SQL_ACCESS_MODE:
+                        *((UDWORD*)pvParam) = pdbc->access_mode;
+                        break;
+
+                case SQL_AUTOCOMMIT:
+                        *((UDWORD*)pvParam) = pdbc->autocommit;
+                        break;
+
+                case SQL_LOGIN_TIMEOUT:
+                        *((UDWORD*)pvParam) = pdbc->login_timeout;
+                        break;
+
+                default:
+                        break;
+        }
+
+        return SQL_SUCCESS;
 }
 
-static RETCODE _iodbcdm_transact( 
-                       HDBC    hdbc,
-                       UWORD   fType )
+static RETCODE  _iodbcdm_transact(
+                        HDBC    hdbc,
+                        UWORD   fType )
 {
-       DBC_t  FAR*     pdbc = (DBC_t FAR*)hdbc;
-       STMT_t FAR*     pstmt;
-       HPROC           hproc;
-       RETCODE         retcode;
-
-       /* check state */
-       switch( pdbc->state )
-       {
-               case en_dbc_allocated:
-               case en_dbc_needdata:
-                       PUSHSQLERR ( pdbc->herr, en_08003 );
-                       return SQL_ERROR;
-
-               case en_dbc_connected:
-                       return SQL_SUCCESS;
-
-               case en_dbc_hstmt:
-               default:
-                       break;
-       }
-
-       for( pstmt  = (STMT_t FAR*)(pdbc->hstmt);
-            pstmt != NULL;
-            pstmt  = pstmt->next )
-       {
-               if( pstmt->state >= en_stmt_needdata
-                || pstmt->asyn_on != en_NullProc )
-               {
-                       PUSHSQLERR ( pdbc->herr, en_S1010 );
-
-                       return SQL_ERROR;
-               }
-       }
-
-       hproc = _iodbcdm_getproc( hdbc, en_Transact );
-
-       if( hproc == SQL_NULL_HPROC )
-       {
-               PUSHSQLERR ( pdbc->herr, en_IM001 );
-
-               return SQL_ERROR;
-       }
-
-       CALL_DRIVER ( hdbc, retcode, hproc, en_Transact, (
-                       SQL_NULL_HENV, pdbc->dhdbc, fType ) )
+        DBC_t  FAR*     pdbc = (DBC_t FAR*)hdbc;
+        STMT_t FAR*     pstmt;
+        HPROC           hproc;
+        RETCODE         retcode;
+
+        /* check state */
+        switch( pdbc->state )
+        {
+                case en_dbc_allocated:
+                case en_dbc_needdata:
+                        PUSHSQLERR ( pdbc->herr, en_08003 );
+                        return SQL_ERROR;
+
+                case en_dbc_connected:
+                        return SQL_SUCCESS;
+
+                case en_dbc_hstmt:
+                default:
+                        break;
+        }
+
+        for( pstmt  = (STMT_t FAR*)(pdbc->hstmt);
+             pstmt != NULL;
+             pstmt  = pstmt->next )
+        {
+                if( pstmt->state >= en_stmt_needdata
+                 || pstmt->asyn_on != en_NullProc )
+                {
+                        PUSHSQLERR ( pdbc->herr, en_S1010 );
+
+                        return SQL_ERROR;
+                }
+        }
+
+        hproc = _iodbcdm_getproc( hdbc, en_Transact );
+
+        if( hproc == SQL_NULL_HPROC )
+        {
+                PUSHSQLERR ( pdbc->herr, en_IM001 );
+
+                return SQL_ERROR;
+        }
+
+        CALL_DRIVER ( hdbc, retcode, hproc, en_Transact, (
+                        SQL_NULL_HENV, pdbc->dhdbc, fType ) )
 
 #if 0
-       retcode = hproc( SQL_NULL_HENV, pdbc->dhdbc, fType );
+        retcode = hproc( SQL_NULL_HENV, pdbc->dhdbc, fType );
 #endif
 
-       /* state transition */
-       if( retcode != SQL_SUCCESS
-        && retcode != SQL_SUCCESS_WITH_INFO )
-       {
-               return retcode;
-       }
-
-       pdbc->state = en_dbc_hstmt;
-
-       for( pstmt  = (STMT_t FAR*)(pdbc->hstmt);
-            pstmt != NULL;
-            pstmt  = pstmt->next )
-       {
-               switch( pstmt->state )
-               {
-                       case en_stmt_prepared:
-                               if( pdbc->cb_commit   == SQL_CB_DELETE
-                                || pdbc->cb_rollback == SQL_CB_DELETE )
-                               {
-                                       pstmt->state = en_stmt_allocated;
-                                       pstmt->prep_state = 0;
-                                       break;
-                               }
-                               break;
-
-                       case en_stmt_executed:
-                       case en_stmt_cursoropen:
-                       case en_stmt_fetched:
-                       case en_stmt_xfetched:
-                               if( ! pstmt->prep_state
-                                && pdbc->cb_commit   != SQL_CB_PRESERVE
-                                && pdbc->cb_rollback != SQL_CB_PRESERVE )
-                               {
-                                       pstmt->state = en_stmt_allocated;
-                                       pstmt->prep_state = 0;
-                                       pstmt->cursor_state = en_stmt_cursor_no;
-                                       break;
-                               }
-
-                               if( pstmt->prep_state )
-                               {
-                                       if( pdbc->cb_commit  == SQL_CB_DELETE
-                                        || pdbc->cb_rollback== SQL_CB_DELETE )
-                                       {
-                                               pstmt->state = en_stmt_allocated;
-                                               pstmt->prep_state = 0;
-                                               pstmt->cursor_state = en_stmt_cursor_no;
-                                               break;
-                                       }
-
-                                       if( pdbc->cb_commit  == SQL_CB_CLOSE
-                                        || pdbc->cb_rollback== SQL_CB_CLOSE )
-                                       {
-                                               pstmt->state 
-                                                       = en_stmt_prepared;
-                                               pstmt->cursor_state 
-                                               = en_stmt_cursor_no;
-                                               break;
-                                       }
-                                       break;
-                               }
-                               break;
-
-                       default:
-                               break;
-               } 
-       }
-
-       return retcode;
+        /* state transition */
+        if( retcode != SQL_SUCCESS
+         && retcode != SQL_SUCCESS_WITH_INFO )
+        {
+                return retcode;
+        }
+
+        pdbc->state = en_dbc_hstmt;
+
+        for( pstmt  = (STMT_t FAR*)(pdbc->hstmt);
+             pstmt != NULL;
+             pstmt  = pstmt->next )
+        {
+                switch( pstmt->state )
+                {
+                        case en_stmt_prepared:
+                                if( pdbc->cb_commit   == SQL_CB_DELETE
+                                 || pdbc->cb_rollback == SQL_CB_DELETE )
+                                {
+                                        pstmt->state = en_stmt_allocated;
+                                        pstmt->prep_state = 0;
+                                        break;
+                                }
+                                break;
+
+                        case en_stmt_executed:
+                        case en_stmt_cursoropen:
+                        case en_stmt_fetched:
+                        case en_stmt_xfetched:
+                                if( ! pstmt->prep_state
+                                 && pdbc->cb_commit   != SQL_CB_PRESERVE
+                                 && pdbc->cb_rollback != SQL_CB_PRESERVE )
+                                {
+                                        pstmt->state = en_stmt_allocated;
+                                        pstmt->prep_state = 0;
+                                        pstmt->cursor_state = en_stmt_cursor_no;
+                                        break;
+                                }
+
+                                if( pstmt->prep_state )
+                                {
+                                        if( pdbc->cb_commit  == SQL_CB_DELETE
+                                         || pdbc->cb_rollback== SQL_CB_DELETE )
+                                        {
+                                                pstmt->state = en_stmt_allocated;
+                                                pstmt->prep_state = 0;
+                                                pstmt->cursor_state = en_stmt_cursor_no;
+                                                break;
+                                        }
+
+                                        if( pdbc->cb_commit  == SQL_CB_CLOSE
+                                         || pdbc->cb_rollback== SQL_CB_CLOSE )
+                                        {
+                                                pstmt->state
+                                                        = en_stmt_prepared;
+                                                pstmt->cursor_state
+                                                = en_stmt_cursor_no;
+                                                break;
+                                        }
+                                        break;
+                                }
+                                break;
+
+                        default:
+                                break;
+                }
+        }
+
+        return retcode;
 }
 
-RETCODE        SQL_API SQLTransact(
-               HENV    henv,
-               HDBC    hdbc,
-               UWORD   fType )
+RETCODE SQL_API SQLTransact(
+                HENV    henv,
+                HDBC    hdbc,
+                UWORD   fType )
 {
-       GENV_t FAR*     genv    = (GENV_t FAR*)henv;
-       DBC_t  FAR*     pdbc    = (DBC_t FAR*)hdbc;
-       HERR            herr;
-       RETCODE         retcode;
-
-       if( hdbc != SQL_NULL_HDBC )
-       {
-               herr = pdbc->herr;
-       }
-       else if( henv != SQL_NULL_HENV )
-       {
-               herr = genv->herr;
-       }
-       else
-       {
-               return SQL_INVALID_HANDLE;
-       }
-       
-       /* check argument */
-       if( fType != SQL_COMMIT
-        && fType != SQL_ROLLBACK )
-       {
-               PUSHSQLERR ( herr, en_S1012 );
-
-               return SQL_ERROR;
-       }
-
-       if( hdbc != SQL_NULL_HDBC )
-       {
-               retcode = _iodbcdm_transact( hdbc, fType );
-       }
-       else
-       {
-               for( pdbc  = (DBC_t FAR*)(genv->hdbc);
-                    pdbc != NULL;
-                    pdbc  = pdbc->next )
-               {
-                       retcode |= _iodbcdm_transact( hdbc, fType );
-               }
-       }
-
-       if( retcode != SQL_SUCCESS
-        && retcode != SQL_SUCCESS_WITH_INFO )
-       {
-               /* fail on one of the connection */
-               return SQL_ERROR;
-       }
-
-       return retcode;
+        GENV_t FAR*     genv    = (GENV_t FAR*)henv;
+        DBC_t  FAR*     pdbc    = (DBC_t FAR*)hdbc;
+        HERR            herr;
+        RETCODE         retcode;
+
+        if( hdbc != SQL_NULL_HDBC )
+        {
+                herr = pdbc->herr;
+        }
+        else if( henv != SQL_NULL_HENV )
+        {
+                herr = genv->herr;
+        }
+        else
+        {
+                return SQL_INVALID_HANDLE;
+        }
+
+        /* check argument */
+        if( fType != SQL_COMMIT
+         && fType != SQL_ROLLBACK )
+        {
+                PUSHSQLERR ( herr, en_S1012 );
+
+                return SQL_ERROR;
+        }
+
+        if( hdbc != SQL_NULL_HDBC )
+        {
+                retcode = _iodbcdm_transact( hdbc, fType );
+        }
+        else
+        {
+                for( pdbc  = (DBC_t FAR*)(genv->hdbc);
+                     pdbc != NULL;
+                     pdbc  = pdbc->next )
+                {
+                        retcode |= _iodbcdm_transact( hdbc, fType );
+                }
+        }
+
+        if( retcode != SQL_SUCCESS
+         && retcode != SQL_SUCCESS_WITH_INFO )
+        {
+                /* fail on one of the connection */
+                return SQL_ERROR;
+        }
+
+        return retcode;
 }