Added support for specifying the IP address the subscription should use instead

of having the Oracle Client library determine the IP address on its own.
This commit is contained in:
Anthony Tuininga 2018-05-16 14:08:28 -06:00
parent 23fac6841a
commit bab41ac544
5 changed files with 40 additions and 12 deletions

View File

@ -480,7 +480,7 @@ Connection Object
This attribute is an extension to the DB API definition. This attribute is an extension to the DB API definition.
.. method:: Connection.subscribe(namespace=cx_Oracle.SUBSCR_NAMESPACE_DBCHANGE, protocol=cx_Oracle.SUBSCR_PROTO_OCI, callback=None, timeout=0, operations=OPCODE_ALLOPS, port=0, qos=0) .. method:: Connection.subscribe(namespace=cx_Oracle.SUBSCR_NAMESPACE_DBCHANGE, protocol=cx_Oracle.SUBSCR_PROTO_OCI, callback=None, timeout=0, operations=OPCODE_ALLOPS, port=0, qos=0, ipAddress=None)
Return a new :ref:`subscription object <subscrobj>` using the connection. Return a new :ref:`subscription object <subscrobj>` using the connection.
Currently the namespace and protocol parameters cannot have any other Currently the namespace and protocol parameters cannot have any other
@ -510,6 +510,10 @@ Connection Object
:data:`cx_Oracle.SUBSCR_QOS_QUERY`, :data:`cx_Oracle.SUBSCR_QOS_QUERY`,
:data:`cx_Oracle.SUBSCR_QOS_BEST_EFFORT`. :data:`cx_Oracle.SUBSCR_QOS_BEST_EFFORT`.
The ipAddress specifies the IP address (IPv4 or IPv6) to bind for callback
notifications from the database server. If not specified, the client IP
address will be determined by the Oracle Client libraries.
.. note:: .. note::
This method is an extension to the DB API definition. This method is an extension to the DB API definition.

View File

@ -43,6 +43,13 @@ Subscription Object
subscription. subscription.
.. attribute:: Subscription.ipAddress
This read-only attribute returns the IP address used for callback
notifications from the database server. If not set during construction,
this value is None.
.. attribute:: Subscription.port .. attribute:: Subscription.port
This read-only attribute returns the port used for callback notifications This read-only attribute returns the port used for callback notifications

View File

@ -1456,21 +1456,21 @@ static PyObject *cxoConnection_subscribe(cxoConnection *conn, PyObject* args,
PyObject* keywordArgs) PyObject* keywordArgs)
{ {
static char *keywordList[] = { "namespace", "protocol", "callback", static char *keywordList[] = { "namespace", "protocol", "callback",
"timeout", "operations", "port", "qos", NULL }; "timeout", "operations", "port", "qos", "ipAddress", NULL };
uint32_t namespace, protocol, port, timeout, operations, qos; uint32_t namespace, protocol, port, timeout, operations, qos;
PyObject *callback; PyObject *callback, *ipAddress;
callback = NULL;
timeout = port = qos = 0; timeout = port = qos = 0;
callback = ipAddress = NULL;
namespace = DPI_SUBSCR_NAMESPACE_DBCHANGE; namespace = DPI_SUBSCR_NAMESPACE_DBCHANGE;
protocol = DPI_SUBSCR_PROTO_CALLBACK; protocol = DPI_SUBSCR_PROTO_CALLBACK;
operations = DPI_OPCODE_ALL_OPS; operations = DPI_OPCODE_ALL_OPS;
if (!PyArg_ParseTupleAndKeywords(args, keywordArgs, "|iiOiiii", if (!PyArg_ParseTupleAndKeywords(args, keywordArgs, "|iiOiiiiO",
keywordList, &namespace, &protocol, &callback, &timeout, keywordList, &namespace, &protocol, &callback, &timeout,
&operations, &port, &qos)) &operations, &port, &qos, &ipAddress))
return NULL; return NULL;
return (PyObject*) cxoSubscr_new(conn, namespace, protocol, port, callback, return (PyObject*) cxoSubscr_new(conn, namespace, protocol, ipAddress,
timeout, operations, qos); port, callback, timeout, operations, qos);
} }

View File

