-
Hiroshi Inoue authored
2) Suppress some error logs for the request to other drivers.
Hiroshi Inoue authored2) Suppress some error logs for the request to other drivers.
environ.c 15.05 KiB
/*-------
* 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"
extern GLOBAL_VALUES globals;
/* The one instance of the handles */
ConnectionClass *conns[MAX_CONNECTIONS];
RETCODE SQL_API
PGAPI_AllocEnv(HENV FAR * phenv)
{
static char *func = "PGAPI_AllocEnv";
mylog("**** in PGAPI_AllocEnv ** \n");
/*
* 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)
getCommonDefaults(DBMS_NAME, ODBCINST_INI, NULL);
*phenv = (HENV) EN_Constructor();
if (!*phenv)
{
*phenv = SQL_NULL_HENV;
EN_log_error(func, "Error allocating environment", NULL);
return SQL_ERROR;
}
mylog("** exit PGAPI_AllocEnv: phenv = %u **\n", *phenv);
return SQL_SUCCESS;
}
RETCODE SQL_API
PGAPI_FreeEnv(HENV henv)
{
static char *func = "PGAPI_FreeEnv";
EnvironmentClass *env = (EnvironmentClass *) henv;
mylog("**** in PGAPI_FreeEnv: env = %u ** \n", env);
if (env && EN_Destructor(env))
{
mylog(" ok\n");
return SQL_SUCCESS;
}
mylog(" error\n");
EN_log_error(func, "Error freeing environment", env);
return SQL_ERROR;
}
#define DRVMNGRDIV 511
/* Returns the next SQL error information. */
RETCODE SQL_API
PGAPI_StmtError( HSTMT hstmt,
SWORD RecNumber,
UCHAR FAR * szSqlState,
SDWORD FAR * pfNativeError,
UCHAR FAR * szErrorMsg,
SWORD cbErrorMsgMax,
SWORD FAR * pcbErrorMsg,
UWORD flag)
{
/* CC: return an error of a hstmt */
StatementClass *stmt = (StatementClass *) hstmt;
char *msg;
int status;
BOOL partial_ok = ((flag & PODBC_ALLOW_PARTIAL_EXTRACT) != 0),
clear_str = ((flag & PODBC_ERROR_CLEAR) != 0);
SWORD msglen, stapos, wrtlen, pcblen;
mylog("**** PGAPI_StmtError: hstmt=%u <%d>\n", hstmt, cbErrorMsgMax);
if (cbErrorMsgMax < 0)
return SQL_ERROR;
if (!SC_get_error(stmt, &status, &msg) || NULL == msg || !msg[0])
{
mylog("SC_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("SC_get_error: status = %d, msg = #%s#\n", status, msg);
msglen = (SWORD) 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 (stmt->error_recsize < 0)
{
if (cbErrorMsgMax > 0)
stmt->error_recsize = cbErrorMsgMax - 1; /* apply the first request */
else
stmt->error_recsize = DRVMNGRDIV;
}
if (RecNumber < 0)
{
if (0 == stmt->errorpos)
RecNumber = 1;
else
RecNumber = 2 + (stmt->errorpos - 1) / stmt->error_recsize;
}
stapos = (RecNumber - 1) * stmt->error_recsize;
if (stapos > msglen)
return SQL_NO_DATA_FOUND;
pcblen = wrtlen = msglen - stapos;
if (pcblen > stmt->error_recsize)
pcblen = stmt->error_recsize;
if (0 == cbErrorMsgMax)
wrtlen = 0;
else if (wrtlen >= cbErrorMsgMax)
{
if (partial_ok)
wrtlen = cbErrorMsgMax - 1;
else if (cbErrorMsgMax <= stmt->error_recsize)
wrtlen = 0;
else
wrtlen = stmt->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 = status;
if (NULL != szSqlState)
switch (status)
{
/* now determine the SQLSTATE to be returned */
case STMT_ROW_VERSION_CHANGED:
strcpy(szSqlState, "01001");
/* data truncated */
break;
case STMT_TRUNCATED:
strcpy(szSqlState, "01004");
/* data truncated */
break;
case STMT_INFO_ONLY:
strcpy(szSqlState, "00000");
/* just information that is returned, no error */
break;
case STMT_BAD_ERROR:
strcpy(szSqlState, "08S01");
/* communication link failure */
break;
case STMT_CREATE_TABLE_ERROR:
strcpy(szSqlState, "S0001");
/* table already exists */
break;
case STMT_STATUS_ERROR:
case STMT_SEQUENCE_ERROR:
strcpy(szSqlState, "S1010");
/* Function sequence error */
break;
case STMT_NO_MEMORY_ERROR:
strcpy(szSqlState, "S1001");
/* memory allocation failure */
break;
case STMT_COLNUM_ERROR:
strcpy(szSqlState, "S1002");
/* invalid column number */
break;
case STMT_NO_STMTSTRING:
strcpy(szSqlState, "S1001");
/* having no stmtstring is also a malloc problem */
break;
case STMT_ERROR_TAKEN_FROM_BACKEND:
strcpy(szSqlState, "S1000");
/* general error */
break;
case STMT_INTERNAL_ERROR:
strcpy(szSqlState, "S1000");
/* general error */
break;
case STMT_ROW_OUT_OF_RANGE:
strcpy(szSqlState, "S1107");
break;
case STMT_OPERATION_CANCELLED:
strcpy(szSqlState, "S1008");
break;
case STMT_NOT_IMPLEMENTED_ERROR:
strcpy(szSqlState, "S1C00"); /* == 'driver not
* capable' */
break;
case STMT_OPTION_OUT_OF_RANGE_ERROR:
strcpy(szSqlState, "S1092");
break;
case STMT_BAD_PARAMETER_NUMBER_ERROR:
strcpy(szSqlState, "S1093");
break;
case STMT_INVALID_COLUMN_NUMBER_ERROR:
strcpy(szSqlState, "S1002");
break;
case STMT_RESTRICTED_DATA_TYPE_ERROR:
strcpy(szSqlState, "07006");
break;
case STMT_INVALID_CURSOR_STATE_ERROR:
strcpy(szSqlState, "24000");
break;
case STMT_ERROR_IN_ROW:
strcpy(szSqlState, "01S01");
break;
case STMT_OPTION_VALUE_CHANGED:
strcpy(szSqlState, "01S02");
break;
case STMT_POS_BEFORE_RECORDSET:
strcpy(szSqlState, "01S06");
break;
case STMT_INVALID_CURSOR_NAME:
strcpy(szSqlState, "34000");
break;
case STMT_NO_CURSOR_NAME:
strcpy(szSqlState, "S1015");
break;
case STMT_INVALID_ARGUMENT_NO:
strcpy(szSqlState, "S1009");
/* invalid argument value */
break;
case STMT_INVALID_CURSOR_POSITION:
strcpy(szSqlState, "S1109");
break;
case STMT_RETURN_NULL_WITHOUT_INDICATOR:
strcpy(szSqlState, "22002");
break;
case STMT_VALUE_OUT_OF_RANGE:
strcpy(szSqlState, "22003");
break;
case STMT_OPERATION_INVALID:
strcpy(szSqlState, "S1011");
break;
case STMT_INVALID_DESCRIPTOR_IDENTIFIER:
strcpy(szSqlState, "HY091");
break;
case STMT_INVALID_OPTION_IDENTIFIER:
strcpy(szSqlState, "HY092");
break;
case STMT_OPTION_NOT_FOR_THE_DRIVER:
strcpy(szSqlState, "HYC00");
break;
case STMT_EXEC_ERROR:
default:
strcpy(szSqlState, "S1000");
/* also a general error */
break;
}
mylog(" szSqlState = '%s',len=%d, szError='%s'\n", szSqlState, pcblen, szErrorMsg);
if (clear_str)
{
stmt->errorpos = stapos + wrtlen;
if (stmt->errorpos >= msglen)
SC_clear_error(stmt);
}
if (wrtlen == 0)
return SQL_SUCCESS_WITH_INFO;
else
return SQL_SUCCESS;
}
RETCODE SQL_API
PGAPI_ConnectError( HDBC hdbc,
SWORD RecNumber,
UCHAR FAR * szSqlState,
SDWORD FAR * pfNativeError,
UCHAR FAR * szErrorMsg,
SWORD cbErrorMsgMax,
SWORD FAR * pcbErrorMsg,
UWORD flag)
{
ConnectionClass *conn = (ConnectionClass *) hdbc;
char *msg;
int status;
BOOL once_again = FALSE;
SWORD msglen;
mylog("**** PGAPI_ConnectError: hdbc=%u <%d>\n", hdbc, cbErrorMsgMax);
if (RecNumber != 1 && RecNumber != -1)
return SQL_NO_DATA_FOUND;
if (cbErrorMsgMax < 0)
return SQL_ERROR;
if (!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 = 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)
switch (status)
{
case STMT_OPTION_VALUE_CHANGED:
case CONN_OPTION_VALUE_CHANGED:
strcpy(szSqlState, "01S02");
break;
case STMT_TRUNCATED:
case CONN_TRUNCATED:
strcpy(szSqlState, "01004");
/* data truncated */
break;
case CONN_INIREAD_ERROR:
strcpy(szSqlState, "IM002");
/* data source not found */
break;
case CONNECTION_SERVER_NOT_REACHED:
case CONN_OPENDB_ERROR:
strcpy(szSqlState, "08001");
/* unable to connect to data source */
break;
case CONN_INVALID_AUTHENTICATION:
case CONN_AUTH_TYPE_UNSUPPORTED:
strcpy(szSqlState, "28000");
break;
case CONN_STMT_ALLOC_ERROR:
strcpy(szSqlState, "S1001");
/* memory allocation failure */
break;
case CONN_IN_USE:
strcpy(szSqlState, "S1000");
/* general error */
break;
case CONN_UNSUPPORTED_OPTION:
strcpy(szSqlState, "IM001");
/* driver does not support this function */
case CONN_INVALID_ARGUMENT_NO:
strcpy(szSqlState, "S1009");
/* invalid argument value */
break;
case CONN_TRANSACT_IN_PROGRES:
strcpy(szSqlState, "S1010");
/*
* when the user tries to switch commit mode in a
* transaction
*/
/* -> function sequence error */
break;
case CONN_NO_MEMORY_ERROR:
strcpy(szSqlState, "S1001");
break;
case CONN_NOT_IMPLEMENTED_ERROR:
case STMT_NOT_IMPLEMENTED_ERROR:
strcpy(szSqlState, "S1C00");
break;
case STMT_RETURN_NULL_WITHOUT_INDICATOR:
strcpy(szSqlState, "22002");
break;
case CONN_VALUE_OUT_OF_RANGE:
case STMT_VALUE_OUT_OF_RANGE:
strcpy(szSqlState, "22003");
break;
default:
strcpy(szSqlState, "S1000");
/* general error */
break;
}
mylog(" szSqlState = '%s',len=%d, szError='%s'\n", szSqlState, msglen, szErrorMsg);
if (once_again)
{
conn->errornumber = status;
return SQL_SUCCESS_WITH_INFO;
}
else
return SQL_SUCCESS;
}
RETCODE SQL_API
PGAPI_EnvError( HENV henv,
SWORD RecNumber,
UCHAR FAR * szSqlState,
SDWORD FAR * pfNativeError,
UCHAR FAR * szErrorMsg,
SWORD cbErrorMsgMax,
SWORD FAR * pcbErrorMsg,
UWORD flag)
{
EnvironmentClass *env = (EnvironmentClass *) henv;
char *msg;
int status;
mylog("**** PGAPI_EnvError: henv=%u <%d>\n", henv, cbErrorMsgMax);
if (RecNumber != 1 && RecNumber != -1)
return SQL_NO_DATA_FOUND;
if (cbErrorMsgMax < 0)
return SQL_ERROR;
if (!EN_get_error(env, &status, &msg) || NULL == msg)
{
mylog("EN_get_error: status = %d, msg = #%s#\n", status, msg);
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("EN_get_error: status = %d, msg = #%s#\n", status, msg);
if (NULL != pcbErrorMsg)
*pcbErrorMsg = (SWORD) strlen(msg);
if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
strncpy_null(szErrorMsg, msg, cbErrorMsgMax);
if (NULL != pfNativeError)
*pfNativeError = status;
if (szSqlState)
{
switch (status)
{
case ENV_ALLOC_ERROR:
/* memory allocation failure */
strcpy(szSqlState, "S1001");
break;
default:
strcpy(szSqlState, "S1000");
/* general error */
break;
}
}
return SQL_SUCCESS;
}
/* Returns the next SQL error information. */
RETCODE SQL_API
PGAPI_Error(
HENV henv,
HDBC hdbc,
HSTMT hstmt,
UCHAR FAR * szSqlState,
SDWORD FAR * pfNativeError,
UCHAR FAR * szErrorMsg,
SWORD cbErrorMsgMax,
SWORD FAR * pcbErrorMsg)
{
RETCODE ret;
UWORD flag = PODBC_ALLOW_PARTIAL_EXTRACT | PODBC_ERROR_CLEAR;
mylog("**** PGAPI_Error: henv=%u, hdbc=%u hstmt=%d\n", henv, hdbc, hstmt);
if (cbErrorMsgMax < 0)
return SQL_ERROR;
if (SQL_NULL_HSTMT != hstmt)
ret = PGAPI_StmtError(hstmt, -1, szSqlState, pfNativeError,
szErrorMsg, cbErrorMsgMax, pcbErrorMsg, flag);
else if (SQL_NULL_HDBC != hdbc)
ret = PGAPI_ConnectError(hdbc, -1, szSqlState, pfNativeError,
szErrorMsg, cbErrorMsgMax, pcbErrorMsg, flag);
else if (SQL_NULL_HENV != hdbc)
ret = PGAPI_EnvError(henv, -1, szSqlState, pfNativeError,
szErrorMsg, cbErrorMsgMax, pcbErrorMsg, flag);
else
{
if (NULL != szSqlState)
strcpy(szSqlState, "00000");
if (NULL != pcbErrorMsg)
*pcbErrorMsg = 0;
if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0))
szErrorMsg[0] = '\0';
ret = SQL_NO_DATA_FOUND;
}
mylog("**** PGAPI_Error exit code=%d\n", ret);
return ret;
}
/*
* EnvironmentClass implementation
*/
EnvironmentClass *
EN_Constructor(void)
{
EnvironmentClass *rv;
rv = (EnvironmentClass *) malloc(sizeof(EnvironmentClass));
if (rv)
{
rv->errormsg = 0;
rv->errornumber = 0;
rv->flag = 0;
}
return rv;
}
char
EN_Destructor(EnvironmentClass *self)
{
int lf;
char rv = 1;
mylog("in EN_Destructor, self=%u\n", self);
/*
* the error messages are static strings distributed throughout the
* source--they should not be freed
*/
/* Free any connections belonging to this environment */
for (lf = 0; lf < MAX_CONNECTIONS; lf++)
{
if (conns[lf] && conns[lf]->henv == self)
rv = rv && CC_Destructor(conns[lf]);
}
free(self);
mylog("exit EN_Destructor: rv = %d\n", rv);
#ifdef _MEMORY_DEBUG_
debug_memory_check();
#endif /* _MEMORY_DEBUG_ */
return rv;
}
char
EN_get_error(EnvironmentClass *self, int *number, char **message)
{
if (self && self->errormsg && self->errornumber)
{
*message = self->errormsg;
*number = self->errornumber;
self->errormsg = 0;
self->errornumber = 0;
return 1;
}
else
return 0;
}
char
EN_add_connection(EnvironmentClass *self, ConnectionClass *conn)
{
int i;
mylog("EN_add_connection: self = %u, conn = %u\n", self, conn);
for (i = 0; i < MAX_CONNECTIONS; i++)
{
if (!conns[i])
{
conn->henv = self;
conns[i] = conn;
mylog(" added at i =%d, conn->henv = %u, conns[i]->henv = %u\n", i, conn->henv, conns[i]->henv);
return TRUE;
}
}
return FALSE;
}
char
EN_remove_connection(EnvironmentClass *self, ConnectionClass *conn)
{
int i;
for (i = 0; i < MAX_CONNECTIONS; i++)
if (conns[i] == conn && conns[i]->status != CONN_EXECUTING)
{
conns[i] = NULL;
return TRUE;
}
return FALSE;
}
void
EN_log_error(char *func, char *desc, EnvironmentClass *self)
{
if (self)
qlog("ENVIRON ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->errornumber, self->errormsg);
else
qlog("INVALID ENVIRON HANDLE ERROR: func=%s, desc='%s'\n", func, desc);
}