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 + -
显示快捷键?