connect.c
来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C语言 代码 · 共 1,242 行 · 第 1/2 页
C
1,242 行
/*
* connect.c
*
* $Id: connect.c,v 1.7 2000/01/20 13:19:20 GT Exp $
*
* Connect (load) driver
*
* 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"
extern char* _iodbcdm_getkeyvalbydsn();
extern char* _iodbcdm_getkeyvalinstr();
extern RETCODE _iodbcdm_driverunload();
/*
* Following id string is a copyright mark. Removing(i.e. use
* souce code of this package without it or make it not appear
* in the final object file) or modifing it without permission
* from original author(kejin@empress.com) are copyright
* violation.
*/
static char sccsid[]
= "@(#)iODBC driver manager 2.5, Copyright(c) 1995 by Ke Jin";
/* - Load driver share library( or increase its reference count
* if it has already been loaded by another active connection)
* - Call driver's SQLAllocEnv() (for the first reference only)
* - Call driver's SQLAllocConnect()
* - Call driver's SQLSetConnectOption() (set login time out)
* - Increase the bookkeeping reference count
*/
static RETCODE
_iodbcdm_driverload (
char FAR * path,
HDBC hdbc)
{
DBC_t FAR *pdbc = (DBC_t FAR *) hdbc;
GENV_t FAR *genv;
ENV_t FAR *penv = NULL;
HDLL hdll;
HPROC hproc;
RETCODE retcode = SQL_SUCCESS;
int sqlstat = en_00000;
if (path == NULL || path[0] == '\0')
{
PUSHSQLERR (pdbc->herr, en_IM002);
return SQL_ERROR;
}
if (hdbc == SQL_NULL_HDBC || pdbc->genv == SQL_NULL_HENV)
{
return SQL_INVALID_HANDLE;
}
genv = (GENV_t FAR *) pdbc->genv;
/* This will either load the driver dll or increase its reference count */
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);
}
else
{
/*
* this will not unload the driver but only decrease its internal
* reference count
*/
_iodbcdm_dllclose (hdll);
}
}
if (penv == NULL)
{
/*
* find out whether this dll has already been loaded on another
* connection
*/
for (penv = (ENV_t FAR *) genv->henv;
penv != NULL;
penv = (ENV_t FAR *) penv->next)
{
if (penv->hdll == hdll)
{
/*
* this will not unload the driver but only decrease its internal
* reference count
*/
_iodbcdm_dllclose (hdll);
break;
}
}
if (penv == NULL)
/* no connection attaching with this dll */
{
int i;
/* create a new dll env instance */
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 < SQL_EXT_API_LAST + 1; i++)
{
(penv->dllproc_tab)[i] = SQL_NULL_HPROC;
}
pdbc->henv = penv;
penv->hdll = hdll;
/* call driver's SQLAllocHandle() or SQLAllocEnv() */
#if (ODBCVER >= 0x0300)
hproc = _iodbcdm_getproc (hdbc, en_AllocHandle);
if (hproc)
{
CALL_DRIVER (hdbc, retcode, hproc, en_AllocHandle,
(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &(penv->dhenv)))
}
else /* try driver's SQLAllocEnv() */
#endif
{
hproc = _iodbcdm_getproc (hdbc, en_AllocEnv);
if (hproc == SQL_NULL_HPROC)
{
sqlstat = en_IM004;
}
else
{
CALL_DRIVER (hdbc, 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;
}
/* insert into dll env list */
penv->next = (ENV_t FAR *) genv->henv;
genv->henv = penv;
/* initiate this new env entry */
penv->refcount = 0; /* we will increase it after
* driver's SQLAllocConnect()
* success
*/
}
pdbc->henv = penv;
if (pdbc->dhdbc == SQL_NULL_HDBC)
{
#if (ODBCVER >= 0x0300)
hproc = _iodbcdm_getproc (hdbc, en_AllocHandle);
if (hproc)
{
CALL_DRIVER (hdbc, retcode, hproc, en_AllocHandle,
(SQL_HANDLE_DBC, penv->dhenv, &(pdbc->dhdbc)))
}
else
#endif
{
hproc = _iodbcdm_getproc (hdbc, en_AllocConnect);
if (hproc == SQL_NULL_HPROC)
{
sqlstat = en_IM005;
}
else
{
CALL_DRIVER (hdbc, 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++; /* bookkeeping reference count on this driver */
}
/* driver's login timeout option must been set before
* its SQLConnect() call */
if (pdbc->login_timeout != 0UL)
{
hproc = _iodbcdm_getproc (hdbc, en_SetConnectOption);
if (hproc == SQL_NULL_HPROC)
{
sqlstat = en_IM004;
}
else
{
CALL_DRIVER (hdbc, 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;
}
}
}
return SQL_SUCCESS;
}
/* - Call driver's SQLFreeConnect()
* - Call driver's SQLFreeEnv() ( for the last reference only)
* - Unload the share library( or decrease its reference
* count if it is not the last referenct )
* - decrease bookkeeping reference count
* - state transition to allocated
*/
RETCODE
_iodbcdm_driverunload (HDBC hdbc)
{
DBC_t FAR *pdbc = (DBC_t FAR *) hdbc;
ENV_t FAR *penv;
ENV_t FAR *tpenv;
GENV_t FAR *genv;
HPROC hproc;
RETCODE retcode = SQL_SUCCESS;
if (hdbc == SQL_NULL_HDBC)
{
return SQL_INVALID_HANDLE;
}
/* no pointer check will be performed in this function */
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 (hdbc, en_FreeHandle);
if (hproc)
{
CALL_DRIVER (hdbc, retcode, hproc, en_FreeHandle,
(SQL_HANDLE_DBC, pdbc->dhdbc))
}
else
#endif
{
hproc = _iodbcdm_getproc (hdbc, en_FreeConnect);
if (hproc != SQL_NULL_HPROC)
{
CALL_DRIVER (hdbc, retcode, hproc,
en_FreeConnect, (pdbc->dhdbc))
pdbc->dhdbc = SQL_NULL_HDBC;
}
}
penv->refcount--;
if (!penv->refcount)
/* no other connections still attaching with this driver */
{
#if (ODBCVER >= 0x0300)
hproc = _iodbcdm_getproc (hdbc, en_FreeHandle);
if (hproc)
{
CALL_DRIVER (hdbc, retcode, hproc, en_FreeHandle,
(SQL_HANDLE_ENV, penv->dhenv))
}
else
#endif
{
hproc = _iodbcdm_getproc (hdbc, en_FreeEnv);
if (hproc != SQL_NULL_HPROC)
{
CALL_DRIVER (hdbc, 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->henv = SQL_NULL_HENV;
pdbc->hstmt = SQL_NULL_HSTMT;
/* pdbc->herr = SQL_NULL_HERR;
-- delay to DM's SQLFreeConnect() */
pdbc->dhdbc = SQL_NULL_HDBC;
pdbc->state = en_dbc_allocated;
/* set connect options to default values */
/**********
pdbc->access_mode = SQL_MODE_DEFAULT;
pdbc->autocommit = SQL_AUTOCOMMIT_DEFAULT;
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;
if (pdbc->current_qualifier != NULL)
{
MEM_FREE (pdbc->current_qualifier);
pdbc->current_qualifier = NULL;
}
return SQL_SUCCESS;
}
static RETCODE
_iodbcdm_dbcdelayset (HDBC hdbc)
{
DBC_t FAR *pdbc = (DBC_t FAR *) hdbc;
ENV_t FAR *penv;
HPROC hproc;
RETCODE retcode = SQL_SUCCESS;
RETCODE ret;
penv = pdbc->henv;
hproc = _iodbcdm_getproc (hdbc, 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, ret, hproc,
en_SetConnectOption, (
SQL_ACCESS_MODE,
pdbc->access_mode))
retcode |= ret;
}
if (pdbc->autocommit != SQL_AUTOCOMMIT_DEFAULT)
{
CALL_DRIVER (hdbc, ret, hproc,
en_SetConnectOption, (
pdbc->dhdbc,
SQL_AUTOCOMMIT,
pdbc->autocommit))
retcode |= ret;
}
if (pdbc->current_qualifier != NULL)
{
CALL_DRIVER (hdbc, ret, hproc,
en_SetConnectOption, (
pdbc->dhdbc,
SQL_CURRENT_QUALIFIER,
pdbc->current_qualifier))
retcode |= ret;
}
if (pdbc->packet_size != 0UL)
{
CALL_DRIVER (hdbc, ret, hproc,
en_SetConnectOption, (
pdbc->dhdbc,
SQL_PACKET_SIZE,
pdbc->packet_size))
retcode |= ret;
}
if (pdbc->quiet_mode != (UDWORD) NULL)
{
CALL_DRIVER (hdbc, 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, ret, hproc,
en_SetConnectOption, (
pdbc->dhdbc,
SQL_TXN_ISOLATION,
pdbc->txn_isolation))
}
/* check error code for driver's SQLSetConnectOption() call */
if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
{
PUSHSQLERR (pdbc->herr, en_IM006);
retcode = SQL_ERROR;
}
/* get cursor behavior on transaction commit or rollback */
hproc = _iodbcdm_getproc (hdbc, en_GetInfo);
if (hproc == SQL_NULL_HPROC)
{
PUSHSQLERR (pdbc->herr, en_01000);
return retcode;
}
CALL_DRIVER (hdbc, ret, hproc,
en_GetInfo, (
pdbc->dhdbc,
SQL_CURSOR_COMMIT_BEHAVIOR,
(PTR) & (pdbc->cb_commit),
sizeof (pdbc->cb_commit),
NULL))
retcode |= ret;
CALL_DRIVER (hdbc, 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 RETCODE
_iodbcdm_settracing (HDBC hdbc, char *dsn, int dsnlen)
{
char buf[256];
char *ptr;
RETCODE setopterr = SQL_SUCCESS;
/* Get Driver's DLL path from specificed or default dsn section */
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 |= SQLSetConnectOption (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 |= SQLSetConnectOption (hdbc,
SQL_OPT_TRACE, opt);
}
}
return setopterr;
}
RETCODE SQL_API
SQLConnect (
HDBC hdbc,
UCHAR FAR * szDSN,
SWORD cbDSN,
UCHAR FAR * szUID,
SWORD cbUID,
UCHAR FAR * szAuthStr,
SWORD cbAuthStr)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?