Fixed support for native doubles and floats in Oracle 10g; added new type

NATIVE_FLOAT to allow specification of a variable of that specific type where
desired. Thanks to D.R. Boxhoorn for pointing out the fact that this was not
working properly when the arraysize was anything other than 1.
This commit is contained in:
Anthony Tuininga 2007-06-27 14:34:34 +00:00
parent 5025b4eb22
commit 21f1839d1a
4 changed files with 84 additions and 36 deletions

View File

@ -10,7 +10,7 @@ static const char gc_NumberFormat[63] =
"999999999999999999999999999999999999999999999999999999999999999";
//-----------------------------------------------------------------------------
// Number type
// Number types
//-----------------------------------------------------------------------------
typedef struct {
Variable_HEAD
@ -18,6 +18,14 @@ typedef struct {
} udt_NumberVar;
#ifdef SQLT_BFLOAT
typedef struct {
Variable_HEAD
double *data;
} udt_NativeFloatVar;
#endif
//-----------------------------------------------------------------------------
// Declaration of number variable functions.
//-----------------------------------------------------------------------------
@ -25,8 +33,8 @@ static int NumberVar_PreDefine(udt_NumberVar*, OCIParam*);
static int NumberVar_SetValue(udt_NumberVar*, unsigned, PyObject*);
static PyObject *NumberVar_GetValue(udt_NumberVar*, unsigned);
#ifdef SQLT_BFLOAT
static int NumberVar_SetValueAsDouble(udt_NumberVar*, unsigned, PyObject*);
static PyObject *NumberVar_GetValueAsDouble(udt_NumberVar*, unsigned);
static int NativeFloatVar_SetValue(udt_NativeFloatVar*, unsigned, PyObject*);
static PyObject *NativeFloatVar_GetValue(udt_NativeFloatVar*, unsigned);
#endif
@ -59,6 +67,34 @@ static PyTypeObject g_NumberVarType = {
};
#ifdef SQLT_BFLOAT
static PyTypeObject g_NativeFloatVarType = {
PyObject_HEAD_INIT(NULL)
0, // ob_size
"cx_Oracle.NATIVE_FLOAT", // tp_name
sizeof(udt_NativeFloatVar), // tp_basicsize
0, // tp_itemsize
(destructor) Variable_Free, // tp_dealloc
0, // tp_print
0, // tp_getattr
0, // tp_setattr
0, // tp_compare
(reprfunc) Variable_Repr, // tp_repr
0, // tp_as_number
0, // tp_as_sequence
0, // tp_as_mapping
0, // tp_hash
0, // tp_call
0, // tp_str
(getattrofunc) Variable_GetAttr, // tp_getattro
0, // tp_setattro
0, // tp_as_buffer
Py_TPFLAGS_DEFAULT, // tp_flags
0 // tp_doc
};
#endif
//-----------------------------------------------------------------------------
// variable type declarations
//-----------------------------------------------------------------------------
@ -87,9 +123,9 @@ static udt_VariableType vt_NativeFloat = {
(PreDefineProc) NULL,
(PostDefineProc) NULL,
(IsNullProc) NULL,
(SetValueProc) NumberVar_SetValueAsDouble,
(GetValueProc) NumberVar_GetValueAsDouble,
&g_NumberVarType, // Python type
(SetValueProc) NativeFloatVar_SetValue,
(GetValueProc) NativeFloatVar_GetValue,
&g_NativeFloatVarType, // Python type
SQLT_BDOUBLE, // Oracle type
SQLCS_IMPLICIT, // charset form
sizeof(double), // element length
@ -415,30 +451,6 @@ static int NumberVar_SetValue(
}
#ifdef SQLT_BFLOAT
//-----------------------------------------------------------------------------
// NumberVar_SetValueAsDouble()
// Set the value of the variable which should be a native double.
//-----------------------------------------------------------------------------
static int NumberVar_SetValueAsDouble(
udt_NumberVar *var, // variable to set value for
unsigned pos, // array position to set
PyObject *value) // value to set
{
double *doublePtr;
if (!PyFloat_Check(value)) {
PyErr_SetString(PyExc_TypeError, "expecting float");
return -1;
}
doublePtr = (double*) &var->data[pos];
*doublePtr = PyFloat_AS_DOUBLE(value);
return 0;
}
#endif
//-----------------------------------------------------------------------------
// NumberVar_GetValue()
// Returns the value stored at the given array position.
@ -492,17 +504,32 @@ static PyObject *NumberVar_GetValue(
#ifdef SQLT_BFLOAT
//-----------------------------------------------------------------------------
// NumberVar_GetValueAsDouble()
// NativeFloatVar_GetValue()
// Returns the value stored at the given array position as a float.
//-----------------------------------------------------------------------------
static PyObject *NumberVar_GetValueAsDouble(
udt_NumberVar *var, // variable to determine value for
static PyObject *NativeFloatVar_GetValue(
udt_NativeFloatVar *var, // variable to determine value for
unsigned pos) // array position
{
double *doublePtr;
return PyFloat_FromDouble(var->data[pos]);
}
doublePtr = (double*) &var->data[pos];
return PyFloat_FromDouble(*doublePtr);
//-----------------------------------------------------------------------------
// NativeFloatVar_SetValue()
// Set the value of the variable which should be a native double.
//-----------------------------------------------------------------------------
static int NativeFloatVar_SetValue(
udt_NativeFloatVar *var, // variable to set value for
unsigned pos, // array position to set
PyObject *value) // value to set
{
if (!PyFloat_Check(value)) {
PyErr_SetString(PyExc_TypeError, "expecting float");
return -1;
}
var->data[pos] = PyFloat_AS_DOUBLE(value);
return 0;
}
#endif

View File

@ -282,6 +282,9 @@ static int Variable_Check(
object->ob_type == &g_BinaryVarType
#ifdef ORACLE_9I
|| object->ob_type == &g_TimestampVarType
#endif
#ifdef SQLT_BFLOAT
|| object->ob_type == &g_NativeFloatVarType
#endif
);
}
@ -350,6 +353,10 @@ static udt_VariableType *Variable_TypeByPythonType(
#endif
if (type == (PyObject*) &g_CursorVarType)
return &vt_Cursor;
#ifdef SQLT_BFLOAT
if (type == (PyObject*) &g_NativeFloatVarType)
return &vt_NativeFloat;
#endif
PyErr_SetString(g_NotSupportedErrorException,
"Variable_TypeByPythonType(): unhandled data type");

View File

@ -355,6 +355,10 @@ void initcx_Oracle(void)
return;
if (PyType_Ready(&g_ExternalObjectVarType) < 0)
return;
#ifdef SQLT_BFLOAT
if (PyType_Ready(&g_NativeFloatVarType) < 0)
return;
#endif
// initialize module and retrieve the dictionary
module = Py_InitModule("cx_Oracle", g_ModuleMethods);
@ -434,6 +438,9 @@ void initcx_Oracle(void)
#ifdef ORACLE_9I
ADD_TYPE_OBJECT("TIMESTAMP", &g_TimestampVarType)
#endif
#ifdef SQLT_BFLOAT
ADD_TYPE_OBJECT("NATIVE_FLOAT", &g_NativeFloatVarType)
#endif
// create constants required by Python DB API 2.0
if (PyModule_AddStringConstant(module, "apilevel", "2.0") < 0)

View File

@ -258,6 +258,13 @@ information on the Python database API specification.
\strong{NOTE:} This attribute is an extension to the DB API definition.
\end{datadesc}
\begin{datadesc}{NATIVE_FLOAT}
This type object is used to describe columns in a database that are of type
binary_double or binary_float and is only available in Oracle 10g.
\strong{NOTE:} This attribute is an extension to the DB API definition.
\end{datadesc}
\begin{datadesc}{NCLOB}
This type object is used to describe columns in a database that are NCLOBs.