]> git.saurik.com Git - wxWidgets.git/blobdiff - src/iodbc/hdbc.c
fixed bug with Broadcast() not waking up all threads (Pieter van der Meulen)
[wxWidgets.git] / src / iodbc / hdbc.c
index 7157480dd1a1a56917bb43de58cb4a4491cf54b4..afb6472d198f0da144fa3e685dbc64780d53fb57 100644 (file)
-/** data source connect object management functions
-
-    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
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-**/
-
-#include       <../iodbc/iodbc.h>
-
-#include       <../iodbc/isql.h>
-#include       <../iodbc/isqlext.h>
-
-#include        <../iodbc/dlproc.h>
-
-#include       <../iodbc/herr.h>
-#include       <../iodbc/henv.h>
-#include       <../iodbc/hdbc.h>
-#include       <../iodbc/hstmt.h>
-
-#include       <../iodbc/itrace.h>
-#include       <stdio.h>
+/*
+ *  hdbc.c
+ *
+ *  $Id$
+ *
+ *  Data source connect object management functions
+ *
+ *  The iODBC driver manager.
+ *  
+ *  Copyright (C) 1995 by Ke Jin <kejin@empress.com> 
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include       "config.h"
+
+#include       "isql.h"
+#include       "isqlext.h"
+
+#include        "dlproc.h"
+
+#include       "herr.h"
+#include       "henv.h"
+#include       "hdbc.h"
+#include       "hstmt.h"
+
+#include       "itrace.h"
+#include       "stdio.h"
 
 extern RETCODE _iodbcdm_driverunload();
 
-RETCODE SQL_API        SQLAllocConnect( 
-                       HENV            henv,
-                       HDBC FAR*       phdbc )
+
+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;
-       }
 
-       if( phdbc == NULL )
-       {
-               PUSHSQLERR ( genv->herr, en_S1009 );
+    {
+      return SQL_INVALID_HANDLE;
+    }
 
-               return SQL_ERROR;
-       }
+  if (phdbc == NULL)
+    {
+      PUSHSQLERR (genv->herr, en_S1009);
 
-       pdbc = (DBC_t FAR*)MEM_ALLOC (sizeof(DBC_t));
+      return SQL_ERROR;
+    }
 
-       if( pdbc == NULL )
-       {
-               *phdbc = SQL_NULL_HDBC;
+  pdbc = (DBC_t FAR *) MEM_ALLOC (sizeof (DBC_t));
 
-               PUSHSQLERR ( genv->herr, en_S1001 );
+  if (pdbc == NULL)
+    {
+      *phdbc = SQL_NULL_HDBC;
 
-               return SQL_ERROR;
-       }
+      PUSHSQLERR (genv->herr, en_S1001);
+
+      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;
+  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;
-       }
+  if (hdbc == SQL_NULL_HDBC)
+    {
+      return SQL_INVALID_HANDLE;
+    }
 
-       /* check state */
-       if( pdbc->state != en_dbc_allocated ) 
-       {
-               PUSHSQLERR ( pdbc->herr, en_S1010 );
+  /* check state */
+  if (pdbc->state != en_dbc_allocated)
+    {
+      PUSHSQLERR (pdbc->herr, en_S1010);
 
-               return SQL_ERROR;
-       }
+      return SQL_ERROR;
+    }
 
-       genv = (GENV_t FAR*)pdbc->genv;
+  genv = (GENV_t FAR *) pdbc->genv;
 
-       for( tpdbc  = (DBC_t FAR*)genv->hdbc;
-            tpdbc != NULL;
-            tpdbc  = tpdbc->next )
+  for (tpdbc = (DBC_t FAR *) genv->hdbc;
+      tpdbc != NULL;
+      tpdbc = tpdbc->next)
+    {
+      if (pdbc == tpdbc)
        {
-               if( pdbc == tpdbc )
-               {
-                       genv->hdbc = pdbc->next;
-                       break;
-               }
-
-               if( pdbc == tpdbc->next )
-               {
-                       tpdbc->next = pdbc->next;
-                       break;
-               }
+         genv->hdbc = pdbc->next;
+         break;
        }
 
-       /* free this dbc */
-       _iodbcdm_driverunload(pdbc);
-       _iodbcdm_freesqlerrlist( pdbc->herr );
-
-       if( pdbc->tfile )
+      if (pdbc == tpdbc->next)
        {
-               MEM_FREE( pdbc->tfile );
+         tpdbc->next = pdbc->next;
+         break;
        }
+    }
 
