python-cx_Oracle/ExternalObjectVar.c

306 lines
12 KiB
C

//-----------------------------------------------------------------------------
// ExternalObjectVar.c
// Defines the routines for handling object variables external to this
// module.
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// external Object type
//-----------------------------------------------------------------------------
typedef struct {
PyObject_HEAD
PyObject *referencedObject;
udt_ObjectType *objectType;
dvoid *instance;
dvoid *indicator;
int isIndependent;
} udt_ExternalObjectVar;
//-----------------------------------------------------------------------------
// Declaration of external object variable functions.
//-----------------------------------------------------------------------------
static void ExternalObjectVar_Free(udt_ExternalObjectVar*);
static PyObject *ExternalObjectVar_GetAttr(udt_ExternalObjectVar*, PyObject*);
static PyObject *ExternalObjectVar_ConvertToPython(udt_Environment*,
OCITypeCode, dvoid*, dvoid*, PyObject*, udt_ObjectType*);
//-----------------------------------------------------------------------------
// Declaration of external object variable members.
//-----------------------------------------------------------------------------
static PyMemberDef g_ExternalObjectVarMembers[] = {
{ "type", T_OBJECT, offsetof(udt_ExternalObjectVar, objectType),
READONLY },
{ NULL }
};
//-----------------------------------------------------------------------------
// Python type declaration
//-----------------------------------------------------------------------------
static PyTypeObject g_ExternalObjectVarType = {
PyVarObject_HEAD_INIT(NULL, 0)
"cx_Oracle.OBJECT", // tp_name
sizeof(udt_ExternalObjectVar), // tp_basicsize
0, // tp_itemsize
(destructor) ExternalObjectVar_Free,
// 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
(getattrofunc) ExternalObjectVar_GetAttr,
// tp_getattro
0, // tp_setattro
0, // tp_as_buffer
Py_TPFLAGS_DEFAULT, // tp_flags
0, // tp_doc
0, // tp_traverse
0, // tp_clear
0, // tp_richcompare
0, // tp_weaklistoffset
0, // tp_iter
0, // tp_iternext
0, // tp_methods
g_ExternalObjectVarMembers // tp_members
};
//-----------------------------------------------------------------------------
// ExternalObjectVar_New()
// Create a new external LOB variable.
//-----------------------------------------------------------------------------
PyObject *ExternalObjectVar_New(
PyObject *referencedObject, // referenced object
udt_ObjectType *objectType, // type of object
dvoid *instance, // object instance data
dvoid *indicator, // indicator structure
int isIndependent) // is object independent?
{
udt_ExternalObjectVar *self;
self = (udt_ExternalObjectVar*)
g_ExternalObjectVarType.tp_alloc(&g_ExternalObjectVarType, 0);
if (!self)
return NULL;
Py_INCREF(referencedObject);
self->referencedObject = referencedObject;
Py_INCREF(objectType);
self->objectType = objectType;
self->instance = instance;
self->indicator = indicator;
self->isIndependent = isIndependent;
return (PyObject*) self;
}
//-----------------------------------------------------------------------------
// ExternalObjectVar_Free()
// Free an external LOB variable.
//-----------------------------------------------------------------------------
static void ExternalObjectVar_Free(
udt_ExternalObjectVar *self) // variable to free
{
if (self->isIndependent)
OCIObjectFree(self->objectType->environment->handle,
self->objectType->environment->errorHandle,
self->instance, OCI_OBJECTFREE_FORCE);
Py_CLEAR(self->objectType);
Py_CLEAR(self->referencedObject);
Py_TYPE(self)->tp_free((PyObject*) self);
}
//-----------------------------------------------------------------------------
// ExternalObjectVar_ConvertCollectionElements()
// Convert the collection elements to Python values.
//-----------------------------------------------------------------------------
static int ExternalObjectVar_ConvertCollectionElements(
udt_Environment *environment, // environment to use
OCIIter *iter, // iterator
PyObject *list, // list result
PyObject *referencedObject, // referenced object
udt_ObjectType *objectType) // collection type information
{
dvoid *elementValue, *elementIndicator;
PyObject *elementObject;
boolean endOfCollection;
sword status;
while (list) {
status = OCIIterNext(environment->handle, environment->errorHandle,
iter, &elementValue, &elementIndicator, &endOfCollection);
if (Environment_CheckForError(environment, status,
"ExternalObjectVar_ConvertCollection(): get next") < 0)
return -1;
if (endOfCollection)
break;
elementObject = ExternalObjectVar_ConvertToPython(environment,
objectType->elementTypeCode, elementValue, elementIndicator,
referencedObject, (udt_ObjectType*) objectType->elementType);
if (!elementObject)
return -1;
if (PyList_Append(list, elementObject) < 0) {
Py_DECREF(elementObject);
return -1;
}
Py_DECREF(elementObject);
}
return 0;
}
//-----------------------------------------------------------------------------
// ExternalObjectVar_ConvertCollection()
// Convert a collection to a Python list.
//-----------------------------------------------------------------------------
static PyObject *ExternalObjectVar_ConvertCollection(
udt_Environment *environment, // environment to use
OCIColl *collectionValue, // collection value
PyObject *referencedObject, // referenced object
udt_ObjectType *objectType) // collection type information
{
PyObject *list;
OCIIter *iter;
sword status;
int result;
// create the iterator
status = OCIIterCreate(environment->handle, environment->errorHandle,
collectionValue, &iter);
if (Environment_CheckForError(environment, status,
"ExternalObjectVar_ConvertCollection(): creating iterator") < 0)
return NULL;
// create the result list
list = PyList_New(0);
if (list) {
result = ExternalObjectVar_ConvertCollectionElements(environment, iter,
list, referencedObject, objectType);
if (result < 0) {
Py_DECREF(list);
list = NULL;
}
}
OCIIterDelete(environment->handle, environment->errorHandle, &iter);
return list;
}
//-----------------------------------------------------------------------------
// ExternalObjectVar_ConvertToPython()
// Convert an Oracle value to a Python value.
//-----------------------------------------------------------------------------
static PyObject *ExternalObjectVar_ConvertToPython(
udt_Environment *environment, // environment to use
OCITypeCode typeCode, // type of Oracle data
dvoid *value, // Oracle value
dvoid *indicator, // null indicator
PyObject *referencedObject, // referenced object (for sub objects)
udt_ObjectType *subType) // sub type (for sub objects)
{
text *stringValue;
ub4 stringSize;
// null values returned as None
if (* (OCIInd*) indicator == OCI_IND_NULL) {
Py_INCREF(Py_None);
return Py_None;
}
switch (typeCode) {
case OCI_TYPECODE_CHAR:
case OCI_TYPECODE_VARCHAR:
case OCI_TYPECODE_VARCHAR2:
stringValue = OCIStringPtr(environment->handle,
* (OCIString**) value);
stringSize = OCIStringSize(environment->handle,
* (OCIString**) value);
return cxString_FromEncodedString( (char*) stringValue,
stringSize, environment->encoding);
case OCI_TYPECODE_NUMBER:
return OracleNumberToPythonFloat(environment, (OCINumber*) value);
case OCI_TYPECODE_DATE:
return OracleDateToPythonDate(&vt_DateTime, (OCIDate*) value);
case OCI_TYPECODE_TIMESTAMP:
return OracleTimestampToPythonDate(environment,
* (OCIDateTime**) value);
case OCI_TYPECODE_OBJECT:
return ExternalObjectVar_New(referencedObject, subType, value,
indicator, 0);
case OCI_TYPECODE_NAMEDCOLLECTION:
return ExternalObjectVar_ConvertCollection(environment,
* (OCIColl**) value, referencedObject, subType);
};
return PyErr_Format(g_NotSupportedErrorException,
"ExternalObjectVar_GetAttributeValue(): unhandled data type %d",
typeCode);
}
//-----------------------------------------------------------------------------
// ExternalObjectVar_GetAttributeValue()
// Retrieve an attribute on the external LOB variable object.
//-----------------------------------------------------------------------------
static PyObject *ExternalObjectVar_GetAttributeValue(
udt_ExternalObjectVar *self, // object
udt_ObjectAttribute *attribute) // attribute to get
{
dvoid *valueIndicator, *value;
OCIInd scalarValueIndicator;
udt_Buffer buffer;
sword status;
OCIType *tdo;
// get the value for the attribute
if (cxBuffer_FromObject(&buffer, attribute->name,
self->objectType->environment->encoding) < 0)
return NULL;
status = OCIObjectGetAttr(self->objectType->environment->handle,
self->objectType->environment->errorHandle, self->instance,
self->indicator, self->objectType->tdo,
(const OraText**) &buffer.ptr, (ub4*) &buffer.size, 1, 0, 0,
&scalarValueIndicator, &valueIndicator, &value, &tdo);
cxBuffer_Clear(&buffer);
if (Environment_CheckForError(self->objectType->environment, status,
"ExternalObjectVar_GetAttributeValue(): getting value") < 0)
return NULL;
// determine the proper null indicator
if (!valueIndicator)
valueIndicator = &scalarValueIndicator;
return ExternalObjectVar_ConvertToPython(self->objectType->environment,
attribute->typeCode, value, valueIndicator, (PyObject*) self,
attribute->subType);
}
//-----------------------------------------------------------------------------
// ExternalObjectVar_GetAttr()
// Retrieve an attribute on the external LOB variable object.
//-----------------------------------------------------------------------------
static PyObject *ExternalObjectVar_GetAttr(
udt_ExternalObjectVar *self, // object
PyObject *nameObject) // name of attribute
{
udt_ObjectAttribute *attribute;
attribute = (udt_ObjectAttribute*)
PyDict_GetItem(self->objectType->attributesByName, nameObject);
if (attribute)
return ExternalObjectVar_GetAttributeValue(self, attribute);
return PyObject_GenericGetAttr( (PyObject*) self, nameObject);
}