#include "dpiImpl.h"
#include <time.h>
static int dpiConn__attachExternal(dpiConn *conn, void *externalHandle,
dpiError *error);
static int dpiConn__createStandalone(dpiConn *conn, const char *userName,
uint32_t userNameLength, const char *password, uint32_t passwordLength,
const char *connectString, uint32_t connectStringLength,
const dpiCommonCreateParams *commonParams,
const dpiConnCreateParams *createParams, dpiError *error);
static int dpiConn__get(dpiConn *conn, const char *userName,
uint32_t userNameLength, const char *password, uint32_t passwordLength,
const char *connectString, uint32_t connectStringLength,
dpiConnCreateParams *createParams, dpiPool *pool, dpiError *error);
static int dpiConn__getHandles(dpiConn *conn, dpiError *error);
static int dpiConn__getServerCharset(dpiConn *conn, dpiError *error);
static int dpiConn__getSession(dpiConn *conn, uint32_t mode,
const char *connectString, uint32_t connectStringLength,
dpiConnCreateParams *params, void *authInfo, dpiError *error);
static int dpiConn__setAttributesFromCreateParams(dpiConn *conn, void *handle,
uint32_t handleType, const char *userName, uint32_t userNameLength,
const char *password, uint32_t passwordLength,
const dpiConnCreateParams *params, dpiError *error);
static int dpiConn__setShardingKey(dpiConn *conn, void **shardingKey,
void *handle, uint32_t handleType, uint32_t attribute,
const char *action, dpiShardingKeyColumn *columns, uint8_t numColumns,
dpiError *error);
static int dpiConn__setShardingKeyValue(dpiConn *conn, void *shardingKey,
dpiShardingKeyColumn *column, dpiError *error);
static int dpiConn__attachExternal(dpiConn *conn, void *externalHandle,
dpiError *error)
{
conn->externalHandle = 1;
conn->handle = externalHandle;
if (dpiConn__getHandles(conn, error) < 0) {
conn->handle = NULL;
return DPI_FAILURE;
}
conn->handle = NULL;
if (dpiOci__handleAlloc(conn->env->handle, &conn->handle,
DPI_OCI_HTYPE_SVCCTX, "allocate service context handle",
error) < 0)
return DPI_FAILURE;
if (dpiOci__attrSet(conn->handle, DPI_OCI_HTYPE_SVCCTX, conn->serverHandle,
0, DPI_OCI_ATTR_SERVER, "set server handle", error) < 0)
return DPI_FAILURE;
if (dpiOci__attrSet(conn->handle, DPI_OCI_HTYPE_SVCCTX,
conn->sessionHandle, 0, DPI_OCI_ATTR_SESSION, "set session handle",
error) < 0)
return DPI_FAILURE;
return DPI_SUCCESS;
}
static int dpiConn__check(dpiConn *conn, const char *fnName, dpiError *error)
{
if (dpiGen__startPublicFn(conn, DPI_HTYPE_CONN, fnName, error) < 0)
return DPI_FAILURE;
return dpiConn__checkConnected(conn, error);
}
int dpiConn__checkConnected(dpiConn *conn, dpiError *error)
{
if (!conn->handle || conn->closing || (conn->pool && !conn->pool->handle))
return dpiError__set(error, "check connected", DPI_ERR_NOT_CONNECTED);
return DPI_SUCCESS;
}
static int dpiConn__close(dpiConn *conn, uint32_t mode, const char *tag,
uint32_t tagLength, int propagateErrors, dpiError *error)
{
int status, txnInProgress;
uint32_t serverStatus, i;
time_t *lastTimeUsed;
dpiObject *obj;
dpiStmt *stmt;
dpiLob *lob;
txnInProgress = 0;
if (!conn->deadSession && !conn->externalHandle && conn->sessionHandle) {
txnInProgress = 1;
if (conn->env->versionInfo->versionNum >= 12)
dpiOci__attrGet(conn->sessionHandle, DPI_OCI_HTYPE_SESSION,
&txnInProgress, NULL, DPI_OCI_ATTR_TRANSACTION_IN_PROGRESS,
NULL, error);
}
if (txnInProgress &&
dpiOci__transRollback(conn, propagateErrors, error) < 0)
conn->deadSession = 1;
if (conn->objects && !conn->externalHandle) {
for (i = 0; i < conn->objects->numSlots; i++) {
obj = (dpiObject*) conn->objects->handles[i];
if (!obj)
continue;
if (conn->env->threaded) {
dpiMutex__acquire(conn->env->mutex);
status = dpiGen__checkHandle(obj, DPI_HTYPE_OBJECT, NULL,
NULL);
if (status == DPI_SUCCESS)
obj->refCount += 1;
dpiMutex__release(conn->env->mutex);
if (status < 0)
continue;
}
status = dpiObject__close(obj, propagateErrors, error);
if (conn->env->threaded)
dpiGen__setRefCount(obj, error, -1);
if (status < 0)
return DPI_FAILURE;
}
}
if (conn->openStmts && !conn->externalHandle) {
for (i = 0; i < conn->openStmts->numSlots; i++) {
stmt = (dpiStmt*) conn->openStmts->handles[i];
if (!stmt)
continue;
if (conn->env->threaded) {
dpiMutex__acquire(conn->env->mutex);
status = dpiGen__checkHandle(stmt, DPI_HTYPE_STMT, NULL, NULL);
if (status == DPI_SUCCESS)
stmt->refCount += 1;
dpiMutex__release(conn->env->mutex);
if (status < 0)
continue;
}
status = dpiStmt__close(stmt, NULL, 0, propagateErrors, error);
if (conn->env->threaded)
dpiGen__setRefCount(stmt, error, -1);
if (status < 0)
return DPI_FAILURE;
}
}
if (conn->openLobs && !conn->externalHandle) {
for (i = 0; i < conn->openLobs->numSlots; i++) {
lob = (dpiLob*) conn->openLobs->handles[i];
if (!lob)
continue;
if (conn->env->threaded) {
dpiMutex__acquire(conn->env->mutex);
status = dpiGen__checkHandle(lob, DPI_HTYPE_LOB, NULL, NULL);
if (status == DPI_SUCCESS)
lob->refCount += 1;
dpiMutex__release(conn->env->mutex);
if (status < 0)
continue;
}
status = dpiLob__close(lob, propagateErrors, error);
if (conn->env->threaded)
dpiGen__setRefCount(lob, error, -1);
if (status < 0)
return DPI_FAILURE;
}
}
if (conn->externalHandle) {
if (conn->handle)
dpiOci__handleFree(conn->handle, DPI_OCI_HTYPE_SVCCTX);
conn->sessionHandle = NULL;
} else if (conn->standalone) {
if (dpiOci__sessionEnd(conn, propagateErrors, error) < 0)
return DPI_FAILURE;
dpiOci__handleFree(conn->sessionHandle, DPI_OCI_HTYPE_SESSION);
conn->sessionHandle = NULL;
if (dpiOci__serverDetach(conn, propagateErrors, error) < 0)
return DPI_FAILURE;
dpiOci__handleFree(conn->serverHandle, DPI_OCI_HTYPE_SERVER);
dpiOci__handleFree(conn->handle, DPI_OCI_HTYPE_SVCCTX);
} else {
if (mode & DPI_OCI_SESSRLS_DROPSESS)
conn->deadSession = 1;
if (conn->sessionHandle && conn->pool && conn->pool->handle) {
lastTimeUsed = NULL;
if (dpiOci__contextGetValue(conn, DPI_CONTEXT_LAST_TIME_USED,
(uint32_t) (sizeof(DPI_CONTEXT_LAST_TIME_USED) - 1),
(void**) &lastTimeUsed, propagateErrors, error) < 0)
return DPI_FAILURE;
if (lastTimeUsed && conn->deadSession) {
dpiOci__contextSetValue(conn, DPI_CONTEXT_LAST_TIME_USED,
(uint32_t) (sizeof(DPI_CONTEXT_LAST_TIME_USED) - 1),
NULL, 0, error);
dpiOci__memoryFree(conn, lastTimeUsed, error);
lastTimeUsed = NULL;
} else if (!lastTimeUsed && !conn->deadSession) {
if (dpiOci__memoryAlloc(conn, (void**) &lastTimeUsed,
sizeof(time_t), propagateErrors, error) < 0)
return DPI_FAILURE;
if (dpiOci__contextSetValue(conn, DPI_CONTEXT_LAST_TIME_USED,
(uint32_t) (sizeof(DPI_CONTEXT_LAST_TIME_USED) - 1),
lastTimeUsed, propagateErrors, error) < 0) {
dpiOci__memoryFree(conn, lastTimeUsed, error);
lastTimeUsed = NULL;
}
}
if (lastTimeUsed)
*lastTimeUsed = time(NULL);
}
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)
mode |= DPI_OCI_SESSRLS_DROPSESS;
else if (dpiUtils__checkClientVersion(conn->env->versionInfo, 12, 2,
NULL) == DPI_SUCCESS && (mode & DPI_MODE_CONN_CLOSE_RETAG) &&
tag && tagLength > 0)
mode |= DPI_OCI_SESSRLS_MULTIPROPERTY_TAG;
if (dpiOci__sessionRelease(conn, tag, tagLength, mode, propagateErrors,
error) < 0)
return DPI_FAILURE;
conn->sessionHandle = NULL;
}
conn->handle = NULL;
conn->serverHandle = NULL;
if (conn->shardingKey) {
dpiOci__descriptorFree(conn->shardingKey, DPI_OCI_DTYPE_SHARDING_KEY);
conn->shardingKey = NULL;
}
if (conn->superShardingKey) {
dpiOci__descriptorFree(conn->superShardingKey,
DPI_OCI_DTYPE_SHARDING_KEY);
conn->superShardingKey = NULL;
}
return DPI_SUCCESS;
}
int dpiConn__create(dpiConn *conn, const dpiContext *context,
const char *userName, uint32_t userNameLength, const char *password,
uint32_t passwordLength, const char *connectString,
uint32_t connectStringLength, dpiPool *pool,
const dpiCommonCreateParams *commonParams,
dpiConnCreateParams *createParams, dpiError *error)
{
if (dpiHandleList__create(&conn->openStmts, error) < 0)
return DPI_FAILURE;
if (dpiHandleList__create(&conn->openLobs, error) < 0)
return DPI_FAILURE;
if (dpiHandleList__create(&conn->objects, error) < 0)
return DPI_FAILURE;
if (!pool && dpiEnv__init(conn->env, context, commonParams, error) < 0)
return DPI_FAILURE;
if (createParams->externalHandle)
return dpiConn__attachExternal(conn, createParams->externalHandle,
error);
if (pool || (createParams->connectionClass &&
createParams->connectionClassLength > 0) ||
createParams->shardingKeyColumns ||
createParams->superShardingKeyColumns)
return dpiConn__get(conn, userName, userNameLength, password,
passwordLength, connectString, connectStringLength,
createParams, pool, error);
return dpiConn__createStandalone(conn, userName, userNameLength, password,
passwordLength, connectString, connectStringLength, commonParams,
createParams, error);
}
static int dpiConn__createStandalone(dpiConn *conn, const char *userName,
uint32_t userNameLength, const char *password, uint32_t passwordLength,
const char *connectString, uint32_t connectStringLength,
const dpiCommonCreateParams *commonParams,
const dpiConnCreateParams *createParams, dpiError *error)
{
uint32_t credentialType, authMode;
conn->standalone = 1;
if (dpiOci__handleAlloc(conn->env->handle, &conn->serverHandle,
DPI_OCI_HTYPE_SERVER, "allocate server handle", error) < 0)
return DPI_FAILURE;
if (dpiOci__serverAttach(conn, connectString, connectStringLength,
error) < 0)
return DPI_FAILURE;
if (dpiOci__handleAlloc(conn->env->handle, &conn->handle,
DPI_OCI_HTYPE_SVCCTX, "allocate service context handle",
error) < 0)
return DPI_FAILURE;
if (dpiOci__attrSet(conn->handle, DPI_OCI_HTYPE_SVCCTX, conn->serverHandle,
0, DPI_OCI_ATTR_SERVER, "set server handle", error) < 0)
return DPI_FAILURE;
if (dpiOci__handleAlloc(conn->env->handle, &conn->sessionHandle,
DPI_OCI_HTYPE_SESSION, "allocate session handle", error) < 0)
return DPI_FAILURE;
if (dpiUtils__setAttributesFromCommonCreateParams(conn->sessionHandle,
DPI_OCI_HTYPE_SESSION, commonParams, error) < 0)
return DPI_FAILURE;
if (dpiConn__setAttributesFromCreateParams(conn, conn->sessionHandle,
DPI_OCI_HTYPE_SESSION, userName, userNameLength, password,
passwordLength, createParams, error) < 0)
return DPI_FAILURE;
if (dpiOci__attrSet(conn->handle, DPI_OCI_HTYPE_SVCCTX,
conn->sessionHandle, 0, DPI_OCI_ATTR_SESSION, "set session handle",
error) < 0)
return DPI_FAILURE;
if (createParams->newPassword && createParams->newPasswordLength > 0) {
authMode = DPI_OCI_AUTH;
if (createParams->authMode & DPI_MODE_AUTH_SYSDBA)
authMode |= DPI_OCI_CPW_SYSDBA;
if (createParams->authMode & DPI_MODE_AUTH_SYSOPER)
authMode |= DPI_OCI_CPW_SYSOPER;
if (createParams->authMode & DPI_MODE_AUTH_SYSASM)
authMode |= DPI_OCI_CPW_SYSASM;
if (createParams->authMode & DPI_MODE_AUTH_SYSBKP)
authMode |= DPI_OCI_CPW_SYSBKP;
if (createParams->authMode & DPI_MODE_AUTH_SYSDGD)
authMode |= DPI_OCI_CPW_SYSDGD;
if (createParams->authMode & DPI_MODE_AUTH_SYSKMT)
authMode |= DPI_OCI_CPW_SYSKMT;
return dpiOci__passwordChange(conn, userName, userNameLength, password,
passwordLength, createParams->newPassword,
createParams->newPasswordLength, authMode, error);
}
credentialType = (createParams->externalAuth) ? DPI_OCI_CRED_EXT :
DPI_OCI_CRED_RDBMS;
authMode = createParams->authMode | DPI_OCI_STMT_CACHE;
if (dpiOci__sessionBegin(conn, credentialType, authMode, error) < 0)
return DPI_FAILURE;
return dpiConn__getServerCharset(conn, error);
}
void dpiConn__free(dpiConn *conn, dpiError *error)
{
if (conn->handle)
dpiConn__close(conn, DPI_MODE_CONN_CLOSE_DEFAULT, NULL, 0, 0,
error);
if (conn->pool) {
dpiGen__setRefCount(conn->pool, error, -1);
conn->pool = NULL;
conn->env = NULL;
}
if (conn->env) {
dpiEnv__free(conn->env, error);
conn->env = NULL;
}
if (conn->releaseString) {
dpiUtils__freeMemory((void*) conn->releaseString);
conn->releaseString = NULL;
}
if (conn->openStmts) {
dpiHandleList__free(conn->openStmts);
conn->openStmts = NULL;
}
if (conn->openLobs) {
dpiHandleList__free(conn->openLobs);
conn->openLobs = NULL;
}
if (conn->objects) {
dpiHandleList__free(conn->objects);
conn->objects = NULL;
}
dpiUtils__freeMemory(conn);
}
static int dpiConn__get(dpiConn *conn, const char *userName,
uint32_t userNameLength, const char *password, uint32_t passwordLength,
const char *connectString, uint32_t connectStringLength,
dpiConnCreateParams *createParams, dpiPool *pool, dpiError *error)
{
int externalAuth, status;
void *authInfo;
uint32_t mode;
if (pool) {
dpiGen__setRefCount(pool, error, 1);
conn->pool = pool;
mode = DPI_OCI_SESSGET_SPOOL;
externalAuth = pool->externalAuth;
if (userName && pool->homogeneous)
return dpiError__set(error, "check proxy", DPI_ERR_INVALID_PROXY);
if (userName && !password && !externalAuth)
mode |= DPI_OCI_SESSGET_CREDPROXY;
if (createParams->matchAnyTag)
mode |= DPI_OCI_SESSGET_SPOOL_MATCHANY;
if (dpiUtils__checkClientVersion(conn->env->versionInfo, 12, 2,
NULL) == DPI_SUCCESS && createParams->tag &&
createParams->tagLength > 0)
mode |= DPI_OCI_SESSGET_MULTIPROPERTY_TAG;
} else {
mode = DPI_OCI_SESSGET_STMTCACHE;
externalAuth = createParams->externalAuth;
}
if (createParams->authMode & DPI_MODE_AUTH_SYSDBA)
mode |= DPI_OCI_SESSGET_SYSDBA;
if (externalAuth)
mode |= DPI_OCI_SESSGET_CREDEXT;
if (dpiOci__handleAlloc(conn->env->handle, &authInfo,
DPI_OCI_HTYPE_AUTHINFO, "allocate authinfo handle", error) < 0)
return DPI_FAILURE;
if (dpiConn__setAttributesFromCreateParams(conn, authInfo,
DPI_OCI_HTYPE_AUTHINFO, userName, userNameLength, password,
passwordLength, createParams, error) < 0) {
dpiOci__handleFree(authInfo, DPI_OCI_HTYPE_AUTHINFO);
return DPI_FAILURE;
}
status = dpiConn__getSession(conn, mode, connectString,
connectStringLength, createParams, authInfo, error);
dpiOci__handleFree(authInfo, DPI_OCI_HTYPE_AUTHINFO);
if (status < 0)
return status;
return dpiConn__getServerCharset(conn, error);
}
static int dpiConn__getAttributeText(dpiConn *conn, uint32_t attribute,
const char **value, uint32_t *valueLength, const char *fnName)
{
dpiError error;
int status;
if (dpiConn__check(conn, fnName, &error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
DPI_CHECK_PTR_NOT_NULL(conn, value)
DPI_CHECK_PTR_NOT_NULL(conn, valueLength)
switch (attribute) {
case DPI_OCI_ATTR_CURRENT_SCHEMA:
case DPI_OCI_ATTR_LTXID:
case DPI_OCI_ATTR_EDITION:
status = dpiOci__attrGet(conn->sessionHandle,
DPI_OCI_HTYPE_SESSION, (void*) value, valueLength,
attribute, "get session value", &error);
break;
case DPI_OCI_ATTR_INTERNAL_NAME:
case DPI_OCI_ATTR_EXTERNAL_NAME:
status = dpiOci__attrGet(conn->serverHandle, DPI_OCI_HTYPE_SERVER,
(void*) value, valueLength, attribute, "get server value",
&error);
break;
default:
status = dpiError__set(&error, "get attribute text",
DPI_ERR_NOT_SUPPORTED);
break;
}
return dpiGen__endPublicFn(conn, status, &error);
}
static int dpiConn__getHandles(dpiConn *conn, dpiError *error)
{
if (dpiOci__attrGet(conn->handle, DPI_OCI_HTYPE_SVCCTX,
(void*) &conn->sessionHandle, NULL, DPI_OCI_ATTR_SESSION,
"get session handle", error) < 0)
return DPI_FAILURE;
if (dpiOci__attrGet(conn->handle, DPI_OCI_HTYPE_SVCCTX,
(void*) &conn->serverHandle, NULL, DPI_OCI_ATTR_SERVER,
"get server handle", error) < 0)
return DPI_FAILURE;
return DPI_SUCCESS;
}
int dpiConn__getRawTDO(dpiConn *conn, dpiError *error)
{
if (conn->rawTDO)
return DPI_SUCCESS;
return dpiOci__typeByName(conn, "SYS", 3, "RAW", 3, &conn->rawTDO, error);
}
static int dpiConn__getServerCharset(dpiConn *conn, dpiError *error)
{
return dpiOci__attrGet(conn->serverHandle, DPI_OCI_HTYPE_SERVER,
&conn->charsetId, NULL, DPI_OCI_ATTR_CHARSET_ID,
"get server charset id", error);
}
int dpiConn__getServerVersion(dpiConn *conn, dpiError *error)
{
uint32_t serverRelease;
char buffer[512];
if (conn->releaseString)
return DPI_SUCCESS;
if (dpiOci__serverRelease(conn, buffer, sizeof(buffer), &serverRelease,
error) < 0)
return DPI_FAILURE;
conn->releaseStringLength = (uint32_t) strlen(buffer);
if (dpiUtils__allocateMemory(1, conn->releaseStringLength, 0,
"allocate release string", (void**) &conn->releaseString,
error) < 0)
return DPI_FAILURE;
strncpy( (char*) conn->releaseString, buffer, conn->releaseStringLength);
conn->versionInfo.versionNum = (int)((serverRelease >> 24) & 0xFF);
if (conn->versionInfo.versionNum >= 18) {
conn->versionInfo.releaseNum = (int)((serverRelease >> 16) & 0xFF);
conn->versionInfo.updateNum = (int)((serverRelease >> 12) & 0x0F);
conn->versionInfo.portReleaseNum = (int)((serverRelease >> 4) & 0xFF);
conn->versionInfo.portUpdateNum = (int)((serverRelease) & 0xF);
} else {
conn->versionInfo.releaseNum = (int)((serverRelease >> 20) & 0x0F);
conn->versionInfo.updateNum = (int)((serverRelease >> 12) & 0xFF);
conn->versionInfo.portReleaseNum = (int)((serverRelease >> 8) & 0x0F);
conn->versionInfo.portUpdateNum = (int)((serverRelease) & 0xFF);
}
conn->versionInfo.fullVersionNum = (uint32_t)
DPI_ORACLE_VERSION_TO_NUMBER(conn->versionInfo.versionNum,
conn->versionInfo.releaseNum,
conn->versionInfo.updateNum,
conn->versionInfo.portReleaseNum,
conn->versionInfo.portUpdateNum);
return DPI_SUCCESS;
}
static int dpiConn__getSession(dpiConn *conn, uint32_t mode,
const char *connectString, uint32_t connectStringLength,
dpiConnCreateParams *params, void *authInfo, dpiError *error)
{
uint8_t savedBreakOnTimeout, breakOnTimeout;
uint32_t savedTimeout;
time_t *lastTimeUsed;
while (1) {
params->outNewSession = 0;
if (dpiOci__sessionGet(conn->env->handle, &conn->handle, authInfo,
connectString, connectStringLength, params->tag,
params->tagLength, ¶ms->outTag, ¶ms->outTagLength,
¶ms->outTagFound, mode, error) < 0)
return DPI_FAILURE;
if (dpiConn__getHandles(conn, error) < 0)
return DPI_FAILURE;
lastTimeUsed = NULL;
if (dpiOci__contextGetValue(conn, DPI_CONTEXT_LAST_TIME_USED,
(uint32_t) (sizeof(DPI_CONTEXT_LAST_TIME_USED) - 1),
(void**) &lastTimeUsed, 1, error) < 0)
return DPI_FAILURE;
if (!lastTimeUsed || !conn->pool) {
params->outNewSession = 1;
break;
}
if (conn->pool->pingInterval < 0 ||
*lastTimeUsed + conn->pool->pingInterval > time(NULL))
break;
dpiOci__attrGet(conn->serverHandle,
DPI_OCI_HTYPE_SERVER, &savedTimeout, NULL,
DPI_OCI_ATTR_RECEIVE_TIMEOUT, NULL, error);
dpiOci__attrSet(conn->serverHandle, DPI_OCI_HTYPE_SERVER,
&conn->pool->pingTimeout, 0, DPI_OCI_ATTR_RECEIVE_TIMEOUT,
NULL, error);
if (conn->env->versionInfo->versionNum >= 12) {
dpiOci__attrGet(conn->serverHandle,
DPI_OCI_HTYPE_SERVER, &savedBreakOnTimeout, NULL,
DPI_OCI_ATTR_BREAK_ON_NET_TIMEOUT, NULL, error);
breakOnTimeout = 0;
dpiOci__attrSet(conn->serverHandle, DPI_OCI_HTYPE_SERVER,
&breakOnTimeout, 0, DPI_OCI_ATTR_BREAK_ON_NET_TIMEOUT,
NULL, error);
}
if (dpiOci__ping(conn, error) == 0) {
dpiOci__attrSet(conn->serverHandle, DPI_OCI_HTYPE_SERVER,
&savedTimeout, 0, DPI_OCI_ATTR_RECEIVE_TIMEOUT, NULL,
error);
if (conn->env->versionInfo->versionNum >= 12)
dpiOci__attrSet(conn->serverHandle, DPI_OCI_HTYPE_SERVER,
&savedBreakOnTimeout, 0,
DPI_OCI_ATTR_BREAK_ON_NET_TIMEOUT, NULL, error);
break;
}
dpiOci__sessionRelease(conn, NULL, 0, DPI_OCI_SESSRLS_DROPSESS, 0,
error);
conn->handle = NULL;
conn->serverHandle = NULL;
conn->sessionHandle = NULL;
conn->deadSession = 0;
}
return DPI_SUCCESS;
}
static int dpiConn__setAppContext(void *handle, uint32_t handleType,
const dpiConnCreateParams *params, dpiError *error)
{
void *listHandle, *entryHandle;
dpiAppContext *entry;
uint32_t i;
if (dpiOci__attrSet(handle, handleType, (void*) ¶ms->numAppContext,
sizeof(params->numAppContext), DPI_OCI_ATTR_APPCTX_SIZE,
"set app context size", error) < 0)
return DPI_FAILURE;
if (dpiOci__attrGet(handle, handleType, &listHandle, NULL,
DPI_OCI_ATTR_APPCTX_LIST, "get context list handle", error) < 0)
return DPI_FAILURE;
for (i = 0; i < params->numAppContext; i++) {
entry = ¶ms->appContext[i];
if (dpiOci__paramGet(listHandle, DPI_OCI_DTYPE_PARAM,
&entryHandle, i + 1, "get context entry handle", error) < 0)
return DPI_FAILURE;
if (dpiOci__attrSet(entryHandle, DPI_OCI_DTYPE_PARAM,
(void*) entry->namespaceName, entry->namespaceNameLength,
DPI_OCI_ATTR_APPCTX_NAME, "set namespace name", error) < 0)
return DPI_FAILURE;
if (dpiOci__attrSet(entryHandle, DPI_OCI_DTYPE_PARAM,
(void*) entry->name, entry->nameLength,
DPI_OCI_ATTR_APPCTX_ATTR, "set name", error) < 0)
return DPI_FAILURE;
if (dpiOci__attrSet(entryHandle, DPI_OCI_DTYPE_PARAM,
(void*) entry->value, entry->valueLength,
DPI_OCI_ATTR_APPCTX_VALUE, "set value", error) < 0)
return DPI_FAILURE;
}
return DPI_SUCCESS;
}
static int dpiConn__setAttributesFromCreateParams(dpiConn *conn, void *handle,
uint32_t handleType, const char *userName, uint32_t userNameLength,
const char *password, uint32_t passwordLength,
const dpiConnCreateParams *params, dpiError *error)
{
uint32_t purity;
if (userName && userNameLength > 0 && dpiOci__attrSet(handle,
handleType, (void*) userName, userNameLength,
DPI_OCI_ATTR_USERNAME, "set user name", error) < 0)
return DPI_FAILURE;
if (password && passwordLength > 0 && dpiOci__attrSet(handle,
handleType, (void*) password, passwordLength,
DPI_OCI_ATTR_PASSWORD, "set password", error) < 0)
return DPI_FAILURE;
if (params->connectionClass && params->connectionClassLength > 0 &&
dpiOci__attrSet(handle, handleType,
(void*) params->connectionClass,
params->connectionClassLength,
DPI_OCI_ATTR_CONNECTION_CLASS, "set connection class",
error) < 0)
return DPI_FAILURE;
if (params->purity != DPI_OCI_ATTR_PURITY_DEFAULT) {
purity = params->purity;
if (dpiOci__attrSet(handle, handleType, &purity,
sizeof(purity), DPI_OCI_ATTR_PURITY, "set purity", error) < 0)
return DPI_FAILURE;
}
if (params->shardingKeyColumns && params->numShardingKeyColumns > 0) {
if (dpiConn__setShardingKey(conn, &conn->shardingKey, handle,
handleType, DPI_OCI_ATTR_SHARDING_KEY, "set sharding key",
params->shardingKeyColumns, params->numShardingKeyColumns,
error) < 0)
return DPI_FAILURE;
}
if (params->superShardingKeyColumns &&
params->numSuperShardingKeyColumns > 0) {
if (dpiConn__setShardingKey(conn, &conn->superShardingKey, handle,
handleType, DPI_OCI_ATTR_SUPER_SHARDING_KEY,
"set super sharding key", params->superShardingKeyColumns,
params->numSuperShardingKeyColumns, error) < 0)
return DPI_FAILURE;
}
if (handleType == DPI_OCI_HTYPE_SESSION && params->numAppContext > 0)
return dpiConn__setAppContext(handle, handleType, params, error);
return DPI_SUCCESS;
}
static int dpiConn__setAttributeText(dpiConn *conn, uint32_t attribute,
const char *value, uint32_t valueLength, const char *fnName)
{
dpiError error;
int status;
if (dpiConn__check(conn, fnName, &error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
DPI_CHECK_PTR_AND_LENGTH(conn, value)
switch (attribute) {
case DPI_OCI_ATTR_ACTION:
case DPI_OCI_ATTR_CLIENT_IDENTIFIER:
case DPI_OCI_ATTR_CLIENT_INFO:
case DPI_OCI_ATTR_CURRENT_SCHEMA:
case DPI_OCI_ATTR_EDITION:
case DPI_OCI_ATTR_MODULE:
case DPI_OCI_ATTR_DBOP:
status = dpiOci__attrSet(conn->sessionHandle,
DPI_OCI_HTYPE_SESSION, (void*) value, valueLength,
attribute, "set session value", &error);
break;
case DPI_OCI_ATTR_INTERNAL_NAME:
case DPI_OCI_ATTR_EXTERNAL_NAME:
status = dpiOci__attrSet(conn->serverHandle, DPI_OCI_HTYPE_SERVER,
(void*) value, valueLength, attribute, "set server value",
&error);
break;
default:
status = dpiError__set(&error, "set attribute text",
DPI_ERR_NOT_SUPPORTED);
break;
}
return dpiGen__endPublicFn(conn, status, &error);
}
static int dpiConn__setShardingKey(dpiConn *conn, void **shardingKey,
void *handle, uint32_t handleType, uint32_t attribute,
const char *action, dpiShardingKeyColumn *columns, uint8_t numColumns,
dpiError *error)
{
uint8_t i;
if (dpiUtils__checkClientVersion(conn->env->versionInfo, 12, 2,
error) < 0)
return DPI_FAILURE;
if (dpiOci__descriptorAlloc(conn->env->handle, shardingKey,
DPI_OCI_DTYPE_SHARDING_KEY, "allocate sharding key", error) < 0)
return DPI_FAILURE;
for (i = 0; i < numColumns; i++) {
if (dpiConn__setShardingKeyValue(conn, *shardingKey, &columns[i],
error) < 0)
return DPI_FAILURE;
}
if (dpiOci__attrSet(handle, handleType, *shardingKey, 0, attribute, action,
error) < 0)
return DPI_FAILURE;
return DPI_SUCCESS;
}
static int dpiConn__setShardingKeyValue(dpiConn *conn, void *shardingKey,
dpiShardingKeyColumn *column, dpiError *error)
{
const dpiOracleType *oracleType;
dpiOciNumber numberValue;
dpiOciDate dateValue;
uint32_t colLen = 0;
void *col = NULL;
uint16_t colType;
int convertOk;
oracleType = dpiOracleType__getFromNum(column->oracleTypeNum, error);
if (!oracleType)
return DPI_FAILURE;
convertOk = 0;
colType = oracleType->oracleType;
switch (column->oracleTypeNum) {
case DPI_ORACLE_TYPE_VARCHAR:
case DPI_ORACLE_TYPE_CHAR:
case DPI_ORACLE_TYPE_RAW:
if (column->nativeTypeNum == DPI_NATIVE_TYPE_BYTES) {
col = column->value.asBytes.ptr;
colLen = column->value.asBytes.length;
convertOk = 1;
}
break;
case DPI_ORACLE_TYPE_NUMBER:
col = &numberValue;
colLen = sizeof(numberValue);
if (column->nativeTypeNum == DPI_NATIVE_TYPE_DOUBLE) {
if (dpiDataBuffer__toOracleNumberFromDouble(&column->value,
error, &numberValue) < 0)
return DPI_FAILURE;
convertOk = 1;
} else if (column->nativeTypeNum == DPI_NATIVE_TYPE_INT64) {
if (dpiDataBuffer__toOracleNumberFromInteger(&column->value,
error, &numberValue) < 0)
return DPI_FAILURE;
convertOk = 1;
} else if (column->nativeTypeNum == DPI_NATIVE_TYPE_UINT64) {
if (dpiDataBuffer__toOracleNumberFromUnsignedInteger(
&column->value, error, &numberValue) < 0)
return DPI_FAILURE;
convertOk = 1;
} else if (column->nativeTypeNum == DPI_NATIVE_TYPE_BYTES) {
if (dpiDataBuffer__toOracleNumberFromText(&column->value,
conn->env, error, &numberValue) < 0)
return DPI_FAILURE;
convertOk = 1;
}
break;
case DPI_ORACLE_TYPE_DATE:
col = &dateValue;
colLen = sizeof(dateValue);
colType = DPI_SQLT_DAT;
if (column->nativeTypeNum == DPI_NATIVE_TYPE_TIMESTAMP) {
if (dpiDataBuffer__toOracleDate(&column->value,
&dateValue) < 0)
return DPI_FAILURE;
convertOk = 1;
}
break;
default:
break;
}
if (!convertOk)
return dpiError__set(error, "check type", DPI_ERR_NOT_SUPPORTED);
return dpiOci__shardingKeyColumnAdd(shardingKey, col, colLen, colType,
error);
}
int dpiConn_addRef(dpiConn *conn)
{
return dpiGen__addRef(conn, DPI_HTYPE_CONN, __func__);
}
int dpiConn_beginDistribTrans(dpiConn *conn, long formatId,
const char *transactionId, uint32_t transactionIdLength,
const char *branchId, uint32_t branchIdLength)
{
void *transactionHandle;
dpiError error;
dpiOciXID xid;
int status;
if (dpiConn__check(conn, __func__, &error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
DPI_CHECK_PTR_AND_LENGTH(conn, transactionId)
DPI_CHECK_PTR_AND_LENGTH(conn, branchId)
if (transactionIdLength > DPI_XA_MAXGTRIDSIZE) {
dpiError__set(&error, "check size of transaction id",
DPI_ERR_TRANS_ID_TOO_LARGE, transactionIdLength,
DPI_XA_MAXGTRIDSIZE);
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
}
if (branchIdLength > DPI_XA_MAXBQUALSIZE) {
dpiError__set(&error, "check size of branch id",
DPI_ERR_BRANCH_ID_TOO_LARGE, branchIdLength,
DPI_XA_MAXBQUALSIZE);
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
}
if (dpiOci__attrGet(conn->handle, DPI_OCI_HTYPE_SVCCTX,
(void*) &transactionHandle, NULL, DPI_OCI_ATTR_TRANS,
"get transaction handle", &error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
if (!transactionHandle) {
if (dpiOci__handleAlloc(conn->env->handle, &transactionHandle,
DPI_OCI_HTYPE_TRANS, "create transaction handle", &error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
if (dpiOci__attrSet(conn->handle, DPI_OCI_HTYPE_SVCCTX,
transactionHandle, 0, DPI_OCI_ATTR_TRANS,
"associate transaction", &error) < 0) {
dpiOci__handleFree(transactionHandle, DPI_OCI_HTYPE_TRANS);
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
}
}
if (formatId != -1) {
xid.formatID = formatId;
xid.gtrid_length = transactionIdLength;
xid.bqual_length = branchIdLength;
if (transactionIdLength > 0)
strncpy(xid.data, transactionId, transactionIdLength);
if (branchIdLength > 0)
strncpy(&xid.data[transactionIdLength], branchId, branchIdLength);
if (dpiOci__attrSet(transactionHandle, DPI_OCI_HTYPE_TRANS, &xid,
sizeof(dpiOciXID), DPI_OCI_ATTR_XID, "set XID", &error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
}
status = dpiOci__transStart(conn, &error);
return dpiGen__endPublicFn(conn, status, &error);
}
int dpiConn_breakExecution(dpiConn *conn)
{
dpiError error;
int status;
if (dpiConn__check(conn, __func__, &error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
status = dpiOci__break(conn, &error);
return dpiGen__endPublicFn(conn, status, &error);
}
int dpiConn_changePassword(dpiConn *conn, const char *userName,
uint32_t userNameLength, const char *oldPassword,
uint32_t oldPasswordLength, const char *newPassword,
uint32_t newPasswordLength)
{
dpiError error;
int status;
if (dpiConn__check(conn, __func__, &error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
DPI_CHECK_PTR_AND_LENGTH(conn, userName)
DPI_CHECK_PTR_AND_LENGTH(conn, oldPassword)
DPI_CHECK_PTR_AND_LENGTH(conn, newPassword)
status = dpiOci__passwordChange(conn, userName, userNameLength,
oldPassword, oldPasswordLength, newPassword, newPasswordLength,
DPI_OCI_DEFAULT, &error);
return dpiGen__endPublicFn(conn, status, &error);
}
int dpiConn_close(dpiConn *conn, dpiConnCloseMode mode, const char *tag,
uint32_t tagLength)
{
int propagateErrors = !(mode & DPI_MODE_CONN_CLOSE_DROP);
dpiError error;
int closing;
if (dpiConn__check(conn, __func__, &error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
DPI_CHECK_PTR_AND_LENGTH(conn, tag)
if (mode && !conn->pool) {
dpiError__set(&error, "check in pool", DPI_ERR_CONN_NOT_IN_POOL);
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
}
if (conn->externalHandle) {
dpiError__set(&error, "check external", DPI_ERR_CONN_IS_EXTERNAL);
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
}
if (conn->env->threaded)
dpiMutex__acquire(conn->env->mutex);
closing = conn->closing;
conn->closing = 1;
if (conn->env->threaded)
dpiMutex__release(conn->env->mutex);
if (closing) {
dpiError__set(&error, "check closing", DPI_ERR_NOT_CONNECTED);
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
}
if (dpiConn__close(conn, mode, tag, tagLength, propagateErrors,
&error) < 0) {
if (conn->env->threaded)
dpiMutex__acquire(conn->env->mutex);
conn->closing = 0;
if (conn->env->threaded)
dpiMutex__release(conn->env->mutex);
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
}
return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error);
}
int dpiConn_commit(dpiConn *conn)
{
dpiError error;
if (dpiConn__check(conn, __func__, &error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
if (dpiOci__transCommit(conn, conn->commitMode, &error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
conn->commitMode = DPI_OCI_DEFAULT;
return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error);
}
int dpiConn_create(const dpiContext *context, const char *userName,
uint32_t userNameLength, const char *password, uint32_t passwordLength,
const char *connectString, uint32_t connectStringLength,
const dpiCommonCreateParams *commonParams,
dpiConnCreateParams *createParams, dpiConn **conn)
{
dpiCommonCreateParams localCommonParams;
dpiConnCreateParams localCreateParams;
dpiConn *tempConn;
dpiError error;
int status;
if (dpiGen__startPublicFn(context, DPI_HTYPE_CONTEXT, __func__,
&error) < 0)
return dpiGen__endPublicFn(context, DPI_FAILURE, &error);
DPI_CHECK_PTR_NOT_NULL(context, conn)
DPI_CHECK_PTR_AND_LENGTH(context, userName)
DPI_CHECK_PTR_AND_LENGTH(context, password)
DPI_CHECK_PTR_AND_LENGTH(context, connectString)
if (!commonParams) {
dpiContext__initCommonCreateParams(&localCommonParams);
commonParams = &localCommonParams;
}
if (!createParams || context->dpiMinorVersion < 1) {
dpiContext__initConnCreateParams(&localCreateParams);
if (createParams)
memcpy(&localCreateParams, createParams,
sizeof(dpiConnCreateParams__v30));
createParams = &localCreateParams;
}
if (createParams->externalAuth && password && passwordLength > 0) {
dpiError__set(&error, "verify no password with external auth",
DPI_ERR_EXT_AUTH_WITH_CREDENTIALS);
return dpiGen__endPublicFn(context, DPI_FAILURE, &error);
}
if (createParams->externalAuth && userName && userNameLength > 0 &&
(userName[0] != '[' || userName[userNameLength - 1] != ']')) {
dpiError__set(&error, "verify proxy user name with external auth",
DPI_ERR_EXT_AUTH_INVALID_PROXY);
return dpiGen__endPublicFn(context, DPI_FAILURE, &error );
}
if (createParams->connectionClass &&
createParams->connectionClassLength > 0 &&
commonParams->edition && commonParams->editionLength > 0) {
dpiError__set(&error, "check edition/conn class",
DPI_ERR_NO_EDITION_WITH_CONN_CLASS);
return dpiGen__endPublicFn(context, DPI_FAILURE, &error);
}
if (createParams->newPassword && createParams->newPasswordLength > 0 &&
commonParams->edition && commonParams->editionLength > 0) {
dpiError__set(&error, "check edition/new password",
DPI_ERR_NO_EDITION_WITH_NEW_PASSWORD);
return dpiGen__endPublicFn(context, DPI_FAILURE, &error);
}
if (createParams->pool) {
if (dpiGen__checkHandle(createParams->pool, DPI_HTYPE_POOL,
"verify pool", &error) < 0)
return dpiGen__endPublicFn(context, DPI_FAILURE, &error);
if (!createParams->pool->handle) {
dpiError__set(&error, "check pool", DPI_ERR_NOT_CONNECTED);
return dpiGen__endPublicFn(context, DPI_FAILURE, &error);
}
status = dpiPool__acquireConnection(createParams->pool, userName,
userNameLength, password, passwordLength, createParams, conn,
&error);
return dpiGen__endPublicFn(context, status, &error);
}
if (dpiGen__allocate(DPI_HTYPE_CONN, NULL, (void**) &tempConn, &error) < 0)
return dpiGen__endPublicFn(context, DPI_FAILURE, &error);
if (dpiConn__create(tempConn, context, userName, userNameLength,
password, passwordLength, connectString, connectStringLength,
NULL, commonParams, createParams, &error) < 0) {
dpiConn__free(tempConn, &error);
return dpiGen__endPublicFn(context, DPI_FAILURE, &error);
}
*conn = tempConn;
dpiHandlePool__release(tempConn->env->errorHandles, &error.handle);
return dpiGen__endPublicFn(context, DPI_SUCCESS, &error);
}
int dpiConn_getSodaDb(dpiConn *conn, dpiSodaDb **db)
{
dpiError error;
if (dpiConn__check(conn, __func__, &error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
if (dpiUtils__checkClientVersion(conn->env->versionInfo, 18, 3,
&error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
if (dpiUtils__checkDatabaseVersion(conn, 18, 0, &error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
if (dpiGen__allocate(DPI_HTYPE_SODA_DB, conn->env, (void**) db,
&error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
dpiGen__setRefCount(conn, &error, 1);
(*db)->conn = conn;
return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error);
}
int dpiConn_deqObject(dpiConn *conn, const char *queueName,
uint32_t queueNameLength, dpiDeqOptions *options, dpiMsgProps *props,
dpiObject *payload, const char **msgId, uint32_t *msgIdLength)
{
dpiError error;
if (dpiConn__check(conn, __func__, &error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
if (dpiGen__checkHandle(options, DPI_HTYPE_DEQ_OPTIONS, "verify options",
&error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
if (dpiGen__checkHandle(props, DPI_HTYPE_MSG_PROPS,
"verify message properties", &error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
if (dpiGen__checkHandle(payload, DPI_HTYPE_OBJECT, "verify payload",
&error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
DPI_CHECK_PTR_AND_LENGTH(conn, queueName)
DPI_CHECK_PTR_NOT_NULL(conn, msgId)
DPI_CHECK_PTR_NOT_NULL(conn, msgIdLength)
if (dpiOci__aqDeq(conn, queueName, options->handle, props->handle,
payload->type->tdo, &payload->instance, &payload->indicator,
&props->msgIdRaw, &error) < 0) {
if (error.buffer->code == 25228) {
*msgId = NULL;
*msgIdLength = 0;
return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error);
}
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
}
dpiMsgProps__extractMsgId(props, msgId, msgIdLength);
return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error);
}
int dpiConn_enqObject(dpiConn *conn, const char *queueName,
uint32_t queueNameLength, dpiEnqOptions *options, dpiMsgProps *props,
dpiObject *payload, const char **msgId, uint32_t *msgIdLength)
{
dpiError error;
if (dpiConn__check(conn, __func__, &error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
if (dpiGen__checkHandle(options, DPI_HTYPE_ENQ_OPTIONS, "verify options",
&error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
if (dpiGen__checkHandle(props, DPI_HTYPE_MSG_PROPS,
"verify message properties", &error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
if (dpiGen__checkHandle(payload, DPI_HTYPE_OBJECT, "verify payload",
&error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
DPI_CHECK_PTR_AND_LENGTH(conn, queueName)
DPI_CHECK_PTR_NOT_NULL(conn, msgId)
DPI_CHECK_PTR_NOT_NULL(conn, msgIdLength)
if (dpiOci__aqEnq(conn, queueName, options->handle, props->handle,
payload->type->tdo, &payload->instance, &payload->indicator,
&props->msgIdRaw, &error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
dpiMsgProps__extractMsgId(props, msgId, msgIdLength);
return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error);
}
int dpiConn_getCallTimeout(dpiConn *conn, uint32_t *value)
{
dpiError error;
int status;
if (dpiConn__check(conn, __func__, &error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
DPI_CHECK_PTR_NOT_NULL(conn, value)
if (dpiUtils__checkClientVersion(conn->env->versionInfo, 18, 1,
&error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
status = dpiOci__attrGet(conn->handle, DPI_OCI_HTYPE_SVCCTX,
(void*) value, 0, DPI_OCI_ATTR_CALL_TIMEOUT, "get call timeout",
&error);
return dpiGen__endPublicFn(conn, status, &error);
}
int dpiConn_getCurrentSchema(dpiConn *conn, const char **value,
uint32_t *valueLength)
{
return dpiConn__getAttributeText(conn, DPI_OCI_ATTR_CURRENT_SCHEMA, value,
valueLength, __func__);
}
int dpiConn_getEdition(dpiConn *conn, const char **value,
uint32_t *valueLength)
{
return dpiConn__getAttributeText(conn, DPI_OCI_ATTR_EDITION, value,
valueLength, __func__);
}
int dpiConn_getEncodingInfo(dpiConn *conn, dpiEncodingInfo *info)
{
dpiError error;
int status;
if (dpiConn__check(conn, __func__, &error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
status = dpiEnv__getEncodingInfo(conn->env, info);
return dpiGen__endPublicFn(conn, status, &error);
}
int dpiConn_getExternalName(dpiConn *conn, const char **value,
uint32_t *valueLength)
{
return dpiConn__getAttributeText(conn, DPI_OCI_ATTR_EXTERNAL_NAME, value,
valueLength, __func__);
}
int dpiConn_getHandle(dpiConn *conn, void **handle)
{
dpiError error;
if (dpiConn__check(conn, __func__, &error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
DPI_CHECK_PTR_NOT_NULL(conn, handle)
*handle = conn->handle;
return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error);
}
int dpiConn_getInternalName(dpiConn *conn, const char **value,
uint32_t *valueLength)
{
return dpiConn__getAttributeText(conn, DPI_OCI_ATTR_INTERNAL_NAME, value,
valueLength, __func__);
}
int dpiConn_getLTXID(dpiConn *conn, const char **value, uint32_t *valueLength)
{
return dpiConn__getAttributeText(conn, DPI_OCI_ATTR_LTXID, value,
valueLength, __func__);
}
int dpiConn_getObjectType(dpiConn *conn, const char *name, uint32_t nameLength,
dpiObjectType **objType)
{
void *describeHandle, *param, *tdo;
int status, useTypeByFullName;
dpiError error;
if (dpiConn__check(conn, __func__, &error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
DPI_CHECK_PTR_NOT_NULL(conn, name)
DPI_CHECK_PTR_NOT_NULL(conn, objType)
if (dpiOci__handleAlloc(conn->env->handle, &describeHandle,
DPI_OCI_HTYPE_DESCRIBE, "allocate describe handle", &error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
useTypeByFullName = 1;
if (conn->env->versionInfo->versionNum < 12)
useTypeByFullName = 0;
else if (dpiConn__getServerVersion(conn, &error) < 0)
return DPI_FAILURE;
else if (conn->versionInfo.versionNum < 12)
useTypeByFullName = 0;
if (useTypeByFullName) {
if (dpiOci__typeByFullName(conn, name, nameLength, &tdo, &error) < 0) {
dpiOci__handleFree(describeHandle, DPI_OCI_HTYPE_DESCRIBE);
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
}
if (dpiOci__describeAny(conn, tdo, 0, DPI_OCI_OTYPE_PTR,
describeHandle, &error) < 0) {
dpiOci__handleFree(describeHandle, DPI_OCI_HTYPE_DESCRIBE);
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
}
} else {
if (dpiOci__describeAny(conn, (void*) name, nameLength,
DPI_OCI_OTYPE_NAME, describeHandle, &error) < 0) {
dpiOci__handleFree(describeHandle, DPI_OCI_HTYPE_DESCRIBE);
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
}
}
if (dpiOci__attrGet(describeHandle,
DPI_OCI_HTYPE_DESCRIBE, ¶m, 0, DPI_OCI_ATTR_PARAM,
"get param", &error) < 0) {
dpiOci__handleFree(describeHandle, DPI_OCI_HTYPE_DESCRIBE);
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
}
status = dpiObjectType__allocate(conn, param, DPI_OCI_ATTR_NAME, objType,
&error);
dpiOci__handleFree(describeHandle, DPI_OCI_HTYPE_DESCRIBE);
return dpiGen__endPublicFn(conn, status, &error);
}
int dpiConn_getServerVersion(dpiConn *conn, const char **releaseString,
uint32_t *releaseStringLength, dpiVersionInfo *versionInfo)
{
dpiError error;
if (dpiConn__check(conn, __func__, &error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
DPI_CHECK_PTR_NOT_NULL(conn, releaseString)
DPI_CHECK_PTR_NOT_NULL(conn, releaseStringLength)
DPI_CHECK_PTR_NOT_NULL(conn, versionInfo)
if (dpiConn__getServerVersion(conn, &error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
*releaseString = conn->releaseString;
*releaseStringLength = conn->releaseStringLength;
memcpy(versionInfo, &conn->versionInfo, sizeof(dpiVersionInfo));
return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error);
}
int dpiConn_getStmtCacheSize(dpiConn *conn, uint32_t *cacheSize)
{
dpiError error;
int status;
if (dpiConn__check(conn, __func__, &error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
DPI_CHECK_PTR_NOT_NULL(conn, cacheSize)
status = dpiOci__attrGet(conn->handle, DPI_OCI_HTYPE_SVCCTX, cacheSize,
NULL, DPI_OCI_ATTR_STMTCACHESIZE, "get stmt cache size", &error);
return dpiGen__endPublicFn(conn, status, &error);
}
int dpiConn_newDeqOptions(dpiConn *conn, dpiDeqOptions **options)
{
dpiDeqOptions *tempOptions;
dpiError error;
if (dpiConn__check(conn, __func__, &error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
DPI_CHECK_PTR_NOT_NULL(conn, options)
if (dpiGen__allocate(DPI_HTYPE_DEQ_OPTIONS, conn->env,
(void**) &tempOptions, &error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
if (dpiDeqOptions__create(tempOptions, conn, &error) < 0) {
dpiDeqOptions__free(tempOptions, &error);
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
}
*options = tempOptions;
return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error);
}
int dpiConn_newEnqOptions(dpiConn *conn, dpiEnqOptions **options)
{
dpiEnqOptions *tempOptions;
dpiError error;
if (dpiConn__check(conn, __func__, &error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
DPI_CHECK_PTR_NOT_NULL(conn, options)
if (dpiGen__allocate(DPI_HTYPE_ENQ_OPTIONS, conn->env,
(void**) &tempOptions, &error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
if (dpiEnqOptions__create(tempOptions, conn, &error) < 0) {
dpiEnqOptions__free(tempOptions, &error);
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
}
*options = tempOptions;
return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error);
}
int dpiConn_newTempLob(dpiConn *conn, dpiOracleTypeNum lobType, dpiLob **lob)
{
const dpiOracleType *type;
dpiLob *tempLob;
dpiError error;
if (dpiConn__check(conn, __func__, &error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
DPI_CHECK_PTR_NOT_NULL(conn, lob)
switch (lobType) {
case DPI_ORACLE_TYPE_CLOB:
case DPI_ORACLE_TYPE_BLOB:
case DPI_ORACLE_TYPE_NCLOB:
type = dpiOracleType__getFromNum(lobType, &error);
break;
default:
dpiError__set(&error, "check lob type",
DPI_ERR_INVALID_ORACLE_TYPE, lobType);
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
}
if (dpiLob__allocate(conn, type, &tempLob, &error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
if (dpiOci__lobCreateTemporary(tempLob, &error) < 0) {
dpiLob__free(tempLob, &error);
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
}
*lob = tempLob;
return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error);
}
int dpiConn_newMsgProps(dpiConn *conn, dpiMsgProps **props)
{
dpiError error;
int status;
if (dpiConn__check(conn, __func__, &error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
DPI_CHECK_PTR_NOT_NULL(conn, props)
status = dpiMsgProps__allocate(conn, props, &error);
return dpiGen__endPublicFn(conn, status, &error);
}
int dpiConn_newQueue(dpiConn *conn, const char *name, uint32_t nameLength,
dpiObjectType *payloadType, dpiQueue **queue)
{
dpiError error;
int status;
if (dpiConn__check(conn, __func__, &error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
DPI_CHECK_PTR_AND_LENGTH(conn, name)
DPI_CHECK_PTR_NOT_NULL(conn, queue)
status = dpiQueue__allocate(conn, name, nameLength, payloadType, queue,
&error);
return dpiGen__endPublicFn(conn, status, &error);
}
int dpiConn_newVar(dpiConn *conn, dpiOracleTypeNum oracleTypeNum,
dpiNativeTypeNum nativeTypeNum, uint32_t maxArraySize, uint32_t size,
int sizeIsBytes, int isArray, dpiObjectType *objType, dpiVar **var,
dpiData **data)
{
dpiError error;
int status;
if (dpiConn__check(conn, __func__, &error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
DPI_CHECK_PTR_NOT_NULL(conn, var)
DPI_CHECK_PTR_NOT_NULL(conn, data)
status = dpiVar__allocate(conn, oracleTypeNum, nativeTypeNum, maxArraySize,
size, sizeIsBytes, isArray, objType, var, data, &error);
return dpiGen__endPublicFn(conn, status, &error);
}
int dpiConn_ping(dpiConn *conn)
{
dpiError error;
int status;
if (dpiConn__check(conn, __func__, &error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
status = dpiOci__ping(conn, &error);
return dpiGen__endPublicFn(conn, status, &error);
}
int dpiConn_prepareDistribTrans(dpiConn *conn, int *commitNeeded)
{
dpiError error;
if (dpiConn__check(conn, __func__, &error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
DPI_CHECK_PTR_NOT_NULL(conn, commitNeeded)
if (dpiOci__transPrepare(conn, commitNeeded, &error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
if (*commitNeeded)
conn->commitMode = DPI_OCI_TRANS_TWOPHASE;
return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error);
}
int dpiConn_prepareStmt(dpiConn *conn, int scrollable, const char *sql,
uint32_t sqlLength, const char *tag, uint32_t tagLength,
dpiStmt **stmt)
{
dpiStmt *tempStmt;
dpiError error;
*stmt = NULL;
if (dpiConn__check(conn, __func__, &error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
DPI_CHECK_PTR_AND_LENGTH(conn, sql)
DPI_CHECK_PTR_AND_LENGTH(conn, tag)
DPI_CHECK_PTR_NOT_NULL(conn, stmt)
if (dpiStmt__allocate(conn, scrollable, &tempStmt, &error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
if (dpiStmt__prepare(tempStmt, sql, sqlLength, tag, tagLength,
&error) < 0) {
dpiStmt__free(tempStmt, &error);
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
}
*stmt = tempStmt;
return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error);
}
int dpiConn_release(dpiConn *conn)
{
return dpiGen__release(conn, DPI_HTYPE_CONN, __func__);
}
int dpiConn_rollback(dpiConn *conn)
{
dpiError error;
int status;
if (dpiConn__check(conn, __func__, &error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
status = dpiOci__transRollback(conn, 1, &error);
return dpiGen__endPublicFn(conn, status, &error);
}
int dpiConn_setAction(dpiConn *conn, const char *value, uint32_t valueLength)
{
return dpiConn__setAttributeText(conn, DPI_OCI_ATTR_ACTION, value,
valueLength, __func__);
}
int dpiConn_setCallTimeout(dpiConn *conn, uint32_t value)
{
dpiError error;
int status;
if (dpiConn__check(conn, __func__, &error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
if (dpiUtils__checkClientVersion(conn->env->versionInfo, 18, 1,
&error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
status = dpiOci__attrSet(conn->handle, DPI_OCI_HTYPE_SVCCTX, &value,
0, DPI_OCI_ATTR_CALL_TIMEOUT, "set call timeout", &error);
return dpiGen__endPublicFn(conn, status, &error);
}
int dpiConn_setClientIdentifier(dpiConn *conn, const char *value,
uint32_t valueLength)
{
return dpiConn__setAttributeText(conn, DPI_OCI_ATTR_CLIENT_IDENTIFIER,
value, valueLength, __func__);
}
int dpiConn_setClientInfo(dpiConn *conn, const char *value,
uint32_t valueLength)
{
return dpiConn__setAttributeText(conn, DPI_OCI_ATTR_CLIENT_INFO, value,
valueLength, __func__);
}
int dpiConn_setCurrentSchema(dpiConn *conn, const char *value,
uint32_t valueLength)
{
return dpiConn__setAttributeText(conn, DPI_OCI_ATTR_CURRENT_SCHEMA, value,
valueLength, __func__);
}
int dpiConn_setDbOp(dpiConn *conn, const char *value, uint32_t valueLength)
{
return dpiConn__setAttributeText(conn, DPI_OCI_ATTR_DBOP, value,
valueLength, __func__);
}
int dpiConn_setExternalName(dpiConn *conn, const char *value,
uint32_t valueLength)
{
return dpiConn__setAttributeText(conn, DPI_OCI_ATTR_EXTERNAL_NAME, value,
valueLength, __func__);
}
int dpiConn_setInternalName(dpiConn *conn, const char *value,
uint32_t valueLength)
{
return dpiConn__setAttributeText(conn, DPI_OCI_ATTR_INTERNAL_NAME, value,
valueLength, __func__);
}
int dpiConn_setModule(dpiConn *conn, const char *value, uint32_t valueLength)
{
return dpiConn__setAttributeText(conn, DPI_OCI_ATTR_MODULE, value,
valueLength, __func__);
}
int dpiConn_setStmtCacheSize(dpiConn *conn, uint32_t cacheSize)
{
dpiError error;
int status;
if (dpiConn__check(conn, __func__, &error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
status = dpiOci__attrSet(conn->handle, DPI_OCI_HTYPE_SVCCTX, &cacheSize, 0,
DPI_OCI_ATTR_STMTCACHESIZE, "set stmt cache size", &error);
return dpiGen__endPublicFn(conn, status, &error);
}
int dpiConn_shutdownDatabase(dpiConn *conn, dpiShutdownMode mode)
{
dpiError error;
int status;
if (dpiConn__check(conn, __func__, &error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
status = dpiOci__dbShutdown(conn, mode, &error);
return dpiGen__endPublicFn(conn, status, &error);
}
int dpiConn_startupDatabase(dpiConn *conn, dpiStartupMode mode)
{
dpiError error;
int status;
if (dpiConn__check(conn, __func__, &error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
status = dpiOci__dbStartup(conn, mode, &error);
return dpiGen__endPublicFn(conn, status, &error);
}
int dpiConn_subscribe(dpiConn *conn, dpiSubscrCreateParams *params,
dpiSubscr **subscr)
{
dpiSubscr *tempSubscr;
dpiError error;
if (dpiConn__check(conn, __func__, &error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
DPI_CHECK_PTR_NOT_NULL(conn, params)
DPI_CHECK_PTR_NOT_NULL(conn, subscr)
if (!conn->env->events) {
dpiError__set(&error, "subscribe", DPI_ERR_EVENTS_MODE_REQUIRED);
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
}
if (dpiGen__allocate(DPI_HTYPE_SUBSCR, conn->env, (void**) &tempSubscr,
&error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
if (dpiSubscr__create(tempSubscr, conn, params, &error) < 0) {
dpiSubscr__free(tempSubscr, &error);
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
}
*subscr = tempSubscr;
return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error);
}
int dpiConn_unsubscribe(dpiConn *conn, dpiSubscr *subscr)
{
dpiError error;
int status;
if (dpiConn__check(conn, __func__, &error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
if (dpiGen__checkHandle(subscr, DPI_HTYPE_SUBSCR, "check subscription",
&error) < 0)
return dpiGen__endPublicFn(conn, DPI_FAILURE, &error);
if (subscr->registered) {
dpiMutex__acquire(subscr->mutex);
status = dpiOci__subscriptionUnRegister(conn, subscr, &error);
if (status == DPI_SUCCESS)
subscr->registered = 0;
dpiMutex__release(subscr->mutex);
if (status < 0)
return dpiGen__endPublicFn(subscr, DPI_FAILURE, &error);
}
dpiGen__setRefCount(subscr, &error, -1);
return dpiGen__endPublicFn(subscr, DPI_SUCCESS, &error);
}