-/** 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>
-
-RETCODE SQL_API SQLAllocConnect(
- HENV henv,
- HDBC FAR* phdbc )
+/*
+ * 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)
{
- 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;
- 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;
}