-       SQLSetConnectOption( pdbc, SQL_OPT_TRACE, SQL_OPT_TRACE_OFF);
+  /* free this dbc */
+  _iodbcdm_driverunload (pdbc);
+  _iodbcdm_freesqlerrlist (pdbc->herr);
 
-       MEM_FREE ( pdbc );
-
-       return SQL_SUCCESS;
-}
-
-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;
-       }
+  if (pdbc->tfile)
+    {
+      MEM_FREE (pdbc->tfile);
+    }
 
-       /* check option */
-       if( fOption < SQL_CONN_OPT_MIN 
-        || ( fOption > SQL_CONN_OPT_MAX 
-          && fOption < SQL_CONNECT_OPT_DRVR_START ) )
-       {
-               PUSHSQLERR ( pdbc->herr, en_S1092 );
+  SQLSetConnectOption (pdbc, SQL_OPT_TRACE, SQL_OPT_TRACE_OFF);
 
-               return SQL_ERROR;
-       }
+  MEM_FREE (pdbc);
 
-       /* 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;
-       }
+  return SQL_SUCCESS;
+}
 
-       /* 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;
-       }
+RETCODE SQL_API 
+SQLSetConnectOption (
+    HDBC hdbc,
+    UWORD fOption,
+    UDWORD vParam)
+{
+  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( 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) )
+              if (STREQ (pdbc->tfile, "stderr"))
+                {
+                  pdbc->tstm = stderr;
+                }
+              else if (STREQ (pdbc->tfile, "stdout"))
+                {
+                  pdbc->tstm = stdout;
+                }
+              else
 #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 ) );
+                {
+                  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( 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);
+#if    defined(stderr) && defined(stdout)
+              if (stderr != (FILE FAR *) (pdbc->tstm)
+                  && stdout != (FILE FAR *) (pdbc->tstm))
 #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;
+                {
+                  fclose (pdbc->tstm);
+                }
+            }
+          pdbc->tstm = NULL;
+          pdbc->trace = 0;
+          break;
 
-               case SQL_AUTOCOMMIT:
-                       pdbc->autocommit  = vParam;
-                       break;
-       }
-
-       /* state transition */
-       if( pdbc->state != en_dbc_allocated )
-       {
-               return retcode;
-       }
+        default:
+          PUSHSQLERR (pdbc->herr, en_S1009);
+          retcode = SQL_ERROR;
+        }
 
-       /* Only 'allocated' state is possible here, and we need to
-        * save the options for delaied setting.
-        */
-       switch( fOption )
+      if (sqlstat != en_00000)
        {
-               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;
+         PUSHSQLERR (pdbc->herr, sqlstat);
        }
 
-       return retcode;
-}
-
-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;
+      return retcode;
+    }
 
-       if( hdbc == SQL_NULL_HDBC )
+  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)
        {
-               return SQL_INVALID_HANDLE;
-       }
+         PUSHSQLERR (pdbc->herr, en_S1009);
 
-       /* 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;
+         return SQL_ERROR;
        }
 
-       /* check state */
-       switch( pdbc->state )
+      if (pdbc->tfile && STREQ (pdbc->tfile, vParam))
        {
-               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;
+         return SQL_SUCCESS;
        }
 
-       if( sqlstat != en_00000 )
+      if (pdbc->trace)
        {
-               PUSHSQLERR ( pdbc->herr, sqlstat );
+         PUSHSQLERR (pdbc->herr, en_IM014);
 
-               return SQL_ERROR;
+         return SQL_ERROR;
        }
 
-       /* Tracing and tracing file options are only 
-        * meaningful for driver manager
-        */
-       if( fOption == SQL_OPT_TRACE )
+      if (pdbc->tfile)
        {
-               if( pdbc->trace )
-                       *((UDWORD*)pvParam) = (UDWORD)SQL_OPT_TRACE_ON;
-               else    
-                       *((UDWORD*)pvParam) = (UDWORD)SQL_OPT_TRACE_OFF;
-
-               return SQL_SUCCESS;
+         MEM_FREE (pdbc->tfile);
        }
 
