//----------------------------------------------------------------------------- // 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; }