@ -359,6 +359,7 @@ struct cxoSubscr {
PyObject *callback; PyObject *callback;
uint32_t namespace; uint32_t namespace;
uint32_t protocol; uint32_t protocol;
PyObject *ipAddress;
uint32_t port; uint32_t port;
uint32_t timeout; uint32_t timeout;
uint32_t operations; uint32_t operations;
@ -430,8 +431,9 @@ cxoObjectType *cxoObjectType_newByName(cxoConnection *connection,
PyObject *name); PyObject *name);
cxoSubscr *cxoSubscr_new(cxoConnection *connection, uint32_t namespace, cxoSubscr *cxoSubscr_new(cxoConnection *connection, uint32_t namespace,
uint32_t protocol, uint32_t port, PyObject *callback, uint32_t timeout, uint32_t protocol, PyObject *ipAddress, uint32_t port,
uint32_t operations, uint32_t qos); PyObject *callback, uint32_t timeout, uint32_t operations,
uint32_t qos);
PyObject *cxoTransform_dateFromTicks(PyObject *args); PyObject *cxoTransform_dateFromTicks(PyObject *args);
int cxoTransform_fromPython(cxoTransformNum transformNum, PyObject *pyValue, int cxoTransform_fromPython(cxoTransformNum transformNum, PyObject *pyValue,

View File

@ -34,6 +34,7 @@ static PyMemberDef cxoSubscrTypeMembers[] = {
READONLY }, READONLY },
{ "namespace", T_INT, offsetof(cxoSubscr, namespace), READONLY }, { "namespace", T_INT, offsetof(cxoSubscr, namespace), READONLY },
{ "protocol", T_INT, offsetof(cxoSubscr, protocol), READONLY }, { "protocol", T_INT, offsetof(cxoSubscr, protocol), READONLY },
{ "ipAddress", T_OBJECT, offsetof(cxoSubscr, ipAddress), READONLY },
{ "port", T_INT, offsetof(cxoSubscr, port), READONLY }, { "port", T_INT, offsetof(cxoSubscr, port), READONLY },
{ "timeout", T_INT, offsetof(cxoSubscr, timeout), READONLY }, { "timeout", T_INT, offsetof(cxoSubscr, timeout), READONLY },
{ "operations", T_INT, offsetof(cxoSubscr, operations), READONLY }, { "operations", T_INT, offsetof(cxoSubscr, operations), READONLY },
@ -517,11 +518,13 @@ static void cxoSubscr_callback(cxoSubscr *subscr,
// Allocate a new subscription object. // Allocate a new subscription object.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
cxoSubscr *cxoSubscr_new(cxoConnection *connection, uint32_t namespace, cxoSubscr *cxoSubscr_new(cxoConnection *connection, uint32_t namespace,
uint32_t protocol, uint32_t port, PyObject *callback, uint32_t timeout, uint32_t protocol, PyObject *ipAddress, uint32_t port,
uint32_t operations, uint32_t qos) PyObject *callback, uint32_t timeout, uint32_t operations,
uint32_t qos)
{ {
dpiSubscrCreateParams params; dpiSubscrCreateParams params;
cxoSubscr *subscr; cxoSubscr *subscr;
cxoBuffer buffer;
subscr = (cxoSubscr*) cxoPyTypeSubscr.tp_alloc(&cxoPyTypeSubscr, 0); subscr = (cxoSubscr*) cxoPyTypeSubscr.tp_alloc(&cxoPyTypeSubscr, 0);
if (!subscr) if (!subscr)
@ -532,6 +535,8 @@ cxoSubscr *cxoSubscr_new(cxoConnection *connection, uint32_t namespace,
subscr->callback = callback; subscr->callback = callback;
subscr->namespace = namespace; subscr->namespace = namespace;
subscr->protocol = protocol; subscr->protocol = protocol;
Py_XINCREF(ipAddress);
subscr->ipAddress = ipAddress;
subscr->port = port; subscr->port = port;
subscr->timeout = timeout; subscr->timeout = timeout;
subscr->operations = operations; subscr->operations = operations;
@ -539,10 +544,20 @@ cxoSubscr *cxoSubscr_new(cxoConnection *connection, uint32_t namespace,
if (dpiContext_initSubscrCreateParams(cxoDpiContext, &params) < 0) { if (dpiContext_initSubscrCreateParams(cxoDpiContext, &params) < 0) {
cxoError_raiseAndReturnNull(); cxoError_raiseAndReturnNull();
Py_DECREF(subscr);
return NULL; return NULL;
} }
params.subscrNamespace = namespace; params.subscrNamespace = namespace;
params.protocol = protocol; params.protocol = protocol;
if (ipAddress) {
if (cxoBuffer_fromObject(&buffer, ipAddress,
connection->encodingInfo.encoding) < 0) {
Py_DECREF(subscr);
return NULL;
}
params.ipAddress = buffer.ptr;
params.ipAddressLength = buffer.size;
}
params.portNumber = port; params.portNumber = port;
if (callback) { if (callback) {
params.callback = (dpiSubscrCallback) cxoSubscr_callback; params.callback = (dpiSubscrCallback) cxoSubscr_callback;