hdbc.c
来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C语言 代码 · 共 812 行 · 第 1/2 页
C
812 行
/*
* hdbc.c
*
* $Id: hdbc.c,v 1.5 1999/06/01 15:31:41 VZ Exp $
*
* 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;
#if (ODBCVER >= 0x0300)
if (henv == SQL_NULL_HENV || genv->type != SQL_HANDLE_ENV)
#else
if (henv == SQL_NULL_HENV)
#endif
{
return SQL_INVALID_HANDLE;
}
if (phdbc == NULL)
{
PUSHSQLERR (genv->herr, en_S1009);
return SQL_ERROR;
}
pdbc = (DBC_t FAR *) MEM_ALLOC (sizeof (DBC_t));
if (pdbc == NULL)
{
*phdbc = SQL_NULL_HDBC;
PUSHSQLERR (genv->herr, en_S1001);
return SQL_ERROR;
}
#if (ODBCVER >= 0x0300)
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;
}
RETCODE SQL_API
SQLFreeConnect (HDBC hdbc)
{
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;
}
/* check state */
if (pdbc->state != en_dbc_allocated)
{
PUSHSQLERR (pdbc->herr, en_S1010);
return SQL_ERROR;
}
genv = (GENV_t FAR *) pdbc->genv;
for (tpdbc = (DBC_t FAR *) genv->hdbc;
tpdbc != NULL;
tpdbc = tpdbc->next)
{
if (pdbc == tpdbc)
{
genv->hdbc = pdbc->next;
break;
}
if (pdbc == tpdbc->next)
{
tpdbc->next = pdbc->next;
break;
}
}
/* free this dbc */
_iodbcdm_driverunload (pdbc);
_iodbcdm_freesqlerrlist (pdbc->herr);
if (pdbc->tfile)
{
MEM_FREE (pdbc->tfile);
}
SQLSetConnectOption (pdbc, SQL_OPT_TRACE, SQL_OPT_TRACE_OFF);
MEM_FREE (pdbc);
return SQL_SUCCESS;
}
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 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))
#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));
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;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?