Added support for the rows in the change notification message.

This commit is contained in:
Anthony Tuininga 2009-01-08 15:16:18 +00:00
parent 825c78c87c
commit 46eeb000b5
2 changed files with 146 additions and 1 deletions

View File

@ -32,6 +32,12 @@ typedef struct {
ub4 operation;
} udt_MessageTable;
typedef struct {
PyObject_HEAD
PyObject *rowid;
ub4 operation;
} udt_MessageRow;
//-----------------------------------------------------------------------------
// Declaration of subscription functions
@ -41,6 +47,7 @@ static PyObject *Subscription_Repr(udt_Subscription*);
static PyObject *Subscription_RegisterQuery(udt_Subscription*, PyObject*);
static void Message_Free(udt_Message*);
static void MessageTable_Free(udt_MessageTable*);
static void MessageRow_Free(udt_MessageRow*);
//-----------------------------------------------------------------------------
// declaration of members for Python types
@ -71,6 +78,12 @@ static PyMemberDef g_MessageTableTypeMembers[] = {
{ NULL }
};
static PyMemberDef g_MessageRowTypeMembers[] = {
{ "rowid", T_OBJECT, offsetof(udt_MessageRow, rowid), READONLY },
{ "operation", T_INT, offsetof(udt_MessageRow, operation), READONLY },
{ NULL }
};
//-----------------------------------------------------------------------------
// declaration of methods for Python types
@ -218,6 +231,85 @@ static PyTypeObject g_MessageTableType = {
};
static PyTypeObject g_MessageRowType = {
PyVarObject_HEAD_INIT(NULL, 0)
"cx_Oracle.MessageRow", // tp_name
sizeof(udt_MessageRow), // tp_basicsize
0, // tp_itemsize
(destructor) MessageRow_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
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
0, // tp_methods
g_MessageRowTypeMembers, // 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
};
//-----------------------------------------------------------------------------
// MessageRow_Initialize()
// Initialize a new message row with the information from the descriptor.
//-----------------------------------------------------------------------------
static int MessageRow_Initialize(
udt_MessageRow *self, // object to initialize
udt_Environment *env, // environment to use
dvoid *descriptor) // descriptor to get information from
{
ub4 rowidLength;
sword status;
char *rowid;
// determine operation
status = OCIAttrGet(descriptor, OCI_DTYPE_ROW_CHDES, &self->operation,
NULL, OCI_ATTR_CHDES_ROW_OPFLAGS, env->errorHandle);
if (Environment_CheckForError(env, status,
"MessageRow_Initialize(): get operation") < 0)
return -1;
// determine table name
status = OCIAttrGet(descriptor, OCI_DTYPE_ROW_CHDES, &rowid, &rowidLength,
OCI_ATTR_CHDES_ROW_ROWID, env->errorHandle);
if (Environment_CheckForError(env, status,
"MessageRow_Initialize(): get rowid") < 0)
return -1;
self->rowid = cxString_FromEncodedString(rowid, rowidLength);
if (!self->rowid)
return -1;
return 0;
}
//-----------------------------------------------------------------------------
// MessageTable_Initialize()
// Initialize a new message table with the information from the descriptor.
@ -227,7 +319,11 @@ static int MessageTable_Initialize(
udt_Environment *env, // environment to use
dvoid *descriptor) // descriptor to get information from
{
ub4 nameLength;
dvoid **rowDescriptor, *indicator;
ub4 nameLength, i, numRows;
udt_MessageRow *row;
boolean exists;
OCIColl *rows;
sword status;
char *name;
@ -248,6 +344,42 @@ static int MessageTable_Initialize(
if (!self->name)
return -1;
// if change invalidated all rows, nothing to do
if (self->operation & OCI_OPCODE_ALLROWS)
return 0;
// determine rows collection
status = OCIAttrGet(descriptor, OCI_DTYPE_TABLE_CHDES, &rows, NULL,
OCI_ATTR_CHDES_TABLE_ROW_CHANGES, env->errorHandle);
if (Environment_CheckForError(env, status,
"MessageTable_Initialize(): get rows collection") < 0)
return -1;
// determine number of rows in collection
status = OCICollSize(env->handle, env->errorHandle, rows, &numRows);
if (Environment_CheckForError(env, status,
"MessageTable_Initialize(): get size of rows collection") < 0)
return -1;
// populate the rows attribute
self->rows = PyList_New(numRows);
if (!self->rows)
return -1;
for (i = 0; i < numRows; i++) {
status = OCICollGetElem(env->handle, env->errorHandle, rows, i,
&exists, (dvoid*) &rowDescriptor, &indicator);
if (Environment_CheckForError(env, status,
"MessageTable_Initialize(): get element from collection") < 0)
return -1;
row = (udt_MessageRow*)
g_MessageRowType.tp_alloc(&g_MessageRowType, 0);
if (!row)
return -1;
PyList_SET_ITEM(self->rows, i, (PyObject*) row);
if (MessageRow_Initialize(row, env, *rowDescriptor) < 0)
return -1;
}
return 0;
}
@ -727,3 +859,15 @@ static void MessageTable_Free(
Py_TYPE(self)->tp_free((PyObject*) self);
}
//-----------------------------------------------------------------------------
// MessageRow_Free()
// Free the memory associated with a row in a message.
//-----------------------------------------------------------------------------
static void MessageRow_Free(
udt_MessageRow *self) // object to free
{
Py_CLEAR(self->rowid);
Py_TYPE(self)->tp_free((PyObject*) self);
}

View File

@ -351,6 +351,7 @@ static PyObject *Module_Initialize(void)
MAKE_TYPE_READY(&g_SubscriptionType);
MAKE_TYPE_READY(&g_MessageType);
MAKE_TYPE_READY(&g_MessageTableType);
MAKE_TYPE_READY(&g_MessageRowType);
#endif
MAKE_VARIABLE_TYPE_READY(&g_StringVarType);
MAKE_VARIABLE_TYPE_READY(&g_FixedCharVarType);