#include <iodbc.h>
#include <sql.h>
#include <sqlext.h>
#include <dlproc.h>
#include <herr.h>
#include <henv.h>
#include <hdbc.h>
#include <hstmt.h>
#include <itrace.h>
#if defined(_MACX) && defined(GUI)
#include <Carbon/Carbon.h>
#endif
extern char *_iodbcdm_getkeyvalbydsn ();
extern char *_iodbcdm_getkeyvalinstr ();
extern SQLRETURN _iodbcdm_driverunload ();
static char sccsid[] = "@(#)iODBC driver manager " VERSION ", (LGPL)\n";
char *version = VERSION;
char *libname = "iODBC Driver Manager";
static SQLRETURN
_iodbcdm_driverload (
char FAR * path,
HDBC hdbc,
SWORD thread_safe)
{
CONN (pdbc, hdbc);
GENV_t FAR *genv;
ENV_t FAR *penv = NULL;
HDLL hdll;
HPROC hproc;
SQLRETURN retcode = SQL_SUCCESS;
int sqlstat = en_00000;
if (path == NULL || path[0] == '\0')
{
PUSHSQLERR (pdbc->herr, en_IM002);
return SQL_ERROR;
}
if (!IS_VALID_HDBC (pdbc) || pdbc->genv == SQL_NULL_HENV)
{
return SQL_INVALID_HANDLE;
}
genv = (GENV_t FAR *) pdbc->genv;
hdll = _iodbcdm_dllopen ((char FAR *) path);
if (hdll == SQL_NULL_HDLL)
{
PUSHSYSERR (pdbc->herr, _iodbcdm_dllerror ());
PUSHSQLERR (pdbc->herr, en_IM003);
return SQL_ERROR;
}
penv = (ENV_t FAR *) (pdbc->henv);
if (penv != NULL)
{
if (penv->hdll != hdll)
{
_iodbcdm_driverunload (hdbc);
penv->hdll = hdll;
}
else
{
_iodbcdm_dllclose (hdll);
}
}
if (penv == NULL)
{
for (penv = (ENV_t FAR *) genv->henv;
penv != NULL;
penv = (ENV_t FAR *) penv->next)
{
if (penv->hdll == hdll)
{
_iodbcdm_dllclose (hdll);
break;
}
}
if (penv == NULL)
{
int i;
penv = (ENV_t FAR *) MEM_ALLOC (sizeof (ENV_t));
if (penv == NULL)
{
_iodbcdm_dllclose (hdll);
PUSHSQLERR (pdbc->herr, en_S1001);
return SQL_ERROR;
}
for (i = 0; i < __LAST_API_FUNCTION__; i++)
{
#if 1
(penv->dllproc_tab)[i] = SQL_NULL_HPROC;
#else
(penv->dllproc_tab)[i] = _iodbcdm_getproc(pdbc, i);
#endif
}
pdbc->henv = penv;
penv->hdll = hdll;
penv->thread_safe = thread_safe;
if (!penv->thread_safe)
MUTEX_INIT (penv->drv_lock);
#if (ODBCVER >= 0x0300)
hproc = _iodbcdm_getproc (pdbc, en_AllocHandle);
if (hproc)
{
penv->dodbc_ver = SQL_OV_ODBC3;
CALL_DRIVER (hdbc, genv, retcode, hproc, en_AllocHandle,
(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &(penv->dhenv)));
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)
{
hproc = _iodbcdm_getproc (pdbc, en_SetEnvAttr);
if (hproc != SQL_NULL_HPROC)
{
CALL_DRIVER (hdbc, genv, retcode, hproc, en_SetStmtAttr,
(penv->dhenv, SQL_ATTR_ODBC_VERSION, genv->odbc_ver, 0));
}
}
}
else
#endif
{
hproc = _iodbcdm_getproc (pdbc, en_AllocEnv);
if (hproc == SQL_NULL_HPROC)
{
sqlstat = en_IM004;
}
else
{
#if (ODBCVER >= 0x0300)
penv->dodbc_ver = SQL_OV_ODBC2;
#endif
CALL_DRIVER (hdbc, genv, retcode, hproc,
en_AllocEnv, (&(penv->dhenv)));
}
}
if (retcode == SQL_ERROR)
{
sqlstat = en_IM004;
}
if (sqlstat != en_00000)
{
_iodbcdm_dllclose (hdll);
MEM_FREE (penv);
PUSHSQLERR (pdbc->herr, en_IM004);
return SQL_ERROR;
}
penv->next = (ENV_t FAR *) genv->henv;
genv->henv = penv;
penv->refcount = 0;
}
pdbc->henv = penv;
if (pdbc->dhdbc == SQL_NULL_HDBC)
{
#if (ODBCVER >= 0x0300)
hproc = _iodbcdm_getproc (pdbc, en_AllocHandle);
if (hproc)
{
CALL_DRIVER (hdbc, genv, retcode, hproc, en_AllocHandle,
(SQL_HANDLE_DBC, penv->dhenv, &(pdbc->dhdbc)));
}
else
#endif
{
hproc = _iodbcdm_getproc (pdbc, en_AllocConnect);
if (hproc == SQL_NULL_HPROC)
{
sqlstat = en_IM005;
}
else
{
CALL_DRIVER (hdbc, genv, retcode, hproc,
en_AllocConnect, (penv->dhenv, &(pdbc->dhdbc)));
}
}
if (retcode == SQL_ERROR)
{
sqlstat = en_IM005;
}
if (sqlstat != en_00000)
{
_iodbcdm_driverunload (hdbc);
pdbc->dhdbc = SQL_NULL_HDBC;
PUSHSQLERR (pdbc->herr, en_IM005);
return SQL_ERROR;
}
}
pdbc->henv = penv;
penv->refcount++;
}
if (pdbc->login_timeout != 0UL)
{
hproc = _iodbcdm_getproc (pdbc, en_SetConnectOption);
if (hproc == SQL_NULL_HPROC)
{
sqlstat = en_IM004;
}
else
{
CALL_DRIVER (hdbc, pdbc, retcode, hproc,
en_SetConnectOption, (
pdbc->dhdbc,
SQL_LOGIN_TIMEOUT,
pdbc->login_timeout));
if (retcode == SQL_ERROR)
{
PUSHSQLERR (pdbc->herr, en_IM006);
return SQL_SUCCESS_WITH_INFO;
}
}
}
if (pdbc->drvopt != NULL)
{
hproc = _iodbcdm_getproc (pdbc, en_SetConnectOption);
if (hproc == SQL_NULL_HPROC)
{
sqlstat = en_IM004;
}
else
{
DRVOPT *popt;
for (popt = pdbc->drvopt; popt != NULL; popt = popt->next)
{
CALL_DRIVER (hdbc, pdbc, retcode, hproc,
en_SetConnectOption, (
pdbc->dhdbc,
popt->Option,
popt->Param));
if (retcode == SQL_ERROR)
{
PUSHSQLERR (pdbc->herr, en_IM006);
return SQL_SUCCESS_WITH_INFO;
}
}
}
}
return SQL_SUCCESS;
}
SQLRETURN
_iodbcdm_driverunload (HDBC hdbc)
{
CONN (pdbc, hdbc);
ENV_t FAR *penv;
ENV_t FAR *tpenv;
GENV_t FAR *genv;
HPROC hproc;
SQLRETURN retcode = SQL_SUCCESS;
if (!IS_VALID_HDBC (pdbc))
{
return SQL_INVALID_HANDLE;
}
penv = (ENV_t FAR *) pdbc->henv;
genv = (GENV_t FAR *) pdbc->genv;
if (penv == NULL || penv->hdll == SQL_NULL_HDLL)
{
return SQL_SUCCESS;
}
#if (ODBCVER >= 0x0300)
hproc = _iodbcdm_getproc (pdbc, en_FreeHandle);
if (hproc)
{
CALL_DRIVER (hdbc, pdbc, retcode, hproc, en_FreeHandle,
(SQL_HANDLE_DBC, pdbc->dhdbc));
}
else
#endif
{
hproc = _iodbcdm_getproc (pdbc, en_FreeConnect);
if (hproc != SQL_NULL_HPROC)
{
CALL_DRIVER (hdbc, pdbc, retcode, hproc,
en_FreeConnect, (pdbc->dhdbc));
pdbc->dhdbc = SQL_NULL_HDBC;
}
}
penv->refcount--;
if (!penv->refcount)
{
#if (ODBCVER >= 0x0300)
hproc = _iodbcdm_getproc (pdbc, en_FreeHandle);
if (hproc)
{
CALL_DRIVER (hdbc, genv, retcode, hproc, en_FreeHandle,
(SQL_HANDLE_ENV, penv->dhenv));
}
else
#endif
{
hproc = _iodbcdm_getproc (pdbc, en_FreeEnv);
if (hproc != SQL_NULL_HPROC)
{
CALL_DRIVER (hdbc, genv, retcode, hproc, en_FreeEnv,
(penv->dhenv));
penv->dhenv = SQL_NULL_HENV;
}
}
_iodbcdm_dllclose (penv->hdll);
penv->hdll = SQL_NULL_HDLL;
for (tpenv = (ENV_t FAR *) genv->henv;
tpenv != NULL;
tpenv = (ENV_t FAR *) penv->next)
{
if (tpenv == penv)
{
genv->henv = penv->next;
break;
}
if (tpenv->next == penv)
{
tpenv->next = penv->next;
break;
}
}
MEM_FREE (penv);
}
pdbc->hstmt = SQL_NULL_HSTMT;
pdbc->dhdbc = SQL_NULL_HDBC;
pdbc->state = en_dbc_allocated;
pdbc->odbc_cursors = SQL_CUR_DEFAULT;
pdbc->packet_size = 0UL;
pdbc->quiet_mode = (UDWORD) NULL;
pdbc->txn_isolation = SQL_TXN_READ_UNCOMMITTED;
if (pdbc->current_qualifier != NULL)
{
MEM_FREE (pdbc->current_qualifier);
pdbc->current_qualifier = NULL;
}
return SQL_SUCCESS;
}
static SQLRETURN
_iodbcdm_dbcdelayset (HDBC hdbc)
{
CONN (pdbc, hdbc);
ENV_t FAR *penv;
HPROC hproc;
SQLRETURN retcode = SQL_SUCCESS;
SQLRETURN ret;
penv = pdbc->henv;
hproc = _iodbcdm_getproc (pdbc, en_SetConnectOption);
if (hproc == SQL_NULL_HPROC)
{
PUSHSQLERR (pdbc->herr, en_IM006);
return SQL_SUCCESS_WITH_INFO;
}
if (pdbc->access_mode != SQL_MODE_DEFAULT)
{
CALL_DRIVER (hdbc, pdbc, ret, hproc,
en_SetConnectOption, (
SQL_ACCESS_MODE,
pdbc->access_mode));
retcode |= ret;
}
if (pdbc->autocommit != SQL_AUTOCOMMIT_DEFAULT)
{
CALL_DRIVER (hdbc, pdbc, ret, hproc,
en_SetConnectOption, (
pdbc->dhdbc,
SQL_AUTOCOMMIT,
pdbc->autocommit));
retcode |= ret;
}
if (pdbc->current_qualifier != NULL)
{
CALL_DRIVER (hdbc, pdbc, ret, hproc,
en_SetConnectOption, (
pdbc->dhdbc,
SQL_CURRENT_QUALIFIER,
pdbc->current_qualifier));
retcode |= ret;
}
if (pdbc->packet_size != 0UL)
{
CALL_DRIVER (hdbc, pdbc, ret, hproc,
en_SetConnectOption, (
pdbc->dhdbc,
SQL_PACKET_SIZE,
pdbc->packet_size));
retcode |= ret;
}
if (pdbc->quiet_mode != (UDWORD) NULL)
{
CALL_DRIVER (hdbc, pdbc, ret, hproc,
en_SetConnectOption, (
pdbc->dhdbc,
SQL_QUIET_MODE,
pdbc->quiet_mode));
retcode |= ret;
}
if (pdbc->txn_isolation != SQL_TXN_READ_UNCOMMITTED)
{
CALL_DRIVER (hdbc, pdbc, ret, hproc,
en_SetConnectOption, (
pdbc->dhdbc,
SQL_TXN_ISOLATION,
pdbc->txn_isolation));
}
if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
{
PUSHSQLERR (pdbc->herr, en_IM006);
retcode = SQL_ERROR;
}
hproc = _iodbcdm_getproc (pdbc, en_GetInfo);
if (hproc == SQL_NULL_HPROC)
{
PUSHSQLERR (pdbc->herr, en_01000);
return retcode;
}
CALL_DRIVER (hdbc, pdbc, ret, hproc,
en_GetInfo, (
pdbc->dhdbc,
SQL_CURSOR_COMMIT_BEHAVIOR,
(PTR) & (pdbc->cb_commit),
sizeof (pdbc->cb_commit),
NULL));
retcode |= ret;
CALL_DRIVER (hdbc, pdbc, ret, hproc,
en_GetInfo, (
pdbc->dhdbc,
SQL_CURSOR_ROLLBACK_BEHAVIOR,
(PTR) & (pdbc->cb_rollback),
sizeof (pdbc->cb_rollback),
NULL));
retcode |= ret;
if (retcode != SQL_SUCCESS
&& retcode != SQL_SUCCESS_WITH_INFO)
{
return SQL_ERROR;
}
return retcode;
}
static SQLRETURN
_iodbcdm_settracing (HDBC hdbc, char *dsn, int dsnlen)
{
char buf[256];
char *ptr;
SQLRETURN setopterr = SQL_SUCCESS;
ptr = _iodbcdm_getkeyvalbydsn (dsn, dsnlen, "TraceFile",
(char FAR *) buf, sizeof (buf));
if (ptr == NULL || ptr[0] == '\0')
{
ptr = (char FAR *) (SQL_OPT_TRACE_FILE_DEFAULT);
}
setopterr |= _iodbcdm_SetConnectOption ((SQLHDBC) hdbc,
SQL_OPT_TRACEFILE, (UDWORD) (ptr));
ptr = _iodbcdm_getkeyvalbydsn (dsn, dsnlen, "Trace",
(char FAR *) buf, sizeof (buf));
if (ptr != NULL)
{
UDWORD opt = (UDWORD) (-1L);
if (STREQ (ptr, "ON")
|| STREQ (ptr, "On")
|| STREQ (ptr, "on")
|| STREQ (ptr, "1"))
{
opt = SQL_OPT_TRACE_ON;
}
if (STREQ (ptr, "OFF")
|| STREQ (ptr, "Off")
|| STREQ (ptr, "off")
|| STREQ (ptr, "0"))
{
opt = SQL_OPT_TRACE_OFF;
}
if (opt != (UDWORD) (-1L))
{
setopterr |= _iodbcdm_SetConnectOption ((SQLHDBC) hdbc,
SQL_OPT_TRACE, opt);
}
}
return setopterr;
}
SQLRETURN SQL_API
SQLConnect (
SQLHDBC hdbc,
SQLCHAR FAR * szDSN,
SQLSMALLINT cbDSN,
SQLCHAR FAR * szUID,
SQLSMALLINT cbUID,
SQLCHAR FAR * szAuthStr,
SQLSMALLINT cbAuthStr)
{
CONN (pdbc, hdbc);
SQLRETURN retcode = SQL_SUCCESS;
SQLRETURN setopterr = SQL_SUCCESS;
char driver[1024] =
{'\0'};
char *ptr;
HPROC hproc;
SWORD thread_safe;
char buf[100];
ODBC_LOCK ();
if (!IS_VALID_HDBC (pdbc))
{
ODBC_UNLOCK ();
return SQL_INVALID_HANDLE;
}
CLEAR_ERRORS (pdbc);
if ((cbDSN < 0 && cbDSN != SQL_NTS)
|| (cbUID < 0 && cbUID != SQL_NTS)
|| (cbAuthStr < 0 && cbAuthStr != SQL_NTS)
|| (cbDSN > SQL_MAX_DSN_LENGTH))
{
PUSHSQLERR (pdbc->herr, en_S1090);
ODBC_UNLOCK ();
return SQL_ERROR;
}
if (szDSN == NULL || cbDSN == 0)
{
PUSHSQLERR (pdbc->herr, en_IM002);
ODBC_UNLOCK ();
return SQL_ERROR;
}
if (pdbc->state != en_dbc_allocated)
{
PUSHSQLERR (pdbc->herr, en_08002);
ODBC_UNLOCK ();
return SQL_ERROR;
}
setopterr |= _iodbcdm_settracing (pdbc,
(char *) szDSN, cbDSN);
ptr = _iodbcdm_getkeyvalbydsn (szDSN, cbDSN, "ThreadManager",
(char FAR *) buf, sizeof (buf));
thread_safe = 1;
if (ptr != NULL)
{
if (STREQ (ptr, "ON")
|| STREQ (ptr, "On")
|| STREQ (ptr, "on")
|| STREQ (ptr, "1"))
{
thread_safe = 0;
}
}
ptr = _iodbcdm_getkeyvalbydsn (szDSN, cbDSN, "Driver",
(char FAR *) driver, sizeof (driver));
if (ptr == NULL)
{
PUSHSQLERR (pdbc->herr, en_IM002);
ODBC_UNLOCK ();
return SQL_ERROR;
}
retcode = _iodbcdm_driverload (driver, pdbc, thread_safe);
switch (retcode)
{
case SQL_SUCCESS:
break;
case SQL_SUCCESS_WITH_INFO:
setopterr = SQL_ERROR;
break;
default:
ODBC_UNLOCK ();
return retcode;
}
hproc = _iodbcdm_getproc (pdbc, en_Connect);
if (hproc == SQL_NULL_HPROC)
{
_iodbcdm_driverunload (pdbc);
PUSHSQLERR (pdbc->herr, en_IM001);
ODBC_UNLOCK ();
return SQL_ERROR;
}
CALL_DRIVER (hdbc, pdbc, retcode, hproc, en_Connect, (
pdbc->dhdbc,
szDSN, cbDSN,
szUID, cbUID,
szAuthStr, cbAuthStr));
if (retcode != SQL_SUCCESS
&& retcode != SQL_SUCCESS_WITH_INFO)
{
ODBC_UNLOCK ();
return retcode;
}
pdbc->state = en_dbc_connected;
setopterr |= _iodbcdm_dbcdelayset (pdbc);
if (setopterr != SQL_SUCCESS)
{
ODBC_UNLOCK ();
return SQL_SUCCESS_WITH_INFO;
}
ODBC_UNLOCK ();
return retcode;
}
#if defined(_MACX) && defined(GUI)
extern SQLRETURN SQL_API _iodbcdm_drvconn_dialbox (HWND hwnd,
LPSTR szInOutConnStr, DWORD cbInOutConnStr, int FAR * sqlStat);
#endif
SQLRETURN SQL_API
SQLDriverConnect (
SQLHDBC hdbc,
SQLHWND hwnd,
SQLCHAR FAR * szConnStrIn,
SQLSMALLINT cbConnStrIn,
SQLCHAR FAR * szConnStrOut,
SQLSMALLINT cbConnStrOutMax,
SQLSMALLINT FAR * pcbConnStrOut,
SQLUSMALLINT fDriverCompletion)
{
CONN (pdbc, hdbc);
HDLL hdll;
char FAR *drv = NULL;
char drvbuf[1024];
char FAR *dsn = NULL;
char dsnbuf[SQL_MAX_DSN_LENGTH + 1];
UCHAR cnstr2drv[1024];
SWORD thread_safe;
char buf[100];
char *ptr;
int i;
HPROC hproc;
HPROC dialproc;
int sqlstat = en_00000;
SQLRETURN retcode = SQL_SUCCESS;
SQLRETURN setopterr = SQL_SUCCESS;
ODBC_LOCK ();
if (!IS_VALID_HDBC (pdbc))
{
ODBC_UNLOCK ();
return SQL_INVALID_HANDLE;
}
CLEAR_ERRORS (pdbc);
if ((cbConnStrIn < 0 && cbConnStrIn != SQL_NTS) || cbConnStrOutMax < 0)
{
PUSHSQLERR (pdbc->herr, en_S1090);
ODBC_UNLOCK ();
return SQL_ERROR;
}
if (pdbc->state != en_dbc_allocated)
{
PUSHSQLERR (pdbc->herr, en_08002);
ODBC_UNLOCK ();
return SQL_ERROR;
}
drv = _iodbcdm_getkeyvalinstr (szConnStrIn, cbConnStrIn,
"DRIVER", drvbuf, sizeof (drvbuf));
dsn = _iodbcdm_getkeyvalinstr (szConnStrIn, cbConnStrIn,
"DSN", dsnbuf, sizeof (dsnbuf));
switch (fDriverCompletion)
{
case SQL_DRIVER_NOPROMPT:
break;
case SQL_DRIVER_COMPLETE:
case SQL_DRIVER_COMPLETE_REQUIRED:
if (dsn != NULL || drv != NULL)
{
break;
}
case SQL_DRIVER_PROMPT:
if (dsn == NULL || dsn[0] == '\0')
dsn = "default";
if (drv == NULL || drv[0] == '\0')
drv = _iodbcdm_getkeyvalbydsn (dsn, SQL_NTS, "Driver", drvbuf,
sizeof (drvbuf));
#ifndef _MACX
if (!(hdll = _iodbcdm_dllopen ("libiodbcadm.so"))
|| !(dialproc = _iodbcdm_dllproc (hdll, "iodbcdm_drvconn_dialbox")))
{
sqlstat = en_IM008;
retcode = SQL_ERROR;
break;
}
#endif
if (cbConnStrOutMax < cbConnStrIn && cbConnStrIn != SQL_NTS)
{
#if (ODBCVER>=0x3000)
sqlstat = en_HY092;
#else
sqlstat = en_S1000;
#endif
retcode = SQL_ERROR;
break;
}
STRNCPY (szConnStrOut, szConnStrIn, (cbConnStrOutMax != SQL_NTS) ?
cbConnStrOutMax : STRLEN (szConnStrIn) + 1);
for (i = STRLEN (szConnStrOut); i; i--)
if (szConnStrOut[i] == ';')
szConnStrOut[i] = 0;
#if defined(GUI)
# if defined(_MACX)
retcode = iodbcdm_drvconn_dialbox (
# else
retcode = dialproc (
# endif
hwnd,
szConnStrOut,
cbConnStrOutMax,
&sqlstat);
#else
sqlstat = en_IM008;
retcode = SQL_ERROR;
#endif
if (retcode != SQL_SUCCESS)
{
break;
}
dsn = dsnbuf;
if (dsn[0] == '\0')
dsn = "default";
if (STRLEN (szConnStrOut) > sizeof (cnstr2drv) - 1)
{
sqlstat = en_S1001;
break;
}
STRNCPY (cnstr2drv, szConnStrOut, sizeof (cnstr2drv));
szConnStrIn = cnstr2drv;
break;
default:
sqlstat = en_S1110;
break;
}
if (sqlstat != en_00000)
{
PUSHSQLERR (pdbc->herr, sqlstat);
ODBC_UNLOCK ();
return SQL_ERROR;
}
if (dsn == NULL || dsn[0] == '\0')
{
dsn = "default";
}
else
{
setopterr |= _iodbcdm_settracing (pdbc, (char *) dsn, SQL_NTS);
}
ptr = _iodbcdm_getkeyvalbydsn (dsn, SQL_NTS, "ThreadManager",
(char FAR *) buf, sizeof (buf));
thread_safe = 1;
if (ptr != NULL)
{
if (STREQ (ptr, "ON")
|| STREQ (ptr, "On") || STREQ (ptr, "on") || STREQ (ptr, "1"))
{
thread_safe = 0;
}
}
if (drv == NULL || drv[0] == '\0')
{
drv = _iodbcdm_getkeyvalbydsn (dsn, SQL_NTS, "Driver",
drvbuf, sizeof (drvbuf));
}
if (drv == NULL)
{
PUSHSQLERR (pdbc->herr, en_IM002);
ODBC_UNLOCK ();
return SQL_ERROR;
}
retcode = _iodbcdm_driverload (drv, pdbc, thread_safe);
switch (retcode)
{
case SQL_SUCCESS:
break;
case SQL_SUCCESS_WITH_INFO:
setopterr = SQL_ERROR;
break;
default:
ODBC_UNLOCK ();
return retcode;
}
hproc = _iodbcdm_getproc (pdbc, en_DriverConnect);
if (hproc == SQL_NULL_HPROC)
{
_iodbcdm_driverunload (pdbc);
PUSHSQLERR (pdbc->herr, en_IM001);
ODBC_UNLOCK ();
return SQL_ERROR;
}
if (cbConnStrIn == SQL_NTS)
{
cbConnStrIn = STRLEN (szConnStrIn);
}
CALL_DRIVER (hdbc, pdbc, retcode, hproc, en_DriverConnect, (pdbc->dhdbc,
hwnd, szConnStrIn, cbConnStrIn, szConnStrOut, cbConnStrOutMax,
pcbConnStrOut, fDriverCompletion));
if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
{
ODBC_UNLOCK ();
return retcode;
}
pdbc->state = en_dbc_connected;
setopterr |= _iodbcdm_dbcdelayset (pdbc);
if (setopterr != SQL_SUCCESS)
{
ODBC_UNLOCK ();
return SQL_SUCCESS_WITH_INFO;
}
ODBC_UNLOCK ();
return retcode;
}
SQLRETURN SQL_API
SQLBrowseConnect (SQLHDBC hdbc,
SQLCHAR FAR * szConnStrIn,
SQLSMALLINT cbConnStrIn,
SQLCHAR FAR * szConnStrOut,
SQLSMALLINT cbConnStrOutMax, SQLSMALLINT FAR * pcbConnStrOut)
{
CONN (pdbc, hdbc);
char FAR *drv;
char drvbuf[1024];
char FAR *dsn;
char dsnbuf[SQL_MAX_DSN_LENGTH + 1];
SWORD thread_safe;
char buf[100];
char *ptr;
HPROC hproc;
SQLRETURN retcode = SQL_SUCCESS;
SQLRETURN setopterr = SQL_SUCCESS;
ODBC_LOCK ();
if (!IS_VALID_HDBC (pdbc))
{
ODBC_UNLOCK ();
return SQL_INVALID_HANDLE;
}
CLEAR_ERRORS (pdbc);
if ((cbConnStrIn < 0 && cbConnStrIn != SQL_NTS) || cbConnStrOutMax < 0)
{
PUSHSQLERR (pdbc->herr, en_S1090);
ODBC_UNLOCK ();
return SQL_ERROR;
}
if (pdbc->state == en_dbc_allocated)
{
drv = _iodbcdm_getkeyvalinstr (szConnStrIn, cbConnStrIn,
"DRIVER", drvbuf, sizeof (drvbuf));
dsn = _iodbcdm_getkeyvalinstr (szConnStrIn, cbConnStrIn,
"DSN", dsnbuf, sizeof (dsnbuf));
if (dsn == NULL || dsn[0] == '\0')
{
dsn = "default";
}
else
{
setopterr |= _iodbcdm_settracing (pdbc, (char *) dsn, SQL_NTS);
}
ptr = _iodbcdm_getkeyvalbydsn (dsn, SQL_NTS, "ThreadManager",
(char FAR *) buf, sizeof (buf));
thread_safe = 1;
if (ptr != NULL)
{
if (STREQ (ptr, "ON") || STREQ (ptr, "On") ||
STREQ (ptr, "on") || STREQ (ptr, "1"))
{
thread_safe = 0;
}
}
if (drv == NULL || drv[0] == '\0')
{
drv = _iodbcdm_getkeyvalbydsn (dsn, SQL_NTS, "Driver",
drvbuf, sizeof (drvbuf));
}
if (drv == NULL)
{
PUSHSQLERR (pdbc->herr, en_IM002);
ODBC_UNLOCK ();
return SQL_ERROR;
}
retcode = _iodbcdm_driverload (drv, pdbc, thread_safe);
switch (retcode)
{
case SQL_SUCCESS:
break;
case SQL_SUCCESS_WITH_INFO:
setopterr = SQL_ERROR;
break;
default:
ODBC_UNLOCK ();
return retcode;
}
}
else if (pdbc->state != en_dbc_needdata)
{
PUSHSQLERR (pdbc->herr, en_08002);
ODBC_UNLOCK ();
return SQL_ERROR;
}
hproc = _iodbcdm_getproc (pdbc, en_BrowseConnect);
if (hproc == SQL_NULL_HPROC)
{
_iodbcdm_driverunload (pdbc);
pdbc->state = en_dbc_allocated;
PUSHSQLERR (pdbc->herr, en_IM001);
ODBC_UNLOCK ();
return SQL_ERROR;
}
CALL_DRIVER (hdbc, pdbc, retcode, hproc, en_BrowseConnect, (pdbc->dhdbc,
szConnStrIn, cbConnStrIn,
szConnStrOut, cbConnStrOutMax, pcbConnStrOut));
switch (retcode)
{
case SQL_SUCCESS:
case SQL_SUCCESS_WITH_INFO:
pdbc->state = en_dbc_connected;
setopterr |= _iodbcdm_dbcdelayset (pdbc);
if (setopterr != SQL_SUCCESS)
{
retcode = SQL_SUCCESS_WITH_INFO;
}
break;
case SQL_NEED_DATA:
pdbc->state = en_dbc_needdata;
break;
case SQL_ERROR:
pdbc->state = en_dbc_allocated;
break;
default:
break;
}
ODBC_UNLOCK ();
return retcode;
}
SQLRETURN SQL_API
SQLDisconnect (SQLHDBC hdbc)
{
CONN (pdbc, hdbc);
STMT_t FAR *pstmt;
SQLRETURN retcode;
HPROC hproc;
int sqlstat = en_00000;
ODBC_LOCK ();
if (!IS_VALID_HDBC (pdbc))
{
ODBC_UNLOCK ();
return SQL_INVALID_HANDLE;
}
CLEAR_ERRORS (pdbc);
if (pdbc->state == en_dbc_allocated)
{
sqlstat = en_08003;
}
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)
{
hproc = _iodbcdm_getproc (pdbc, en_Disconnect);
if (hproc == SQL_NULL_HPROC)
{
sqlstat = en_IM001;
}
}
if (sqlstat != en_00000)
{
PUSHSQLERR (pdbc->herr, sqlstat);
ODBC_UNLOCK ();
return SQL_ERROR;
}
CALL_DRIVER (hdbc, pdbc, retcode, hproc, en_Disconnect, (
pdbc->dhdbc));
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)
{
retcode = SQL_SUCCESS;
}
else
{
ODBC_UNLOCK ();
return retcode;
}
for (; pdbc->hstmt;)
{
_iodbcdm_dropstmt (pdbc->hstmt);
}
if (retcode == SQL_SUCCESS)
{
pdbc->state = en_dbc_allocated;
}
ODBC_UNLOCK ();
return retcode;
}
SQLRETURN SQL_API
SQLNativeSql (
SQLHDBC hdbc,
SQLCHAR FAR * szSqlStrIn,
SQLINTEGER cbSqlStrIn,
SQLCHAR FAR * szSqlStr,
SQLINTEGER cbSqlStrMax,
SQLINTEGER FAR * pcbSqlStr)
{
CONN (pdbc, hdbc);
HPROC hproc;
int sqlstat = en_00000;
SQLRETURN retcode;
ENTER_HDBC (pdbc);
if (szSqlStrIn == NULL)
{
sqlstat = en_S1009;
}
else if (cbSqlStrIn < 0 && cbSqlStrIn != SQL_NTS)
{
sqlstat = en_S1090;
}
if (sqlstat != en_00000)
{
PUSHSQLERR (pdbc->herr, sqlstat);
LEAVE_HDBC (pdbc, SQL_ERROR);
}
if (pdbc->state <= en_dbc_needdata)
{
PUSHSQLERR (pdbc->herr, en_08003);
LEAVE_HDBC (pdbc, SQL_ERROR);
}
hproc = _iodbcdm_getproc (pdbc, en_NativeSql);
if (hproc == SQL_NULL_HPROC)
{
PUSHSQLERR (pdbc->herr, en_IM001);
LEAVE_HDBC (pdbc, SQL_ERROR);
}
CALL_DRIVER (hdbc, pdbc, retcode, hproc, en_NativeSql,
(pdbc->dhdbc, szSqlStrIn, cbSqlStrIn, szSqlStr, cbSqlStrMax, pcbSqlStr));
LEAVE_HDBC (pdbc, retcode);
}