-       if( fOption == SQL_OPT_TRACEFILE )
+      pdbc->tfile = (char FAR *) MEM_ALLOC (1 + STRLEN (vParam));
+
+      if (pdbc->tfile == NULL)
        {
-               STRCPY (pvParam, pdbc->tfile );
+         PUSHSQLERR (pdbc->herr, en_S1001);
 
-               return SQL_ERROR;
+         return SQL_ERROR;
        }
 
-       if( pdbc->state !=  en_dbc_allocated )
-       /* if already connected, we will invoke driver's function */
-       {
-               hproc = _iodbcdm_getproc( hdbc, en_GetConnectOption );
+      STRCPY (pdbc->tfile, vParam);
 
-               if( hproc == SQL_NULL_HPROC )
-               {
-                       PUSHSQLERR( pdbc->herr, en_IM001 );
-               
-                       return SQL_ERROR;
-               }
+      return SQL_SUCCESS;
+    }
 
-               CALL_DRIVER ( hdbc, retcode, hproc, en_GetConnectOption, (
-                       pdbc->dhdbc, fOption, pvParam ) )
+  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 0
-               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 )
+      if (hproc == SQL_NULL_HPROC)
        {
-               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;
+         PUSHSQLERR (pdbc->herr, en_IM001);
 
-               default:
-                       break;
+         return SQL_ERROR;
        }
 
-       return SQL_SUCCESS;
-}
-
-static RETCODE _iodbcdm_transact( 
-                       HDBC    hdbc,
-                       UWORD   fType )
-{
-       DBC_t  FAR*     pdbc = (DBC_t FAR*)hdbc;
-       STMT_t FAR*     pstmt;
-       HPROC           hproc;
-       RETCODE         retcode;
+      CALL_DRIVER (hdbc, retcode, hproc, en_SetConnectOption, 
+        (pdbc->dhdbc, fOption, vParam))
 
-       /* check state */
-       switch( pdbc->state )
+      if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
        {
-               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;
+         return retcode;
        }
+    }
 
-       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 );
+  /* 
+   * 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, ...
+   */
 
-                       return SQL_ERROR;
-               }
-       }
+  /* 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;
 
-       hproc = _iodbcdm_getproc( hdbc, en_Transact );
+     case SQL_AUTOCOMMIT:
+       pdbc->autocommit = vParam;
+       break;
+     }
 
-       if( hproc == SQL_NULL_HPROC )
-       {
-               PUSHSQLERR ( pdbc->herr, en_IM001 );
+  /* state transition */
+  if (pdbc->state != en_dbc_allocated)
+    {
+      return retcode;
+    }
 
-               return SQL_ERROR;
-       }
+  /* 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);
+        }
 
-       CALL_DRIVER ( hdbc, retcode, hproc, en_Transact, (
-                       SQL_NULL_HENV, pdbc->dhdbc, fType ) )
+       if (vParam == 0UL)
+        {
+          pdbc->current_qualifier = NULL;
 
-#if 0
-       retcode = hproc( SQL_NULL_HENV, pdbc->dhdbc, fType );
-#endif
+          break;
+        }
 
-       /* state transition */
-       if( retcode != SQL_SUCCESS
-        && retcode != SQL_SUCCESS_WITH_INFO )
-       {
-               return retcode;
-       }
+       pdbc->current_qualifier
+          = (char FAR *) MEM_ALLOC (
+          STRLEN (vParam) + 1);
 
-       pdbc->state = en_dbc_hstmt;
+       if (pdbc->current_qualifier == NULL)
+        {
+          PUSHSQLERR (pdbc->herr, en_S1001);
+          return SQL_ERROR;
+        }
 
-       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;
-               } 
-       }
+       STRCPY (pdbc->current_qualifier, vParam);
+       break;
 
-       return retcode;
+     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 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 = 0;
 
-       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 );
+RETCODE SQL_API 
+SQLGetConnectOption (
+    HDBC hdbc,
+    UWORD fOption,
+    PTR pvParam)
+{
+  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))
+
+      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 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 );
-               }
-       }
+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))
+
+  /* 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;
+}
 
-       if( retcode != SQL_SUCCESS
-        && retcode != SQL_SUCCESS_WITH_INFO )
-       {
-               /* fail on one of the connection */
-               return SQL_ERROR;
-       }
 
-       return retcode;
+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 = 0;
+
+  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;
 }