303 lines
11 KiB
C
303 lines
11 KiB
C
//-----------------------------------------------------------------------------
|
|
// Copyright 2016-2018, Oracle and/or its affiliates. All rights reserved.
|
|
//
|
|
// Portions Copyright 2007-2015, Anthony Tuininga. All rights reserved.
|
|
//
|
|
// Portions Copyright 2001-2007, Computronix (Canada) Ltd., Edmonton, Alberta,
|
|
// Canada. All rights reserved.
|
|
//-----------------------------------------------------------------------------
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// cxoObjectType.c
|
|
// Defines the routines for handling Oracle type information.
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#include "cxoModule.h"
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Declaration of functions
|
|
//-----------------------------------------------------------------------------
|
|
static void cxoObjectType_free(cxoObjectType*);
|
|
static PyObject *cxoObjectType_repr(cxoObjectType*);
|
|
static PyObject *cxoObjectType_newObject(cxoObjectType*, PyObject*, PyObject*);
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// declaration of methods for Python type "ObjectType"
|
|
//-----------------------------------------------------------------------------
|
|
static PyMethodDef cxoObjectTypeMethods[] = {
|
|
{ "newobject", (PyCFunction) cxoObjectType_newObject,
|
|
METH_VARARGS | METH_KEYWORDS },
|
|
{ NULL }
|
|
};
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// declaration of members for Python type "ObjectType"
|
|
//-----------------------------------------------------------------------------
|
|
static PyMemberDef cxoObjectTypeMembers[] = {
|
|
{ "schema", T_OBJECT, offsetof(cxoObjectType, schema), READONLY },
|
|
{ "name", T_OBJECT, offsetof(cxoObjectType, name), READONLY },
|
|
{ "attributes", T_OBJECT, offsetof(cxoObjectType, attributes), READONLY },
|
|
{ "elementType", T_OBJECT, offsetof(cxoObjectType, elementType),
|
|
READONLY },
|
|
{ "iscollection", T_BOOL, offsetof(cxoObjectType, isCollection),
|
|
READONLY },
|
|
{ NULL }
|
|
};
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Python type declarations
|
|
//-----------------------------------------------------------------------------
|
|
PyTypeObject cxoPyTypeObjectType = {
|
|
PyVarObject_HEAD_INIT(NULL, 0)
|
|
"cx_Oracle.ObjectType", // tp_name
|
|
sizeof(cxoObjectType), // tp_basicsize
|
|
0, // tp_itemsize
|
|
(destructor) cxoObjectType_free, // tp_dealloc
|
|
0, // tp_print
|
|
0, // tp_getattr
|
|
0, // tp_setattr
|
|
0, // tp_compare
|
|
(reprfunc) cxoObjectType_repr, // tp_repr
|
|
0, // tp_as_number
|
|
0, // tp_as_sequence
|
|
0, // tp_as_mapping
|
|
0, // tp_hash
|
|
(ternaryfunc) cxoObjectType_newObject, // tp_call
|
|
0, // tp_str
|
|
0, // 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
|
|
cxoObjectTypeMethods, // tp_methods
|
|
cxoObjectTypeMembers, // tp_members
|
|
0, // tp_getset
|
|
0, // tp_base
|
|
0, // tp_dict
|
|
0, // tp_descr_get
|
|
0, // tp_descr_set
|
|
0, // tp_dictoffset
|
|
0, // tp_init
|
|
0, // tp_alloc
|
|
0, // tp_new
|
|
0, // tp_free
|
|
0, // tp_is_gc
|
|
0 // tp_bases
|
|
};
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// cxoObjectType_initialize()
|
|
// Initialize the object type with the information that is required.
|
|
//-----------------------------------------------------------------------------
|
|
static int cxoObjectType_initialize(cxoObjectType *objType,
|
|
cxoConnection *connection)
|
|
{
|
|
dpiObjectAttr **attributes;
|
|
dpiObjectTypeInfo info;
|
|
cxoObjectAttr *attr;
|
|
uint16_t i;
|
|
|
|
// get object type information
|
|
if (dpiObjectType_getInfo(objType->handle, &info) < 0)
|
|
return cxoError_raiseAndReturnInt();
|
|
Py_INCREF(connection);
|
|
objType->connection = connection;
|
|
objType->schema = cxoPyString_fromEncodedString(info.schema,
|
|
info.schemaLength, connection->encodingInfo.encoding);
|
|
if (!objType->schema)
|
|
return -1;
|
|
objType->name = cxoPyString_fromEncodedString(info.name, info.nameLength,
|
|
connection->encodingInfo.encoding);
|
|
if (!objType->name)
|
|
return -1;
|
|
objType->isCollection = info.isCollection;
|
|
objType->elementOracleTypeNum = info.elementTypeInfo.oracleTypeNum;
|
|
objType->elementTransformNum =
|
|
cxoTransform_getNumFromDataTypeInfo(&info.elementTypeInfo);
|
|
if (info.elementTypeInfo.objectType) {
|
|
objType->elementType = (PyObject*) cxoObjectType_new(connection,
|
|
info.elementTypeInfo.objectType);
|
|
if (!objType->elementType)
|
|
return -1;
|
|
}
|
|
|
|
// allocate the attribute list (temporary and permanent) and dictionary
|
|
objType->attributes = PyList_New(info.numAttributes);
|
|
if (!objType->attributes)
|
|
return -1;
|
|
objType->attributesByName = PyDict_New();
|
|
if (!objType->attributesByName)
|
|
return -1;
|
|
|
|
// get the list of attributes from DPI
|
|
attributes = PyMem_Malloc(sizeof(dpiObjectAttr*) * info.numAttributes);
|
|
if (!attributes) {
|
|
PyErr_NoMemory();
|
|
return -1;
|
|
}
|
|
if (dpiObjectType_getAttributes(objType->handle, info.numAttributes,
|
|
attributes) < 0) {
|
|
PyMem_Free(attributes);
|
|
return cxoError_raiseAndReturnInt();
|
|
}
|
|
|
|
// create attribute information for each attribute
|
|
for (i = 0; i < info.numAttributes; i++) {
|
|
attr = cxoObjectAttr_new(connection, attributes[i]);
|
|
if (!attr) {
|
|
PyMem_Free(attributes);
|
|
return -1;
|
|
}
|
|
PyList_SET_ITEM(objType->attributes, i, (PyObject*) attr);
|
|
if (PyDict_SetItem(objType->attributesByName, attr->name,
|
|
(PyObject*) attr) < 0)
|
|
return -1;
|
|
}
|
|
PyMem_Free(attributes);
|
|
return 0;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// cxoObjectType_new()
|
|
// Allocate a new object type.
|
|
//-----------------------------------------------------------------------------
|
|
cxoObjectType *cxoObjectType_new(cxoConnection *connection,
|
|
dpiObjectType *handle)
|
|
{
|
|
cxoObjectType *objType;
|
|
|
|
objType = (cxoObjectType*)
|
|
cxoPyTypeObjectType.tp_alloc(&cxoPyTypeObjectType, 0);
|
|
if (!objType)
|
|
return NULL;
|
|
if (dpiObjectType_addRef(handle) < 0) {
|
|
Py_DECREF(objType);
|
|
cxoError_raiseAndReturnNull();
|
|
return NULL;
|
|
}
|
|
objType->handle = handle;
|
|
if (cxoObjectType_initialize(objType, connection) < 0) {
|
|
Py_DECREF(objType);
|
|
return NULL;
|
|
}
|
|
|
|
return objType;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// cxoObjectType_newByName()
|
|
// Create a new object type given its name.
|
|
//-----------------------------------------------------------------------------
|
|
cxoObjectType *cxoObjectType_newByName(cxoConnection *connection,
|
|
PyObject *name)
|
|
{
|
|
cxoObjectType *objType;
|
|
dpiObjectType *handle;
|
|
cxoBuffer buffer;
|
|
int status;
|
|
|
|
if (cxoBuffer_fromObject(&buffer, name,
|
|
connection->encodingInfo.encoding) < 0)
|
|
return NULL;
|
|
status = dpiConn_getObjectType(connection->handle, buffer.ptr,
|
|
buffer.size, &handle);
|
|
cxoBuffer_clear(&buffer);
|
|
if (status < 0)
|
|
return (cxoObjectType*) cxoError_raiseAndReturnNull();
|
|
objType = cxoObjectType_new(connection, handle);
|
|
dpiObjectType_release(handle);
|
|
return objType;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// cxoObjectType_free()
|
|
// Free the memory associated with an object type.
|
|
//-----------------------------------------------------------------------------
|
|
static void cxoObjectType_free(cxoObjectType *objType)
|
|
{
|
|
if (objType->handle) {
|
|
dpiObjectType_release(objType->handle);
|
|
objType->handle = NULL;
|
|
}
|
|
Py_CLEAR(objType->connection);
|
|
Py_CLEAR(objType->schema);
|
|
Py_CLEAR(objType->name);
|
|
Py_CLEAR(objType->attributes);
|
|
Py_CLEAR(objType->attributesByName);
|
|
Py_CLEAR(objType->elementType);
|
|
Py_TYPE(objType)->tp_free((PyObject*) objType);
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// cxoObjectType_repr()
|
|
// Return a string representation of the object type.
|
|
//-----------------------------------------------------------------------------
|
|
static PyObject *cxoObjectType_repr(cxoObjectType *objType)
|
|
{
|
|
PyObject *module, *name, *result;
|
|
|
|
if (cxoUtils_getModuleAndName(Py_TYPE(objType), &module, &name) < 0)
|
|
return NULL;
|
|
result = cxoUtils_formatString("<%s.%s %s.%s>",
|
|
PyTuple_Pack(4, module, name, objType->schema, objType->name));
|
|
Py_DECREF(module);
|
|
Py_DECREF(name);
|
|
return result;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// cxoObjectType_newObject()
|
|
// Factory function for creating objects of the type which can be bound.
|
|
//-----------------------------------------------------------------------------
|
|
static PyObject *cxoObjectType_newObject(cxoObjectType *objType,
|
|
PyObject *args, PyObject *keywordArgs)
|
|
{
|
|
static char *keywordList[] = { "value", NULL };
|
|
PyObject *initialValue;
|
|
dpiObject *handle;
|
|
cxoObject *obj;
|
|
|
|
// parse arguments
|
|
initialValue = NULL;
|
|
if (!PyArg_ParseTupleAndKeywords(args, keywordArgs, "|O", keywordList,
|
|
&initialValue))
|
|
return NULL;
|
|
|
|
// get handle to newly created object
|
|
if (dpiObjectType_createObject(objType->handle, &handle) < 0)
|
|
return cxoError_raiseAndReturnNull();
|
|
|
|
// create the object
|
|
obj = (cxoObject*) cxoObject_new(objType, handle);
|
|
if (!obj) {
|
|
dpiObject_release(handle);
|
|
return NULL;
|
|
}
|
|
|
|
// populate collection, if applicable
|
|
if (initialValue) {
|
|
if (cxoObject_internalExtend(obj, initialValue) < 0) {
|
|
Py_DECREF(obj);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
return (PyObject*) obj;
|
|
}
|
|
|