#include "dpiImpl.h"
#include "dpiErrorMessages.h"
int dpiError__getInfo(dpiError *error, dpiErrorInfo *info)
{
if (!info)
return DPI_FAILURE;
info->code = error->buffer->code;
info->offset = error->buffer->offset;
info->offset16 = (uint16_t) error->buffer->offset;
info->message = error->buffer->message;
info->messageLength = error->buffer->messageLength;
info->fnName = error->buffer->fnName;
info->action = error->buffer->action;
info->isRecoverable = error->buffer->isRecoverable;
info->encoding = error->buffer->encoding;
info->isWarning = error->buffer->isWarning;
if (info->code == 12154) {
info->sqlState = "42S02";
} else if (error->buffer->errorNum == DPI_ERR_CONN_CLOSED) {
info->sqlState = "01002";
} else if (error->buffer->code == 0 &&
error->buffer->errorNum == (dpiErrorNum) 0) {
info->sqlState = "00000";
} else {
info->sqlState = "HY000";
}
return DPI_FAILURE;
}
int dpiError__initHandle(dpiError *error)
{
if (dpiHandlePool__acquire(error->env->errorHandles, &error->handle,
error) < 0)
return DPI_FAILURE;
if (!error->handle) {
if (dpiOci__handleAlloc(error->env->handle, &error->handle,
DPI_OCI_HTYPE_ERROR, "allocate OCI error", error) < 0)
return DPI_FAILURE;
}
return DPI_SUCCESS;
}
int dpiError__set(dpiError *error, const char *action, dpiErrorNum errorNum,
...)
{
va_list varArgs;
if (error) {
error->buffer->code = 0;
error->buffer->isRecoverable = 0;
error->buffer->isWarning = 0;
error->buffer->offset = 0;
strcpy(error->buffer->encoding, DPI_CHARSET_NAME_UTF8);
error->buffer->action = action;
error->buffer->errorNum = errorNum;
va_start(varArgs, errorNum);
error->buffer->messageLength =
(uint32_t) vsnprintf(error->buffer->message,
sizeof(error->buffer->message),
dpiErrorMessages[errorNum - DPI_ERR_NO_ERR], varArgs);
va_end(varArgs);
if (dpiDebugLevel & DPI_DEBUG_LEVEL_ERRORS)
dpiDebug__print("internal error %.*s (%s / %s)\n",
error->buffer->messageLength, error->buffer->message,
error->buffer->fnName, action);
}
return DPI_FAILURE;
}
int dpiError__setFromOCI(dpiError *error, int status, dpiConn *conn,
const char *action)
{
uint32_t callTimeout, serverStatus;
if (status == DPI_OCI_INVALID_HANDLE)
return dpiError__set(error, action, DPI_ERR_INVALID_HANDLE, "OCI");
else if (!error)
return DPI_FAILURE;
else if (!error->handle)
return dpiError__set(error, action, DPI_ERR_ERR_NOT_INITIALIZED);
else if (status != DPI_OCI_ERROR && status != DPI_OCI_NO_DATA &&
status != DPI_OCI_SUCCESS_WITH_INFO)
return dpiError__set(error, action,
DPI_ERR_UNEXPECTED_OCI_RETURN_VALUE, status,
error->buffer->fnName);
error->buffer->action = action;
strcpy(error->buffer->encoding, error->env->encoding);
if (dpiOci__errorGet(error->handle, DPI_OCI_HTYPE_ERROR,
error->env->charsetId, action, error) < 0)
return DPI_FAILURE;
if (dpiDebugLevel & DPI_DEBUG_LEVEL_ERRORS)
dpiDebug__print("OCI error %.*s (%s / %s)\n",
error->buffer->messageLength, error->buffer->message,
error->buffer->fnName, action);
if (status == DPI_OCI_SUCCESS_WITH_INFO) {
error->buffer->isWarning = 1;
return DPI_SUCCESS;
}
error->buffer->isRecoverable = 0;
dpiOci__attrGet(error->handle, DPI_OCI_HTYPE_ERROR,
(void*) &error->buffer->isRecoverable, 0,
DPI_OCI_ATTR_ERROR_IS_RECOVERABLE, NULL, error);
if (conn && !conn->creating && !conn->deadSession) {
if (conn->serverHandle) {
if (dpiOci__attrGet(conn->serverHandle, DPI_OCI_HTYPE_SERVER,
&serverStatus, NULL, DPI_OCI_ATTR_SERVER_STATUS,
"get server status", error) < 0 ||
serverStatus != DPI_OCI_SERVER_NORMAL) {
conn->deadSession = 1;
}
}
if (!conn->deadSession) {
switch (error->buffer->code) {
case 22: case 28: case 31: case 45: case 378: case 602: case 603: case 609: case 1012: case 1041: case 1043: case 1089: case 1092: case 2396: case 3113: case 3114: case 3122: case 3135: case 12153: case 12537: case 12547: case 12570: case 12583: case 27146: case 28511: case 56600: conn->deadSession = 1;
break;
}
}
if (conn->deadSession)
return dpiError__wrap(error, DPI_ERR_CONN_CLOSED,
error->buffer->code);
switch (error->buffer->code) {
case 3136: case 3156: case 12161: callTimeout = 0;
if (conn->env->versionInfo->versionNum >= 18)
dpiOci__attrGet(conn->handle, DPI_OCI_HTYPE_SVCCTX,
(void*) &callTimeout, 0, DPI_OCI_ATTR_CALL_TIMEOUT,
NULL, error);
if (callTimeout > 0)
return dpiError__wrap(error, DPI_ERR_CALL_TIMEOUT,
callTimeout, error->buffer->code);
break;
}
}
return DPI_FAILURE;
}
int dpiError__setFromOS(dpiError *error, const char *action)
{
char *message;
#ifdef _WIN32
size_t messageLength = 0;
message = NULL;
if (dpiUtils__getWindowsError(GetLastError(), &message, &messageLength,
error) < 0)
return DPI_FAILURE;
dpiError__set(error, action, DPI_ERR_OS, message);
dpiUtils__freeMemory(message);
#else
char buffer[512];
int err = errno;
#if defined(__GLIBC__) || defined(__CYGWIN__)
message = strerror_r(err, buffer, sizeof(buffer));
#else
message = (strerror_r(err, buffer, sizeof(buffer)) == 0) ? buffer : NULL;
#endif
if (!message) {
(void) sprintf(buffer, "unable to get OS error %d", err);
message = buffer;
}
dpiError__set(error, action, DPI_ERR_OS, message);
#endif
return DPI_FAILURE;
}
int dpiError__wrap(dpiError *error, dpiErrorNum errorNum, ...)
{
uint32_t origMessageLength;
char *origMessage, *ptr;
size_t ptrLength;
va_list varArgs;
origMessageLength = error->buffer->messageLength;
origMessage = malloc(origMessageLength);
if (origMessage)
memcpy(origMessage, error->buffer->message, origMessageLength);
error->buffer->code = 0;
error->buffer->errorNum = errorNum;
va_start(varArgs, errorNum);
error->buffer->messageLength =
(uint32_t) vsnprintf(error->buffer->message,
sizeof(error->buffer->message),
dpiErrorMessages[errorNum - DPI_ERR_NO_ERR], varArgs);
va_end(varArgs);
if (origMessage) {
ptr = error->buffer->message + error->buffer->messageLength;
ptrLength = sizeof(error->buffer->message) -
error->buffer->messageLength;
error->buffer->messageLength += (uint32_t) snprintf(ptr, ptrLength,
"\n%*s", origMessageLength, origMessage);
free(origMessage);
}
if (dpiDebugLevel & DPI_DEBUG_LEVEL_ERRORS)
dpiDebug__print("internal error %.*s (%s / %s)\n",
error->buffer->messageLength, error->buffer->message,
error->buffer->fnName, error->buffer->action);
return DPI_FAILURE;
}