Added support for binding objects and setting attributes on objects of numbers,
strings and dates.
This commit is contained in:
parent
371717623b
commit
cb3f833a63
@ -56,6 +56,7 @@ static udt_VariableType vt_Boolean = {
|
||||
(FinalizeProc) NULL,
|
||||
(PreDefineProc) NULL,
|
||||
(PostDefineProc) NULL,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) NULL,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) BooleanVar_SetValue,
|
||||
|
||||
20
Connection.c
20
Connection.c
@ -64,6 +64,7 @@ static PyObject *Connection_GetMaxBytesPerCharacter(udt_Connection*, void*);
|
||||
static PyObject *Connection_ContextManagerEnter(udt_Connection*, PyObject*);
|
||||
static PyObject *Connection_ContextManagerExit(udt_Connection*, PyObject*);
|
||||
static PyObject *Connection_ChangePasswordExternal(udt_Connection*, PyObject*);
|
||||
static PyObject *Connection_GetType(udt_Connection*, PyObject*);
|
||||
static PyObject *Connection_GetStmtCacheSize(udt_Connection*, void*);
|
||||
static int Connection_SetStmtCacheSize(udt_Connection*, PyObject*, void*);
|
||||
#if ORACLE_VERSION_HEX >= ORACLE_VERSION(10, 2)
|
||||
@ -112,6 +113,7 @@ static PyMethodDef g_ConnectionMethods[] = {
|
||||
#endif
|
||||
{ "changepassword", (PyCFunction) Connection_ChangePasswordExternal,
|
||||
METH_VARARGS },
|
||||
{ "gettype", (PyCFunction) Connection_GetType, METH_VARARGS },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
@ -1081,6 +1083,24 @@ static int Connection_SetStmtCacheSize(
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Connection_GetType()
|
||||
// Return a type object given its name.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *Connection_GetType(
|
||||
udt_Connection *self, // connection
|
||||
PyObject *args) // arguments
|
||||
{
|
||||
PyObject *nameObj = NULL;
|
||||
|
||||
// parse the arguments
|
||||
if (!PyArg_ParseTuple(args, "O", &nameObj))
|
||||
return NULL;
|
||||
|
||||
return (PyObject*) ObjectType_NewByName(self, nameObj);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Connection_GetVersion()
|
||||
// Retrieve the version of the database and return it. Note that this
|
||||
|
||||
@ -59,6 +59,7 @@ static udt_VariableType vt_Cursor = {
|
||||
(FinalizeProc) CursorVar_Finalize,
|
||||
(PreDefineProc) NULL,
|
||||
(PostDefineProc) NULL,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) NULL,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) CursorVar_SetValue,
|
||||
|
||||
@ -55,6 +55,7 @@ static udt_VariableType vt_DateTime = {
|
||||
(FinalizeProc) NULL,
|
||||
(PreDefineProc) NULL,
|
||||
(PostDefineProc) NULL,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) NULL,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) DateTimeVar_SetValue,
|
||||
@ -76,6 +77,7 @@ static udt_VariableType vt_Date = {
|
||||
(FinalizeProc) NULL,
|
||||
(PreDefineProc) NULL,
|
||||
(PostDefineProc) NULL,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) NULL,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) DateTimeVar_SetValue,
|
||||
@ -101,31 +103,7 @@ static int DateTimeVar_SetValue(
|
||||
unsigned pos, // array position to set
|
||||
PyObject *value) // value to set
|
||||
{
|
||||
ub1 month, day, hour, minute, second;
|
||||
short year;
|
||||
|
||||
if (PyDateTime_Check(value)) {
|
||||
year = (short) PyDateTime_GET_YEAR(value);
|
||||
month = PyDateTime_GET_MONTH(value);
|
||||
day = PyDateTime_GET_DAY(value);
|
||||
hour = PyDateTime_DATE_GET_HOUR(value);
|
||||
minute = PyDateTime_DATE_GET_MINUTE(value);
|
||||
second = PyDateTime_DATE_GET_SECOND(value);
|
||||
} else if (PyDate_Check(value)) {
|
||||
year = (short) PyDateTime_GET_YEAR(value);
|
||||
month = PyDateTime_GET_MONTH(value);
|
||||
day = PyDateTime_GET_DAY(value);
|
||||
hour = minute = second = 0;
|
||||
} else {
|
||||
PyErr_SetString(PyExc_TypeError, "expecting date data");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// store a copy of the value
|
||||
OCIDateSetDate(&var->data[pos], year, month, day);
|
||||
OCIDateSetTime(&var->data[pos], hour, minute, second);
|
||||
|
||||
return 0;
|
||||
return PythonDateToOracleDate(value, &var->data[pos]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -18,6 +18,8 @@ typedef struct {
|
||||
udt_Buffer numberToStringFormatBuffer;
|
||||
udt_Buffer numberFromStringFormatBuffer;
|
||||
udt_Buffer nlsNumericCharactersBuffer;
|
||||
OCIString *tempStringValue;
|
||||
OCIDateTime *tempTimestampValue;
|
||||
} udt_Environment;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -72,6 +74,7 @@ static udt_Environment *Environment_New(
|
||||
env = (udt_Environment*) g_EnvironmentType.tp_alloc(&g_EnvironmentType, 0);
|
||||
if (!env)
|
||||
return NULL;
|
||||
env->handle = handle;
|
||||
env->fixedWidth = 1;
|
||||
env->maxBytesPerCharacter = 1;
|
||||
cxBuffer_Init(&env->numberToStringFormatBuffer);
|
||||
@ -94,7 +97,14 @@ static udt_Environment *Environment_New(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
env->handle = handle;
|
||||
// create the temp datetime handle (used for converting timestamps in
|
||||
// objects)
|
||||
status = OCIDescriptorAlloc(handle, (dvoid**) &env->tempTimestampValue,
|
||||
OCI_DTYPE_TIMESTAMP, 0, 0);
|
||||
if (Environment_CheckForError(env, status,
|
||||
"Environment_New(): create timestamp descriptor") < 0)
|
||||
return NULL;
|
||||
|
||||
return env;
|
||||
}
|
||||
|
||||
|
||||
@ -57,6 +57,7 @@ static udt_VariableType vt_Interval = {
|
||||
(FinalizeProc) IntervalVar_Finalize,
|
||||
(PreDefineProc) NULL,
|
||||
(PostDefineProc) NULL,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) NULL,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) IntervalVar_SetValue,
|
||||
|
||||
4
LobVar.c
4
LobVar.c
@ -134,6 +134,7 @@ static udt_VariableType vt_CLOB = {
|
||||
(FinalizeProc) LobVar_Finalize,
|
||||
(PreDefineProc) NULL,
|
||||
(PostDefineProc) NULL,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) LobVar_PreFetch,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) LobVar_SetValue,
|
||||
@ -155,6 +156,7 @@ static udt_VariableType vt_NCLOB = {
|
||||
(FinalizeProc) LobVar_Finalize,
|
||||
(PreDefineProc) NULL,
|
||||
(PostDefineProc) NULL,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) LobVar_PreFetch,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) LobVar_SetValue,
|
||||
@ -176,6 +178,7 @@ static udt_VariableType vt_BLOB = {
|
||||
(FinalizeProc) LobVar_Finalize,
|
||||
(PreDefineProc) NULL,
|
||||
(PostDefineProc) NULL,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) LobVar_PreFetch,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) LobVar_SetValue,
|
||||
@ -197,6 +200,7 @@ static udt_VariableType vt_BFILE = {
|
||||
(FinalizeProc) LobVar_Finalize,
|
||||
(PreDefineProc) NULL,
|
||||
(PostDefineProc) NULL,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) LobVar_PreFetch,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) LobVar_SetValue,
|
||||
|
||||
@ -106,6 +106,7 @@ static udt_VariableType vt_LongString = {
|
||||
(FinalizeProc) NULL,
|
||||
(PreDefineProc) NULL,
|
||||
(PostDefineProc) NULL,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) NULL,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) LongVar_SetValue,
|
||||
@ -127,6 +128,7 @@ static udt_VariableType vt_LongNationalCharString = {
|
||||
(FinalizeProc) NULL,
|
||||
(PreDefineProc) NULL,
|
||||
(PostDefineProc) NULL,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) NULL,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) LongVar_SetValue,
|
||||
@ -148,6 +150,7 @@ static udt_VariableType vt_LongBinary = {
|
||||
(FinalizeProc) NULL,
|
||||
(PreDefineProc) NULL,
|
||||
(PostDefineProc) NULL,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) NULL,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) LongVar_SetValue,
|
||||
|
||||
249
NumberVar.c
249
NumberVar.c
@ -122,6 +122,7 @@ static udt_VariableType vt_Float = {
|
||||
(FinalizeProc) NULL,
|
||||
(PreDefineProc) NumberVar_PreDefine,
|
||||
(PostDefineProc) NULL,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) NULL,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) NumberVar_SetValue,
|
||||
@ -143,6 +144,7 @@ static udt_VariableType vt_NativeFloat = {
|
||||
(FinalizeProc) NULL,
|
||||
(PreDefineProc) NULL,
|
||||
(PostDefineProc) NULL,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) NULL,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) NativeFloatVar_SetValue,
|
||||
@ -164,6 +166,7 @@ static udt_VariableType vt_NativeInteger = {
|
||||
(FinalizeProc) NULL,
|
||||
(PreDefineProc) NULL,
|
||||
(PostDefineProc) NULL,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) NULL,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) NativeIntVar_SetValue,
|
||||
@ -185,6 +188,7 @@ static udt_VariableType vt_Integer = {
|
||||
(FinalizeProc) NULL,
|
||||
(PreDefineProc) NumberVar_PreDefine,
|
||||
(PostDefineProc) NULL,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) NULL,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) NumberVar_SetValue,
|
||||
@ -206,6 +210,7 @@ static udt_VariableType vt_LongInteger = {
|
||||
(FinalizeProc) NULL,
|
||||
(PreDefineProc) NumberVar_PreDefine,
|
||||
(PostDefineProc) NULL,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) NULL,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) NumberVar_SetValue,
|
||||
@ -227,6 +232,7 @@ static udt_VariableType vt_NumberAsString = {
|
||||
(FinalizeProc) NULL,
|
||||
(PreDefineProc) NumberVar_PreDefine,
|
||||
(PostDefineProc) NULL,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) NULL,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) NumberVar_SetValue,
|
||||
@ -249,6 +255,7 @@ static udt_VariableType vt_Boolean = {
|
||||
(FinalizeProc) NULL,
|
||||
(PreDefineProc) NumberVar_PreDefine,
|
||||
(PostDefineProc) NULL,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) NULL,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) NumberVar_SetValue,
|
||||
@ -306,232 +313,6 @@ static int NumberVar_PreDefine(
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// NumberVar_SetValueFromBoolean()
|
||||
// Set the value of the variable from a Python boolean.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int NumberVar_SetValueFromBoolean(
|
||||
udt_NumberVar *var, // variable to set value for
|
||||
unsigned pos, // array position to set
|
||||
PyObject *value) // value to set
|
||||
{
|
||||
long integerValue;
|
||||
sword status;
|
||||
|
||||
integerValue = (value == Py_True);
|
||||
status = OCINumberFromInt(var->environment->errorHandle, &integerValue,
|
||||
sizeof(long), OCI_NUMBER_SIGNED, &var->data[pos]);
|
||||
return Environment_CheckForError(var->environment, status,
|
||||
"NumberVar_SetValueFromBoolean()");
|
||||
}
|
||||
|
||||
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
//-----------------------------------------------------------------------------
|
||||
// NumberVar_SetValueFromInteger()
|
||||
// Set the value of the variable from a Python integer.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int NumberVar_SetValueFromInteger(
|
||||
udt_NumberVar *var, // variable to set value for
|
||||
unsigned pos, // array position to set
|
||||
PyObject *value) // value to set
|
||||
{
|
||||
long integerValue;
|
||||
sword status;
|
||||
|
||||
integerValue = PyInt_AS_LONG(value);
|
||||
status = OCINumberFromInt(var->environment->errorHandle, &integerValue,
|
||||
sizeof(long), OCI_NUMBER_SIGNED, &var->data[pos]);
|
||||
return Environment_CheckForError(var->environment, status,
|
||||
"NumberVar_SetValueFromInteger()");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// NumberVar_SetValueFromFloat()
|
||||
// Set the value of the variable from a Python float.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int NumberVar_SetValueFromFloat(
|
||||
udt_NumberVar *var, // variable to set value for
|
||||
unsigned pos, // array position to set
|
||||
PyObject *value) // value to set
|
||||
{
|
||||
double doubleValue;
|
||||
sword status;
|
||||
|
||||
doubleValue = PyFloat_AS_DOUBLE(value);
|
||||
status = OCINumberFromReal(var->environment->errorHandle, &doubleValue,
|
||||
sizeof(double), &var->data[pos]);
|
||||
return Environment_CheckForError(var->environment, status,
|
||||
"NumberVar_SetValueFromFloat()");
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// NumberVar_SetValueFromLong()
|
||||
// Set the value of the variable from a Python long.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int NumberVar_SetValueFromLong(
|
||||
udt_NumberVar *var, // variable to set value for
|
||||
unsigned pos, // array position to set
|
||||
PyObject *value) // value to set
|
||||
{
|
||||
udt_Buffer textBuffer;
|
||||
PyObject *textValue;
|
||||
sword status;
|
||||
|
||||
textValue = PyObject_Str(value);
|
||||
if (!textValue)
|
||||
return -1;
|
||||
if (cxBuffer_FromObject(&textBuffer, textValue,
|
||||
var->environment->encoding) < 0)
|
||||
return -1;
|
||||
status = OCINumberFromText(var->environment->errorHandle,
|
||||
(text*) textBuffer.ptr, textBuffer.size,
|
||||
(text*) var->environment->numberFromStringFormatBuffer.ptr,
|
||||
var->environment->numberFromStringFormatBuffer.size, NULL, 0,
|
||||
&var->data[pos]);
|
||||
cxBuffer_Clear(&textBuffer);
|
||||
Py_DECREF(textValue);
|
||||
return Environment_CheckForError(var->environment, status,
|
||||
"NumberVar_SetValueFromLong()");
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// NumberVar_GetFormatAndTextFromDecimal()
|
||||
// Return the number format and text to use for the Decimal object.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int NumberVar_GetFormatAndTextFromDecimal(
|
||||
PyObject *tupleValue, // decimal as_tuple() value
|
||||
PyObject **textObj, // text string for conversion
|
||||
PyObject **formatObj) // format for conversion
|
||||
{
|
||||
long numDigits, scale, i, sign, length, digit;
|
||||
char *textValue, *format, *textPtr, *formatPtr;
|
||||
PyObject *digits;
|
||||
|
||||
// acquire basic information from the value tuple
|
||||
sign = PyInt_AsLong(PyTuple_GET_ITEM(tupleValue, 0));
|
||||
if (PyErr_Occurred())
|
||||
return -1;
|
||||
digits = PyTuple_GET_ITEM(tupleValue, 1);
|
||||
scale = PyInt_AsLong(PyTuple_GET_ITEM(tupleValue, 2));
|
||||
if (PyErr_Occurred())
|
||||
return -1;
|
||||
numDigits = PyTuple_GET_SIZE(digits);
|
||||
|
||||
// allocate memory for the string and format to use in conversion
|
||||
length = numDigits + abs(scale) + 3;
|
||||
textValue = textPtr = PyMem_Malloc(length);
|
||||
if (!textValue) {
|
||||
PyErr_NoMemory();
|
||||
return -1;
|
||||
}
|
||||
format = formatPtr = PyMem_Malloc(length);
|
||||
if (!format) {
|
||||
PyMem_Free(textValue);
|
||||
PyErr_NoMemory();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// populate the string and format
|
||||
if (sign)
|
||||
*textPtr++ = '-';
|
||||
for (i = 0; i < numDigits + scale; i++) {
|
||||
*formatPtr++ = '9';
|
||||
if (i < numDigits) {
|
||||
digit = PyInt_AsLong(PyTuple_GetItem(digits, i));
|
||||
if (PyErr_Occurred()) {
|
||||
PyMem_Free(textValue);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else digit = 0;
|
||||
*textPtr++ = '0' + (char) digit;
|
||||
}
|
||||
if (scale < 0) {
|
||||
*formatPtr++ = 'D';
|
||||
*textPtr++ = '.';
|
||||
for (i = scale; i < 0; i++) {
|
||||
*formatPtr++ = '9';
|
||||
if (numDigits + i < 0)
|
||||
digit = 0;
|
||||
else {
|
||||
digit = PyInt_AsLong(PyTuple_GetItem(digits, numDigits + i));
|
||||
if (PyErr_Occurred()) {
|
||||
PyMem_Free(textValue);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
*textPtr++ = '0' + (char) digit;
|
||||
}
|
||||
}
|
||||
*formatPtr = '\0';
|
||||
*textPtr = '\0';
|
||||
*textObj = cxString_FromAscii(textValue);
|
||||
PyMem_Free(textValue);
|
||||
if (!*textObj) {
|
||||
PyMem_Free(format);
|
||||
return -1;
|
||||
}
|
||||
*formatObj = cxString_FromAscii(format);
|
||||
PyMem_Free(format);
|
||||
if (!*formatObj) {
|
||||
Py_DECREF(*textObj);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// NumberVar_SetValueFromDecimal()
|
||||
// Set the value of the variable from a Python decimal.Decimal object.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int NumberVar_SetValueFromDecimal(
|
||||
udt_NumberVar *var, // variable to set value for
|
||||
unsigned pos, // array position to set
|
||||
PyObject *value) // value to set
|
||||
{
|
||||
PyObject *textValue, *format, *tupleValue;
|
||||
udt_Buffer textBuffer, formatBuffer;
|
||||
sword status;
|
||||
|
||||
tupleValue = PyObject_CallMethod(value, "as_tuple", NULL);
|
||||
if (!tupleValue)
|
||||
return -1;
|
||||
if (NumberVar_GetFormatAndTextFromDecimal(tupleValue, &textValue,
|
||||
&format) < 0) {
|
||||
Py_DECREF(tupleValue);
|
||||
return -1;
|
||||
}
|
||||
Py_DECREF(tupleValue);
|
||||
if (cxBuffer_FromObject(&textBuffer, textValue,
|
||||
var->environment->encoding) < 0)
|
||||
return -1;
|
||||
if (cxBuffer_FromObject(&formatBuffer, format,
|
||||
var->environment->encoding) < 0) {
|
||||
cxBuffer_Clear(&textBuffer);
|
||||
return -1;
|
||||
}
|
||||
status = OCINumberFromText(var->environment->errorHandle,
|
||||
(text*) textBuffer.ptr, textBuffer.size, (text*) formatBuffer.ptr,
|
||||
formatBuffer.size,
|
||||
var->environment->nlsNumericCharactersBuffer.ptr,
|
||||
var->environment->nlsNumericCharactersBuffer.size,
|
||||
&var->data[pos]);
|
||||
cxBuffer_Clear(&textBuffer);
|
||||
cxBuffer_Clear(&formatBuffer);
|
||||
Py_DECREF(textValue);
|
||||
Py_DECREF(format);
|
||||
return Environment_CheckForError(var->environment, status,
|
||||
"NumberVar_SetValueFromDecimal()");
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// NumberVar_SetValue()
|
||||
// Set the value of the variable.
|
||||
@ -541,20 +322,8 @@ static int NumberVar_SetValue(
|
||||
unsigned pos, // array position to set
|
||||
PyObject *value) // value to set
|
||||
{
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
if (PyInt_Check(value))
|
||||
return NumberVar_SetValueFromInteger(var, pos, value);
|
||||
#endif
|
||||
if (PyBool_Check(value))
|
||||
return NumberVar_SetValueFromBoolean(var, pos, value);
|
||||
if (PyLong_Check(value))
|
||||
return NumberVar_SetValueFromLong(var, pos, value);
|
||||
if (PyFloat_Check(value))
|
||||
return NumberVar_SetValueFromFloat(var, pos, value);
|
||||
if (Py_TYPE(value) == g_DecimalType)
|
||||
return NumberVar_SetValueFromDecimal(var, pos, value);
|
||||
PyErr_SetString(PyExc_TypeError, "expecting numeric data");
|
||||
return -1;
|
||||
return PythonNumberToOracleNumber(var->environment, value,
|
||||
&var->data[pos]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
140
Object.c
140
Object.c
@ -20,6 +20,7 @@ typedef struct {
|
||||
//-----------------------------------------------------------------------------
|
||||
static void Object_Free(udt_Object*);
|
||||
static PyObject *Object_GetAttr(udt_Object*, PyObject*);
|
||||
static int Object_SetAttr(udt_Object*, PyObject*, PyObject*);
|
||||
static PyObject *Object_ConvertToPython(udt_Environment*, OCITypeCode, dvoid*,
|
||||
dvoid*, udt_ObjectType*);
|
||||
|
||||
@ -52,7 +53,7 @@ static PyTypeObject g_ObjectType = {
|
||||
0, // tp_call
|
||||
0, // tp_str
|
||||
(getattrofunc) Object_GetAttr, // tp_getattro
|
||||
0, // tp_setattro
|
||||
(setattrofunc) Object_SetAttr, // tp_setattro
|
||||
0, // tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT, // tp_flags
|
||||
0, // tp_doc
|
||||
@ -99,9 +100,9 @@ static void Object_Free(
|
||||
udt_Object *self) // variable to free
|
||||
{
|
||||
if (self->isIndependent)
|
||||
OCIObjectFree(self->objectType->environment->handle,
|
||||
self->objectType->environment->errorHandle,
|
||||
self->instance, OCI_OBJECTFREE_FORCE);
|
||||
OCIObjectFree(self->objectType->connection->environment->handle,
|
||||
self->objectType->connection->environment->errorHandle,
|
||||
self->instance, OCI_DEFAULT);
|
||||
Py_CLEAR(self->objectType);
|
||||
Py_TYPE(self)->tp_free((PyObject*) self);
|
||||
}
|
||||
@ -243,21 +244,23 @@ static PyObject *Object_GetAttributeValue(
|
||||
{
|
||||
dvoid *valueIndicator, *value;
|
||||
OCIInd scalarValueIndicator;
|
||||
udt_Connection *connection;
|
||||
udt_Buffer buffer;
|
||||
sword status;
|
||||
OCIType *tdo;
|
||||
|
||||
// get the value for the attribute
|
||||
connection = self->objectType->connection;
|
||||
if (cxBuffer_FromObject(&buffer, attribute->name,
|
||||
self->objectType->environment->encoding) < 0)
|
||||
connection->environment->encoding) < 0)
|
||||
return NULL;
|
||||
status = OCIObjectGetAttr(self->objectType->environment->handle,
|
||||
self->objectType->environment->errorHandle, self->instance,
|
||||
status = OCIObjectGetAttr(connection->environment->handle,
|
||||
connection->environment->errorHandle, self->instance,
|
||||
self->indicator, self->objectType->tdo,
|
||||
(const OraText**) &buffer.ptr, (ub4*) &buffer.size, 1, 0, 0,
|
||||
&scalarValueIndicator, &valueIndicator, &value, &tdo);
|
||||
cxBuffer_Clear(&buffer);
|
||||
if (Environment_CheckForError(self->objectType->environment, status,
|
||||
if (Environment_CheckForError(connection->environment, status,
|
||||
"Object_GetAttributeValue(): getting value") < 0)
|
||||
return NULL;
|
||||
|
||||
@ -265,14 +268,111 @@ static PyObject *Object_GetAttributeValue(
|
||||
if (!valueIndicator)
|
||||
valueIndicator = &scalarValueIndicator;
|
||||
|
||||
return Object_ConvertToPython(self->objectType->environment,
|
||||
return Object_ConvertToPython(connection->environment,
|
||||
attribute->typeCode, value, valueIndicator, attribute->subType);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Object_SetAttributeValue()
|
||||
// Set an attribute on the object.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int Object_SetAttributeValue(
|
||||
udt_Object *self, // object
|
||||
udt_ObjectAttribute *attribute, // attribute to set
|
||||
PyObject *value) // value to set
|
||||
{
|
||||
dvoid *ociValueIndicator, *ociValue;
|
||||
OCIInd ociScalarValueIndicator;
|
||||
udt_Connection *connection;
|
||||
OCINumber numericValue;
|
||||
udt_Buffer buffer;
|
||||
OCIDate dateValue;
|
||||
sword status;
|
||||
|
||||
// initialization
|
||||
ociValue = NULL;
|
||||
ociValueIndicator = NULL;
|
||||
connection = self->objectType->connection;
|
||||
|
||||
// None is treated as null
|
||||
if (value == Py_None) {
|
||||
ociScalarValueIndicator = OCI_IND_NULL;
|
||||
|
||||
// all other values need to be converted
|
||||
} else {
|
||||
|
||||
ociScalarValueIndicator = OCI_IND_NOTNULL;
|
||||
switch (attribute->typeCode) {
|
||||
case OCI_TYPECODE_CHAR:
|
||||
case OCI_TYPECODE_VARCHAR:
|
||||
case OCI_TYPECODE_VARCHAR2:
|
||||
if (cxBuffer_FromObject(&buffer, value,
|
||||
connection->environment->encoding) < 0)
|
||||
return -1;
|
||||
status = OCIStringAssignText(connection->environment->handle,
|
||||
connection->environment->errorHandle, buffer.ptr,
|
||||
buffer.size,
|
||||
&connection->environment->tempStringValue);
|
||||
cxBuffer_Clear(&buffer);
|
||||
if (Environment_CheckForError(connection->environment, status,
|
||||
"Object_SetAttributeValue(): assigning string") < 0)
|
||||
return -1;
|
||||
ociValue = connection->environment->tempStringValue;
|
||||
break;
|
||||
case OCI_TYPECODE_NUMBER:
|
||||
ociValue = &numericValue;
|
||||
if (PythonNumberToOracleNumber(connection->environment, value,
|
||||
ociValue) < 0)
|
||||
return -1;
|
||||
break;
|
||||
case OCI_TYPECODE_DATE:
|
||||
ociValue = &dateValue;
|
||||
if (PythonDateToOracleDate(value, ociValue) < 0)
|
||||
return -1;
|
||||
break;
|
||||
case OCI_TYPECODE_TIMESTAMP:
|
||||
ociValue = connection->environment->tempTimestampValue;
|
||||
if (PythonDateToOracleTimestamp(connection->environment, value,
|
||||
ociValue) < 0)
|
||||
return -1;
|
||||
break;
|
||||
case OCI_TYPECODE_OBJECT:
|
||||
break;
|
||||
case OCI_TYPECODE_NAMEDCOLLECTION:
|
||||
break;
|
||||
};
|
||||
|
||||
if (!ociValue) {
|
||||
PyErr_Format(g_NotSupportedErrorException,
|
||||
"Object_SetAttributeValue(): unhandled data type %d",
|
||||
attribute->typeCode);
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// set the value for the attribute
|
||||
if (cxBuffer_FromObject(&buffer, attribute->name,
|
||||
connection->environment->encoding) < 0)
|
||||
return -1;
|
||||
status = OCIObjectSetAttr(connection->environment->handle,
|
||||
connection->environment->errorHandle, self->instance,
|
||||
self->indicator, self->objectType->tdo,
|
||||
(const OraText**) &buffer.ptr, (ub4*) &buffer.size, 1, 0, 0,
|
||||
ociScalarValueIndicator, ociValueIndicator, ociValue);
|
||||
cxBuffer_Clear(&buffer);
|
||||
if (Environment_CheckForError(connection->environment, status,
|
||||
"Object_SetAttributeValue(): setting value") < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Object_GetAttr()
|
||||
// Retrieve an attribute on object.
|
||||
// Retrieve an attribute on an object.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *Object_GetAttr(
|
||||
udt_Object *self, // object
|
||||
@ -288,3 +388,23 @@ static PyObject *Object_GetAttr(
|
||||
return PyObject_GenericGetAttr( (PyObject*) self, nameObject);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Object_SetAttr()
|
||||
// Set an attribute on an object.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int Object_SetAttr(
|
||||
udt_Object *self, // object
|
||||
PyObject *nameObject, // name of attribute
|
||||
PyObject *value) // value to set
|
||||
{
|
||||
udt_ObjectAttribute *attribute;
|
||||
|
||||
attribute = (udt_ObjectAttribute*)
|
||||
PyDict_GetItem(self->objectType->attributesByName, nameObject);
|
||||
if (attribute)
|
||||
return Object_SetAttributeValue(self, attribute, value);
|
||||
|
||||
return PyObject_GenericSetAttr( (PyObject*) self, nameObject, value);
|
||||
}
|
||||
|
||||
|
||||
140
ObjectType.c
140
ObjectType.c
@ -8,7 +8,7 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
udt_Environment *environment;
|
||||
udt_Connection *connection;
|
||||
OCIType *tdo;
|
||||
PyObject *schema;
|
||||
PyObject *name;
|
||||
@ -27,6 +27,7 @@ typedef struct {
|
||||
udt_ObjectType *subType;
|
||||
} udt_ObjectAttribute;
|
||||
|
||||
#include "Object.c"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Declaration of type variable functions.
|
||||
@ -34,11 +35,21 @@ 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 udt_ObjectAttribute *ObjectAttribute_New(udt_Connection*, OCIParam*);
|
||||
static void ObjectAttribute_Free(udt_ObjectAttribute*);
|
||||
static PyObject *ObjectAttribute_Repr(udt_ObjectAttribute*);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// declaration of methods for Python type "ObjectType"
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyMethodDef g_ObjectTypeMethods[] = {
|
||||
{ "newobject", (PyCFunction) ObjectType_NewObject, METH_NOARGS },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// declaration of members for Python type "ObjectType"
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -90,7 +101,7 @@ static PyTypeObject g_ObjectTypeType = {
|
||||
0, // tp_weaklistoffset
|
||||
0, // tp_iter
|
||||
0, // tp_iternext
|
||||
0, // tp_methods
|
||||
g_ObjectTypeMethods, // tp_methods
|
||||
g_ObjectTypeMembers, // tp_members
|
||||
0, // tp_getset
|
||||
0, // tp_base
|
||||
@ -158,7 +169,6 @@ static PyTypeObject g_ObjectAttributeType = {
|
||||
//-----------------------------------------------------------------------------
|
||||
static int ObjectType_Describe(
|
||||
udt_ObjectType *self, // type to populate
|
||||
udt_Connection *connection, // connection for type information
|
||||
OCIDescribe *describeHandle) // describe handle
|
||||
{
|
||||
OCIParam *topLevelParam, *attributeListParam, *attributeParam;
|
||||
@ -170,24 +180,24 @@ static int ObjectType_Describe(
|
||||
int i;
|
||||
|
||||
// describe the type
|
||||
status = OCIDescribeAny(connection->handle, self->environment->errorHandle,
|
||||
(dvoid*) self->tdo, 0, OCI_OTYPE_PTR, OCI_DEFAULT, OCI_PTYPE_TYPE,
|
||||
describeHandle);
|
||||
if (Environment_CheckForError(self->environment, status,
|
||||
status = OCIDescribeAny(self->connection->handle,
|
||||
self->connection->environment->errorHandle, (dvoid*) self->tdo, 0,
|
||||
OCI_OTYPE_PTR, OCI_DEFAULT, OCI_PTYPE_TYPE, describeHandle);
|
||||
if (Environment_CheckForError(self->connection->environment, status,
|
||||
"ObjectType_Describe(): describe type") < 0)
|
||||
return -1;
|
||||
|
||||
// get top level parameter descriptor
|
||||
status = OCIAttrGet(describeHandle, OCI_HTYPE_DESCRIBE, &topLevelParam, 0,
|
||||
OCI_ATTR_PARAM, self->environment->errorHandle);
|
||||
if (Environment_CheckForError(self->environment, status,
|
||||
OCI_ATTR_PARAM, self->connection->environment->errorHandle);
|
||||
if (Environment_CheckForError(self->connection->environment, status,
|
||||
"ObjectType_Describe(): get top level parameter descriptor") < 0)
|
||||
return -1;
|
||||
|
||||
// determine type of type
|
||||
status = OCIAttrGet(topLevelParam, OCI_DTYPE_PARAM, &typeCode, 0,
|
||||
OCI_ATTR_TYPECODE, self->environment->errorHandle);
|
||||
if (Environment_CheckForError(self->environment, status,
|
||||
OCI_ATTR_TYPECODE, self->connection->environment->errorHandle);
|
||||
if (Environment_CheckForError(self->connection->environment, status,
|
||||
"ObjectType_Describe(): get type code") < 0)
|
||||
return -1;
|
||||
|
||||
@ -198,31 +208,31 @@ static int ObjectType_Describe(
|
||||
// determine type of collection
|
||||
status = OCIAttrGet(topLevelParam, OCI_DTYPE_PARAM,
|
||||
&self->collectionTypeCode, 0, OCI_ATTR_COLLECTION_TYPECODE,
|
||||
self->environment->errorHandle);
|
||||
if (Environment_CheckForError(self->environment, status,
|
||||
self->connection->environment->errorHandle);
|
||||
if (Environment_CheckForError(self->connection->environment, status,
|
||||
"ObjectType_Describe(): get collection type code") < 0)
|
||||
return -1;
|
||||
|
||||
// acquire collection parameter descriptor
|
||||
status = OCIAttrGet(topLevelParam, OCI_DTYPE_PARAM, &collectionParam,
|
||||
0, OCI_ATTR_COLLECTION_ELEMENT,
|
||||
self->environment->errorHandle);
|
||||
if (Environment_CheckForError(self->environment, status,
|
||||
self->connection->environment->errorHandle);
|
||||
if (Environment_CheckForError(self->connection->environment, status,
|
||||
"ObjectType_Describe(): get collection descriptor") < 0)
|
||||
return -1;
|
||||
|
||||
// determine type of element
|
||||
status = OCIAttrGet(collectionParam, OCI_DTYPE_PARAM,
|
||||
&self->elementTypeCode, 0, OCI_ATTR_TYPECODE,
|
||||
self->environment->errorHandle);
|
||||
if (Environment_CheckForError(self->environment, status,
|
||||
self->connection->environment->errorHandle);
|
||||
if (Environment_CheckForError(self->connection->environment, status,
|
||||
"ObjectType_Describe(): get element type code") < 0)
|
||||
return -1;
|
||||
|
||||
// if element type is an object type get its type
|
||||
if (self->elementTypeCode == OCI_TYPECODE_OBJECT) {
|
||||
self->elementType = (PyObject*)
|
||||
ObjectType_New(connection, collectionParam,
|
||||
ObjectType_New(self->connection, collectionParam,
|
||||
OCI_ATTR_TYPE_NAME);
|
||||
if (!self->elementType)
|
||||
return -1;
|
||||
@ -233,8 +243,8 @@ static int ObjectType_Describe(
|
||||
// determine the number of attributes
|
||||
status = OCIAttrGet(topLevelParam, OCI_DTYPE_PARAM,
|
||||
(dvoid*) &numAttributes, 0, OCI_ATTR_NUM_TYPE_ATTRS,
|
||||
self->environment->errorHandle);
|
||||
if (Environment_CheckForError(self->environment, status,
|
||||
self->connection->environment->errorHandle);
|
||||
if (Environment_CheckForError(self->connection->environment, status,
|
||||
"ObjectType_Describe(): get number of attributes") < 0)
|
||||
return -1;
|
||||
|
||||
@ -249,20 +259,20 @@ static int ObjectType_Describe(
|
||||
// acquire the list parameter descriptor
|
||||
status = OCIAttrGet(topLevelParam, OCI_DTYPE_PARAM,
|
||||
(dvoid*) &attributeListParam, 0, OCI_ATTR_LIST_TYPE_ATTRS,
|
||||
self->environment->errorHandle);
|
||||
if (Environment_CheckForError(self->environment, status,
|
||||
self->connection->environment->errorHandle);
|
||||
if (Environment_CheckForError(self->connection->environment, status,
|
||||
"ObjectType_Describe(): get list parameter descriptor") < 0)
|
||||
return -1;
|
||||
|
||||
// create attribute information for each attribute
|
||||
for (i = 0; i < numAttributes; i++) {
|
||||
status = OCIParamGet(attributeListParam, OCI_DTYPE_PARAM,
|
||||
self->environment->errorHandle, (dvoid**) &attributeParam,
|
||||
(ub4) i + 1);
|
||||
if (Environment_CheckForError(self->environment, status,
|
||||
self->connection->environment->errorHandle,
|
||||
(dvoid**) &attributeParam, (ub4) i + 1);
|
||||
if (Environment_CheckForError(self->connection->environment, status,
|
||||
"ObjectType_Describe(): get attribute param descriptor") < 0)
|
||||
return -1;
|
||||
attribute = ObjectAttribute_New(connection, attributeParam);
|
||||
attribute = ObjectAttribute_New(self->connection, attributeParam);
|
||||
if (!attribute)
|
||||
return -1;
|
||||
PyList_SET_ITEM(self->attributes, i, (PyObject*) attribute);
|
||||
@ -281,7 +291,6 @@ static int ObjectType_Describe(
|
||||
//-----------------------------------------------------------------------------
|
||||
static int ObjectType_Initialize(
|
||||
udt_ObjectType *self, // type to initialize
|
||||
udt_Connection *connection, // connection for type information
|
||||
OCIParam *param, // parameter descriptor
|
||||
ub4 nameAttribute) // value for the name attribute
|
||||
{
|
||||
@ -293,53 +302,54 @@ static int ObjectType_Initialize(
|
||||
|
||||
// determine the schema of the type
|
||||
status = OCIAttrGet(param, OCI_HTYPE_DESCRIBE, (dvoid*) &name, &size,
|
||||
OCI_ATTR_SCHEMA_NAME, self->environment->errorHandle);
|
||||
if (Environment_CheckForError(self->environment, status,
|
||||
OCI_ATTR_SCHEMA_NAME, self->connection->environment->errorHandle);
|
||||
if (Environment_CheckForError(self->connection->environment, status,
|
||||
"ObjectType_Initialize(): get schema name") < 0)
|
||||
return -1;
|
||||
self->schema = cxString_FromEncodedString(name, size,
|
||||
self->environment->encoding);
|
||||
self->connection->environment->encoding);
|
||||
if (!self->schema)
|
||||
return -1;
|
||||
|
||||
// determine the name of the type
|
||||
status = OCIAttrGet(param, OCI_HTYPE_DESCRIBE, (dvoid*) &name, &size,
|
||||
nameAttribute, self->environment->errorHandle);
|
||||
if (Environment_CheckForError(self->environment, status,
|
||||
nameAttribute, self->connection->environment->errorHandle);
|
||||
if (Environment_CheckForError(self->connection->environment, status,
|
||||
"ObjectType_Initialize(): get name") < 0)
|
||||
return -1;
|
||||
self->name = cxString_FromEncodedString(name, size,
|
||||
self->environment->encoding);
|
||||
self->connection->environment->encoding);
|
||||
if (!self->name)
|
||||
return -1;
|
||||
|
||||
// retrieve TDO of the parameter
|
||||
status = OCIAttrGet(param, OCI_HTYPE_DESCRIBE, (dvoid*) &tdoReference, 0,
|
||||
OCI_ATTR_REF_TDO, self->environment->errorHandle);
|
||||
if (Environment_CheckForError(self->environment, status,
|
||||
OCI_ATTR_REF_TDO, self->connection->environment->errorHandle);
|
||||
if (Environment_CheckForError(self->connection->environment, status,
|
||||
"ObjectType_Initialize(): get TDO reference") < 0)
|
||||
return -1;
|
||||
status = OCIObjectPin(self->environment->handle,
|
||||
self->environment->errorHandle, tdoReference, NULL, OCI_PIN_ANY,
|
||||
OCI_DURATION_SESSION, OCI_LOCK_NONE, (dvoid**) &self->tdo);
|
||||
if (Environment_CheckForError(self->environment, status,
|
||||
status = OCIObjectPin(self->connection->environment->handle,
|
||||
self->connection->environment->errorHandle, tdoReference, NULL,
|
||||
OCI_PIN_ANY, OCI_DURATION_SESSION, OCI_LOCK_NONE,
|
||||
(dvoid**) &self->tdo);
|
||||
if (Environment_CheckForError(self->connection->environment, status,
|
||||
"ObjectType_Initialize(): pin TDO reference") < 0)
|
||||
return -1;
|
||||
|
||||
// acquire a describe handle
|
||||
status = OCIHandleAlloc(self->environment->handle,
|
||||
status = OCIHandleAlloc(self->connection->environment->handle,
|
||||
(dvoid**) &describeHandle, OCI_HTYPE_DESCRIBE, 0, 0);
|
||||
if (Environment_CheckForError(self->environment, status,
|
||||
if (Environment_CheckForError(self->connection->environment, status,
|
||||
"ObjectType_Initialize(): allocate describe handle") < 0)
|
||||
return -1;
|
||||
|
||||
// describe the type
|
||||
if (ObjectType_Describe(self, connection, describeHandle) < 0)
|
||||
if (ObjectType_Describe(self, describeHandle) < 0)
|
||||
return -1;
|
||||
|
||||
// free the describe handle
|
||||
status = OCIHandleFree(describeHandle, OCI_HTYPE_DESCRIBE);
|
||||
if (Environment_CheckForError(self->environment, status,
|
||||
if (Environment_CheckForError(self->connection->environment, status,
|
||||
"ObjectType_Initialize(): free describe handle") < 0)
|
||||
return -1;
|
||||
|
||||
@ -361,9 +371,9 @@ static udt_ObjectType *ObjectType_New(
|
||||
self = (udt_ObjectType*) g_ObjectTypeType.tp_alloc(&g_ObjectTypeType, 0);
|
||||
if (!self)
|
||||
return NULL;
|
||||
Py_INCREF(connection->environment);
|
||||
self->environment = connection->environment;
|
||||
if (ObjectType_Initialize(self, connection, param, nameAttribute) < 0) {
|
||||
Py_INCREF(connection);
|
||||
self->connection = connection;
|
||||
if (ObjectType_Initialize(self, param, nameAttribute) < 0) {
|
||||
Py_DECREF(self);
|
||||
return NULL;
|
||||
}
|
||||
@ -443,9 +453,9 @@ static void ObjectType_Free(
|
||||
udt_ObjectType *self) // object type to free
|
||||
{
|
||||
if (self->tdo)
|
||||
OCIObjectUnpin(self->environment->handle,
|
||||
self->environment->errorHandle, self->tdo);
|
||||
Py_CLEAR(self->environment);
|
||||
OCIObjectUnpin(self->connection->environment->handle,
|
||||
self->connection->environment->errorHandle, self->tdo);
|
||||
Py_CLEAR(self->connection);
|
||||
Py_CLEAR(self->schema);
|
||||
Py_CLEAR(self->name);
|
||||
Py_CLEAR(self->attributes);
|
||||
@ -486,6 +496,38 @@ static PyObject *ObjectType_Repr(
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ObjectType_NewObject()
|
||||
// Factory function for creating objects of the type which can be bound.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *ObjectType_NewObject(
|
||||
udt_ObjectType *self, // object type to return the string for
|
||||
PyObject *args) // arguments (none, ignored)
|
||||
{
|
||||
dvoid *instance, *indicator;
|
||||
sword status;
|
||||
|
||||
// create the object instance
|
||||
status = OCIObjectNew(self->connection->environment->handle,
|
||||
self->connection->environment->errorHandle,
|
||||
self->connection->handle, OCI_TYPECODE_OBJECT, self->tdo, NULL,
|
||||
OCI_DURATION_SESSION, TRUE, &instance);
|
||||
if (Environment_CheckForError(self->connection->environment, status,
|
||||
"ObjectType_NewObject(): create object instance") < 0)
|
||||
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)
|
||||
return NULL;
|
||||
|
||||
return Object_New(self, instance, indicator, 1);
|
||||
}
|
||||
|
||||
|
||||
static PyObject *ObjectType_NewObject(udt_ObjectType*, PyObject*);
|
||||
//-----------------------------------------------------------------------------
|
||||
// ObjectAttribute_Initialize()
|
||||
// Initialize the new object attribute.
|
||||
|
||||
70
ObjectVar.c
70
ObjectVar.c
@ -4,7 +4,6 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "ObjectType.c"
|
||||
#include "Object.c"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Object type
|
||||
@ -23,9 +22,11 @@ typedef struct {
|
||||
//-----------------------------------------------------------------------------
|
||||
static int ObjectVar_Initialize(udt_ObjectVar*, udt_Cursor*);
|
||||
static void ObjectVar_Finalize(udt_ObjectVar*);
|
||||
static int ObjectVar_SetValue(udt_ObjectVar*, unsigned, PyObject*);
|
||||
static PyObject *ObjectVar_GetValue(udt_ObjectVar*, unsigned);
|
||||
static int ObjectVar_PreDefine(udt_ObjectVar*, OCIParam*);
|
||||
static int ObjectVar_PostDefine(udt_ObjectVar*);
|
||||
static int ObjectVar_PostBind(udt_ObjectVar*);
|
||||
static int ObjectVar_PreFetch(udt_ObjectVar*);
|
||||
static int ObjectVar_IsNull(udt_ObjectVar*, unsigned);
|
||||
|
||||
@ -82,9 +83,10 @@ static udt_VariableType vt_Object = {
|
||||
(FinalizeProc) ObjectVar_Finalize,
|
||||
(PreDefineProc) ObjectVar_PreDefine,
|
||||
(PostDefineProc) ObjectVar_PostDefine,
|
||||
(PostBindProc) ObjectVar_PostBind,
|
||||
(PreFetchProc) ObjectVar_PreFetch,
|
||||
(IsNullProc) ObjectVar_IsNull,
|
||||
(SetValueProc) NULL,
|
||||
(SetValueProc) ObjectVar_SetValue,
|
||||
(GetValueProc) ObjectVar_GetValue,
|
||||
(GetBufferSizeProc) NULL,
|
||||
&g_ObjectVarType, // Python type
|
||||
@ -142,8 +144,9 @@ static void ObjectVar_Finalize(
|
||||
ub4 i;
|
||||
|
||||
for (i = 0; i < self->allocatedElements; i++) {
|
||||
Py_CLEAR(self->objects[i]);
|
||||
if (self->data[i])
|
||||
if (self->objects[i])
|
||||
Py_CLEAR(self->objects[i]);
|
||||
else if (self->data[i])
|
||||
OCIObjectFree(self->environment->handle,
|
||||
self->environment->errorHandle, self->data[i],
|
||||
OCI_DEFAULT);
|
||||
@ -190,6 +193,22 @@ static int ObjectVar_PostDefine(
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ObjectVar_PostBind()
|
||||
// Performs additional steps required for binding objects.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int ObjectVar_PostBind(
|
||||
udt_ObjectVar *self) // variable to set up
|
||||
{
|
||||
sword status;
|
||||
|
||||
status = OCIBindObject(self->bindHandle, self->environment->errorHandle,
|
||||
self->objectType->tdo, self->data, 0, self->objectIndicator, 0);
|
||||
return Environment_CheckForError(self->environment, status,
|
||||
"ObjectVar_PostBind(): bind object");
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ObjectVar_PreFetch()
|
||||
// Free objects prior to next fetch.
|
||||
@ -224,6 +243,47 @@ static int ObjectVar_IsNull(
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ObjectVar_SetValue()
|
||||
// Set the value of the variable.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int ObjectVar_SetValue(
|
||||
udt_ObjectVar *self, // variable to determine value for
|
||||
unsigned pos, // array position
|
||||
PyObject *value) // value to set
|
||||
{
|
||||
udt_Object *object;
|
||||
|
||||
// only cx_Oracle.Object values are permitted and the types must match
|
||||
// if the variable doesn't have a type yet, assign it
|
||||
if (Py_TYPE(value) != &g_ObjectType) {
|
||||
PyErr_SetString(PyExc_TypeError, "expecting cx_Oracle.Object");
|
||||
return -1;
|
||||
}
|
||||
object = (udt_Object*) value;
|
||||
if (!self->objectType) {
|
||||
Py_INCREF(object->objectType);
|
||||
self->objectType = object->objectType;
|
||||
} else if (object->objectType != self->objectType) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"expecting same type as the variable itself");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// eliminate prior value, if needed
|
||||
if (self->objects[pos])
|
||||
Py_CLEAR(self->objects[pos]);
|
||||
else OCIObjectFree(self->environment->handle,
|
||||
self->environment->errorHandle, self->data[pos], OCI_DEFAULT);
|
||||
|
||||
// set new value
|
||||
Py_INCREF(value);
|
||||
self->objects[pos] = value;
|
||||
self->data[pos] = object->instance;
|
||||
self->objectIndicator[pos] = object->indicator;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ObjectVar_GetValue()
|
||||
// Returns the value stored at the given array position.
|
||||
@ -245,8 +305,6 @@ static PyObject *ObjectVar_GetValue(
|
||||
if (!obj)
|
||||
return NULL;
|
||||
self->objects[pos] = obj;
|
||||
self->data[pos] = NULL;
|
||||
self->objectIndicator[pos] = NULL;
|
||||
}
|
||||
|
||||
Py_INCREF(self->objects[pos]);
|
||||
|
||||
@ -182,6 +182,7 @@ static udt_VariableType vt_String = {
|
||||
(FinalizeProc) NULL,
|
||||
(PreDefineProc) NULL,
|
||||
(PostDefineProc) NULL,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) NULL,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) StringVar_SetValue,
|
||||
@ -203,6 +204,7 @@ static udt_VariableType vt_NationalCharString = {
|
||||
(FinalizeProc) NULL,
|
||||
(PreDefineProc) NULL,
|
||||
(PostDefineProc) StringVar_PostDefine,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) NULL,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) StringVar_SetValue,
|
||||
@ -224,6 +226,7 @@ static udt_VariableType vt_FixedChar = {
|
||||
(FinalizeProc) NULL,
|
||||
(PreDefineProc) NULL,
|
||||
(PostDefineProc) NULL,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) NULL,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) StringVar_SetValue,
|
||||
@ -245,6 +248,7 @@ static udt_VariableType vt_FixedNationalChar = {
|
||||
(FinalizeProc) NULL,
|
||||
(PreDefineProc) NULL,
|
||||
(PostDefineProc) StringVar_PostDefine,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) NULL,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) StringVar_SetValue,
|
||||
@ -266,6 +270,7 @@ static udt_VariableType vt_Rowid = {
|
||||
(FinalizeProc) NULL,
|
||||
(PreDefineProc) NULL,
|
||||
(PostDefineProc) NULL,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) NULL,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) StringVar_SetValue,
|
||||
@ -287,6 +292,7 @@ static udt_VariableType vt_Binary = {
|
||||
(FinalizeProc) NULL,
|
||||
(PreDefineProc) NULL,
|
||||
(PostDefineProc) NULL,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) NULL,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) StringVar_SetValue,
|
||||
|
||||
@ -57,6 +57,7 @@ static udt_VariableType vt_Timestamp = {
|
||||
(FinalizeProc) TimestampVar_Finalize,
|
||||
(PreDefineProc) NULL,
|
||||
(PostDefineProc) NULL,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) NULL,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) TimestampVar_SetValue,
|
||||
@ -122,39 +123,8 @@ static int TimestampVar_SetValue(
|
||||
unsigned pos, // array position to set
|
||||
PyObject *value) // value to set
|
||||
{
|
||||
sword status;
|
||||
uword valid;
|
||||
|
||||
// make sure a timestamp is being bound
|
||||
if (!PyDateTime_Check(value)) {
|
||||
PyErr_SetString(PyExc_TypeError, "expecting timestamp data");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// store a copy of the value
|
||||
status = OCIDateTimeConstruct(var->environment->handle,
|
||||
var->environment->errorHandle, var->data[pos],
|
||||
(sb2) PyDateTime_GET_YEAR(value),
|
||||
PyDateTime_GET_MONTH(value),
|
||||
PyDateTime_GET_DAY(value),
|
||||
PyDateTime_DATE_GET_HOUR(value),
|
||||
PyDateTime_DATE_GET_MINUTE(value),
|
||||
PyDateTime_DATE_GET_SECOND(value),
|
||||
PyDateTime_DATE_GET_MICROSECOND(value) * 1000, NULL, 0);
|
||||
if (Environment_CheckForError(var->environment, status,
|
||||
"TimestampVar_SetValue(): create structure") < 0)
|
||||
return -1;
|
||||
status = OCIDateTimeCheck(var->environment->handle,
|
||||
var->environment->errorHandle, var->data[pos], &valid);
|
||||
if (Environment_CheckForError(var->environment, status,
|
||||
"TimestampVar_SetValue()") < 0)
|
||||
return -1;
|
||||
if (valid != 0) {
|
||||
PyErr_SetString(g_DataErrorException, "invalid date");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return PythonDateToOracleTimestamp(var->environment, value,
|
||||
var->data[pos]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
332
Transforms.c
332
Transforms.c
@ -96,3 +96,335 @@ static PyObject *OracleNumberToPythonFloat(
|
||||
return PyFloat_FromDouble(doubleValue);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PythonBooleanToOracleNumber()
|
||||
// Transform a Python boolean into an Oracle number.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int PythonBooleanToOracleNumber(
|
||||
udt_Environment *environment, // environment
|
||||
PyObject *pythonValue, // Python value to convert
|
||||
OCINumber *oracleValue) // Oracle value to set
|
||||
{
|
||||
long integerValue;
|
||||
sword status;
|
||||
|
||||
integerValue = (pythonValue == Py_True);
|
||||
status = OCINumberFromInt(environment->errorHandle, &integerValue,
|
||||
sizeof(long), OCI_NUMBER_SIGNED, oracleValue);
|
||||
return Environment_CheckForError(environment, status,
|
||||
"PythonBooleanToOracleNumber()");
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PythonDateToOracleDate()
|
||||
// Transform a Python date into an Oracle date.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int PythonDateToOracleDate(
|
||||
PyObject *pythonValue, // Python value to convert
|
||||
OCIDate *oracleValue) // Oracle value to set
|
||||
{
|
||||
ub1 month, day, hour, minute, second;
|
||||
sb2 year;
|
||||
|
||||
if (PyDateTime_Check(pythonValue)) {
|
||||
year = (short) PyDateTime_GET_YEAR(pythonValue);
|
||||
month = PyDateTime_GET_MONTH(pythonValue);
|
||||
day = PyDateTime_GET_DAY(pythonValue);
|
||||
hour = PyDateTime_DATE_GET_HOUR(pythonValue);
|
||||
minute = PyDateTime_DATE_GET_MINUTE(pythonValue);
|
||||
second = PyDateTime_DATE_GET_SECOND(pythonValue);
|
||||
} else if (PyDate_Check(pythonValue)) {
|
||||
year = (short) PyDateTime_GET_YEAR(pythonValue);
|
||||
month = PyDateTime_GET_MONTH(pythonValue);
|
||||
day = PyDateTime_GET_DAY(pythonValue);
|
||||
hour = minute = second = 0;
|
||||
} else {
|
||||
PyErr_SetString(PyExc_TypeError, "expecting date data");
|
||||
return -1;
|
||||
}
|
||||
|
||||
OCIDateSetDate(oracleValue, year, month, day);
|
||||
OCIDateSetTime(oracleValue, hour, minute, second);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
//-----------------------------------------------------------------------------
|
||||
// PythonIntegerToOracleNumber()
|
||||
// Transform a Python integer into an Oracle number.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int PythonIntegerToOracleNumber(
|
||||
udt_Environment *environment, // environment
|
||||
PyObject *pythonValue, // Python value to convert
|
||||
OCINumber *oracleValue) // Oracle value to set
|
||||
{
|
||||
long integerValue;
|
||||
sword status;
|
||||
|
||||
integerValue = PyInt_AS_LONG(pythonValue);
|
||||
status = OCINumberFromInt(environment->errorHandle, &integerValue,
|
||||
sizeof(long), OCI_NUMBER_SIGNED, oracleValue);
|
||||
return Environment_CheckForError(environment, status,
|
||||
"PythonIntegerToOracleNumber()");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PythonFloatToOracleNumber()
|
||||
// Transform a Python float into an Oracle number.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int PythonFloatToOracleNumber(
|
||||
udt_Environment *environment, // environment
|
||||
PyObject *pythonValue, // Python value to convert
|
||||
OCINumber *oracleValue) // Oracle value to set
|
||||
{
|
||||
double doubleValue;
|
||||
sword status;
|
||||
|
||||
doubleValue = PyFloat_AS_DOUBLE(pythonValue);
|
||||
status = OCINumberFromReal(environment->errorHandle, &doubleValue,
|
||||
sizeof(double), oracleValue);
|
||||
return Environment_CheckForError(environment, status,
|
||||
"PythonFloatToOracleNumber()");
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PythonLongToOracleNumber()
|
||||
// Set the value of the variable from a Python long.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int PythonLongToOracleNumber(
|
||||
udt_Environment *environment, // environment
|
||||
PyObject *pythonValue, // Python value to convert
|
||||
OCINumber *oracleValue) // Oracle value to set
|
||||
{
|
||||
udt_Buffer textBuffer;
|
||||
PyObject *textValue;
|
||||
sword status;
|
||||
|
||||
textValue = PyObject_Str(pythonValue);
|
||||
if (!textValue)
|
||||
return -1;
|
||||
if (cxBuffer_FromObject(&textBuffer, textValue, environment->encoding) < 0)
|
||||
return -1;
|
||||
status = OCINumberFromText(environment->errorHandle,
|
||||
(text*) textBuffer.ptr, textBuffer.size,
|
||||
(text*) environment->numberFromStringFormatBuffer.ptr,
|
||||
environment->numberFromStringFormatBuffer.size, NULL, 0,
|
||||
oracleValue);
|
||||
cxBuffer_Clear(&textBuffer);
|
||||
Py_DECREF(textValue);
|
||||
return Environment_CheckForError(environment, status,
|
||||
"PythonLongToOracleNumber()");
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// GetFormatAndTextFromPythonDecimal()
|
||||
// Return the number format and text to use for the Decimal object.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int GetFormatAndTextFromPythonDecimal(
|
||||
PyObject *tupleValue, // decimal as_tuple() value
|
||||
PyObject **textObj, // text string for conversion
|
||||
PyObject **formatObj) // format for conversion
|
||||
{
|
||||
long numDigits, scale, i, sign, length, digit;
|
||||
char *textValue, *format, *textPtr, *formatPtr;
|
||||
PyObject *digits;
|
||||
|
||||
// acquire basic information from the value tuple
|
||||
sign = PyInt_AsLong(PyTuple_GET_ITEM(tupleValue, 0));
|
||||
if (PyErr_Occurred())
|
||||
return -1;
|
||||
digits = PyTuple_GET_ITEM(tupleValue, 1);
|
||||
scale = PyInt_AsLong(PyTuple_GET_ITEM(tupleValue, 2));
|
||||
if (PyErr_Occurred())
|
||||
return -1;
|
||||
numDigits = PyTuple_GET_SIZE(digits);
|
||||
|
||||
// allocate memory for the string and format to use in conversion
|
||||
length = numDigits + abs(scale) + 3;
|
||||
textValue = textPtr = PyMem_Malloc(length);
|
||||
if (!textValue) {
|
||||
PyErr_NoMemory();
|
||||
return -1;
|
||||
}
|
||||
format = formatPtr = PyMem_Malloc(length);
|
||||
if (!format) {
|
||||
PyMem_Free(textValue);
|
||||
PyErr_NoMemory();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// populate the string and format
|
||||
if (sign)
|
||||
*textPtr++ = '-';
|
||||
for (i = 0; i < numDigits + scale; i++) {
|
||||
*formatPtr++ = '9';
|
||||
if (i < numDigits) {
|
||||
digit = PyInt_AsLong(PyTuple_GetItem(digits, i));
|
||||
if (PyErr_Occurred()) {
|
||||
PyMem_Free(textValue);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else digit = 0;
|
||||
*textPtr++ = '0' + (char) digit;
|
||||
}
|
||||
if (scale < 0) {
|
||||
*formatPtr++ = 'D';
|
||||
*textPtr++ = '.';
|
||||
for (i = scale; i < 0; i++) {
|
||||
*formatPtr++ = '9';
|
||||
if (numDigits + i < 0)
|
||||
digit = 0;
|
||||
else {
|
||||
digit = PyInt_AsLong(PyTuple_GetItem(digits, numDigits + i));
|
||||
if (PyErr_Occurred()) {
|
||||
PyMem_Free(textValue);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
*textPtr++ = '0' + (char) digit;
|
||||
}
|
||||
}
|
||||
*formatPtr = '\0';
|
||||
*textPtr = '\0';
|
||||
*textObj = cxString_FromAscii(textValue);
|
||||
PyMem_Free(textValue);
|
||||
if (!*textObj) {
|
||||
PyMem_Free(format);
|
||||
return -1;
|
||||
}
|
||||
*formatObj = cxString_FromAscii(format);
|
||||
PyMem_Free(format);
|
||||
if (!*formatObj) {
|
||||
Py_DECREF(*textObj);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PythonDecimalToOracleNumber()
|
||||
// Transform a Python decimal object into an Oracle number.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int PythonDecimalToOracleNumber(
|
||||
udt_Environment *environment, // environment
|
||||
PyObject *pythonValue, // Python value to convert
|
||||
OCINumber *oracleValue) // Oracle value to set
|
||||
{
|
||||
PyObject *textValue, *format, *tupleValue;
|
||||
udt_Buffer textBuffer, formatBuffer;
|
||||
sword status;
|
||||
|
||||
tupleValue = PyObject_CallMethod(pythonValue, "as_tuple", NULL);
|
||||
if (!tupleValue)
|
||||
return -1;
|
||||
if (GetFormatAndTextFromPythonDecimal(tupleValue, &textValue,
|
||||
&format) < 0) {
|
||||
Py_DECREF(tupleValue);
|
||||
return -1;
|
||||
}
|
||||
Py_DECREF(tupleValue);
|
||||
if (cxBuffer_FromObject(&textBuffer, textValue, environment->encoding) < 0)
|
||||
return -1;
|
||||
if (cxBuffer_FromObject(&formatBuffer, format,
|
||||
environment->encoding) < 0) {
|
||||
cxBuffer_Clear(&textBuffer);
|
||||
return -1;
|
||||
}
|
||||
status = OCINumberFromText(environment->errorHandle,
|
||||
(text*) textBuffer.ptr, textBuffer.size, (text*) formatBuffer.ptr,
|
||||
formatBuffer.size, environment->nlsNumericCharactersBuffer.ptr,
|
||||
environment->nlsNumericCharactersBuffer.size, oracleValue);
|
||||
cxBuffer_Clear(&textBuffer);
|
||||
cxBuffer_Clear(&formatBuffer);
|
||||
Py_DECREF(textValue);
|
||||
Py_DECREF(format);
|
||||
return Environment_CheckForError(environment, status,
|
||||
"PythonDecimalToOracleNumber()");
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PythonNumberToOracleNumber()
|
||||
// Convert a Python number to an Oracle number.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int PythonNumberToOracleNumber(
|
||||
udt_Environment *environment, // environment
|
||||
PyObject *pythonValue, // Python value
|
||||
OCINumber* oracleValue) // Oracle value
|
||||
{
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
if (PyInt_Check(pythonValue))
|
||||
return PythonIntegerToOracleNumber(environment, pythonValue,
|
||||
oracleValue);
|
||||
#endif
|
||||
if (PyBool_Check(pythonValue))
|
||||
return PythonBooleanToOracleNumber(environment, pythonValue,
|
||||
oracleValue);
|
||||
if (PyLong_Check(pythonValue))
|
||||
return PythonLongToOracleNumber(environment, pythonValue, oracleValue);
|
||||
if (PyFloat_Check(pythonValue))
|
||||
return PythonFloatToOracleNumber(environment, pythonValue,
|
||||
oracleValue);
|
||||
if (Py_TYPE(pythonValue) == g_DecimalType)
|
||||
return PythonDecimalToOracleNumber(environment, pythonValue,
|
||||
oracleValue);
|
||||
PyErr_SetString(PyExc_TypeError, "expecting numeric data");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PythonDateToOracleTimestamp()
|
||||
// Convert a Python date to an Oracle timestamp.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int PythonDateToOracleTimestamp(
|
||||
udt_Environment *environment, // environment
|
||||
PyObject *pythonValue, // Python value
|
||||
OCIDateTime* oracleValue) // Oracle value
|
||||
{
|
||||
sword status;
|
||||
uword valid;
|
||||
|
||||
// make sure a timestamp is being bound
|
||||
if (!PyDateTime_Check(pythonValue)) {
|
||||
PyErr_SetString(PyExc_TypeError, "expecting timestamp data");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// store a copy of the value
|
||||
status = OCIDateTimeConstruct(environment->handle,
|
||||
environment->errorHandle, oracleValue,
|
||||
(sb2) PyDateTime_GET_YEAR(pythonValue),
|
||||
PyDateTime_GET_MONTH(pythonValue),
|
||||
PyDateTime_GET_DAY(pythonValue),
|
||||
PyDateTime_DATE_GET_HOUR(pythonValue),
|
||||
PyDateTime_DATE_GET_MINUTE(pythonValue),
|
||||
PyDateTime_DATE_GET_SECOND(pythonValue),
|
||||
PyDateTime_DATE_GET_MICROSECOND(pythonValue) * 1000, NULL, 0);
|
||||
if (Environment_CheckForError(environment, status,
|
||||
"PythonDateToOracleTimestamp(): create structure") < 0)
|
||||
return -1;
|
||||
status = OCIDateTimeCheck(environment->handle, environment->errorHandle,
|
||||
oracleValue, &valid);
|
||||
if (Environment_CheckForError(environment, status,
|
||||
"PythonDateToOracleTimestamp(): check validity") < 0)
|
||||
return -1;
|
||||
if (valid != 0) {
|
||||
PyErr_SetString(g_DataErrorException, "invalid date");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
13
Variable.c
13
Variable.c
@ -53,6 +53,7 @@ typedef int (*InitializeProc)(udt_Variable*, udt_Cursor*);
|
||||
typedef void (*FinalizeProc)(udt_Variable*);
|
||||
typedef int (*PreDefineProc)(udt_Variable*, OCIParam*);
|
||||
typedef int (*PostDefineProc)(udt_Variable*);
|
||||
typedef int (*PostBindProc)(udt_Variable*);
|
||||
typedef int (*PreFetchProc)(udt_Variable*);
|
||||
typedef int (*IsNullProc)(udt_Variable*, unsigned);
|
||||
typedef int (*SetValueProc)(udt_Variable*, unsigned, PyObject*);
|
||||
@ -68,6 +69,7 @@ typedef struct _udt_VariableType {
|
||||
FinalizeProc finalizeProc;
|
||||
PreDefineProc preDefineProc;
|
||||
PostDefineProc postDefineProc;
|
||||
PostBindProc postBindProc;
|
||||
PreFetchProc preFetchProc;
|
||||
IsNullProc isNullProc;
|
||||
SetValueProc setValueProc;
|
||||
@ -371,6 +373,7 @@ static int Variable_Check(
|
||||
Py_TYPE(object) == &g_BinaryVarType ||
|
||||
Py_TYPE(object) == &g_TimestampVarType ||
|
||||
Py_TYPE(object) == &g_IntervalVarType ||
|
||||
Py_TYPE(object) == &g_ObjectVarType ||
|
||||
#if ORACLE_VERSION_HEX >= ORACLE_VERSION(12,1)
|
||||
Py_TYPE(object) == &g_BooleanVarType ||
|
||||
#endif
|
||||
@ -461,6 +464,8 @@ static udt_VariableType *Variable_TypeByPythonType(
|
||||
return &vt_NativeInteger;
|
||||
if (type == (PyObject*) &g_ObjectVarType)
|
||||
return &vt_Object;
|
||||
if (type == (PyObject*) &g_ObjectType)
|
||||
return &vt_Object;
|
||||
|
||||
PyErr_SetString(g_NotSupportedErrorException,
|
||||
"Variable_TypeByPythonType(): unhandled data type");
|
||||
@ -538,6 +543,8 @@ static udt_VariableType *Variable_TypeByValue(
|
||||
return &vt_DateTime;
|
||||
if (Py_TYPE(value) == g_DecimalType)
|
||||
return &vt_NumberAsString;
|
||||
if (Py_TYPE(value) == &g_ObjectType)
|
||||
return &vt_Object;
|
||||
|
||||
// handle arrays
|
||||
if (PyList_Check(value)) {
|
||||
@ -1119,6 +1126,12 @@ static int Variable_InternalBind(
|
||||
return -1;
|
||||
}
|
||||
|
||||
// call the procedure to set values after define
|
||||
if (var->type->postBindProc) {
|
||||
if ((*var->type->postBindProc)(var) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -169,6 +169,19 @@ Connection Object
|
||||
available in Python 2.x when not built in unicode mode.
|
||||
|
||||
|
||||
.. method:: Connection.gettype(name)
|
||||
|
||||
Return a type object (:ref:`objecttype`) given its name. This can then be
|
||||
used to create objects which can be bound to cursors created by this
|
||||
connection.
|
||||
|
||||
.. versionadded:: development
|
||||
|
||||
.. note::
|
||||
|
||||
This method is an extension to the DB API definition.
|
||||
|
||||
|
||||
.. attribute:: Connection.inputtypehandler
|
||||
|
||||
This read-write attribute specifies a method called for each value that is
|
||||
|
||||
@ -490,9 +490,7 @@ Cursor Object
|
||||
outconverter specify methods used for converting values to/from the
|
||||
database. More information can be found in the section on variable objects.
|
||||
|
||||
To create an empty SQL object variable, specify the typename. Additional
|
||||
support for editing the attributes of this object is not yet available but
|
||||
will be forthcoming in a future release.
|
||||
To create an empty SQL object variable, specify the typename.
|
||||
|
||||
This method was designed for use with PL/SQL in/out variables where the
|
||||
length or type cannot be determined automatically from the Python object
|
||||
|
||||
@ -21,6 +21,7 @@ Contents:
|
||||
session_pool.rst
|
||||
subscription.rst
|
||||
lob.rst
|
||||
objecttype.rst
|
||||
releasenotes.rst
|
||||
license.rst
|
||||
|
||||
|
||||
35
doc/objecttype.rst
Normal file
35
doc/objecttype.rst
Normal file
@ -0,0 +1,35 @@
|
||||
.. _objecttype:
|
||||
|
||||
*******************
|
||||
Object Type Objects
|
||||
*******************
|
||||
|
||||
.. note::
|
||||
|
||||
This object is an extension to the DB API. It is returned by the
|
||||
:meth:`~Connection.gettype()` call and is available as the
|
||||
:data:`~Variable.type` for variables containing Oracle objects.
|
||||
|
||||
|
||||
.. attribute:: ObjectType.attributes
|
||||
|
||||
This read-only attribute returns a list of the attributes that make up the
|
||||
object type. Each attribute has a name attribute on it.
|
||||
|
||||
|
||||
.. attribute:: ObjectType.name
|
||||
|
||||
This read-only attribute returns the name of the type.
|
||||
|
||||
|
||||
.. method:: ObjectType.newobject()
|
||||
|
||||
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.
|
||||
|
||||
|
||||
.. attribute:: ObjectType.schema
|
||||
|
||||
This read-only attribute returns the name of the schema that owns the type.
|
||||
|
||||
@ -73,3 +73,10 @@ Variable Objects
|
||||
value is the size in characters. For all others, this is same value as the
|
||||
attribute bufferSize.
|
||||
|
||||
|
||||
.. attribute:: Variable.type
|
||||
|
||||
This read-only attribute returns the type of the variable for those
|
||||
variables that bind Oracle objects (it is not present for any other type of
|
||||
variable).
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user