environ.c

来自「postgresql-odbc,跨平台应用」· C语言 代码 · 共 696 行 · 第 1/2 页

C
696
字号
/*------- * Module:			environ.c * * Description:		This module contains routines related to *					the environment, such as storing connection handles, *					and returning errors. * * Classes:			EnvironmentClass (Functions prefix: "EN_") * * API functions:	SQLAllocEnv, SQLFreeEnv, SQLError * * Comments:		See "notice.txt" for copyright and license information. *------- */#include "environ.h"#include "connection.h"#include "dlg_specific.h"#include "statement.h"#include <stdlib.h>#include <string.h>#include "pgapifunc.h"#ifdef	WIN32#ifndef	_WSASTARTUP_IN_DLLMAIN_#include <winsock2.h>#endif /* _WSASTARTUP_IN_DLLMAIN_ */#endif /* WIN32 */#include "loadlib.h"extern GLOBAL_VALUES globals;/* The one instance of the handles */static int conns_count = 0;static ConnectionClass **conns = NULL;#if defined(WIN_MULTITHREAD_SUPPORT)CRITICAL_SECTION	conns_cs;CRITICAL_SECTION	common_cs; /* commonly used for short term blocking */#elif defined(POSIX_MULTITHREAD_SUPPORT)pthread_mutex_t     conns_cs;pthread_mutex_t     common_cs;#endif /* WIN_MULTITHREAD_SUPPORT */int	getConnCount(){	return conns_count;}ConnectionClass * const *getConnList(){	return conns;}RETCODE		SQL_APIPGAPI_AllocEnv(HENV FAR * phenv){	CSTR func = "PGAPI_AllocEnv";	SQLRETURN	ret = SQL_SUCCESS;	mylog("**** in %s ** \n", func);	/*	 * Hack for systems on which none of the constructor-making techniques	 * in psqlodbc.c work: if globals appears not to have been	 * initialized, then cause it to be initialized.  Since this should be	 * the first function called in this shared library, doing it here	 * should work.	 */	if (globals.socket_buffersize <= 0)	{		initialize_global_cs();		getCommonDefaults(DBMS_NAME, ODBCINST_INI, NULL);	}	*phenv = (HENV) EN_Constructor();	if (!*phenv)	{		*phenv = SQL_NULL_HENV;		EN_log_error(func, "Error allocating environment", NULL);		ret = SQL_ERROR;	}	mylog("** exit %s: phenv = %p **\n", func, *phenv);	return ret;}RETCODE		SQL_APIPGAPI_FreeEnv(HENV henv){	CSTR func = "PGAPI_FreeEnv";	SQLRETURN	ret = SQL_SUCCESS;	EnvironmentClass *env = (EnvironmentClass *) henv;	mylog("**** in PGAPI_FreeEnv: env = %p ** \n", env);	if (env && EN_Destructor(env))	{#ifdef	_HANDLE_ENLIST_IN_DTC_		CALL_DtcOnRelease();#endif /* _HANDLE_ENLIST_IN_DTC_ */		mylog("   ok\n");		goto cleanup;	}	mylog("    error\n");	ret = SQL_ERROR;	EN_log_error(func, "Error freeing environment", env);cleanup:	return ret;}static voidpg_sqlstate_set(const EnvironmentClass *env, UCHAR *szSqlState, const UCHAR *ver3str, const UCHAR *ver2str){	strcpy(szSqlState, EN_is_odbc3(env) ? ver3str : ver2str);}PG_ErrorInfo	*ER_Constructor(SDWORD errnumber, const char *msg){	PG_ErrorInfo	*error;	ssize_t		aladd, errsize;	if (DESC_OK == errnumber)		return NULL;	if (msg)	{		errsize = strlen(msg);		aladd = errsize;	}	else	{		errsize = -1;		aladd = 0;	}	error = (PG_ErrorInfo *) malloc(sizeof(PG_ErrorInfo) + aladd);	if (error)	{		memset(error, 0, sizeof(PG_ErrorInfo));		error->status = errnumber;		error->errorsize = (Int4) errsize;		if (errsize > 0)			memcpy(error->__error_message, msg, errsize);		error->__error_message[aladd] = '\0';        	error->recsize = -1;	}	return error;}voidER_Destructor(PG_ErrorInfo *self){	free(self);}PG_ErrorInfo *ER_Dup(const PG_ErrorInfo *self){	PG_ErrorInfo	*new;	Int4		alsize;	if (!self)		return NULL;	alsize = sizeof(PG_ErrorInfo);	if (self->errorsize  > 0)		alsize += self->errorsize;	new = (PG_ErrorInfo *) malloc(alsize);	memcpy(new, self, alsize);	return new;}#define	DRVMNGRDIV	511/*		Returns the next SQL error information. */RETCODE		SQL_APIER_ReturnError(PG_ErrorInfo **pgerror,		SQLSMALLINT	RecNumber,		SQLCHAR FAR * szSqlState,		SQLINTEGER FAR * pfNativeError,		SQLCHAR FAR * szErrorMsg,		SQLSMALLINT cbErrorMsgMax,		SQLSMALLINT FAR * pcbErrorMsg,		UWORD flag){	CSTR func = "ER_ReturnError";	/* CC: return an error of a hstmt  */	PG_ErrorInfo	*error;	BOOL		partial_ok = ((flag & PODBC_ALLOW_PARTIAL_EXTRACT) != 0),			clear_str = ((flag & PODBC_ERROR_CLEAR) != 0);	const char	*msg;	SWORD		msglen, stapos, wrtlen, pcblen;	if (!pgerror || !*pgerror)		return SQL_NO_DATA_FOUND;	error = *pgerror;	msg = error->__error_message;	mylog("%s: status = %d, msg = #%s#\n", func, error->status, msg);	msglen = (SQLSMALLINT) strlen(msg);	/*	 *	Even though an application specifies a larger error message	 *	buffer, the driver manager changes it silently.	 *	Therefore we divide the error message into ... 	 */	if (error->recsize < 0)	{		if (cbErrorMsgMax > 0)			error->recsize = cbErrorMsgMax - 1; /* apply the first request */		else			error->recsize = DRVMNGRDIV;	}	if (RecNumber < 0)	{		if (0 == error->errorpos)			RecNumber = 1;		else			RecNumber = 2 + (error->errorpos - 1) / error->recsize;	}	stapos = (RecNumber - 1) * error->recsize;	if (stapos > msglen)		return SQL_NO_DATA_FOUND; 	pcblen = wrtlen = msglen - stapos;	if (pcblen > error->recsize)		pcblen = error->recsize;	if (0 == cbErrorMsgMax)		wrtlen = 0; 	else if (wrtlen >= cbErrorMsgMax)	{		if (partial_ok)			wrtlen = cbErrorMsgMax - 1;		else if (cbErrorMsgMax <= error->recsize)			wrtlen = 0;		else 			wrtlen = error->recsize;	}	if (wrtlen > pcblen)		wrtlen = pcblen;	if (NULL != pcbErrorMsg)		*pcbErrorMsg = pcblen;	if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))	{		memcpy(szErrorMsg, msg + stapos, wrtlen);		szErrorMsg[wrtlen] = '\0';	}	if (NULL != pfNativeError)		*pfNativeError = error->status;	if (NULL != szSqlState)		strncpy(szSqlState, error->sqlstate, 6);	mylog("	     szSqlState = '%s',len=%d, szError='%s'\n", szSqlState, pcblen, szErrorMsg);	if (clear_str)	{		error->errorpos = stapos + wrtlen;		if (error->errorpos >= msglen)		{			ER_Destructor(error);			*pgerror = NULL;		}	}	if (wrtlen == 0)		return SQL_SUCCESS_WITH_INFO;	else		return SQL_SUCCESS;}RETCODE		SQL_APIPGAPI_ConnectError(	HDBC hdbc,			SQLSMALLINT	RecNumber,			SQLCHAR FAR * szSqlState,			SQLINTEGER FAR * pfNativeError,			SQLCHAR FAR * szErrorMsg,			SQLSMALLINT cbErrorMsgMax,			SQLSMALLINT FAR * pcbErrorMsg,			UWORD flag){	ConnectionClass *conn = (ConnectionClass *) hdbc;	EnvironmentClass *env = (EnvironmentClass *) conn->henv;	char		*msg;	int		status;	BOOL	once_again = FALSE;	ssize_t		msglen;	mylog("**** PGAPI_ConnectError: hdbc=%p <%d>\n", hdbc, cbErrorMsgMax);	if (RecNumber != 1 && RecNumber != -1)		return SQL_NO_DATA_FOUND;	if (cbErrorMsgMax < 0)		return SQL_ERROR;	if (CONN_EXECUTING == conn->status || !CC_get_error(conn, &status, &msg) || NULL == msg)	{		mylog("CC_Get_error returned nothing.\n");		if (NULL != szSqlState)			strcpy(szSqlState, "00000");		if (NULL != pcbErrorMsg)			*pcbErrorMsg = 0;		if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))			szErrorMsg[0] = '\0';		return SQL_NO_DATA_FOUND;	}	mylog("CC_get_error: status = %d, msg = #%s#\n", status, msg);	msglen = strlen(msg);	if (NULL != pcbErrorMsg)	{		*pcbErrorMsg = (SQLSMALLINT) msglen;		if (cbErrorMsgMax == 0)			once_again = TRUE;		else if (msglen >= cbErrorMsgMax)			*pcbErrorMsg = cbErrorMsgMax - 1;	}	if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))		strncpy_null(szErrorMsg, msg, cbErrorMsgMax);	if (NULL != pfNativeError)		*pfNativeError = status;	if (NULL != szSqlState)	{		if (conn->sqlstate[0])			strcpy(szSqlState, conn->sqlstate);		else			switch (status)		{			case CONN_OPTION_VALUE_CHANGED:				pg_sqlstate_set(env, szSqlState, "01S02", "01S02");				break;			case CONN_TRUNCATED:				pg_sqlstate_set(env, szSqlState, "01004", "01004");				/* data truncated */				break;			case CONN_INIREAD_ERROR:				pg_sqlstate_set(env, szSqlState, "IM002", "IM002");				/* data source not found */				break;			case CONNECTION_SERVER_NOT_REACHED:			case CONN_OPENDB_ERROR:				pg_sqlstate_set(env, szSqlState, "08001", "08001");				/* unable to connect to data source */				break;			case CONN_INVALID_AUTHENTICATION:			case CONN_AUTH_TYPE_UNSUPPORTED:				pg_sqlstate_set(env, szSqlState, "28000", "28000");				break;			case CONN_STMT_ALLOC_ERROR:				pg_sqlstate_set(env, szSqlState, "HY001", "S1001");				/* memory allocation failure */

⌨️ 快捷键说明

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