As requested by Helge Tesdal, allow an output type handler to be specified
at the connection and cursor levels. This handler will be called for each variable being defined with the parameters cursor, name, defaultType, size, precision and scale and expects to have a variable of the correct type returned or None to indicate that default processing should take place.
This commit is contained in:
parent
64eeeabda7
commit
780423a59e
@ -13,6 +13,7 @@ typedef struct {
|
||||
OCISession *sessionHandle;
|
||||
udt_Environment *environment;
|
||||
udt_SessionPool *sessionPool;
|
||||
PyObject *outputTypeHandler;
|
||||
PyObject *username;
|
||||
PyObject *password;
|
||||
PyObject *dsn;
|
||||
@ -105,6 +106,8 @@ static PyMemberDef g_ConnectionMembers[] = {
|
||||
{ "dsn", T_OBJECT, offsetof(udt_Connection, dsn), READONLY },
|
||||
{ "tnsentry", T_OBJECT, offsetof(udt_Connection, dsn), READONLY },
|
||||
{ "autocommit", T_INT, offsetof(udt_Connection, autocommit), 0 },
|
||||
{ "outputtypehandler", T_OBJECT,
|
||||
offsetof(udt_Connection, outputTypeHandler), 0 },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
||||
3
Cursor.c
3
Cursor.c
@ -16,6 +16,7 @@ typedef struct {
|
||||
PyObject *bindVariables;
|
||||
PyObject *fetchVariables;
|
||||
PyObject *rowFactory;
|
||||
PyObject *outputTypeHandler;
|
||||
int arraySize;
|
||||
int bindArraySize;
|
||||
int fetchArraySize;
|
||||
@ -109,6 +110,8 @@ static PyMemberDef g_CursorMembers[] = {
|
||||
{ "connection", T_OBJECT_EX, offsetof(udt_Cursor, connection), READONLY },
|
||||
{ "numbersAsStrings", T_INT, offsetof(udt_Cursor, numbersAsStrings), 0 },
|
||||
{ "rowfactory", T_OBJECT, offsetof(udt_Cursor, rowFactory), 0 },
|
||||
{ "outputtypehandler", T_OBJECT, offsetof(udt_Cursor, outputTypeHandler),
|
||||
0 },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
||||
75
Variable.c
75
Variable.c
@ -637,6 +637,71 @@ static udt_Variable *Variable_NewByType(
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Variable_NewByOutputTypeHandler()
|
||||
// Create a new variable by calling the output type handler.
|
||||
//-----------------------------------------------------------------------------
|
||||
static udt_Variable *Variable_NewByOutputTypeHandler(
|
||||
udt_Cursor *cursor, // cursor to associate variable with
|
||||
OCIParam *param, // parameter descriptor
|
||||
PyObject *outputTypeHandler, // method to call to get type
|
||||
udt_VariableType *varType, // variable type already chosen
|
||||
ub4 maxLength, // maximum length of variable
|
||||
unsigned numElements) // number of elements
|
||||
{
|
||||
PyObject *result;
|
||||
ub4 nameLength;
|
||||
sb2 precision;
|
||||
sword status;
|
||||
char *name;
|
||||
sb1 scale;
|
||||
|
||||
// determine name of variable
|
||||
status = OCIAttrGet(param, OCI_HTYPE_DESCRIBE, (dvoid*) &name,
|
||||
&nameLength, OCI_ATTR_NAME, cursor->environment->errorHandle);
|
||||
if (Environment_CheckForError(cursor->environment, status,
|
||||
"Variable_NewByOutputTypeHandler(): get name") < 0)
|
||||
return NULL;
|
||||
|
||||
// retrieve scale and precision of the parameter, if applicable
|
||||
scale = precision = 0;
|
||||
if (varType->pythonType == &g_NumberVarType) {
|
||||
status = OCIAttrGet(param, OCI_HTYPE_DESCRIBE, (dvoid*) &scale, 0,
|
||||
OCI_ATTR_SCALE, cursor->environment->errorHandle);
|
||||
if (Environment_CheckForError(cursor->environment, status,
|
||||
"Variable_NewByOutputTypeHandler(): get scale") < 0)
|
||||
return NULL;
|
||||
status = OCIAttrGet(param, OCI_HTYPE_DESCRIBE, (dvoid*) &precision, 0,
|
||||
OCI_ATTR_PRECISION, cursor->environment->errorHandle);
|
||||
if (Environment_CheckForError(cursor->environment, status,
|
||||
"Variable_NewByOutputTypeHandler(): get precision") < 0)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// call method, passing parameters
|
||||
result = PyObject_CallFunction(outputTypeHandler, "Os#Oiii",
|
||||
cursor, name, nameLength, varType->pythonType, maxLength,
|
||||
precision, scale);
|
||||
if (!result)
|
||||
return NULL;
|
||||
|
||||
// if result is None, assume default behavior
|
||||
if (result == Py_None) {
|
||||
Py_DECREF(result);
|
||||
return Variable_New(cursor, numElements, varType, maxLength);
|
||||
}
|
||||
|
||||
// otherwise, return the result, ensuring it is a variable first
|
||||
if (!Variable_Check(result)) {
|
||||
Py_DECREF(result);
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"expecting variable from output type handler");
|
||||
return NULL;
|
||||
}
|
||||
return (udt_Variable*) result;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Variable_DefineHelper()
|
||||
// Helper routine for Variable_Define() used so that constant calls to
|
||||
@ -707,7 +772,15 @@ static udt_Variable *Variable_DefineHelper(
|
||||
}
|
||||
|
||||
// create a variable of the correct type
|
||||
var = Variable_New(cursor, numElements, varType, maxLength);
|
||||
if (cursor->outputTypeHandler && cursor->outputTypeHandler != Py_None)
|
||||
var = Variable_NewByOutputTypeHandler(cursor, param,
|
||||
cursor->outputTypeHandler, varType, maxLength, numElements);
|
||||
else if (cursor->connection->outputTypeHandler &&
|
||||
cursor->connection->outputTypeHandler != Py_None)
|
||||
var = Variable_NewByOutputTypeHandler(cursor, param,
|
||||
cursor->connection->outputTypeHandler, varType, maxLength,
|
||||
numElements);
|
||||
else var = Variable_New(cursor, numElements, varType, maxLength);
|
||||
if (!var)
|
||||
return NULL;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user