python-cx_Oracle/ObjectVar.c

228 lines
8.5 KiB
C

//-----------------------------------------------------------------------------
// ObjectVar.c
// Defines the routines for handling Oracle object variables.
//-----------------------------------------------------------------------------
#include "ObjectType.c"
#include "ExternalObjectVar.c"
//-----------------------------------------------------------------------------
// Object type
//-----------------------------------------------------------------------------
typedef struct {
Variable_HEAD
dvoid **data;
dvoid **objectIndicator;
udt_Connection *connection;
udt_ObjectType *objectType;
} udt_ObjectVar;
//-----------------------------------------------------------------------------
// Declaration of object variable functions.
//-----------------------------------------------------------------------------
static int ObjectVar_Initialize(udt_ObjectVar*, udt_Cursor*);
static void ObjectVar_Finalize(udt_ObjectVar*);
static PyObject *ObjectVar_GetAttr(udt_ObjectVar*, PyObject*);
static PyObject *ObjectVar_GetValue(udt_ObjectVar*, unsigned);
static int ObjectVar_PreDefine(udt_ObjectVar*, OCIParam*);
static int ObjectVar_PostDefine(udt_ObjectVar*);
static int ObjectVar_IsNull(udt_ObjectVar*, unsigned);
//-----------------------------------------------------------------------------
// Python type declarations
//-----------------------------------------------------------------------------
static PyTypeObject g_ObjectVarType = {
PyObject_HEAD_INIT(NULL)
0, // ob_size
"cx_Oracle.OBJECTVAR", // tp_name
sizeof(udt_ObjectVar), // tp_basicsize
0, // tp_itemsize
(destructor) Variable_Free, // tp_dealloc
0, // tp_print
0, // tp_getattr
0, // tp_setattr
0, // tp_compare
(reprfunc) Variable_Repr, // tp_repr
0, // tp_as_number
0, // tp_as_sequence
0, // tp_as_mapping
0, // tp_hash
0, // tp_call
0, // tp_str
(getattrofunc) ObjectVar_GetAttr, // tp_getattro
0, // tp_setattro
0, // tp_as_buffer
Py_TPFLAGS_DEFAULT, // tp_flags
0 // tp_doc
};
//-----------------------------------------------------------------------------
// variable type declarations
//-----------------------------------------------------------------------------
static udt_VariableType vt_Object = {
(InitializeProc) ObjectVar_Initialize,
(FinalizeProc) ObjectVar_Finalize,
(PreDefineProc) ObjectVar_PreDefine,
(PostDefineProc) ObjectVar_PostDefine,
(IsNullProc) ObjectVar_IsNull,
(SetValueProc) NULL,
(GetValueProc) ObjectVar_GetValue,
&g_ObjectVarType, // Python type
SQLT_NTY, // Oracle type
SQLCS_IMPLICIT, // charset form
sizeof(dvoid*), // element length
0, // is variable length
0, // can be copied
0 // can be in array
};
//-----------------------------------------------------------------------------
// ObjectVar_Initialize()
// Initialize the variable.
//-----------------------------------------------------------------------------
static int ObjectVar_Initialize(
udt_ObjectVar *self, // variable to initialize
udt_Cursor *cursor) // cursor to use
{
int i;
Py_INCREF(cursor->connection);
self->connection = cursor->connection;
self->objectType = NULL;
self->objectIndicator =
PyMem_Malloc(self->allocatedElements * sizeof(dvoid*));
if (!self->objectIndicator) {
PyErr_NoMemory();
return -1;
}
for (i = 0; i < self->allocatedElements; i++) {
self->data[i] = NULL;
self->objectIndicator[i] = NULL;
}
return 0;
}
//-----------------------------------------------------------------------------
// ObjectVar_Finalize()
// Prepare for variable destruction.
//-----------------------------------------------------------------------------
static void ObjectVar_Finalize(
udt_ObjectVar *self) // variable to free
{
int i;
for (i = 0; i < self->allocatedElements; i++) {
if (self->data[i])
OCIObjectFree(self->environment->handle,
self->environment->errorHandle, self->data[i],
OCI_OBJECTFREE_FORCE);
}
Py_DECREF(self->connection);
Py_XDECREF(self->objectType);
if (self->objectIndicator)
PyMem_Free(self->objectIndicator);
}
//-----------------------------------------------------------------------------
// ObjectVar_GetAttr()
// Retrieve an attribute on the variable object.
//-----------------------------------------------------------------------------
static PyObject *ObjectVar_GetAttr(
udt_ObjectVar *self, // variable object
PyObject *nameObject) // name of attribute
{
char *name;
name = PyString_AS_STRING(nameObject);
if (name[0] == 't' && strcmp(name, "type") == 0) {
Py_INCREF(self->objectType);
return (PyObject*) self->objectType;
}
return Variable_GetAttr((udt_Variable*) self, nameObject);
}
//-----------------------------------------------------------------------------
// ObjectVar_PreDefine()
// Performs additional steps required for defining objects.
//-----------------------------------------------------------------------------
static int ObjectVar_PreDefine(
udt_ObjectVar *self, // variable to set up
OCIParam *param) // parameter being defined
{
self->objectType = ObjectType_New(self->connection, param);
if (!self->objectType)
return -1;
return 0;
}
//-----------------------------------------------------------------------------
// ObjectVar_PostDefine()
// Performs additional steps required for defining objects.
//-----------------------------------------------------------------------------
static int ObjectVar_PostDefine(
udt_ObjectVar *self) // variable to set up
{
sword status;
status = OCIDefineObject(self->defineHandle,
self->environment->errorHandle, self->objectType->tdo, self->data,
0, self->objectIndicator, 0);
return Environment_CheckForError(self->environment, status,
"ObjectVar_PostDefine(): define object");
}
//-----------------------------------------------------------------------------
// ObjectVar_IsNull()
// Returns a boolean indicating if the variable is null or not.
//-----------------------------------------------------------------------------
static int ObjectVar_IsNull(
udt_ObjectVar *self, // variable to set up
unsigned pos) // position to check
{
if (!self->objectIndicator[pos])
return 1;
return (*((OCIInd*) self->objectIndicator[pos]) == OCI_IND_NULL);
}
//-----------------------------------------------------------------------------
// ObjectVar_GetValue()
// Returns the value stored at the given array position.
//-----------------------------------------------------------------------------
static PyObject *ObjectVar_GetValue(
udt_ObjectVar *self, // variable to determine value for
unsigned pos) // array position
{
PyObject *var;
// only allowed to get the value once (for now)
if (!self->data[pos]) {
PyErr_SetString(g_ProgrammingErrorException,
"variable value can only be acquired once");
return NULL;
}
// for collections, return the list rather than the object
if (self->objectType->isCollection)
return ExternalObjectVar_ConvertCollection(self->environment,
self->data[pos], (PyObject*) self, self->objectType);
// for objects, return a representation of the object
var = ExternalObjectVar_New((PyObject*) self, self->objectType,
self->data[pos], self->objectIndicator[pos], 1);
if (!var)
return NULL;
self->data[pos] = NULL;
self->objectIndicator[pos] = NULL;
return var;
}