python-cx_Oracle/LobVar.c
2016-02-09 14:51:30 -07:00

434 lines
16 KiB
C

//-----------------------------------------------------------------------------
// LobVar.c
// Defines the routines for handling LOB variables.
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// LOB type
//-----------------------------------------------------------------------------
typedef struct {
Variable_HEAD
OCILobLocator **data;
udt_Connection *connection;
int isFile;
} udt_LobVar;
//-----------------------------------------------------------------------------
// Declaration of LOB variable functions.
//-----------------------------------------------------------------------------
static int LobVar_Initialize(udt_LobVar*, udt_Cursor*);
static int LobVar_PreFetch(udt_LobVar*);
static void LobVar_Finalize(udt_LobVar*);
static PyObject *LobVar_GetValue(udt_LobVar*, unsigned);
static int LobVar_SetValue(udt_LobVar*, unsigned, PyObject*);
static int LobVar_Write(udt_LobVar*, unsigned, PyObject*, oraub8, oraub8*);
//-----------------------------------------------------------------------------
// Python type declarations
//-----------------------------------------------------------------------------
static PyTypeObject g_CLOBVarType = {
PyVarObject_HEAD_INIT(NULL, 0)
"cx_Oracle.CLOB", // tp_name
sizeof(udt_LobVar), // tp_basicsize
0, // tp_itemsize
0, // tp_dealloc
0, // tp_print
0, // tp_getattr
0, // tp_setattr
0, // tp_compare
0, // tp_repr
0, // tp_as_number
0, // tp_as_sequence
0, // tp_as_mapping
0, // tp_hash
0, // tp_call
0, // tp_str
0, // tp_getattro
0, // tp_setattro
0, // tp_as_buffer
Py_TPFLAGS_DEFAULT, // tp_flags
0 // tp_doc
};
static PyTypeObject g_NCLOBVarType = {
PyVarObject_HEAD_INIT(NULL, 0)
"cx_Oracle.NCLOB", // tp_name
sizeof(udt_LobVar), // tp_basicsize
0, // tp_itemsize
0, // tp_dealloc
0, // tp_print
0, // tp_getattr
0, // tp_setattr
0, // tp_compare
0, // tp_repr
0, // tp_as_number
0, // tp_as_sequence
0, // tp_as_mapping
0, // tp_hash
0, // tp_call
0, // tp_str
0, // tp_getattro
0, // tp_setattro
0, // tp_as_buffer
Py_TPFLAGS_DEFAULT, // tp_flags
0 // tp_doc
};
static PyTypeObject g_BLOBVarType = {
PyVarObject_HEAD_INIT(NULL, 0)
"cx_Oracle.BLOB", // tp_name
sizeof(udt_LobVar), // tp_basicsize
0, // tp_itemsize
0, // tp_dealloc
0, // tp_print
0, // tp_getattr
0, // tp_setattr
0, // tp_compare
0, // tp_repr
0, // tp_as_number
0, // tp_as_sequence
0, // tp_as_mapping
0, // tp_hash
0, // tp_call
0, // tp_str
0, // tp_getattro
0, // tp_setattro
0, // tp_as_buffer
Py_TPFLAGS_DEFAULT, // tp_flags
0 // tp_doc
};
static PyTypeObject g_BFILEVarType = {
PyVarObject_HEAD_INIT(NULL, 0)
"cx_Oracle.BFILE", // tp_name
sizeof(udt_LobVar), // tp_basicsize
0, // tp_itemsize
0, // tp_dealloc
0, // tp_print
0, // tp_getattr
0, // tp_setattr
0, // tp_compare
0, // tp_repr
0, // tp_as_number
0, // tp_as_sequence
0, // tp_as_mapping
0, // tp_hash
0, // tp_call
0, // tp_str
0, // tp_getattro
0, // tp_setattro
0, // tp_as_buffer
Py_TPFLAGS_DEFAULT, // tp_flags
0 // tp_doc
};
//-----------------------------------------------------------------------------
// variable type declarations
//-----------------------------------------------------------------------------
static udt_VariableType vt_CLOB = {
(InitializeProc) LobVar_Initialize,
(FinalizeProc) LobVar_Finalize,
(PreDefineProc) NULL,
(PostDefineProc) NULL,
(PostBindProc) NULL,
(PreFetchProc) LobVar_PreFetch,
(IsNullProc) NULL,
(SetValueProc) LobVar_SetValue,
(GetValueProc) LobVar_GetValue,
(GetBufferSizeProc) NULL,
&g_CLOBVarType, // Python type
SQLT_CLOB, // Oracle type
SQLCS_IMPLICIT, // charset form
sizeof(OCILobLocator*), // element length
1, // is character data
0, // is variable length
0, // can be copied
0 // can be in array
};
static udt_VariableType vt_NCLOB = {
(InitializeProc) LobVar_Initialize,
(FinalizeProc) LobVar_Finalize,
(PreDefineProc) NULL,
(PostDefineProc) NULL,
(PostBindProc) NULL,
(PreFetchProc) LobVar_PreFetch,
(IsNullProc) NULL,
(SetValueProc) LobVar_SetValue,
(GetValueProc) LobVar_GetValue,
(GetBufferSizeProc) NULL,
&g_NCLOBVarType, // Python type
SQLT_CLOB, // Oracle type
SQLCS_NCHAR, // charset form
sizeof(OCILobLocator*), // element length
1, // is character data
0, // is variable length
0, // can be copied
0 // can be in array
};
static udt_VariableType vt_BLOB = {
(InitializeProc) LobVar_Initialize,
(FinalizeProc) LobVar_Finalize,
(PreDefineProc) NULL,
(PostDefineProc) NULL,
(PostBindProc) NULL,
(PreFetchProc) LobVar_PreFetch,
(IsNullProc) NULL,
(SetValueProc) LobVar_SetValue,
(GetValueProc) LobVar_GetValue,
(GetBufferSizeProc) NULL,
&g_BLOBVarType, // Python type
SQLT_BLOB, // Oracle type
SQLCS_IMPLICIT, // charset form
sizeof(OCILobLocator*), // element length
0, // is character data
0, // is variable length
0, // can be copied
0 // can be in array
};
static udt_VariableType vt_BFILE = {
(InitializeProc) LobVar_Initialize,
(FinalizeProc) LobVar_Finalize,
(PreDefineProc) NULL,
(PostDefineProc) NULL,
(PostBindProc) NULL,
(PreFetchProc) LobVar_PreFetch,
(IsNullProc) NULL,
(SetValueProc) LobVar_SetValue,
(GetValueProc) LobVar_GetValue,
(GetBufferSizeProc) NULL,
&g_BFILEVarType, // Python type
SQLT_BFILE, // Oracle type
SQLCS_IMPLICIT, // charset form
sizeof(OCILobLocator*), // element length
0, // is character data
0, // is variable length
0, // can be copied
0 // can be in array
};
#include "ExternalLobVar.c"
//-----------------------------------------------------------------------------
// LobVar_Initialize()
// Initialize the variable.
//-----------------------------------------------------------------------------
static int LobVar_Initialize(
udt_LobVar *var, // variable to initialize
udt_Cursor *cursor) // cursor created by
{
sword status;
ub4 i;
// initialize members
Py_INCREF(cursor->connection);
var->connection = cursor->connection;
var->isFile = (var->type == &vt_BFILE);
// initialize the LOB locators
for (i = 0; i < var->allocatedElements; i++) {
status = OCIDescriptorAlloc(var->environment->handle,
(dvoid**) &var->data[i], OCI_DTYPE_LOB, 0, 0);
if (Environment_CheckForError(var->environment, status,
"LobVar_Initialize()") < 0)
return -1;
}
return 0;
}
//-----------------------------------------------------------------------------
// LobVar_PreFetch()
// Free temporary LOBs prior to fetch.
//-----------------------------------------------------------------------------
static int LobVar_PreFetch(
udt_LobVar *var) // variable to free
{
boolean isTemporary;
sword status;
ub4 i;
for (i = 0; i < var->allocatedElements; i++) {
if (var->data[i]) {
status = OCILobIsTemporary(var->environment->handle,
var->environment->errorHandle, var->data[i], &isTemporary);
if (Environment_CheckForError(var->environment, status,
"LobVar_PreFetch(): is temporary LOB?") < 0)
return -1;
if (isTemporary) {
Py_BEGIN_ALLOW_THREADS
status = OCILobFreeTemporary(var->connection->handle,
var->environment->errorHandle, var->data[i]);
Py_END_ALLOW_THREADS
if (Environment_CheckForError(var->environment, status,
"LobVar_PreFetch(): free temporary LOB") < 0)
return -1;
}
}
}
return 0;
}
//-----------------------------------------------------------------------------
// LobVar_Finalize()
// Prepare for variable destruction.
//-----------------------------------------------------------------------------
static void LobVar_Finalize(
udt_LobVar *var) // variable to free
{
boolean isTemporary;
ub4 i;
for (i = 0; i < var->allocatedElements; i++) {
if (var->data[i]) {
OCILobIsTemporary(var->environment->handle,
var->environment->errorHandle, var->data[i], &isTemporary);
if (isTemporary) {
Py_BEGIN_ALLOW_THREADS
OCILobFreeTemporary(var->connection->handle,
var->environment->errorHandle, var->data[i]);
Py_END_ALLOW_THREADS
}
OCIDescriptorFree(var->data[i], OCI_DTYPE_LOB);
}
}
Py_DECREF(var->connection);
}
//-----------------------------------------------------------------------------
// LobVar_Write()
// Write data to the LOB variable.
//-----------------------------------------------------------------------------
static int LobVar_Write(
udt_LobVar *var, // variable to perform write against
unsigned position, // position to perform write against
PyObject *dataObj, // data object to write into LOB
oraub8 offset, // offset into variable
oraub8 *amount) // amount to write
{
udt_Buffer buffer;
sword status;
// verify the data type
if (var->type == &vt_BFILE) {
PyErr_SetString(PyExc_TypeError, "BFILEs are read only");
return -1;
} else if (var->type == &vt_BLOB) {
if (cxBuffer_FromObject(&buffer, dataObj,
var->environment->encoding) < 0)
return -1;
*amount = buffer.size;
#if PY_MAJOR_VERSION < 3
} else if (var->type == &vt_NCLOB) {
if (cxBuffer_FromObject(&buffer, dataObj,
var->environment->nencoding) < 0)
return -1;
*amount = buffer.size;
#endif
} else {
if (cxBuffer_FromObject(&buffer, dataObj,
var->environment->encoding) < 0)
return -1;
if (var->environment->fixedWidth
&& var->environment->maxBytesPerCharacter > 1)
*amount = buffer.size / var->environment->maxBytesPerCharacter;
else *amount = buffer.size;
}
// nothing to do if no data to write
if (*amount == 0) {
cxBuffer_Clear(&buffer);
return 0;
}
Py_BEGIN_ALLOW_THREADS
status = OCILobWrite2(var->connection->handle,
var->environment->errorHandle, var->data[position], amount, 0,
offset, (void*) buffer.ptr, buffer.size, OCI_ONE_PIECE, NULL, NULL,
0, var->type->charsetForm);
Py_END_ALLOW_THREADS
cxBuffer_Clear(&buffer);
if (Environment_CheckForError(var->environment, status,
"LobVar_Write()") < 0)
return -1;
return 0;
}
//-----------------------------------------------------------------------------
// LobVar_GetValue()
// Returns the value stored at the given array position.
//-----------------------------------------------------------------------------
static PyObject *LobVar_GetValue(
udt_LobVar *var, // variable to determine value for
unsigned pos) // array position
{
return ExternalLobVar_New(var, pos);
}
//-----------------------------------------------------------------------------
// LobVar_SetValue()
// Sets the value stored at the given array position.
//-----------------------------------------------------------------------------
static int LobVar_SetValue(
udt_LobVar *var, // variable to determine value for
unsigned position, // array position
PyObject *value) // value to set
{
boolean isTemporary;
oraub8 amount;
sword status;
ub1 lobType;
// make sure have temporary LOBs set up
status = OCILobIsTemporary(var->environment->handle,
var->environment->errorHandle, var->data[position], &isTemporary);
if (Environment_CheckForError(var->environment, status,
"LobVar_SetValue(): is temporary?") < 0)
return -1;
if (!isTemporary) {
if (var->type->oracleType == SQLT_BLOB)
lobType = OCI_TEMP_BLOB;
else lobType = OCI_TEMP_CLOB;
Py_BEGIN_ALLOW_THREADS
status = OCILobCreateTemporary(var->connection->handle,
var->environment->errorHandle, var->data[position],
OCI_DEFAULT, var->type->charsetForm, lobType, FALSE,
OCI_DURATION_SESSION);
Py_END_ALLOW_THREADS
if (Environment_CheckForError(var->environment, status,
"LobVar_SetValue(): create temporary") < 0)
return -1;
}
// trim the current value
Py_BEGIN_ALLOW_THREADS
status = OCILobTrim(var->connection->handle,
var->environment->errorHandle, var->data[position], 0);
Py_END_ALLOW_THREADS
if (Environment_CheckForError(var->environment, status,
"LobVar_SetValue(): trim") < 0)
return -1;
// set the current value
return LobVar_Write(var, position, value, 1, &amount);
}