connect.c

来自「一个可以替代windows ODBC驱动程序管理器的通用ODBC数据库引擎」· C语言 代码 · 共 1,380 行 · 第 1/2 页

C
1,380
字号
/* *  connect.c * *  $Id: connect.c,v 1.15 2001/06/06 12:36:16 source 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 <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>#ifdef _MACX#include <Carbon/Carbon.h>#endif /* _MACX */extern char *_iodbcdm_getkeyvalbydsn ();extern char *_iodbcdm_getkeyvalinstr ();extern SQLRETURN _iodbcdm_driverunload ();/* *  Identification strings */static char sccsid[] = "@(#)iODBC driver manager " VERSION ", (LGPL)\n";char *version = VERSION;char *libname = "iODBC Driver Manager";/* - 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 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;  /* 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);	  penv->hdll = hdll;	}      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;	    }	  /*	   *  Initialize array of ODBC functions	   */	  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;          /*           *  If the driver appears not to be thread safe, use a           *  driver mutex to serialize all calls to this driver           */          penv->thread_safe = thread_safe;          if (!penv->thread_safe)            MUTEX_INIT (penv->drv_lock);     	  /* call driver's SQLAllocHandle() or SQLAllocEnv() */#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)		{		/* this is an ODBC3 driver - introduce the app's requested version  */		  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			/* try driver's SQLAllocEnv() */#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;	    }	  /* 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 (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++;		/* 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 (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;	    }	}    }  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 */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;    }  /* 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 (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)    /* no other connections still attaching with this driver */    {#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->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 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));    }  /* 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 (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;  /* 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 |= _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_APISQLConnect (    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;  /* MS SDK Guide specifies driver path can't longer than 255. */  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);  /* check arguments */  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 ();

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?