#include <iodbc.h>
#include <assert.h>
#include <sql.h>
#include <sqlext.h>
#include <sqlucode.h>
#include <iodbcext.h>
#include <odbcinst.h>
#include <dlproc.h>
#include <herr.h>
#include <henv.h>
#include <hdbc.h>
#include <hstmt.h>
#include <itrace.h>
#include <unicode.h>
#if defined (__APPLE__) && !(defined (NO_FRAMEWORKS) || defined (_LP64))
#include <Carbon/Carbon.h>
#endif
#include "misc.h"
#include "iodbc_misc.h"
static char sccsid[] = "@(#)iODBC driver manager " VERSION "\n";
char *iodbc_version = VERSION;
extern SQLRETURN _iodbcdm_driverunload (HDBC hdbc, int ver);
extern SQLRETURN SQL_API _iodbcdm_SetConnectOption (SQLHDBC hdbc,
SQLUSMALLINT fOption, SQLULEN vParam, SQLCHAR waMode);
#define CHECK_DRVCONN_DIALBOX(path) \
{ \
if ((handle = DLL_OPEN(path)) != NULL) \
{ \
if (DLL_PROC(handle, "_iodbcdm_drvconn_dialboxw") != NULL) \
{ \
DLL_CLOSE(handle); \
retVal = TRUE; \
goto quit; \
} \
else \
{ \
if (DLL_PROC(handle, "_iodbcdm_drvconn_dialbox") != NULL) \
{ \
DLL_CLOSE(handle); \
retVal = TRUE; \
goto quit; \
} \
} \
DLL_CLOSE(handle); \
} \
}
static BOOL
_iodbcdm_CheckDriverLoginDlg (
LPSTR drv,
LPSTR dsn
)
{
char tokenstr[4096];
char drvbuf[4096] = { L'\0'};
HDLL handle;
BOOL retVal = FALSE;
if (drv == NULL)
{
SQLSetConfigMode (ODBC_BOTH_DSN);
SQLGetPrivateProfileString ("ODBC Data Sources",
dsn && dsn[0] != '\0' ? dsn : "Default",
"", tokenstr, sizeof (tokenstr), NULL);
drv = tokenstr;
}
SQLSetConfigMode (ODBC_USER_DSN);
if (!access (drv, X_OK))
{ CHECK_DRVCONN_DIALBOX (drv); }
if (SQLGetPrivateProfileString (drv, "Driver", "", drvbuf,
sizeof (drvbuf), "odbcinst.ini"))
{ CHECK_DRVCONN_DIALBOX (drvbuf); }
if (SQLGetPrivateProfileString (drv, "Setup", "", drvbuf,
sizeof (drvbuf), "odbcinst.ini"))
{ CHECK_DRVCONN_DIALBOX (drvbuf); }
if (SQLGetPrivateProfileString ("Default", "Driver", "", drvbuf,
sizeof (drvbuf), "odbcinst.ini"))
{ CHECK_DRVCONN_DIALBOX (drvbuf); }
if (SQLGetPrivateProfileString ("Default", "Setup", "", drvbuf,
sizeof (drvbuf), "odbcinst.ini"))
{ CHECK_DRVCONN_DIALBOX (drvbuf); }
SQLSetConfigMode (ODBC_SYSTEM_DSN);
if (!access (drv, X_OK))
{ CHECK_DRVCONN_DIALBOX (drv); }
if (SQLGetPrivateProfileString (drv, "Driver", "", drvbuf,
sizeof (drvbuf), "odbcinst.ini"))
{ CHECK_DRVCONN_DIALBOX (drvbuf); }
if (SQLGetPrivateProfileString (drv, "Setup", "", drvbuf,
sizeof (drvbuf), "odbcinst.ini"))
{ CHECK_DRVCONN_DIALBOX (drvbuf); }
if (SQLGetPrivateProfileString ("Default", "Driver", "", drvbuf,
sizeof (drvbuf), "odbcinst.ini"))
{ CHECK_DRVCONN_DIALBOX (drvbuf); }
if (SQLGetPrivateProfileString ("Default", "Setup", "", drvbuf,
sizeof (drvbuf), "odbcinst.ini"))
{ CHECK_DRVCONN_DIALBOX (drvbuf); }
quit:
return retVal;
}
#define RETURN(_ret) \
do { \
retcode = _ret; \
goto end; \
} while (0)
#if 0
#define DPRINTF(a) fprintf a
#else
#define DPRINTF(a)
#endif
static SQLRETURN
_iodbcdm_SetConnectOption_init (
SQLHDBC hdbc,
SQLUSMALLINT fOption,
SQLULEN vParam,
UCHAR waMode)
{
CONN (pdbc, hdbc);
ENVR (penv, pdbc->henv);
HPROC hproc = SQL_NULL_HPROC;
SQLRETURN retcode = SQL_SUCCESS;
int retinfo = 0;
SQLINTEGER strLength = 0;
void *ptr = (void *) vParam;
void *_vParam = NULL;
if (fOption >= 1000)
{
retinfo = 1;
}
if ((penv->unicode_driver && waMode != 'W')
|| (!penv->unicode_driver && waMode == 'W'))
{
switch (fOption)
{
case SQL_ATTR_TRACEFILE:
case SQL_CURRENT_QUALIFIER:
case SQL_TRANSLATE_DLL:
case SQL_APPLICATION_NAME:
case SQL_COPT_SS_ENLIST_IN_DTC:
case SQL_COPT_SS_PERF_QUERY_LOG:
case SQL_COPT_SS_PERF_DATA_LOG:
case SQL_CURRENT_SCHEMA:
if (waMode != 'W')
{
_vParam = dm_SQL_A2W((SQLCHAR *)vParam, SQL_NTS);
}
else
{
_vParam = dm_SQL_W2A((SQLWCHAR *)vParam, SQL_NTS);
}
ptr = _vParam;
strLength = SQL_NTS;
break;
}
}
if (penv->unicode_driver)
{
if ((hproc = _iodbcdm_getproc (pdbc, en_SetConnectOptionW))
!= SQL_NULL_HPROC)
{
CALL_DRIVER (hdbc, pdbc, retcode, hproc,
(pdbc->dhdbc, fOption, ptr));
}
#if (ODBCVER >= 0x300)
else if ((hproc = _iodbcdm_getproc (pdbc, en_SetConnectAttrW))
!= SQL_NULL_HPROC)
{
CALL_DRIVER (hdbc, pdbc, retcode, hproc,
(pdbc->dhdbc, fOption, ptr, strLength));
}
#endif
}
else
{
if ((hproc = _iodbcdm_getproc (pdbc, en_SetConnectOption))
!= SQL_NULL_HPROC)
{
CALL_DRIVER (hdbc, pdbc, retcode, hproc,
(pdbc->dhdbc, fOption, vParam));
}
else if ((hproc = _iodbcdm_getproc (pdbc, en_SetConnectOptionA))
!= SQL_NULL_HPROC)
{
CALL_DRIVER (hdbc, pdbc, retcode, hproc,
(pdbc->dhdbc, fOption, vParam));
}
#if (ODBCVER >= 0x300)
else if ((hproc = _iodbcdm_getproc (pdbc, en_SetConnectAttr))
!= SQL_NULL_HPROC)
{
CALL_DRIVER (hdbc, pdbc, retcode, hproc,
(pdbc->dhdbc, fOption, vParam, strLength));
}
else if ((hproc = _iodbcdm_getproc (pdbc, en_SetConnectAttrA))
!= SQL_NULL_HPROC)
{
CALL_DRIVER (hdbc, pdbc, retcode, hproc,
(pdbc->dhdbc, fOption, vParam, strLength));
}
#endif
}
MEM_FREE(_vParam);
if (hproc == SQL_NULL_HPROC)
{
PUSHSQLERR (pdbc->herr, en_IM004);
return SQL_SUCCESS_WITH_INFO;
}
if (retcode != SQL_SUCCESS && retinfo)
return SQL_SUCCESS_WITH_INFO;
return retcode;
}
static SQLRETURN
_iodbcdm_getInfo_init (SQLHDBC hdbc,
SQLUSMALLINT fInfoType,
SQLPOINTER rgbInfoValue,
SQLSMALLINT cbInfoValueMax,
SQLSMALLINT * pcbInfoValue,
SQLCHAR waMode)
{
CONN (pdbc, hdbc);
ENVR (penv, pdbc->henv);
HPROC hproc = SQL_NULL_HPROC;
SQLRETURN retcode = SQL_SUCCESS;
waMode = waMode;
switch(fInfoType)
{
case SQL_CURSOR_COMMIT_BEHAVIOR:
case SQL_CURSOR_ROLLBACK_BEHAVIOR:
break;
default:
return SQL_ERROR;
}
CALL_UDRIVER(hdbc, pdbc, retcode, hproc, penv->unicode_driver,
en_GetInfo, (
pdbc->dhdbc,
fInfoType,
rgbInfoValue,
cbInfoValueMax,
pcbInfoValue));
if (hproc == SQL_NULL_HPROC)
{
PUSHSQLERR (pdbc->herr, en_IM004);
return SQL_SUCCESS_WITH_INFO;
}
return retcode;
}
static SQLRETURN
_iodbcdm_finish_disconnect (HDBC hdbc, BOOL driver_disconnect)
{
CONN (pdbc, hdbc);
HPROC hproc = SQL_NULL_HPROC;
DPRINTF ((stderr,
"DEBUG: _iodbcdm_finish_disconnect (conn %p, driver_disconnect %d)\n",
hdbc, driver_disconnect));
if (driver_disconnect)
{
SQLRETURN retcode;
hproc = _iodbcdm_getproc (pdbc, en_Disconnect);
if (hproc == SQL_NULL_HPROC)
{
PUSHSQLERR (pdbc->herr, en_IM001);
return SQL_ERROR;
}
ODBC_UNLOCK ();
CALL_DRIVER (hdbc, pdbc, retcode, hproc, (pdbc->dhdbc));
ODBC_LOCK ();
if (!SQL_SUCCEEDED (retcode))
{
return retcode;
}
}
while (pdbc->hstmt != NULL)
_iodbcdm_dropstmt (pdbc->hstmt);
pdbc->state = en_dbc_allocated;
return SQL_SUCCESS;
}
#if (ODBCVER >= 0x300)
static void
_iodbcdm_pool_set_retry_wait (HDBC hdbc)
{
CONN (pdbc, hdbc);
int retry_wait = 0;
char buf[1024];
SQLSetConfigMode (ODBC_BOTH_DSN);
if (SQLGetPrivateProfileString ("ODBC Connection Pooling", "Retry Wait", "",
buf, sizeof (buf), "odbcinst.ini") != 0 &&
buf[0] != '\0')
retry_wait = atoi(buf);
DPRINTF ((stderr, "DEBUG: setting RetryWait %d (conn %p)\n",
retry_wait, hdbc));
pdbc->cp_retry_wait = time(NULL) + retry_wait;
}
extern SQLRETURN SQLFreeConnect_Internal (SQLHDBC hdbc);
void
_iodbcdm_pool_drop_conn (HDBC hdbc, HDBC hdbc_prev)
{
CONN (pdbc, hdbc);
CONN (pdbc_prev, hdbc_prev);
assert (!pdbc->cp_in_use);
DPRINTF ((stderr, "DEBUG: dropping connection %p (prev %p) from the pool\n",
hdbc, hdbc_prev));
if (pdbc_prev != NULL)
pdbc_prev->next = pdbc->next;
else
{
GENV (genv, pdbc->genv);
genv->pdbc_pool = pdbc->next;
}
_iodbcdm_finish_disconnect (hdbc, TRUE);
SQLFreeConnect_Internal (hdbc);
MEM_FREE (hdbc);
}
static void
_iodbcdm_pool_copy_conn (HDBC hdbc_dst, HDBC hdbc_src)
{
CONN (pdbc_dst, hdbc_dst);
CONN (pdbc_src, hdbc_src);
HDBC next;
time_t cp_timeout, cp_expiry_time;
next = pdbc_dst->next;
cp_timeout = pdbc_dst->cp_timeout;
cp_expiry_time = pdbc_dst->cp_expiry_time;
*pdbc_dst = *pdbc_src;
pdbc_dst->next = next;
pdbc_dst->cp_timeout = cp_timeout;
pdbc_dst->cp_expiry_time = cp_expiry_time;
pdbc_src->herr = SQL_NULL_HERR;
pdbc_src->dhdbc = SQL_NULL_HDBC;
pdbc_src->henv = SQL_NULL_HENV;
pdbc_src->hstmt = SQL_NULL_HSTMT;
pdbc_src->hdesc = SQL_NULL_HDESC;
pdbc_src->current_qualifier = NULL;
pdbc_src->drvopt = NULL;
pdbc_src->cp_probe = NULL;
pdbc_src->cp_dsn = NULL;
pdbc_src->cp_uid = NULL;
pdbc_src->cp_pwd = NULL;
pdbc_src->cp_connstr = NULL;
}
static BOOL
_iodbcdm_pool_check_attr_match (HDBC hdbc, HDBC cp_hdbc)
{
CONN (pdbc, hdbc);
GENV (genv, pdbc->genv);
CONN (cp_pdbc, cp_hdbc);
BOOL strict_match = (genv->cp_match == SQL_CP_STRICT_MATCH);
DPRINTF ((stderr, "DEBUG: check attr match (conn %p, cp_conn %p)\n",
hdbc, cp_hdbc));
if (strict_match && pdbc->packet_size != cp_pdbc->packet_size)
{
DPRINTF ((stderr, "DEBUG: packet_size does not match (conn %p, cp_conn %p, strict_match %d)",
hdbc, cp_hdbc, strict_match));
return FALSE;
}
if (pdbc->odbc_cursors != cp_pdbc->odbc_cursors)
{
DPRINTF ((stderr, "DEBUG: odbc_cursors does not match (conn %p, cp_conn %p, strict_match %d)",
hdbc, cp_hdbc, strict_match));
return FALSE;
}
if (pdbc->current_qualifier == NULL && cp_pdbc->current_qualifier != NULL)
{
DPRINTF ((stderr, "DEBUG: current_qualifier has not been set by application, but is set in the pool (conn %p, cp_conn %p)",
hdbc, cp_hdbc));
return FALSE;
}
if (pdbc->quiet_mode == 0 && cp_pdbc->quiet_mode != 0)
{
DPRINTF ((stderr, "DEBUG: quiet_mode has not been set by application, but is set in the pool (conn %p, cp_conn %p)",
hdbc, cp_hdbc));
return FALSE;
}
return TRUE;
}
SQLRETURN
_iodbcdm_pool_reset_conn_attrs (SQLHDBC hdbc, SQLHDBC cp_hdbc)
{
CONN (pdbc, hdbc);
CONN (cp_pdbc, cp_hdbc);
SQLRETURN retcode = SQL_SUCCESS;
SQLRETURN ret;
if (pdbc->access_mode != cp_pdbc->access_mode)
{
cp_pdbc->access_mode = pdbc->access_mode;
ret = _iodbcdm_SetConnectOption_init (
cp_pdbc, SQL_ACCESS_MODE, cp_pdbc->access_mode, 'A');
retcode |= ret;
}
if (pdbc->autocommit != cp_pdbc->autocommit)
{
cp_pdbc->autocommit = pdbc->autocommit;
ret = _iodbcdm_SetConnectOption_init (
cp_pdbc, SQL_AUTOCOMMIT, cp_pdbc->autocommit, 'A');
retcode |= ret;
}
if (pdbc->current_qualifier != NULL)
{
if (cp_pdbc->current_qualifier != NULL)
MEM_FREE (cp_pdbc->current_qualifier);
cp_pdbc->current_qualifier = pdbc->current_qualifier;
pdbc->current_qualifier = NULL;
cp_pdbc->current_qualifier_WA = pdbc->current_qualifier_WA;
ret = _iodbcdm_SetConnectOption_init (
cp_pdbc, SQL_CURRENT_QUALIFIER,
(SQLULEN) cp_pdbc->current_qualifier, cp_pdbc->current_qualifier_WA);
retcode |= ret;
}
if (cp_pdbc->quiet_mode != pdbc->quiet_mode)
{
cp_pdbc->quiet_mode = pdbc->quiet_mode;
ret = _iodbcdm_SetConnectOption_init (
cp_pdbc, SQL_QUIET_MODE, cp_pdbc->quiet_mode, 'A');
retcode |= ret;
}
if (pdbc->txn_isolation != cp_pdbc->txn_isolation)
{
cp_pdbc->txn_isolation = pdbc->txn_isolation;
ret = _iodbcdm_SetConnectOption_init (
cp_pdbc, SQL_TXN_ISOLATION, cp_pdbc->txn_isolation, 'A');
retcode |= ret;
}
return retcode;
}
extern SQLRETURN
SQLAllocStmt_Internal (SQLHDBC hdbc, SQLHSTMT *phstmt);
extern SQLRETURN
SQLFreeStmt_Internal (SQLHSTMT hstmt, SQLUSMALLINT fOption);
extern SQLRETURN SQL_API
SQLExecDirect_Internal (SQLHSTMT hstmt,
SQLPOINTER szSqlStr, SQLINTEGER cbSqlStr, SQLCHAR waMode);
extern SQLRETURN SQLFetch_Internal (SQLHSTMT hstmt);
static SQLRETURN
_iodbcdm_pool_exec_cpprobe (HDBC hdbc, char *cp_probe)
{
HSTMT hstmt = SQL_NULL_HSTMT;
SQLRETURN retcode;
SQLSMALLINT num_cols;
DPRINTF ((stderr, "DEBUG: executing CPProbe (conn %p, stmt [%s])\n",
hdbc, cp_probe));
retcode = SQLAllocStmt_Internal (hdbc, &hstmt);
if (!SQL_SUCCEEDED (retcode))
RETURN (retcode);
retcode = SQLExecDirect_Internal (hstmt, cp_probe, SQL_NTS, 'A');
if (!SQL_SUCCEEDED (retcode))
RETURN (retcode);
retcode = _iodbcdm_NumResultCols (hstmt, &num_cols);
if (!SQL_SUCCEEDED (retcode))
RETURN (retcode);
if (num_cols == 0)
RETURN (SQL_SUCCESS);
do
{
retcode = SQLFetch_Internal (hstmt);
if (!SQL_SUCCEEDED (retcode))
RETURN (retcode);
}
while (retcode != SQL_NO_DATA);
RETURN (SQL_SUCCESS);
end:
if (hstmt != SQL_NULL_HSTMT)
SQLFreeStmt_Internal (hstmt, SQL_DROP);
return retcode;
}
static BOOL
_iodbcdm_pool_conn_dead (HDBC hdbc)
{
CONN (pdbc, hdbc);
HPROC hproc = SQL_NULL_HPROC;
SQLRETURN retcode;
SQLINTEGER attr_dead;
DPRINTF ((stderr, "DEBUG: checking if connection is dead (conn %p)\n",
hdbc));
CALL_UDRIVER(pdbc, pdbc, retcode, hproc, 'A', en_GetConnectAttr,
(pdbc->dhdbc, SQL_ATTR_CONNECTION_DEAD, &attr_dead, 0, NULL));
if (hproc != SQL_NULL_HPROC && SQL_SUCCEEDED (retcode))
{
DPRINTF ((stderr, "DEBUG: GetConnectAttr: attr_dead = %ld (conn %p)\n",
attr_dead, hdbc));
return attr_dead == SQL_CD_TRUE;
}
CALL_UDRIVER(pdbc, pdbc, retcode, hproc, 'A', en_GetConnectOption,
(pdbc->dhdbc, SQL_ATTR_CONNECTION_DEAD, &attr_dead));
if (hproc != SQL_NULL_HPROC && SQL_SUCCEEDED (retcode))
{
DPRINTF ((stderr, "DEBUG: GetConnectOption: attr_dead = %ld (conn %p)\n",
attr_dead, hdbc));
return attr_dead == SQL_CD_TRUE;
}
if (pdbc->cp_probe != NULL && STRLEN(pdbc->cp_probe) > 0)
{
retcode = _iodbcdm_pool_exec_cpprobe (pdbc, pdbc->cp_probe);
return SQL_SUCCEEDED (retcode);
}
return FALSE;
}
static SQLRETURN
_iodbcdm_pool_get_conn (
HDBC hdbc, char *dsn, char *uid, char *pwd, char *connstr)
{
CONN (pdbc, hdbc);
GENV (genv, pdbc->genv);
DBC_t *cp_pdbc, *cp_pdbc_next, *cp_pdbc_prev = NULL;
time_t current_time;
DPRINTF ((stderr, "DEBUG: getting connection %p from the pool (dsn [%s], uid [%s], pwd [%s], connstr [%s])\n",
hdbc, dsn, uid, pwd, connstr));
current_time = time(NULL);
for (cp_pdbc = genv->pdbc_pool; cp_pdbc != NULL;
cp_pdbc_prev = cp_pdbc, cp_pdbc = cp_pdbc_next)
{
SQLRETURN retcode;
cp_pdbc_next = cp_pdbc->next;
if (cp_pdbc->cp_in_use)
{
DPRINTF ((stderr, "DEBUG: skipping connection %p (in use)\n",
cp_pdbc));
continue;
}
if (current_time >= cp_pdbc->cp_expiry_time)
{
DPRINTF ((stderr, "DEBUG: connection %p expired (cp_expiry_time %d, current_time %d)\n",
cp_pdbc, cp_pdbc->cp_expiry_time, current_time));
_iodbcdm_pool_drop_conn (cp_pdbc, cp_pdbc_prev);
continue;
}
if (dsn != NULL)
{
if (cp_pdbc->cp_dsn == NULL ||
strcmp (dsn, cp_pdbc->cp_dsn) != 0)
continue;
}
else if (cp_pdbc->cp_dsn != NULL)
continue;
if (uid != NULL)
{
if (cp_pdbc->cp_uid == NULL ||
strcmp (uid, cp_pdbc->cp_uid) != 0)
continue;
}
else if (cp_pdbc->cp_uid != NULL)
continue;
if (pwd != NULL)
{
if (cp_pdbc->cp_pwd == NULL ||
strcmp (pwd, cp_pdbc->cp_pwd) != 0)
continue;
}
else if (cp_pdbc->cp_pwd != NULL)
continue;
if (connstr != NULL)
{
if (cp_pdbc->cp_connstr == NULL ||
strcmp (connstr, cp_pdbc->cp_connstr) != 0)
continue;
}
else if (cp_pdbc->cp_connstr != NULL)
continue;
DPRINTF ((stderr, "DEBUG: found matching pooled connection %p\n",
cp_pdbc));
if (!_iodbcdm_pool_check_attr_match (pdbc, cp_pdbc))
continue;
if (cp_pdbc->cp_retry_wait != 0)
{
if (current_time < cp_pdbc->cp_retry_wait)
{
DPRINTF ((stderr,
"DEBUG: RetryWait timeout has not expired yet (cp_pdbc %p, cp_retry_wait %d, current_time %d)\n",
cp_pdbc, cp_pdbc->cp_retry_wait, current_time));
pdbc->cp_pdbc = cp_pdbc;
return SQL_ERROR;
}
DPRINTF ((stderr, "DEBUG: RetryWait timeout reset (cp_pdbc %p)\n",
cp_pdbc));
cp_pdbc->cp_retry_wait = 0;
}
if (_iodbcdm_pool_conn_dead (cp_pdbc))
{
DPRINTF ((stderr, "DEBUG: pooled connection is dead (cp_pdbc %p)\n",
cp_pdbc));
pdbc->cp_pdbc = cp_pdbc;
cp_pdbc->cp_in_use = TRUE;
return SQL_ERROR;
}
retcode = _iodbcdm_pool_reset_conn_attrs (pdbc, cp_pdbc);
if (retcode != SQL_SUCCESS)
retcode = SQL_SUCCESS_WITH_INFO;
_iodbcdm_pool_copy_conn (pdbc, cp_pdbc);
pdbc->cp_pdbc = cp_pdbc;
cp_pdbc->cp_in_use = TRUE;
DPRINTF ((stderr, "DEBUG: got connection from the pool (cp_pdbc %p)\n",
cp_pdbc));
return retcode;
}
DPRINTF ((stderr, "DEBUG: no matching connection in the pool\n"));
return SQL_ERROR;
}
static int
_iodbcdm_pool_put_conn (HDBC hdbc)
{
CONN (pdbc, hdbc);
GENV (genv, NULL);
DBC_t *cp_pdbc = pdbc->cp_pdbc;
DPRINTF ((stderr, "DEBUG: putting connection back to the pool (conn %p, dsn [%s], uid [%s], pwd [%s], connstr [%s])\n",
hdbc, pdbc->cp_dsn, pdbc->cp_uid, pdbc->cp_pwd, pdbc->cp_connstr));
if (cp_pdbc == NULL)
{
cp_pdbc = (DBC_t *) MEM_ALLOC (sizeof (DBC_t));
if (cp_pdbc == NULL)
{
return -1;
}
genv = (GENV_t *) pdbc->genv;
cp_pdbc->next = genv->pdbc_pool;
genv->pdbc_pool = cp_pdbc;
cp_pdbc->cp_timeout = pdbc->cp_timeout;
DPRINTF ((stderr, "DEBUG: new pooled connection %p\n", cp_pdbc));
}
_iodbcdm_pool_copy_conn(cp_pdbc, pdbc);
pdbc->cp_pdbc = NULL;
while (cp_pdbc->hstmt != NULL)
_iodbcdm_dropstmt (cp_pdbc->hstmt);
cp_pdbc->cp_pdbc = NULL;
if (cp_pdbc->cp_retry_wait == 0)
{
cp_pdbc->cp_expiry_time = time(NULL) + cp_pdbc->cp_timeout;
}
cp_pdbc->cp_in_use = FALSE;
DPRINTF ((stderr, "DEBUG: connection %p put back to the pool (cp_pdbc %p, cp_timeout %d)\n",
hdbc, cp_pdbc, cp_pdbc->cp_timeout));
return 0;
}
#endif
SQLRETURN
_iodbcdm_driverload (
char * dsn,
char * drv,
HDBC hdbc,
SWORD thread_safe,
SWORD unload_safe,
UCHAR waMode)
{
CONN (pdbc, hdbc);
ENVR (penv, NULL);
GENV (genv, NULL);
HDLL hdll = SQL_NULL_HDLL;
HPROC hproc;
SQLRETURN retcode = SQL_SUCCESS;
sqlstcode_t sqlstat = en_00000;
char buf[1024];
char path_tmp[1024];
char *path = drv;
char cp_probe[1024] = {""};
int cp_timeout = 0;
if (drv == NULL || ((char*)drv)[0] == '\0')
{
PUSHSQLERR (pdbc->herr, en_IM002);
return SQL_ERROR;
}
if (!IS_VALID_HDBC (pdbc) || pdbc->genv == SQL_NULL_HENV)
{
return SQL_INVALID_HANDLE;
}
if (!(drv[0] == '/' || drv[0] == '.'))
{
char *tmp_drv = NULL;
if (drv[0] == '{')
{
tmp_drv = strdup (drv);
if (tmp_drv[strlen (drv) - 1] == '}')
tmp_drv[strlen (drv) - 1] = '\0';
drv = &tmp_drv[1];
}
if (SQLGetPrivateProfileString ((char *) drv, "Driver", "",
path_tmp, sizeof (path_tmp), "odbcinst.ini") && path_tmp[0])
path = path_tmp;
if (tmp_drv)
free (tmp_drv);
SQLSetConfigMode (ODBC_BOTH_DSN);
if (SQLGetPrivateProfileString (drv, "CPTimeout", "",
buf, sizeof(buf), "odbcinst.ini") && buf[0])
cp_timeout = atoi(buf);
SQLGetPrivateProfileString (drv, "CPProbe", "",
cp_probe, sizeof(cp_probe), "odbcinst.ini");
}
else if (dsn != NULL && *dsn != '\0')
{
char tmp_drv[1024] = {""};
SQLSetConfigMode (ODBC_BOTH_DSN);
if (SQLGetPrivateProfileString ("ODBC Data Sources", dsn, "",
tmp_drv, sizeof(tmp_drv), NULL) && tmp_drv[0])
{
if (SQLGetPrivateProfileString (tmp_drv, "CPTimeout", "",
buf, sizeof(buf), "odbcinst.ini") && buf[0])
cp_timeout = atoi(buf);
SQLGetPrivateProfileString (tmp_drv, "CPProbe", "",
cp_probe, sizeof(cp_probe), "odbcinst.ini");
}
}
genv = (GENV_t *) pdbc->genv;
hdll = _iodbcdm_dllopen ((char *) path);
if (unload_safe)
_iodbcdm_safe_unload (hdll);
if (hdll == SQL_NULL_HDLL)
{
PUSHSYSERR (pdbc->herr, _iodbcdm_dllerror ());
PUSHSQLERR (pdbc->herr, en_IM003);
return SQL_ERROR;
}
penv = (ENV_t *) (pdbc->henv);
if (penv != NULL)
{
if (penv->hdll != hdll)
{
_iodbcdm_driverunload (hdbc, 3);
penv->hdll = hdll;
}
else
{
_iodbcdm_dllclose (hdll);
}
}
if (penv == NULL)
{
for (penv = (ENV_t *) genv->henv;
penv != NULL;
penv = (ENV_t *) penv->next)
{
if (penv->hdll == hdll)
{
_iodbcdm_dllclose (hdll);
break;
}
}
if (penv == NULL)
{
int i;
penv = (ENV_t *) 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);
penv->unicode_driver = 0;
if ( _iodbcdm_getproc (pdbc, en_ConnectW))
penv->unicode_driver = 1;
#if (ODBCVER >= 0x0300)
hproc = _iodbcdm_getproc (pdbc, en_AllocHandle);
if (hproc)
{
CALL_DRIVER (hdbc, genv, retcode, hproc,
(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &(penv->dhenv)));
if (SQL_SUCCEEDED (retcode))
{
SQLRETURN save_retcode = retcode;
penv->dodbc_ver = SQL_OV_ODBC2;
hproc = _iodbcdm_getproc (pdbc, en_SetEnvAttr);
if (hproc != SQL_NULL_HPROC)
{
CALL_DRIVER (hdbc, genv, retcode, hproc,
(penv->dhenv, SQL_ATTR_ODBC_VERSION, genv->odbc_ver,
0));
if (retcode == SQL_SUCCESS)
penv->dodbc_ver = SQL_OV_ODBC3;
}
retcode = save_retcode;
}
}
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, (&(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 *) 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,
(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,
(penv->dhenv, &(pdbc->dhdbc)));
}
}
if (retcode == SQL_ERROR)
{
sqlstat = en_IM005;
}
if (sqlstat != en_00000)
{
_iodbcdm_driverunload (hdbc, 3);
pdbc->dhdbc = SQL_NULL_HDBC;
PUSHSQLERR (pdbc->herr, en_IM005);
return SQL_ERROR;
}
}
pdbc->henv = penv;
penv->refcount++;
}
if (pdbc->login_timeout != 0UL)
{
retcode = _iodbcdm_SetConnectOption_init (hdbc, SQL_LOGIN_TIMEOUT,
pdbc->login_timeout, waMode);
if (retcode == SQL_ERROR)
{
PUSHSQLERR (pdbc->herr, en_IM006);
return SQL_SUCCESS_WITH_INFO;
}
}
if (pdbc->drvopt != NULL)
{
DRVOPT *popt;
for (popt = pdbc->drvopt; popt != NULL; popt = popt->next)
{
retcode = _iodbcdm_SetConnectOption_init (hdbc, popt->Option,
popt->Param, popt->waMode);
if (retcode == SQL_ERROR)
{
PUSHSQLERR (pdbc->herr, en_IM006);
return SQL_SUCCESS_WITH_INFO;
}
}
}
pdbc->cp_timeout = cp_timeout;
pdbc->cp_probe = strdup (cp_probe);
return SQL_SUCCESS;
}
SQLRETURN
_iodbcdm_driverunload (HDBC hdbc, int ver)
{
CONN (pdbc, hdbc);
ENVR (penv, pdbc->henv);
GENV (genv, pdbc->genv);
ENV_t *tpenv;
HPROC hproc2, hproc3;
SQLRETURN retcode = SQL_SUCCESS;
if (!IS_VALID_HDBC (pdbc))
{
return SQL_INVALID_HANDLE;
}
if (penv == NULL || penv->hdll == SQL_NULL_HDLL ||
pdbc->dhdbc == SQL_NULL_HDBC)
{
return SQL_SUCCESS;
}
hproc2 = _iodbcdm_getproc (pdbc, en_FreeConnect);
#if (ODBCVER >= 0x0300)
hproc3 = _iodbcdm_getproc (pdbc, en_FreeHandle);
if (ver == 3 && hproc2 != SQL_NULL_HPROC && hproc3 != SQL_NULL_HPROC)
hproc2 = SQL_NULL_HPROC;
#else
hproc3 = SQL_NULL_HPROC;
#endif
if (hproc2 != SQL_NULL_HPROC)
{
CALL_DRIVER (hdbc, pdbc, retcode, hproc2, (pdbc->dhdbc));
pdbc->dhdbc = SQL_NULL_HDBC;
}
#if (ODBCVER >= 0x0300)
else if (hproc3 != SQL_NULL_HPROC)
{
CALL_DRIVER (hdbc, pdbc, retcode, hproc3,
(SQL_HANDLE_DBC, pdbc->dhdbc));
}
#endif
penv->refcount--;
if (!penv->refcount)
{
hproc2 = _iodbcdm_getproc (pdbc, en_FreeEnv);
#if (ODBCVER >= 0x0300)
hproc3 = _iodbcdm_getproc (pdbc, en_FreeHandle);
if (ver == 3 && hproc2 != SQL_NULL_HPROC && hproc3 != SQL_NULL_HPROC)
hproc2 = SQL_NULL_HPROC;
#else
hproc3 = SQL_NULL_HPROC;
#endif
if (hproc2 != SQL_NULL_HPROC)
{
CALL_DRIVER (hdbc, genv, retcode, hproc2, (penv->dhenv));
penv->dhenv = SQL_NULL_HENV;
}
#if (ODBCVER >= 0x0300)
else if (hproc3 != SQL_NULL_HPROC)
{
CALL_DRIVER (hdbc, genv, retcode, hproc3,
(SQL_HANDLE_ENV, penv->dhenv));
}
#endif
_iodbcdm_dllclose (penv->hdll);
penv->hdll = SQL_NULL_HDLL;
for (tpenv = (ENV_t *) genv->henv;
tpenv != NULL; tpenv = (ENV_t *) 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 (ODBCVER >= 0x0300)
if (pdbc->cp_probe != NULL)
{
MEM_FREE (pdbc->cp_probe);
pdbc->cp_probe = NULL;
}
if (pdbc->cp_dsn != NULL)
{
MEM_FREE (pdbc->cp_dsn);
pdbc->cp_dsn = NULL;
}
if (pdbc->cp_uid != NULL)
{
MEM_FREE (pdbc->cp_uid);
pdbc->cp_uid = NULL;
}
if (pdbc->cp_pwd != NULL)
{
MEM_FREE (pdbc->cp_pwd);
pdbc->cp_pwd = NULL;
}
if (pdbc->cp_connstr != NULL)
{
MEM_FREE (pdbc->cp_connstr);
pdbc->cp_connstr = NULL;
}
#endif
if (pdbc->current_qualifier != NULL)
{
MEM_FREE (pdbc->current_qualifier);
pdbc->current_qualifier = NULL;
}
return SQL_SUCCESS;
}
static SQLRETURN
_iodbcdm_dbcdelayset (HDBC hdbc, UCHAR waMode)
{
CONN (pdbc, hdbc);
SQLRETURN retcode = SQL_SUCCESS;
SQLRETURN ret;
if (pdbc->access_mode != SQL_MODE_DEFAULT)
{
ret = _iodbcdm_SetConnectOption_init (hdbc, SQL_ACCESS_MODE,
pdbc->access_mode, waMode);
retcode |= ret;
}
if (pdbc->autocommit != SQL_AUTOCOMMIT_DEFAULT)
{
ret = _iodbcdm_SetConnectOption_init (hdbc, SQL_AUTOCOMMIT,
pdbc->autocommit, waMode);
retcode |= ret;
}
if (pdbc->current_qualifier != NULL)
{
ret = _iodbcdm_SetConnectOption_init (hdbc, SQL_CURRENT_QUALIFIER,
(SQLULEN) pdbc->current_qualifier,
pdbc->current_qualifier_WA);
retcode |= ret;
}
if (pdbc->packet_size != 0UL)
{
ret = _iodbcdm_SetConnectOption_init (hdbc, SQL_PACKET_SIZE,
pdbc->packet_size, waMode);
retcode |= ret;
}
if (pdbc->quiet_mode != (UDWORD) NULL)
{
ret = _iodbcdm_SetConnectOption_init (hdbc, SQL_QUIET_MODE,
pdbc->quiet_mode, waMode);
retcode |= ret;
}
if (pdbc->txn_isolation != SQL_TXN_READ_UNCOMMITTED)
{
ret = _iodbcdm_SetConnectOption_init (hdbc, SQL_TXN_ISOLATION,
pdbc->txn_isolation, waMode);
retcode |= ret;
}
if (!SQL_SUCCEEDED (retcode))
{
PUSHSQLERR (pdbc->herr, en_IM006);
retcode = SQL_ERROR;
}
ret = _iodbcdm_getInfo_init (hdbc, SQL_CURSOR_COMMIT_BEHAVIOR,
(PTR) & (pdbc->cb_commit),
sizeof (pdbc->cb_commit),
NULL, waMode);
retcode |= ret;
ret = _iodbcdm_getInfo_init (hdbc, SQL_CURSOR_ROLLBACK_BEHAVIOR,
(PTR) & (pdbc->cb_rollback),
sizeof (pdbc->cb_rollback),
NULL, waMode);
retcode |= ret;
if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
{
return SQL_ERROR;
}
return retcode;
}
static SQLRETURN
_iodbcdm_con_settracing (HDBC hdbc, SQLCHAR *dsn, int dsnlen, UCHAR waMode)
{
SQLUINTEGER trace = SQL_OPT_TRACE_OFF;
char buf[1024];
hdbc=hdbc;
dsnlen=dsnlen;
waMode = waMode;
SQLSetConfigMode (ODBC_BOTH_DSN);
if ((SQLGetPrivateProfileString ((char *) dsn, "TraceFile", "",
buf, sizeof (buf), "odbc.ini") == 0 || !buf[0]))
STRCPY (buf, SQL_OPT_TRACE_FILE_DEFAULT);
trace_set_filename (buf);
SQLSetConfigMode (ODBC_BOTH_DSN);
if (SQLGetPrivateProfileString ((char *) dsn, "Trace", "",
buf, sizeof (buf), "odbc.ini")
&& (STRCASEEQ (buf, "on") || STRCASEEQ (buf, "yes")
|| STRCASEEQ (buf, "1")))
{
trace = SQL_OPT_TRACE_ON;
}
if (trace == SQL_OPT_TRACE_ON)
trace_start ();
return SQL_SUCCESS;
}
#define CATBUF(buf, str, buf_sz) \
do { \
if (_iodbcdm_strlcat (buf, str, buf_sz) >= buf_sz) \
return -1; \
} while (0)
static int
_iodbcdm_cfg_merge_filedsn (PCONFIG pconfig, const char *filedsn,
char *buf, size_t buf_sz, int wide)
{
BOOL override;
WORD len;
char *p, *p_next;
char entries[1024];
char value[1024];
char drv_value[1024] = {"\0"};
char *tmp = NULL;
int rc = 0;
if (SQLReadFileDSN (filedsn, "ODBC", "DRIVER", value, sizeof (value), &len) &&
len > 0)
{
if (_iodbcdm_cfg_find (pconfig, "ODBC", "DRIVER") == 0 &&
!strcasecmp (value, pconfig->value))
override = TRUE;
else
override = FALSE;
}
else
override = TRUE;
if (!SQLReadFileDSN (filedsn, "ODBC", NULL,
entries, sizeof (entries), &len))
return -1;
_iodbcdm_cfg_write (pconfig, "ODBC", "DSN", NULL);
for (p = entries; *p != '\0'; p = p_next)
{
p_next = strchr (p, ';');
if (p_next)
*p_next++ = '\0';
if ((override || !strcasecmp (p, "DRIVER")) &&
_iodbcdm_cfg_find (pconfig, "ODBC", p) == 0)
{
continue;
}
if (!SQLReadFileDSN (filedsn, "ODBC", p, value, sizeof(value), &len))
return -1;
_iodbcdm_cfg_write (pconfig, "ODBC", p, value);
}
_iodbcdm_cfg_write (pconfig, "ODBC", "FILEDSN", NULL);
if (_iodbcdm_cfg_find (pconfig, "ODBC", "DRIVER") == 0)
strncpy(drv_value, pconfig->value, sizeof(drv_value));
_iodbcdm_cfg_write (pconfig, "ODBC", "DRIVER", NULL);
if ((rc =_iodbcdm_cfg_to_string (pconfig, "ODBC", buf, buf_sz)) == -1)
goto done;
tmp = strdup(buf);
strncpy(buf, "DRIVER=", buf_sz);
CATBUF(buf, drv_value, buf_sz);
CATBUF(buf, ";", buf_sz);
CATBUF(buf, tmp, buf_sz);
MEM_FREE(tmp);
if (wide)
{
SQLWCHAR *_in = dm_SQL_U8toW (buf, SQL_NTS);
if (_in == NULL)
{
rc = -1;
goto done;
}
WCSNCPY (buf, _in, buf_sz / sizeof (SQLWCHAR));
MEM_FREE (_in);
}
rc = 0;
done:
if (drv_value[0])
_iodbcdm_cfg_write (pconfig, "ODBC", "DRIVER", drv_value);
return rc;
}
static int
_iodbcdm_cfg_savefile (const char *savefile, void *conn_str, int wide)
{
int ret = 0;
PCONFIG pconfig;
BOOL atsection = FALSE;
if (_iodbcdm_cfg_init_str (&pconfig, conn_str, SQL_NTS, wide) == -1)
return -1;
_iodbcdm_cfg_write (pconfig, "ODBC", "PWD", NULL);
_iodbcdm_cfg_write (pconfig, "ODBC", "FILEDSN", NULL);
_iodbcdm_cfg_write (pconfig, "ODBC", "SAVEFILE", NULL);
_iodbcdm_cfg_write (pconfig, "ODBC", "DSN", NULL);
SQLWriteFileDSN (savefile, "ODBC", "DSN", NULL);
_iodbcdm_cfg_rewind (pconfig);
while (_iodbcdm_cfg_nextentry (pconfig) == 0)
{
if (atsection)
{
if (_iodbcdm_cfg_section (pconfig))
{
break;
}
else if (_iodbcdm_cfg_define (pconfig))
{
if (!SQLWriteFileDSN (savefile, "ODBC",
pconfig->id, pconfig->value))
{
ret = -1;
break;
}
}
}
else if (_iodbcdm_cfg_section (pconfig)
&& !strcasecmp (pconfig->section, "ODBC"))
atsection = TRUE;
}
_iodbcdm_cfg_done (pconfig);
return ret;
}
static
SQLRETURN SQL_API
SQLConnect_Internal (SQLHDBC hdbc,
SQLPOINTER szDSN,
SQLSMALLINT cbDSN,
SQLPOINTER szUID,
SQLSMALLINT cbUID,
SQLPOINTER szAuthStr,
SQLSMALLINT cbAuthStr,
SQLCHAR waMode)
{
CONN (pdbc, hdbc);
ENVR (penv, NULL);
#if (ODBCVER >= 0x300)
GENV (genv, NULL);
#endif
SQLRETURN retcode = SQL_SUCCESS;
SQLRETURN setopterr = SQL_SUCCESS;
char driver[1024] = { '\0' };
char buf[256];
HPROC hproc = SQL_NULL_HPROC;
SWORD thread_safe;
SWORD unload_safe;
void * _szDSN = NULL;
void * _szUID = NULL;
void * _szAuthStr = NULL;
SQLCHAR *_dsn = (SQLCHAR *) szDSN;
SQLSMALLINT _dsn_len = cbDSN;
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);
RETURN (SQL_ERROR);
}
if (szDSN == NULL || cbDSN == 0)
{
PUSHSQLERR (pdbc->herr, en_IM002);
RETURN (SQL_ERROR);
}
if (pdbc->state != en_dbc_allocated)
{
PUSHSQLERR (pdbc->herr, en_08002);
RETURN (SQL_ERROR);
}
if (waMode == 'W')
{
_szDSN = (void *) dm_SQL_WtoU8((SQLWCHAR *)szDSN, cbDSN);
_dsn = (SQLCHAR *) _szDSN;
_dsn_len = SQL_NTS;
if (_dsn == NULL)
{
PUSHSQLERR (pdbc->herr, en_S1001);
RETURN (SQL_ERROR);
}
}
if (_iodbcdm_con_settracing (pdbc, _dsn, _dsn_len, waMode) == SQL_ERROR)
RETURN (SQL_ERROR);
#if (ODBCVER >= 0x300)
genv = (GENV_t *) pdbc->genv;
if (genv->connection_pooling != SQL_CP_OFF)
{
char *_uid = szUID;
char *_pwd = szAuthStr;
if (waMode == 'W')
{
if (szUID != NULL)
{
_szUID = (void *) dm_SQL_WtoU8((SQLWCHAR *) szUID, cbUID);
if (_szUID == NULL)
{
PUSHSQLERR (pdbc->herr, en_S1001);
RETURN (SQL_ERROR);
}
}
if (szAuthStr != NULL)
{
_szAuthStr = (void *) dm_SQL_WtoU8(
(SQLWCHAR *) szAuthStr, cbAuthStr);
if (_szAuthStr == NULL)
{
PUSHSQLERR (pdbc->herr, en_S1001);
RETURN (SQL_ERROR);
}
}
_uid = _szUID;
_pwd = _szAuthStr;
}
retcode = _iodbcdm_pool_get_conn (pdbc, _dsn, _uid, _pwd, NULL);
if (SQL_SUCCEEDED (retcode))
{
pdbc->state = en_dbc_connected;
RETURN (retcode);
}
if (pdbc->cp_pdbc != NULL)
{
if (pdbc->cp_pdbc->cp_retry_wait != 0)
{
PUSHSQLERR (pdbc->herr, en_08004);
RETURN (SQL_ERROR);
}
if (waMode == 'W')
{
if (_szUID != NULL)
{
MEM_FREE (_szUID);
_szUID = NULL;
}
if (_szAuthStr != NULL)
{
MEM_FREE (_szAuthStr);
_szAuthStr = NULL;
}
}
}
else
{
if (pdbc->cp_dsn != NULL)
MEM_FREE (pdbc->cp_dsn);
if (pdbc->cp_uid != NULL)
MEM_FREE (pdbc->cp_uid);
if (pdbc->cp_pwd != NULL)
MEM_FREE (pdbc->cp_pwd);
if (waMode == 'W')
{
pdbc->cp_dsn = _szDSN;
_szDSN = NULL;
pdbc->cp_uid = _szUID;
_szUID = NULL;
pdbc->cp_pwd = _szAuthStr;
_szAuthStr = NULL;
}
else
{
pdbc->cp_dsn = strdup (_dsn);
if (pdbc->cp_dsn == NULL)
{
PUSHSQLERR (pdbc->herr, en_S1001);
RETURN (SQL_ERROR);
}
if (_uid != NULL)
{
pdbc->cp_uid = strdup (_uid);
if (pdbc->cp_uid == NULL)
{
PUSHSQLERR (pdbc->herr, en_S1001);
RETURN (SQL_ERROR);
}
}
if (_pwd != NULL)
{
pdbc->cp_pwd = strdup (_pwd);
if (pdbc->cp_pwd == NULL)
{
PUSHSQLERR (pdbc->herr, en_S1001);
RETURN (SQL_ERROR);
}
}
}
}
}
#endif
thread_safe = 1;
SQLSetConfigMode (ODBC_BOTH_DSN);
if ( SQLGetPrivateProfileString ((char *) _dsn, "ThreadManager", "",
buf, sizeof(buf), "odbc.ini") &&
(STRCASEEQ (buf, "on") || STRCASEEQ (buf, "1")))
{
thread_safe = 0;
}
unload_safe = 0;
SQLSetConfigMode (ODBC_BOTH_DSN);
if ( SQLGetPrivateProfileString ((char *) _dsn, "UnloadSafe", "",
buf, sizeof(buf), "odbc.ini") &&
(STRCASEEQ (buf, "on") || STRCASEEQ (buf, "1")))
{
unload_safe = 1;
}
SQLSetConfigMode (ODBC_BOTH_DSN);
if ( SQLGetPrivateProfileString ((char *) _dsn, "Driver", "",
(char *) driver, sizeof(driver), "odbc.ini") == 0)
{
PUSHSQLERR (pdbc->herr, en_IM002);
RETURN (SQL_ERROR);
}
MEM_FREE(_szDSN);
_szDSN = NULL;
retcode = _iodbcdm_driverload (_dsn, (char *)driver, pdbc, thread_safe, unload_safe, waMode);
switch (retcode)
{
case SQL_SUCCESS:
break;
case SQL_SUCCESS_WITH_INFO:
#if 0
setopterr = SQL_ERROR;
#endif
break;
default:
return retcode;
}
penv = (ENV_t *) pdbc->henv;
if ((penv->unicode_driver && waMode != 'W')
|| (!penv->unicode_driver && waMode == 'W'))
{
if (waMode != 'W')
{
_szDSN = dm_SQL_A2W((SQLCHAR *)szDSN, cbDSN);
_szUID = dm_SQL_A2W((SQLCHAR *)szUID, cbUID);
_szAuthStr = dm_SQL_A2W((SQLCHAR *)szAuthStr, cbAuthStr);
}
else
{
_szDSN = dm_SQL_W2A((SQLWCHAR *)szDSN, cbDSN);
_szUID = dm_SQL_W2A((SQLWCHAR *)szUID, cbUID);
_szAuthStr = dm_SQL_W2A((SQLWCHAR *)szAuthStr, cbAuthStr);
}
cbDSN = SQL_NTS;
cbUID = SQL_NTS;
cbAuthStr = SQL_NTS;
szDSN = _szDSN;
szUID = _szUID;
szAuthStr = _szAuthStr;
}
ODBC_UNLOCK ();
CALL_UDRIVER(hdbc, pdbc, retcode, hproc, penv->unicode_driver,
en_Connect, (
pdbc->dhdbc,
szDSN,
cbDSN,
szUID,
cbUID,
szAuthStr,
cbAuthStr));
ODBC_LOCK ();
if (hproc == SQL_NULL_HPROC)
{
_iodbcdm_driverunload (pdbc, 3);
PUSHSQLERR (pdbc->herr, en_IM001);
RETURN (SQL_ERROR);
}
if (!SQL_SUCCEEDED (retcode))
{
RETURN (retcode);
}
pdbc->state = en_dbc_connected;
setopterr |= _iodbcdm_dbcdelayset (pdbc, waMode);
if (setopterr != SQL_SUCCESS)
retcode = SQL_SUCCESS_WITH_INFO;
end:
#if (ODBCVER >= 0x300)
if (!SQL_SUCCEEDED (retcode) &&
pdbc->cp_pdbc != NULL)
{
int rc;
_iodbcdm_pool_set_retry_wait (pdbc);
rc = _iodbcdm_pool_put_conn (pdbc);
assert (rc == 0);
}
#endif
if (_szDSN != NULL)
MEM_FREE(_szDSN);
if (_szUID != NULL)
MEM_FREE (_szUID);
if (_szAuthStr != NULL)
MEM_FREE (_szAuthStr);
return retcode;
}
SQLRETURN SQL_API
SQLConnect (
SQLHDBC hdbc,
SQLCHAR * szDSN,
SQLSMALLINT cbDSN,
SQLCHAR * szUID,
SQLSMALLINT cbUID,
SQLCHAR * szAuthStr,
SQLSMALLINT cbAuthStr)
{
ENTER_HDBC (hdbc, 1,
trace_SQLConnect (TRACE_ENTER,
hdbc,
szDSN, cbDSN,
szUID, cbUID,
szAuthStr, cbAuthStr));
retcode = SQLConnect_Internal (
hdbc,
szDSN, cbDSN,
szUID, cbUID,
szAuthStr, cbAuthStr, 'A');
LEAVE_HDBC (hdbc, 1,
trace_SQLConnect (TRACE_LEAVE,
hdbc,
szDSN, cbDSN,
szUID, cbUID,
szAuthStr, cbAuthStr));
}
SQLRETURN SQL_API
SQLConnectA (
SQLHDBC hdbc,
SQLCHAR * szDSN,
SQLSMALLINT cbDSN,
SQLCHAR * szUID,
SQLSMALLINT cbUID,
SQLCHAR * szAuthStr,
SQLSMALLINT cbAuthStr)
{
ENTER_HDBC (hdbc, 1,
trace_SQLConnect (TRACE_ENTER,
hdbc,
szDSN, cbDSN,
szUID, cbUID,
szAuthStr, cbAuthStr));
retcode = SQLConnect_Internal (
hdbc,
szDSN, cbDSN,
szUID, cbUID,
szAuthStr, cbAuthStr, 'A');
LEAVE_HDBC (hdbc, 1,
trace_SQLConnect (TRACE_LEAVE,
hdbc,
szDSN, cbDSN,
szUID, cbUID,
szAuthStr, cbAuthStr));
}
SQLRETURN SQL_API
SQLConnectW (SQLHDBC hdbc,
SQLWCHAR * szDSN,
SQLSMALLINT cbDSN,
SQLWCHAR * szUID,
SQLSMALLINT cbUID,
SQLWCHAR * szAuthStr,
SQLSMALLINT cbAuthStr)
{
ENTER_HDBC (hdbc, 1,
trace_SQLConnectW (TRACE_ENTER,
hdbc,
szDSN, cbDSN,
szUID, cbUID,
szAuthStr, cbAuthStr));
retcode = SQLConnect_Internal (
hdbc,
szDSN, cbDSN,
szUID, cbUID,
szAuthStr, cbAuthStr,
'W');
LEAVE_HDBC (hdbc, 1,
trace_SQLConnectW (TRACE_LEAVE,
hdbc,
szDSN, cbDSN,
szUID, cbUID,
szAuthStr, cbAuthStr));
}
SQLRETURN SQL_API
SQLDriverConnect_Internal (
SQLHDBC hdbc,
SQLHWND hwnd,
SQLPOINTER szConnStrIn,
SQLSMALLINT cbConnStrIn,
SQLPOINTER szConnStrOut,
SQLSMALLINT cbConnStrOutMax,
SQLPOINTER pcbConnStrOut,
SQLUSMALLINT fDriverCompletion,
SQLCHAR waMode)
{
CONN (pdbc, hdbc);
ENVR (penv, NULL);
#if (ODBCVER >= 0x300)
GENV (genv, NULL);
#endif
HDLL hdll;
SQLCHAR *drv = NULL;
SQLCHAR drvbuf[1024];
SQLCHAR *dsn = NULL;
SQLCHAR dsnbuf[SQL_MAX_DSN_LENGTH + 1];
SQLWCHAR prov[2048];
SWORD thread_safe;
SWORD unload_safe;
SQLCHAR buf[1024];
HPROC hproc = SQL_NULL_HPROC;
void *_ConnStrIn = NULL;
void *_ConnStrOut = NULL;
void *connStrOut = szConnStrOut;
void *connStrIn = szConnStrIn;
SQLSMALLINT connStrOutMax = cbConnStrOutMax;
SQLWCHAR connStrOut_buf[2048];
SQLWCHAR connStrIn_buf[2048];
UWORD config;
PCONFIG pconfig = NULL;
BOOL bCallDmDlg = FALSE;
#if defined (__APPLE__) && !(defined (NO_FRAMEWORKS) || defined (_LP64))
CFStringRef libname = NULL;
CFBundleRef bundle = NULL;
CFURLRef liburl = NULL;
char name[1024] = { 0 };
#endif
SQLCHAR *filedsn = NULL;
SQLCHAR *savefile = NULL;
HPROC dialproc = SQL_NULL_HPROC;
sqlstcode_t sqlstat = en_00000;
SQLRETURN retcode = SQL_SUCCESS;
SQLRETURN setopterr = SQL_SUCCESS;
if ((cbConnStrIn < 0 && cbConnStrIn != SQL_NTS) ||
(cbConnStrOutMax < 0 && cbConnStrOutMax != SQL_NTS))
{
PUSHSQLERR (pdbc->herr, en_S1090);
RETURN (SQL_ERROR);
}
if (pdbc->state != en_dbc_allocated)
{
PUSHSQLERR (pdbc->herr, en_08002);
RETURN (SQL_ERROR);
}
SQLGetConfigMode (&config);
if (_iodbcdm_cfg_init_str (&pconfig, connStrIn, cbConnStrIn,
waMode == 'W') == -1)
{
PUSHSQLERR (pdbc->herr, en_HY001);
RETURN (SQL_ERROR);
}
assert (_iodbcdm_cfg_valid(pconfig));
if (_iodbcdm_cfg_find (pconfig, "ODBC", "SAVEFILE") == 0)
{
savefile = strdup (pconfig->value);
if (savefile == NULL)
{
PUSHSQLERR (pdbc->herr, en_HY001);
RETURN (SQL_ERROR);
}
}
#if (ODBCVER >= 0x300)
genv = (GENV_t *) pdbc->genv;
if (genv->connection_pooling != SQL_CP_OFF && savefile == NULL)
{
char *_connstr = connStrIn;
if (fDriverCompletion != SQL_DRIVER_NOPROMPT)
{
PUSHSQLERR (pdbc->herr, en_HY110);
RETURN (SQL_ERROR);
}
if (waMode == 'W')
{
_ConnStrIn = dm_SQL_WtoU8((SQLWCHAR *) connStrIn, cbConnStrIn);
if (_ConnStrIn == NULL)
{
PUSHSQLERR (pdbc->herr, en_HY001);
RETURN (SQL_ERROR);
}
_connstr = _ConnStrIn;
}
retcode = _iodbcdm_pool_get_conn (pdbc, NULL, NULL, NULL, _connstr);
if (SQL_SUCCEEDED (retcode))
{
if (szConnStrOut != NULL)
{
if (waMode == 'W')
{
WCSNCPY (szConnStrOut, szConnStrIn, cbConnStrOutMax);
*(SQLSMALLINT *) pcbConnStrOut =
WCSLEN (szConnStrOut) * sizeof (SQLWCHAR);
}
else
{
_iodbcdm_strlcpy (szConnStrOut, szConnStrIn, cbConnStrOutMax);
*(SQLSMALLINT *) pcbConnStrOut = strlen (szConnStrOut);
}
}
pdbc->state = en_dbc_connected;
RETURN (retcode);
}
if (pdbc->cp_pdbc != NULL)
{
if (pdbc->cp_pdbc->cp_retry_wait != 0)
{
PUSHSQLERR (pdbc->herr, en_08004);
RETURN (SQL_ERROR);
}
if (waMode == 'W')
{
if (_ConnStrIn != NULL)
{
MEM_FREE (_ConnStrIn);
_ConnStrIn = NULL;
}
}
}
else
{
if (pdbc->cp_connstr != NULL)
MEM_FREE (pdbc->cp_connstr);
if (waMode == 'W')
{
pdbc->cp_connstr = _ConnStrIn;
_ConnStrIn = NULL;
}
else
{
pdbc->cp_connstr = strdup (_connstr);
if (pdbc->cp_connstr == NULL)
{
PUSHSQLERR (pdbc->herr, en_HY001);
RETURN (SQL_ERROR);
}
}
}
}
#endif
if (!connStrOut)
{
connStrOut = connStrOut_buf;
connStrOutMax = sizeof(connStrOut_buf);
}
_iodbcdm_cfg_rewind (pconfig);
while (_iodbcdm_cfg_nextentry (pconfig) == 0)
{
if (!_iodbcdm_cfg_define (pconfig))
continue;
if (!strcasecmp(pconfig->id, "DSN"))
{
break;
}
else if (!strcasecmp(pconfig->id, "FILEDSN"))
{
filedsn = strdup (pconfig->value);
if (filedsn == NULL)
{
PUSHSQLERR (pdbc->herr, en_HY001);
RETURN (SQL_ERROR);
}
break;
}
}
if (filedsn != NULL)
{
if (_iodbcdm_cfg_merge_filedsn (pconfig, filedsn,
(char *) connStrIn_buf, sizeof (connStrIn_buf),
waMode == 'W') == -1)
{
PUSHSQLERR (pdbc->herr, en_IM015);
RETURN (SQL_ERROR);
}
connStrIn = connStrIn_buf;
if (cbConnStrIn != SQL_NTS)
{
if (waMode != 'W')
cbConnStrIn = STRLEN (connStrIn);
else
cbConnStrIn = WCSLEN (connStrIn);
}
}
if (_iodbcdm_cfg_find (pconfig, "ODBC", "DRIVER") == 0)
{
_iodbcdm_strlcpy ((char *) drvbuf, pconfig->value, sizeof (drvbuf));
drv = drvbuf;
}
if (_iodbcdm_cfg_find (pconfig, "ODBC", "DSN") == 0)
{
_iodbcdm_strlcpy ((char *) dsnbuf, pconfig->value, sizeof (dsnbuf));
dsn = dsnbuf;
}
switch (fDriverCompletion)
{
case SQL_DRIVER_NOPROMPT:
if (!dsn && !drv)
{
PUSHSQLERR (pdbc->herr, en_IM007);
RETURN (SQL_ERROR);
}
break;
case SQL_DRIVER_COMPLETE:
case SQL_DRIVER_COMPLETE_REQUIRED:
if (dsn != NULL || drv != NULL)
{
break;
}
case SQL_DRIVER_PROMPT:
if (waMode == 'A')
_iodbcdm_strlcpy ((char *) prov, connStrIn, sizeof (prov));
else
wcsncpy (prov, connStrIn, sizeof (prov) / sizeof (wchar_t));
#if 0
if (!dsn && !drv)
bCallDmDlg = TRUE;
else if ( _iodbcdm_CheckDriverLoginDlg(drv, dsn) == FALSE)
bCallDmDlg = TRUE;
if (!bCallDmDlg)
break;
#endif
ODBC_UNLOCK ();
#if defined (__APPLE__) && !(defined (NO_FRAMEWORKS) || defined (_LP64))
bundle = CFBundleGetBundleWithIdentifier (CFSTR ("org.iodbc.core"));
if (bundle)
{
liburl =
CFBundleCopyResourceURL (bundle, CFSTR ("iODBCadm.bundle"),
NULL, NULL);
if (liburl
&& (libname =
CFURLCopyFileSystemPath (liburl, kCFURLPOSIXPathStyle)))
{
CFStringGetCString (libname, name, sizeof (name),
kCFStringEncodingASCII);
_iodbcdm_strlcat (name, "/Contents/MacOS/iODBCadm",
sizeof (name));
hdll = _iodbcdm_dllopen (name);
}
if (liburl)
CFRelease (liburl);
if (libname)
CFRelease (libname);
}
#else
hdll = _iodbcdm_dllopen ("libiodbcadm.so");
#endif
if (!hdll)
break;
if (waMode != 'W')
dialproc = _iodbcdm_dllproc (hdll, "iodbcdm_drvconn_dialbox");
else
dialproc = _iodbcdm_dllproc (hdll, "iodbcdm_drvconn_dialboxw");
if (dialproc == SQL_NULL_HPROC)
{
sqlstat = en_IM008;
break;
}
retcode = dialproc (hwnd,
prov,
sizeof (prov) / (waMode == 'A' ? 1 : sizeof (SQLWCHAR)),
&sqlstat,
fDriverCompletion,
&config);
ODBC_LOCK ();
fDriverCompletion = SQL_DRIVER_NOPROMPT;
if (retcode != SQL_SUCCESS)
{
if (retcode != SQL_NO_DATA_FOUND)
PUSHSQLERR (pdbc->herr, sqlstat);
goto end;
}
connStrIn = prov;
if (cbConnStrIn != SQL_NTS)
{
if (waMode != 'W')
cbConnStrIn = STRLEN (connStrIn);
else
cbConnStrIn = WCSLEN (connStrIn);
}
if (_iodbcdm_cfg_parse_str (pconfig, connStrIn, cbConnStrIn,
waMode == 'W') == -1)
{
PUSHSQLERR (pdbc->herr, en_HY001);
RETURN (SQL_ERROR);
}
if (_iodbcdm_cfg_find (pconfig, "ODBC", "DSN") == 0)
dsn = pconfig->value;
if (_iodbcdm_cfg_find (pconfig, "ODBC", "DRIVER") == 0)
{
_iodbcdm_strlcpy ((char *) drvbuf, pconfig->value, sizeof (drvbuf));
drv = drvbuf;
}
break;
default:
sqlstat = en_S1110;
break;
}
if (sqlstat != en_00000)
{
PUSHSQLERR (pdbc->herr, sqlstat);
RETURN (SQL_ERROR);
}
if (dsn == NULL || *(char *) dsn == '\0')
{
dsn = (void *) "default";
}
else
{
setopterr |=
_iodbcdm_con_settracing (pdbc, (SQLCHAR *) dsn, SQL_NTS, waMode);
}
thread_safe = 1;
SQLSetConfigMode (ODBC_BOTH_DSN);
if (SQLGetPrivateProfileString ((char *) dsn, "ThreadManager", "",
buf, sizeof (buf), "odbc.ini")
&& (STRCASEEQ (buf, "on") || STRCASEEQ (buf, "1")))
{
thread_safe = 0;
}
unload_safe = 0;
SQLSetConfigMode (ODBC_BOTH_DSN);
if (SQLGetPrivateProfileString ((char *) dsn, "UnloadSafe", "",
buf, sizeof (buf), "odbc.ini")
&& (STRCASEEQ (buf, "on") || STRCASEEQ (buf, "1")))
{
unload_safe = 1;
}
if (drv == NULL || *(char *) drv == '\0')
{
SQLSetConfigMode (ODBC_BOTH_DSN);
if (SQLGetPrivateProfileString ((char *) dsn, "Driver", "",
(char *) drvbuf, sizeof (drvbuf), "odbc.ini") != 0)
{
drv = drvbuf;
}
}
if (drv == NULL)
{
PUSHSQLERR (pdbc->herr, en_IM002);
RETURN (SQL_ERROR);
}
retcode =
_iodbcdm_driverload (dsn, (char *) drv, pdbc, thread_safe, unload_safe,
waMode);
switch (retcode)
{
case SQL_SUCCESS:
break;
case SQL_SUCCESS_WITH_INFO:
#if 0
setopterr = SQL_ERROR;
#endif
break;
default:
RETURN (retcode);
}
#if (ODBCVER >= 0x300)
if (savefile != NULL)
pdbc->cp_timeout = 0;
#endif
penv = (ENV_t *) pdbc->henv;
if ((penv->unicode_driver && waMode != 'W')
|| (!penv->unicode_driver && waMode == 'W'))
{
if (waMode != 'W')
{
if ((_ConnStrOut =
malloc (connStrOutMax * sizeof (SQLWCHAR) + 1)) == NULL)
{
PUSHSQLERR (pdbc->herr, en_HY001);
RETURN (SQL_ERROR);
}
_ConnStrIn = dm_SQL_A2W ((SQLCHAR *) connStrIn, cbConnStrIn);
}
else
{
if ((_ConnStrOut = malloc (connStrOutMax + 1)) == NULL)
{
PUSHSQLERR (pdbc->herr, en_HY001);
RETURN (SQL_ERROR);
}
_ConnStrIn = dm_SQL_W2A ((SQLWCHAR *) connStrIn, cbConnStrIn);
}
connStrOut = _ConnStrOut;
connStrIn = _ConnStrIn;
cbConnStrIn = SQL_NTS;
}
SQLSetConfigMode (config);
ODBC_UNLOCK ();
CALL_UDRIVER (hdbc, pdbc, retcode, hproc, penv->unicode_driver,
en_DriverConnect, (pdbc->dhdbc,
hwnd,
connStrIn,
cbConnStrIn,
connStrOut, connStrOutMax, pcbConnStrOut, fDriverCompletion));
ODBC_LOCK ();
if (hproc == SQL_NULL_HPROC)
{
_iodbcdm_driverunload (pdbc, 3);
PUSHSQLERR (pdbc->herr, en_IM001);
RETURN (SQL_ERROR);
}
if (szConnStrOut
&& SQL_SUCCEEDED (retcode)
&& ((penv->unicode_driver && waMode != 'W')
|| (!penv->unicode_driver && waMode == 'W')))
{
if (waMode != 'W')
{
dm_StrCopyOut2_W2A ((SQLWCHAR *) connStrOut,
(SQLCHAR *) szConnStrOut, cbConnStrOutMax, NULL);
}
else
{
dm_StrCopyOut2_A2W ((SQLCHAR *) connStrOut,
(SQLWCHAR *) szConnStrOut, cbConnStrOutMax, NULL);
}
}
if (szConnStrOut != NULL)
{
if (filedsn != NULL)
{
if (waMode == 'W')
{
SQLWCHAR *_tmp = dm_SQL_U8toW (filedsn, SQL_NTS);
if (_tmp == NULL)
{
PUSHSQLERR (pdbc->herr, en_HY001);
RETURN (SQL_ERROR);
}
WCSNCAT (szConnStrOut, L";FILEDSN=", cbConnStrOutMax);
WCSNCAT (szConnStrOut, _tmp, cbConnStrOutMax);
MEM_FREE (_tmp);
}
else
{
_iodbcdm_strlcat (szConnStrOut, ";FILEDSN=", cbConnStrOutMax);
_iodbcdm_strlcat (szConnStrOut, filedsn, cbConnStrOutMax);
}
}
if (savefile != NULL)
{
if (waMode == 'W')
{
SQLWCHAR *_tmp = dm_SQL_U8toW (savefile, SQL_NTS);
if (_tmp == NULL)
{
PUSHSQLERR (pdbc->herr, en_HY001);
RETURN (SQL_ERROR);
}
WCSNCAT (szConnStrOut, L";SAVEFILE=", cbConnStrOutMax);
WCSNCAT (szConnStrOut, _tmp, cbConnStrOutMax);
MEM_FREE (_tmp);
}
else
{
_iodbcdm_strlcat (szConnStrOut, ";SAVEFILE=", cbConnStrOutMax);
_iodbcdm_strlcat (szConnStrOut, savefile, cbConnStrOutMax);
}
}
if (waMode == 'W')
{
*(SQLSMALLINT *) pcbConnStrOut =
WCSLEN (szConnStrOut) * sizeof (SQLWCHAR);
}
else
*(SQLSMALLINT *) pcbConnStrOut = strlen (szConnStrOut);
}
if (!SQL_SUCCEEDED (retcode))
{
RETURN (retcode);
}
pdbc->state = en_dbc_connected;
setopterr |= _iodbcdm_dbcdelayset (pdbc, waMode);
if (setopterr != SQL_SUCCESS)
retcode = SQL_SUCCESS_WITH_INFO;
if (savefile != NULL)
{
assert (connStrOut != NULL);
if (_iodbcdm_cfg_savefile (savefile, connStrOut,
penv->unicode_driver) == -1)
{
PUSHSQLERR (pdbc->herr, en_01S08);
retcode = SQL_SUCCESS_WITH_INFO;
}
}
end:
#if (ODBCVER >= 0x300)
if (!SQL_SUCCEEDED (retcode) &&
pdbc->cp_pdbc != NULL)
{
int rc;
_iodbcdm_pool_set_retry_wait (pdbc);
rc = _iodbcdm_pool_put_conn (pdbc);
assert (rc == 0);
}
#endif
_iodbcdm_cfg_done (pconfig);
if (_ConnStrIn != NULL)
MEM_FREE (_ConnStrIn);
if (_ConnStrOut != NULL)
MEM_FREE (_ConnStrOut);
if (savefile != NULL)
MEM_FREE (savefile);
if (filedsn != NULL)
MEM_FREE (filedsn);
return retcode;
}
SQLRETURN SQL_API
SQLDriverConnect (SQLHDBC hdbc,
SQLHWND hwnd,
SQLCHAR * szConnStrIn,
SQLSMALLINT cbConnStrIn,
SQLCHAR * szConnStrOut,
SQLSMALLINT cbConnStrOutMax,
SQLSMALLINT * pcbConnStrOut,
SQLUSMALLINT fDriverCompletion)
{
ENTER_HDBC (hdbc, 1,
trace_SQLDriverConnect (TRACE_ENTER,
hdbc,
hwnd,
szConnStrIn, cbConnStrIn,
szConnStrOut, cbConnStrOutMax, pcbConnStrOut,
fDriverCompletion));
retcode = SQLDriverConnect_Internal(
hdbc,
hwnd,
szConnStrIn, cbConnStrIn,
szConnStrOut, cbConnStrOutMax, pcbConnStrOut,
fDriverCompletion,
'A');
LEAVE_HDBC (hdbc, 1,
trace_SQLDriverConnect (TRACE_LEAVE,
hdbc,
hwnd,
szConnStrIn, cbConnStrIn,
szConnStrOut, cbConnStrOutMax, pcbConnStrOut,
fDriverCompletion));
}
SQLRETURN SQL_API
SQLDriverConnectA (SQLHDBC hdbc,
SQLHWND hwnd,
SQLCHAR * szConnStrIn,
SQLSMALLINT cbConnStrIn,
SQLCHAR * szConnStrOut,
SQLSMALLINT cbConnStrOutMax,
SQLSMALLINT * pcbConnStrOut,
SQLUSMALLINT fDriverCompletion)
{
ENTER_HDBC (hdbc, 1,
trace_SQLDriverConnect (TRACE_ENTER,
hdbc,
hwnd,
szConnStrIn, cbConnStrIn,
szConnStrOut, cbConnStrOutMax, pcbConnStrOut,
fDriverCompletion));
retcode = SQLDriverConnect_Internal(
hdbc,
hwnd,
szConnStrIn, cbConnStrIn,
szConnStrOut, cbConnStrOutMax, pcbConnStrOut,
fDriverCompletion,
'A');
LEAVE_HDBC (hdbc, 1,
trace_SQLDriverConnect (TRACE_LEAVE,
hdbc,
hwnd,
szConnStrIn, cbConnStrIn,
szConnStrOut, cbConnStrOutMax, pcbConnStrOut,
fDriverCompletion));
}
SQLRETURN SQL_API
SQLDriverConnectW (SQLHDBC hdbc,
SQLHWND hwnd,
SQLWCHAR * szConnStrIn,
SQLSMALLINT cbConnStrIn,
SQLWCHAR * szConnStrOut,
SQLSMALLINT cbConnStrOutMax,
SQLSMALLINT * pcbConnStrOut,
SQLUSMALLINT fDriverCompletion)
{
ENTER_HDBC (hdbc, 1,
trace_SQLDriverConnectW (TRACE_ENTER,
hdbc,
hwnd,
szConnStrIn, cbConnStrIn,
szConnStrOut, cbConnStrOutMax, pcbConnStrOut,
fDriverCompletion));
retcode = SQLDriverConnect_Internal(
hdbc,
hwnd,
szConnStrIn, cbConnStrIn,
szConnStrOut, cbConnStrOutMax, pcbConnStrOut,
fDriverCompletion,
'W');
LEAVE_HDBC (hdbc, 1,
trace_SQLDriverConnectW (TRACE_LEAVE,
hdbc,
hwnd,
szConnStrIn, cbConnStrIn,
szConnStrOut, cbConnStrOutMax, pcbConnStrOut,
fDriverCompletion));
}
SQLRETURN SQL_API
SQLBrowseConnect_Internal (SQLHDBC hdbc,
SQLPOINTER szConnStrIn,
SQLSMALLINT cbConnStrIn,
SQLPOINTER szConnStrOut,
SQLSMALLINT cbConnStrOutMax, SQLSMALLINT * pcbConnStrOut,
SQLCHAR waMode)
{
CONN (pdbc, hdbc);
ENVR (penv, NULL);
char buf[1024];
SWORD thread_safe;
SWORD unload_safe;
HPROC hproc = SQL_NULL_HPROC;
void * _ConnStrIn = NULL;
void * _ConnStrOut = NULL;
void * connStrOut = szConnStrOut;
void * connStrIn = szConnStrIn;
SQLRETURN retcode = SQL_SUCCESS;
SQLRETURN setopterr = SQL_SUCCESS;
if ((cbConnStrIn < 0 && cbConnStrIn != SQL_NTS) || cbConnStrOutMax < 0)
{
PUSHSQLERR (pdbc->herr, en_S1090);
return SQL_ERROR;
}
if (pdbc->state == en_dbc_allocated)
{
PCONFIG pconfig;
void *drv = NULL, *dsn = NULL;
if (_iodbcdm_cfg_init_str (&pconfig, szConnStrIn, cbConnStrIn,
waMode == 'W') == -1)
{
PUSHSQLERR (pdbc->herr, en_HY001);
return SQL_ERROR;
}
if (_iodbcdm_cfg_find (pconfig, "ODBC", "DRIVER") == 0)
drv = pconfig->value;
if (_iodbcdm_cfg_find (pconfig, "ODBC", "DSN") == 0)
dsn = pconfig->value;
if (dsn == NULL || ((char*)dsn)[0] == '\0')
dsn = (void *) "default";
else
{
if (_iodbcdm_con_settracing (pdbc, (SQLCHAR *) dsn, SQL_NTS, waMode) == SQL_ERROR)
{
_iodbcdm_cfg_done (pconfig);
return SQL_ERROR;
}
}
thread_safe = 1;
SQLSetConfigMode (ODBC_BOTH_DSN);
if ( SQLGetPrivateProfileString ((char *) dsn, "ThreadManager", "",
buf, sizeof(buf), "odbc.ini") &&
(STRCASEEQ (buf, "on") || STRCASEEQ (buf, "1")))
{
thread_safe = 0;
}
unload_safe = 0;
SQLSetConfigMode (ODBC_BOTH_DSN);
if ( SQLGetPrivateProfileString ((char *) dsn, "ThreadManager", "",
buf, sizeof(buf), "odbc.ini") &&
(STRCASEEQ (buf, "on") || STRCASEEQ (buf, "1")))
{
unload_safe = 1;
}
if (drv == NULL || *(char*)drv == '\0')
{
SQLSetConfigMode (ODBC_BOTH_DSN);
if ( SQLGetPrivateProfileString ((char *) dsn, "Driver", "",
buf, sizeof(buf), "odbc.ini") != 0)
{
drv = buf;
}
}
if (drv == NULL)
{
PUSHSQLERR (pdbc->herr, en_IM002);
_iodbcdm_cfg_done (pconfig);
return SQL_ERROR;
}
retcode = _iodbcdm_driverload (dsn, (char *) drv, pdbc, thread_safe, unload_safe, waMode);
_iodbcdm_cfg_done (pconfig);
switch (retcode)
{
case SQL_SUCCESS:
break;
case SQL_SUCCESS_WITH_INFO:
#if 0
setopterr = SQL_ERROR;
#endif
break;
default:
return retcode;
}
}
else if (pdbc->state != en_dbc_needdata)
{
PUSHSQLERR (pdbc->herr, en_08002);
return SQL_ERROR;
}
penv = (ENV_t *) pdbc->henv;
if ((penv->unicode_driver && waMode != 'W')
|| (!penv->unicode_driver && waMode == 'W'))
{
if (waMode != 'W')
{
if ((_ConnStrOut = malloc((cbConnStrOutMax + 1) * sizeof(SQLWCHAR))) == NULL)
{
PUSHSQLERR (pdbc->herr, en_HY001);
return SQL_ERROR;
}
_ConnStrIn = dm_SQL_A2W((SQLCHAR *)szConnStrIn, SQL_NTS);
}
else
{
if ((_ConnStrOut = malloc(cbConnStrOutMax + 1)) == NULL)
{
PUSHSQLERR (pdbc->herr, en_HY001);
return SQL_ERROR;
}
_ConnStrIn = dm_SQL_W2A((SQLWCHAR *)szConnStrIn, SQL_NTS);
}
connStrIn = _ConnStrIn;
cbConnStrIn = SQL_NTS;
connStrOut = _ConnStrOut;
}
ODBC_UNLOCK ();
CALL_UDRIVER(hdbc, pdbc, retcode, hproc, penv->unicode_driver,
en_BrowseConnect, (
pdbc->dhdbc,
connStrIn,
cbConnStrIn,
connStrOut,
cbConnStrOutMax,
pcbConnStrOut));
ODBC_LOCK ();
MEM_FREE(_ConnStrIn);
if (hproc == SQL_NULL_HPROC)
{
MEM_FREE(_ConnStrOut);
_iodbcdm_driverunload (pdbc, 3);
pdbc->state = en_dbc_allocated;
PUSHSQLERR (pdbc->herr, en_IM001);
return SQL_ERROR;
}
if (szConnStrOut
&& SQL_SUCCEEDED (retcode)
&& ((penv->unicode_driver && waMode != 'W')
|| (!penv->unicode_driver && waMode == 'W')))
{
if (waMode != 'W')
{
dm_StrCopyOut2_W2A ((SQLWCHAR *) connStrOut, (SQLCHAR *) szConnStrOut, cbConnStrOutMax, NULL);
}
else
{
dm_StrCopyOut2_A2W ((SQLCHAR *) connStrOut, (SQLWCHAR *) szConnStrOut, cbConnStrOutMax, NULL);
}
}
MEM_FREE(_ConnStrOut);
switch (retcode)
{
case SQL_SUCCESS:
case SQL_SUCCESS_WITH_INFO:
pdbc->state = en_dbc_connected;
setopterr |= _iodbcdm_dbcdelayset (pdbc, waMode);
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;
}
return retcode;
}
SQLRETURN SQL_API
SQLBrowseConnect (SQLHDBC hdbc,
SQLCHAR * szConnStrIn,
SQLSMALLINT cbConnStrIn,
SQLCHAR * szConnStrOut,
SQLSMALLINT cbConnStrOutMax,
SQLSMALLINT * pcbConnStrOut)
{
ENTER_HDBC (hdbc, 1,
trace_SQLBrowseConnect (TRACE_ENTER,
hdbc,
szConnStrIn, cbConnStrIn,
szConnStrOut, cbConnStrOutMax, pcbConnStrOut));
retcode = SQLBrowseConnect_Internal (
hdbc,
szConnStrIn, cbConnStrIn,
szConnStrOut, cbConnStrOutMax, pcbConnStrOut,
'A');
LEAVE_HDBC (hdbc, 1,
trace_SQLBrowseConnect (TRACE_LEAVE,
hdbc,
szConnStrIn, cbConnStrIn,
szConnStrOut, cbConnStrOutMax, pcbConnStrOut));
}
SQLRETURN SQL_API
SQLBrowseConnectA (SQLHDBC hdbc,
SQLCHAR * szConnStrIn,
SQLSMALLINT cbConnStrIn,
SQLCHAR * szConnStrOut,
SQLSMALLINT cbConnStrOutMax,
SQLSMALLINT * pcbConnStrOut)
{
ENTER_HDBC (hdbc, 1,
trace_SQLBrowseConnect (TRACE_ENTER,
hdbc,
szConnStrIn, cbConnStrIn,
szConnStrOut, cbConnStrOutMax, pcbConnStrOut));
retcode = SQLBrowseConnect_Internal (
hdbc,
szConnStrIn, cbConnStrIn,
szConnStrOut, cbConnStrOutMax, pcbConnStrOut,
'A');
LEAVE_HDBC (hdbc, 1,
trace_SQLBrowseConnect (TRACE_LEAVE,
hdbc,
szConnStrIn, cbConnStrIn,
szConnStrOut, cbConnStrOutMax, pcbConnStrOut));
}
SQLRETURN SQL_API
SQLBrowseConnectW (SQLHDBC hdbc,
SQLWCHAR * szConnStrIn,
SQLSMALLINT cbConnStrIn,
SQLWCHAR * szConnStrOut,
SQLSMALLINT cbConnStrOutMax,
SQLSMALLINT * pcbConnStrOut)
{
ENTER_HDBC (hdbc, 1,
trace_SQLBrowseConnectW (TRACE_ENTER,
hdbc,
szConnStrIn, cbConnStrIn,
szConnStrOut, cbConnStrOutMax, pcbConnStrOut));
retcode = SQLBrowseConnect_Internal (
hdbc,
szConnStrIn, cbConnStrIn,
szConnStrOut, cbConnStrOutMax, pcbConnStrOut,
'W');
LEAVE_HDBC (hdbc, 1,
trace_SQLBrowseConnectW (TRACE_LEAVE,
hdbc,
szConnStrIn, cbConnStrIn,
szConnStrOut, cbConnStrOutMax, pcbConnStrOut));
}
static SQLRETURN
SQLDisconnect_Internal (SQLHDBC hdbc)
{
CONN (pdbc, hdbc);
#if (ODBCVER >= 0x300)
GENV (genv, pdbc->genv);
#endif
STMT (pstmt, NULL);
if (pdbc->state == en_dbc_allocated)
{
PUSHSQLERR (pdbc->herr, en_08003);
return SQL_ERROR;
}
for (pstmt = (STMT_t *) pdbc->hstmt;
pstmt != NULL;
pstmt = (STMT_t *) pstmt->next)
{
if (pstmt->state >= en_stmt_needdata
|| pstmt->asyn_on != en_NullProc)
{
PUSHSQLERR (pdbc->herr, en_S1010);
return SQL_ERROR;
}
}
#if (ODBCVER >= 0x300)
if ((pdbc->state == en_dbc_connected || pdbc->state == en_dbc_hstmt)
&& (pdbc->cp_pdbc != NULL ||
(genv->connection_pooling != SQL_CP_OFF && pdbc->cp_timeout > 0)))
{
if (_iodbcdm_pool_put_conn (pdbc) == 0)
{
_iodbcdm_finish_disconnect (pdbc, FALSE);
return SQL_SUCCESS;
}
}
#endif
return _iodbcdm_finish_disconnect (pdbc, TRUE);
}
SQLRETURN SQL_API
SQLDisconnect (SQLHDBC hdbc)
{
ENTER_HDBC (hdbc, 1,
trace_SQLDisconnect (TRACE_ENTER, hdbc));
retcode = SQLDisconnect_Internal (hdbc);
LEAVE_HDBC (hdbc, 1,
trace_SQLDisconnect (TRACE_LEAVE, hdbc));
}
SQLRETURN SQL_API
SQLNativeSql_Internal (SQLHDBC hdbc,
SQLPOINTER szSqlStrIn,
SQLINTEGER cbSqlStrIn,
SQLPOINTER szSqlStr,
SQLINTEGER cbSqlStrMax,
SQLINTEGER * pcbSqlStr,
SQLCHAR waMode)
{
CONN (pdbc, hdbc);
ENVR (penv, pdbc->henv);
sqlstcode_t sqlstat = en_00000;
SQLRETURN retcode = SQL_SUCCESS;
HPROC hproc = SQL_NULL_HPROC;
void * _SqlStrIn = NULL;
void * _SqlStr = NULL;
void * sqlStr = szSqlStr;
if (szSqlStrIn == NULL)
{
sqlstat = en_S1009;
}
else if (cbSqlStrIn < 0 && cbSqlStrIn != SQL_NTS)
{
sqlstat = en_S1090;
}
if (sqlstat != en_00000)
{
PUSHSQLERR (pdbc->herr, sqlstat);
return SQL_ERROR;
}
if (pdbc->state <= en_dbc_needdata)
{
PUSHSQLERR (pdbc->herr, en_08003);
return SQL_ERROR;
}
if ((penv->unicode_driver && waMode != 'W')
|| (!penv->unicode_driver && waMode == 'W'))
{
if (waMode != 'W')
{
if ((_SqlStr = malloc(cbSqlStrMax * sizeof(SQLWCHAR) + 1)) == NULL)
{
PUSHSQLERR (pdbc->herr, en_HY001);
return SQL_ERROR;
}
_SqlStrIn = dm_SQL_A2W((SQLCHAR *)szSqlStrIn, SQL_NTS);
}
else
{
if ((_SqlStr = malloc(cbSqlStrMax + 1)) == NULL)
{
PUSHSQLERR (pdbc->herr, en_HY001);
return SQL_ERROR;
}
_SqlStrIn = dm_SQL_W2A((SQLWCHAR *)szSqlStrIn, SQL_NTS);
}
szSqlStrIn = _SqlStrIn;
cbSqlStrIn = SQL_NTS;
sqlStr = _SqlStr;
}
CALL_UDRIVER(hdbc, pdbc, retcode, hproc, penv->unicode_driver,
en_NativeSql, (
pdbc->dhdbc,
szSqlStrIn,
cbSqlStrIn,
sqlStr,
cbSqlStrMax,
pcbSqlStr));
MEM_FREE(_SqlStrIn);
if (hproc == SQL_NULL_HPROC)
{
MEM_FREE(_SqlStr);
PUSHSQLERR (pdbc->herr, en_IM001);
return SQL_ERROR;
}
if (szSqlStr
&& SQL_SUCCEEDED (retcode)
&& ((penv->unicode_driver && waMode != 'W')
|| (!penv->unicode_driver && waMode == 'W')))
{
if (waMode != 'W')
{
dm_StrCopyOut2_W2A ((SQLWCHAR *) sqlStr, (SQLCHAR *) szSqlStr, cbSqlStrMax, NULL);
}
else
{
dm_StrCopyOut2_A2W ((SQLCHAR *) sqlStr, (SQLWCHAR *) szSqlStr, cbSqlStrMax, NULL);
}
}
MEM_FREE(_SqlStr);
return retcode;
}
SQLRETURN SQL_API
SQLNativeSql (
SQLHDBC hdbc,
SQLCHAR * szSqlStrIn,
SQLINTEGER cbSqlStrIn,
SQLCHAR * szSqlStr,
SQLINTEGER cbSqlStrMax,
SQLINTEGER * pcbSqlStr)
{
ENTER_HDBC (hdbc, 0,
trace_SQLNativeSql (TRACE_ENTER,
hdbc,
szSqlStrIn, cbSqlStrIn,
szSqlStr, cbSqlStrMax, pcbSqlStr));
retcode = SQLNativeSql_Internal (
hdbc,
szSqlStrIn, cbSqlStrIn,
szSqlStr, cbSqlStrMax, pcbSqlStr,
'A');
LEAVE_HDBC (hdbc, 0,
trace_SQLNativeSql (TRACE_LEAVE,
hdbc,
szSqlStrIn, cbSqlStrIn,
szSqlStr, cbSqlStrMax, pcbSqlStr));
}
SQLRETURN SQL_API
SQLNativeSqlA (
SQLHDBC hdbc,
SQLCHAR * szSqlStrIn,
SQLINTEGER cbSqlStrIn,
SQLCHAR * szSqlStr,
SQLINTEGER cbSqlStrMax,
SQLINTEGER * pcbSqlStr)
{
ENTER_HDBC (hdbc, 0,
trace_SQLNativeSql (TRACE_ENTER,
hdbc,
szSqlStrIn, cbSqlStrIn,
szSqlStr, cbSqlStrMax, pcbSqlStr));
retcode = SQLNativeSql_Internal(
hdbc,
szSqlStrIn, cbSqlStrIn,
szSqlStr, cbSqlStrMax, pcbSqlStr,
'A');
LEAVE_HDBC (hdbc, 0,
trace_SQLNativeSql (TRACE_LEAVE,
hdbc,
szSqlStrIn, cbSqlStrIn,
szSqlStr, cbSqlStrMax, pcbSqlStr));
}
SQLRETURN SQL_API
SQLNativeSqlW (
SQLHDBC hdbc,
SQLWCHAR * szSqlStrIn,
SQLINTEGER cbSqlStrIn,
SQLWCHAR * szSqlStr,
SQLINTEGER cbSqlStrMax,
SQLINTEGER * pcbSqlStr)
{
ENTER_HDBC (hdbc, 0,
trace_SQLNativeSqlW (TRACE_ENTER,
hdbc,
szSqlStrIn, cbSqlStrIn,
szSqlStr, cbSqlStrMax, pcbSqlStr));
retcode = SQLNativeSql_Internal(
hdbc,
szSqlStrIn, cbSqlStrIn,
szSqlStr, cbSqlStrMax, pcbSqlStr,
'W');
LEAVE_HDBC (hdbc, 0,
trace_SQLNativeSqlW (TRACE_LEAVE,
hdbc,
szSqlStrIn, cbSqlStrIn,
szSqlStr, cbSqlStrMax, pcbSqlStr));
}