#include "dpiImpl.h"
int dpiLob__allocate(dpiConn *conn, const dpiOracleType *type, dpiLob **lob,
dpiError *error)
{
dpiLob *tempLob;
if (dpiGen__allocate(DPI_HTYPE_LOB, conn->env, (void**) &tempLob,
error) < 0)
return DPI_FAILURE;
dpiGen__setRefCount(conn, error, 1);
tempLob->conn = conn;
tempLob->type = type;
if (dpiOci__descriptorAlloc(conn->env->handle, &tempLob->locator,
DPI_OCI_DTYPE_LOB, "allocate descriptor", error) < 0) {
dpiLob__free(tempLob, error);
return DPI_FAILURE;
}
if (dpiHandleList__addHandle(conn->openLobs, tempLob,
&tempLob->openSlotNum, error) < 0) {
dpiOci__descriptorFree(tempLob->locator, DPI_OCI_DTYPE_LOB);
tempLob->locator = NULL;
dpiLob__free(tempLob, error);
return DPI_FAILURE;
}
*lob = tempLob;
return DPI_SUCCESS;
}
static int dpiLob__check(dpiLob *lob, const char *fnName, dpiError *error)
{
if (dpiGen__startPublicFn(lob, DPI_HTYPE_LOB, fnName, error) < 0)
return DPI_FAILURE;
if (!lob->conn || !lob->conn->handle)
return dpiError__set(error, "conn closed?", DPI_ERR_NOT_CONNECTED);
if (!lob->locator)
return dpiError__set(error, "LOB closed?", DPI_ERR_LOB_CLOSED);
return dpiConn__checkConnected(lob->conn, error);
}
int dpiLob__close(dpiLob *lob, int propagateErrors, dpiError *error)
{
int isTemporary, closing, status = DPI_SUCCESS;
if (lob->env->threaded)
dpiMutex__acquire(lob->env->mutex);
closing = lob->closing;
lob->closing = 1;
if (lob->env->threaded)
dpiMutex__release(lob->env->mutex);
if (closing)
return DPI_SUCCESS;
if (lob->locator) {
if (!lob->conn->deadSession && lob->conn->handle) {
status = dpiOci__lobIsTemporary(lob, &isTemporary, propagateErrors,
error);
if (isTemporary && status == DPI_SUCCESS)
status = dpiOci__lobFreeTemporary(lob->conn,
lob->locator, propagateErrors, error);
}
dpiOci__descriptorFree(lob->locator, DPI_OCI_DTYPE_LOB);
if (!lob->conn->closing)
dpiHandleList__removeHandle(lob->conn->openLobs, lob->openSlotNum);
lob->locator = NULL;
}
if (lob->buffer) {
dpiUtils__freeMemory(lob->buffer);
lob->buffer = NULL;
}
if (status < 0) {
if (lob->env->threaded)
dpiMutex__acquire(lob->env->mutex);
lob->closing = 0;
if (lob->env->threaded)
dpiMutex__release(lob->env->mutex);
}
return status;
}
void dpiLob__free(dpiLob *lob, dpiError *error)
{
dpiLob__close(lob, 0, error);
if (lob->conn) {
dpiGen__setRefCount(lob->conn, error, -1);
lob->conn = NULL;
}
dpiUtils__freeMemory(lob);
}
int dpiLob__readBytes(dpiLob *lob, uint64_t offset, uint64_t amount,
char *value, uint64_t *valueLength, dpiError *error)
{
uint64_t lengthInBytes = 0, lengthInChars = 0;
int isOpen = 0;
if (lob->type->isCharacterData)
lengthInChars = amount;
else lengthInBytes = amount;
if (lob->type->oracleTypeNum == DPI_ORACLE_TYPE_BFILE) {
if (dpiOci__lobIsOpen(lob, &isOpen, error) < 0)
return DPI_FAILURE;
if (!isOpen) {
if (dpiOci__lobOpen(lob, error) < 0)
return DPI_FAILURE;
}
}
if (dpiOci__lobRead2(lob, offset, &lengthInBytes, &lengthInChars,
value, *valueLength, error) < 0)
return DPI_FAILURE;
*valueLength = lengthInBytes;
if (lob->type->oracleTypeNum == DPI_ORACLE_TYPE_BFILE && !isOpen) {
if (dpiOci__lobClose(lob, error) < 0)
return DPI_FAILURE;
}
return DPI_SUCCESS;
}
int dpiLob__setFromBytes(dpiLob *lob, const char *value, uint64_t valueLength,
dpiError *error)
{
if (dpiOci__lobTrim2(lob, 0, error) < 0)
return DPI_FAILURE;
if (valueLength == 0)
return DPI_SUCCESS;
return dpiOci__lobWrite2(lob, 1, value, valueLength, error);
}
int dpiLob_addRef(dpiLob *lob)
{
return dpiGen__addRef(lob, DPI_HTYPE_LOB, __func__);
}
int dpiLob_close(dpiLob *lob)
{
dpiError error;
int status;
if (dpiLob__check(lob, __func__, &error) < 0)
return dpiGen__endPublicFn(lob, DPI_FAILURE, &error);
status = dpiLob__close(lob, 1, &error);
return dpiGen__endPublicFn(lob, status, &error);
}
int dpiLob_closeResource(dpiLob *lob)
{
dpiError error;
int status;
if (dpiLob__check(lob, __func__, &error) < 0)
return dpiGen__endPublicFn(lob, DPI_FAILURE, &error);
status = dpiOci__lobClose(lob, &error);
return dpiGen__endPublicFn(lob, status, &error);
}
int dpiLob_copy(dpiLob *lob, dpiLob **copiedLob)
{
dpiLob *tempLob;
dpiError error;
if (dpiLob__check(lob, __func__, &error) < 0)
return dpiGen__endPublicFn(lob, DPI_FAILURE, &error);
DPI_CHECK_PTR_NOT_NULL(lob, copiedLob)
if (dpiLob__allocate(lob->conn, lob->type, &tempLob, &error) < 0)
return dpiGen__endPublicFn(lob, DPI_FAILURE, &error);
if (dpiOci__lobLocatorAssign(lob, &tempLob->locator, &error) < 0) {
dpiLob__free(tempLob, &error);
return dpiGen__endPublicFn(lob, DPI_FAILURE, &error);
}
*copiedLob = tempLob;
return dpiGen__endPublicFn(lob, DPI_SUCCESS, &error);
}
int dpiLob_getBufferSize(dpiLob *lob, uint64_t sizeInChars,
uint64_t *sizeInBytes)
{
dpiError error;
if (dpiLob__check(lob, __func__, &error) < 0)
return dpiGen__endPublicFn(lob, DPI_FAILURE, &error);
DPI_CHECK_PTR_NOT_NULL(lob, sizeInBytes)
if (lob->type->oracleTypeNum == DPI_ORACLE_TYPE_CLOB)
*sizeInBytes = sizeInChars * lob->env->maxBytesPerCharacter;
else if (lob->type->oracleTypeNum == DPI_ORACLE_TYPE_NCLOB)
*sizeInBytes = sizeInChars * lob->env->nmaxBytesPerCharacter;
else *sizeInBytes = sizeInChars;
return dpiGen__endPublicFn(lob, DPI_SUCCESS, &error);
}
int dpiLob_getChunkSize(dpiLob *lob, uint32_t *size)
{
dpiError error;
int status;
if (dpiLob__check(lob, __func__, &error) < 0)
return dpiGen__endPublicFn(lob, DPI_FAILURE, &error);
DPI_CHECK_PTR_NOT_NULL(lob, size)
status = dpiOci__lobGetChunkSize(lob, size, &error);
return dpiGen__endPublicFn(lob, status, &error);
}
int dpiLob_getDirectoryAndFileName(dpiLob *lob, const char **directoryAlias,
uint32_t *directoryAliasLength, const char **fileName,
uint32_t *fileNameLength)
{
uint16_t ociDirectoryAliasLength, ociFileNameLength;
dpiError error;
if (dpiLob__check(lob, __func__, &error) < 0)
return dpiGen__endPublicFn(lob, DPI_FAILURE, &error);
DPI_CHECK_PTR_NOT_NULL(lob, directoryAlias)
DPI_CHECK_PTR_NOT_NULL(lob, directoryAliasLength)
DPI_CHECK_PTR_NOT_NULL(lob, fileName)
DPI_CHECK_PTR_NOT_NULL(lob, fileNameLength)
ociDirectoryAliasLength = 30;
ociFileNameLength = 255;
if (!lob->buffer) {
if (dpiUtils__allocateMemory(1,
ociDirectoryAliasLength + ociFileNameLength, 0,
"allocate name buffer", (void**) &lob->buffer, &error) < 0)
return dpiGen__endPublicFn(lob, DPI_FAILURE, &error);
}
*directoryAlias = lob->buffer;
*fileName = lob->buffer + ociDirectoryAliasLength;
if (dpiOci__lobFileGetName(lob, (char*) *directoryAlias,
&ociDirectoryAliasLength, (char*) *fileName, &ociFileNameLength,
&error) < 0)
return dpiGen__endPublicFn(lob, DPI_FAILURE, &error);
*directoryAliasLength = ociDirectoryAliasLength;
*fileNameLength = ociFileNameLength;
return dpiGen__endPublicFn(lob, DPI_SUCCESS, &error);
}
int dpiLob_getFileExists(dpiLob *lob, int *exists)
{
dpiError error;
int status;
if (dpiLob__check(lob, __func__, &error) < 0)
return dpiGen__endPublicFn(lob, DPI_FAILURE, &error);
DPI_CHECK_PTR_NOT_NULL(lob, exists)
status = dpiOci__lobFileExists(lob, exists, &error);
return dpiGen__endPublicFn(lob, status, &error);
}
int dpiLob_getIsResourceOpen(dpiLob *lob, int *isOpen)
{
dpiError error;
int status;
if (dpiLob__check(lob, __func__, &error) < 0)
return dpiGen__endPublicFn(lob, DPI_FAILURE, &error);
DPI_CHECK_PTR_NOT_NULL(lob, isOpen)
status = dpiOci__lobIsOpen(lob, isOpen, &error);
return dpiGen__endPublicFn(lob, status, &error);
}
int dpiLob_getSize(dpiLob *lob, uint64_t *size)
{
dpiError error;
int status;
if (dpiLob__check(lob, __func__, &error) < 0)
return dpiGen__endPublicFn(lob, DPI_FAILURE, &error);
DPI_CHECK_PTR_NOT_NULL(lob, size)
status = dpiOci__lobGetLength2(lob, size, &error);
return dpiGen__endPublicFn(lob, status, &error);
}
int dpiLob_getType(dpiLob *lob, dpiOracleTypeNum *type)
{
dpiError error;
if (dpiLob__check(lob, __func__, &error) < 0)
return dpiGen__endPublicFn(lob, DPI_FAILURE, &error);
DPI_CHECK_PTR_NOT_NULL(lob, type)
*type = lob->type->oracleTypeNum;
return dpiGen__endPublicFn(lob, DPI_SUCCESS, &error);
}
int dpiLob_openResource(dpiLob *lob)
{
dpiError error;
int status;
if (dpiLob__check(lob, __func__, &error) < 0)
return dpiGen__endPublicFn(lob, DPI_FAILURE, &error);
status = dpiOci__lobOpen(lob, &error);
return dpiGen__endPublicFn(lob, status, &error);
}
int dpiLob_readBytes(dpiLob *lob, uint64_t offset, uint64_t amount,
char *value, uint64_t *valueLength)
{
dpiError error;
int status;
if (dpiLob__check(lob, __func__, &error) < 0)
return dpiGen__endPublicFn(lob, DPI_FAILURE, &error);
DPI_CHECK_PTR_NOT_NULL(lob, value)
DPI_CHECK_PTR_NOT_NULL(lob, valueLength)
status = dpiLob__readBytes(lob, offset, amount, value, valueLength,
&error);
return dpiGen__endPublicFn(lob, status, &error);
}
int dpiLob_release(dpiLob *lob)
{
return dpiGen__release(lob, DPI_HTYPE_LOB, __func__);
}
int dpiLob_setDirectoryAndFileName(dpiLob *lob, const char *directoryAlias,
uint32_t directoryAliasLength, const char *fileName,
uint32_t fileNameLength)
{
dpiError error;
int status;
if (dpiLob__check(lob, __func__, &error) < 0)
return dpiGen__endPublicFn(lob, DPI_FAILURE, &error);
DPI_CHECK_PTR_NOT_NULL(lob, directoryAlias)
DPI_CHECK_PTR_NOT_NULL(lob, fileName)
status = dpiOci__lobFileSetName(lob, directoryAlias,
(uint16_t) directoryAliasLength, fileName,
(uint16_t) fileNameLength, &error);
return dpiGen__endPublicFn(lob, status, &error);
}
int dpiLob_setFromBytes(dpiLob *lob, const char *value, uint64_t valueLength)
{
dpiError error;
int status;
if (dpiLob__check(lob, __func__, &error) < 0)
return dpiGen__endPublicFn(lob, DPI_FAILURE, &error);
DPI_CHECK_PTR_AND_LENGTH(lob, value)
status = dpiLob__setFromBytes(lob, value, valueLength, &error);
return dpiGen__endPublicFn(lob, status, &error);
}
int dpiLob_trim(dpiLob *lob, uint64_t newSize)
{
dpiError error;
int status;
if (dpiLob__check(lob, __func__, &error) < 0)
return dpiGen__endPublicFn(lob, DPI_FAILURE, &error);
status = dpiOci__lobTrim2(lob, newSize, &error);
return dpiGen__endPublicFn(lob, status, &error);
}
int dpiLob_writeBytes(dpiLob *lob, uint64_t offset, const char *value,
uint64_t valueLength)
{
dpiError error;
int status;
if (dpiLob__check(lob, __func__, &error) < 0)
return dpiGen__endPublicFn(lob, DPI_FAILURE, &error);
DPI_CHECK_PTR_NOT_NULL(lob, value)
status = dpiOci__lobWrite2(lob, offset, value, valueLength, &error);
return dpiGen__endPublicFn(lob, status, &error);
}