Added support for initializing a collection upon creation; provided a synonym
for newobject() in simply calling the type directly (as a convenience).
This commit is contained in:
parent
9a7fb0065f
commit
92ec23930b
95
Object.c
95
Object.c
|
@ -167,6 +167,49 @@ PyObject *Object_New(
|
|||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Object_Create()
|
||||
// Create a new object in the OCI.
|
||||
//-----------------------------------------------------------------------------
|
||||
static udt_Object *Object_Create(
|
||||
udt_ObjectType *self) // type of object to create
|
||||
{
|
||||
dvoid *instance;
|
||||
udt_Object *obj;
|
||||
sword status;
|
||||
|
||||
// create the object instance
|
||||
status = OCIObjectNew(self->connection->environment->handle,
|
||||
self->connection->environment->errorHandle,
|
||||
self->connection->handle, self->typeCode, self->tdo, NULL,
|
||||
OCI_DURATION_SESSION, TRUE, &instance);
|
||||
if (Environment_CheckForError(self->connection->environment, status,
|
||||
"Object_Create(): create object instance") < 0)
|
||||
return NULL;
|
||||
|
||||
// create the object
|
||||
obj = (udt_Object*) Object_New(self, instance, NULL, 1);
|
||||
if (!obj) {
|
||||
OCIObjectFree(self->connection->environment->handle,
|
||||
self->connection->environment->errorHandle, instance,
|
||||
OCI_DEFAULT);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// get the null indicator structure
|
||||
status = OCIObjectGetInd(self->connection->environment->handle,
|
||||
self->connection->environment->errorHandle, instance,
|
||||
&obj->indicator);
|
||||
if (Environment_CheckForError(self->connection->environment, status,
|
||||
"Object_Create(): get indicator structure") < 0) {
|
||||
Py_DECREF(obj);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Object_Free()
|
||||
// Free an object.
|
||||
|
@ -578,6 +621,36 @@ static int Object_InternalAppend(
|
|||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Object_InternalExtend()
|
||||
// Extend the collection by appending each of the items in the sequence.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int Object_InternalExtend(
|
||||
udt_Object *self, // object
|
||||
PyObject *sequence) // sequence to extend collection with
|
||||
{
|
||||
PyObject *fastSequence, *element;
|
||||
Py_ssize_t size, i;
|
||||
|
||||
// make sure we are dealing with a collection
|
||||
if (Object_CheckIsCollection(self) < 0)
|
||||
return -1;
|
||||
|
||||
// append each of the items in the sequence to the collection
|
||||
fastSequence = PySequence_Fast(sequence, "expecting sequence");
|
||||
if (!fastSequence)
|
||||
return -1;
|
||||
size = PySequence_Fast_GET_SIZE(fastSequence);
|
||||
for (i = 0; i < size; i++) {
|
||||
element = PySequence_Fast_GET_ITEM(fastSequence, i);
|
||||
if (Object_InternalAppend(self, element) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Object_Append()
|
||||
// Append an item to the collection.
|
||||
|
@ -651,7 +724,7 @@ static PyObject *Object_Copy(
|
|||
udt_Object *copiedObject;
|
||||
sword status;
|
||||
|
||||
copiedObject = (udt_Object*) ObjectType_NewObject(self->objectType, args);
|
||||
copiedObject = Object_Create(self->objectType);
|
||||
if (!copiedObject)
|
||||
return NULL;
|
||||
environment = self->objectType->connection->environment;
|
||||
|
@ -730,28 +803,12 @@ static PyObject *Object_Extend(
|
|||
udt_Object *self, // object
|
||||
PyObject *args) // arguments
|
||||
{
|
||||
PyObject *sequence, *fastSequence, *element;
|
||||
Py_ssize_t size, i;
|
||||
PyObject *sequence;
|
||||
|
||||
// make sure we are dealing with a collection
|
||||
if (Object_CheckIsCollection(self) < 0)
|
||||
return NULL;
|
||||
|
||||
// parse arguments
|
||||
if (!PyArg_ParseTuple(args, "O", &sequence))
|
||||
return NULL;
|
||||
fastSequence = PySequence_Fast(sequence, "expecting sequence");
|
||||
if (!fastSequence)
|
||||
if (Object_InternalExtend(self, sequence) < 0)
|
||||
return NULL;
|
||||
|
||||
// append each of the items in the sequence to the collection
|
||||
size = PySequence_Fast_GET_SIZE(fastSequence);
|
||||
for (i = 0; i < size; i++) {
|
||||
element = PySequence_Fast_GET_ITEM(fastSequence, i);
|
||||
if (Object_InternalAppend(self, element) < 0)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
|
45
ObjectType.c
45
ObjectType.c
|
@ -34,7 +34,7 @@ typedef struct {
|
|||
static udt_ObjectType *ObjectType_New(udt_Connection*, OCIParam*, ub4);
|
||||
static void ObjectType_Free(udt_ObjectType*);
|
||||
static PyObject *ObjectType_Repr(udt_ObjectType*);
|
||||
static PyObject *ObjectType_NewObject(udt_ObjectType*, PyObject*);
|
||||
static PyObject *ObjectType_NewObject(udt_ObjectType*, PyObject*, PyObject*);
|
||||
static udt_ObjectAttribute *ObjectAttribute_New(udt_Connection*, OCIParam*);
|
||||
static void ObjectAttribute_Free(udt_ObjectAttribute*);
|
||||
static PyObject *ObjectAttribute_Repr(udt_ObjectAttribute*);
|
||||
|
@ -45,7 +45,8 @@ static PyObject *ObjectAttribute_Repr(udt_ObjectAttribute*);
|
|||
// declaration of methods for Python type "ObjectType"
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyMethodDef g_ObjectTypeMethods[] = {
|
||||
{ "newobject", (PyCFunction) ObjectType_NewObject, METH_NOARGS },
|
||||
{ "newobject", (PyCFunction) ObjectType_NewObject,
|
||||
METH_VARARGS | METH_KEYWORDS },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
|
@ -92,7 +93,7 @@ static PyTypeObject g_ObjectTypeType = {
|
|||
0, // tp_as_sequence
|
||||
0, // tp_as_mapping
|
||||
0, // tp_hash
|
||||
0, // tp_call
|
||||
(ternaryfunc) ObjectType_NewObject, // tp_call
|
||||
0, // tp_str
|
||||
0, // tp_getattro
|
||||
0, // tp_setattro
|
||||
|
@ -529,32 +530,36 @@ static PyObject *ObjectType_Repr(
|
|||
//-----------------------------------------------------------------------------
|
||||
static PyObject *ObjectType_NewObject(
|
||||
udt_ObjectType *self, // object type to return the string for
|
||||
PyObject *args) // arguments (none, ignored)
|
||||
PyObject *args, // arguments
|
||||
PyObject *keywordArgs) // keyword arguments
|
||||
{
|
||||
dvoid *instance, *indicator;
|
||||
sword status;
|
||||
static char *keywordList[] = { "value", NULL };
|
||||
PyObject *initialValue;
|
||||
udt_Object *obj;
|
||||
|
||||
// create the object instance
|
||||
status = OCIObjectNew(self->connection->environment->handle,
|
||||
self->connection->environment->errorHandle,
|
||||
self->connection->handle, self->typeCode, self->tdo, NULL,
|
||||
OCI_DURATION_SESSION, TRUE, &instance);
|
||||
if (Environment_CheckForError(self->connection->environment, status,
|
||||
"ObjectType_NewObject(): create object instance") < 0)
|
||||
// parse arguments
|
||||
initialValue = NULL;
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywordArgs, "|O", keywordList,
|
||||
&initialValue))
|
||||
return NULL;
|
||||
|
||||
// get the null indicator structure
|
||||
status = OCIObjectGetInd(self->connection->environment->handle,
|
||||
self->connection->environment->errorHandle, instance, &indicator);
|
||||
if (Environment_CheckForError(self->connection->environment, status,
|
||||
"ObjectType_NewObject(): get indicator structure") < 0)
|
||||
// create the object
|
||||
obj = Object_Create(self);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
return Object_New(self, instance, indicator, 1);
|
||||
// populate collection, if applicable
|
||||
if (initialValue) {
|
||||
if (Object_InternalExtend(obj, initialValue) < 0) {
|
||||
Py_DECREF(obj);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return (PyObject*) obj;
|
||||
}
|
||||
|
||||
|
||||
static PyObject *ObjectType_NewObject(udt_ObjectType*, PyObject*);
|
||||
//-----------------------------------------------------------------------------
|
||||
// ObjectAttribute_Initialize()
|
||||
// Initialize the new object attribute.
|
||||
|
|
|
@ -11,6 +11,12 @@ Object Type Objects
|
|||
:data:`~Variable.type` for variables containing Oracle objects.
|
||||
|
||||
|
||||
.. method:: ObjectType([sequence])
|
||||
|
||||
The object type may be called directly and serves as an alternative way of
|
||||
calling newobject().
|
||||
|
||||
|
||||
.. attribute:: ObjectType.attributes
|
||||
|
||||
This read-only attribute returns a list of the attributes that make up the
|
||||
|
@ -28,11 +34,13 @@ Object Type Objects
|
|||
This read-only attribute returns the name of the type.
|
||||
|
||||
|
||||
.. method:: ObjectType.newobject()
|
||||
.. method:: ObjectType.newobject([sequence])
|
||||
|
||||
Return a new Oracle object of the given type. This object can then be
|
||||
modified by setting its attributes and then bound to a cursor for
|
||||
interaction with Oracle.
|
||||
interaction with Oracle. If the object type refers to a collection, a
|
||||
sequence may be passed and the collection will be initialized with the
|
||||
items in that sequnce.
|
||||
|
||||
|
||||
.. attribute:: ObjectType.schema
|
||||
|
|
|
@ -75,6 +75,20 @@ class TestObjectVar(BaseTestCase):
|
|||
"udt_Object(null, 'Test With Dates', null, null, null, " \
|
||||
"udt_SubObject(15, 'Sub String'), null)")
|
||||
|
||||
def testCopyObject(self):
|
||||
"test copying an object"
|
||||
typeObj = self.connection.gettype("UDT_OBJECT")
|
||||
obj = typeObj()
|
||||
obj.NUMBERVALUE = 5124
|
||||
obj.STRINGVALUE = "A test string"
|
||||
obj.DATEVALUE = datetime.datetime(2016, 2, 24)
|
||||
obj.TIMESTAMPVALUE = datetime.datetime(2016, 2, 24, 13, 39, 10)
|
||||
copiedObj = obj.copy()
|
||||
self.assertEqual(obj.NUMBERVALUE, copiedObj.NUMBERVALUE)
|
||||
self.assertEqual(obj.STRINGVALUE, copiedObj.STRINGVALUE)
|
||||
self.assertEqual(obj.DATEVALUE, copiedObj.DATEVALUE)
|
||||
self.assertEqual(obj.TIMESTAMPVALUE, copiedObj.TIMESTAMPVALUE)
|
||||
|
||||
def testFetchData(self):
|
||||
"test fetching objects"
|
||||
self.cursor.execute("""
|
||||
|
|
Loading…
Reference in New Issue