Add support for setting a CLOB attribute on a SQL object, as requested

(https://github.com/oracle/python-cx_Oracle/issues/299).
This commit is contained in:
Anthony Tuininga 2019-04-29 11:41:28 -06:00
parent ce511e2fb7
commit 82097891b3
7 changed files with 45 additions and 14 deletions

2
odpi

@ -1 +1 @@
Subproject commit e0c1f03eaea9954863cff77ac26bbcde4bd29807 Subproject commit 0fe226c8b5b15b0cc42ab8e638f4bb875c78d479

View File

@ -371,11 +371,13 @@ static int cxoConnectionParams_processShardingKeyValue(
cxoConnectionParams *params, PyObject *value, cxoConnectionParams *params, PyObject *value,
dpiShardingKeyColumn *column, cxoBuffer *buffer) dpiShardingKeyColumn *column, cxoBuffer *buffer)
{ {
dpiNativeTypeNum nativeTypeNum;
cxoTransformNum transformNum; cxoTransformNum transformNum;
transformNum = cxoTransform_getNumFromValue(value, 0); transformNum = cxoTransform_getNumFromValue(value, 0);
if (cxoTransform_fromPython(transformNum, value, &column->value, buffer, if (cxoTransform_fromPython(transformNum, &nativeTypeNum, value,
params->encoding, params->nencoding, NULL, 0) < 0) &column->value, buffer, params->encoding, params->nencoding, NULL,
0) < 0)
return -1; return -1;
cxoTransform_getTypeInfo(transformNum, &column->oracleTypeNum, cxoTransform_getTypeInfo(transformNum, &column->oracleTypeNum,
&column->nativeTypeNum); &column->nativeTypeNum);

View File

@ -504,7 +504,8 @@ cxoSodaOperation *cxoSodaOperation_new(cxoSodaCollection *collection);
void cxoSubscr_callback(cxoSubscr *subscr, dpiSubscrMessage *message); void cxoSubscr_callback(cxoSubscr *subscr, dpiSubscrMessage *message);
PyObject *cxoTransform_dateFromTicks(PyObject *args); PyObject *cxoTransform_dateFromTicks(PyObject *args);
int cxoTransform_fromPython(cxoTransformNum transformNum, PyObject *pyValue, int cxoTransform_fromPython(cxoTransformNum transformNum,
dpiNativeTypeNum *nativeTypeNum, PyObject *pyValue,
dpiDataBuffer *dbValue, cxoBuffer *buffer, const char *encoding, dpiDataBuffer *dbValue, cxoBuffer *buffer, const char *encoding,
const char *nencoding, cxoVar *var, uint32_t arrayPos); const char *nencoding, cxoVar *var, uint32_t arrayPos);
cxoTransformNum cxoTransform_getNumFromDataTypeInfo(dpiDataTypeInfo *info); cxoTransformNum cxoTransform_getNumFromDataTypeInfo(dpiDataTypeInfo *info);

View File

@ -176,7 +176,8 @@ static int cxoObject_convertFromPython(cxoObject *obj, PyObject *value,
// convert the different Python types // convert the different Python types
cxoTransform_getTypeInfo(transformNum, &oracleTypeNum, nativeTypeNum); cxoTransform_getTypeInfo(transformNum, &oracleTypeNum, nativeTypeNum);
if (cxoTransform_fromPython(transformNum, value, &data->value, buffer, if (cxoTransform_fromPython(transformNum, nativeTypeNum, value,
&data->value, buffer,
obj->objectType->connection->encodingInfo.encoding, obj->objectType->connection->encodingInfo.encoding,
obj->objectType->connection->encodingInfo.nencoding, NULL, 0) < 0) obj->objectType->connection->encodingInfo.nencoding, NULL, 0) < 0)
return -1; return -1;

View File

@ -193,7 +193,8 @@ PyObject *cxoTransform_dateFromTicks(PyObject *args)
// cxoTransform_fromPython() // cxoTransform_fromPython()
// Transforms a Python object into its corresponding database value. // Transforms a Python object into its corresponding database value.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
int cxoTransform_fromPython(cxoTransformNum transformNum, PyObject *pyValue, int cxoTransform_fromPython(cxoTransformNum transformNum,
dpiNativeTypeNum *nativeTypeNum, PyObject *pyValue,
dpiDataBuffer *dbValue, cxoBuffer *buffer, const char *encoding, dpiDataBuffer *dbValue, cxoBuffer *buffer, const char *encoding,
const char *nencoding, cxoVar *var, uint32_t arrayPos) const char *nencoding, cxoVar *var, uint32_t arrayPos)
{ {
@ -242,12 +243,18 @@ int cxoTransform_fromPython(cxoTransformNum transformNum, PyObject *pyValue,
encoding = nencoding; encoding = nencoding;
if (cxoBuffer_fromObject(buffer, pyValue, encoding) < 0) if (cxoBuffer_fromObject(buffer, pyValue, encoding) < 0)
return -1; return -1;
Py_BEGIN_ALLOW_THREADS if (var) {
status = dpiLob_setFromBytes(dbValue->asLOB, buffer->ptr, Py_BEGIN_ALLOW_THREADS
buffer->size); status = dpiLob_setFromBytes(dbValue->asLOB, buffer->ptr,
Py_END_ALLOW_THREADS buffer->size);
if (status < 0) Py_END_ALLOW_THREADS
return cxoError_raiseAndReturnInt(); if (status < 0)
return cxoError_raiseAndReturnInt();
} else {
*nativeTypeNum = DPI_NATIVE_TYPE_BYTES;
dbValue->asBytes.ptr = (char*) buffer->ptr;
dbValue->asBytes.length = buffer->size;
}
return 0; return 0;
case CXO_TRANSFORM_NATIVE_INT: case CXO_TRANSFORM_NATIVE_INT:
#if PY_MAJOR_VERSION < 3 #if PY_MAJOR_VERSION < 3

View File

@ -601,6 +601,7 @@ static int cxoVar_setSingleValue(cxoVar *var, uint32_t arrayPos,
{ {
dpiDataBuffer tempDbValue, *dbValue; dpiDataBuffer tempDbValue, *dbValue;
PyObject *convertedValue = NULL; PyObject *convertedValue = NULL;
dpiNativeTypeNum nativeTypeNum;
cxoBuffer buffer; cxoBuffer buffer;
int result = 0; int result = 0;
dpiData *data; dpiData *data;
@ -632,8 +633,9 @@ static int cxoVar_setSingleValue(cxoVar *var, uint32_t arrayPos,
if (var->type->size > 0) if (var->type->size > 0)
dbValue = &tempDbValue; dbValue = &tempDbValue;
else dbValue = &data->value; else dbValue = &data->value;
result = cxoTransform_fromPython(var->type->transformNum, value, result = cxoTransform_fromPython(var->type->transformNum,
dbValue, &buffer, var->connection->encodingInfo.encoding, &nativeTypeNum, value, dbValue, &buffer,
var->connection->encodingInfo.encoding,
var->connection->encodingInfo.nencoding, var, arrayPos); var->connection->encodingInfo.nencoding, var, arrayPos);
if (result == 0 && var->type->size > 0) if (result == 0 && var->type->size > 0)
result = cxoVar_setValueBytes(var, arrayPos, data, &buffer); result = cxoVar_setValueBytes(var, arrayPos, data, &buffer);

View File

@ -238,6 +238,24 @@ class TestCase(TestEnv.BaseTestCase):
cx_Oracle.Timestamp(1999, 11, 12, 23, 5, 2), cx_Oracle.Timestamp(1999, 11, 12, 23, 5, 2),
'A short CLOB', 'A short NCLOB', b'A short BLOB', 'A short CLOB', 'A short NCLOB', b'A short BLOB',
(23, 'Substring value'), None), None) (23, 'Substring value'), None), None)
obj.CLOBVALUE = "A short CLOB (modified)"
obj.NCLOBVALUE = "A short NCLOB (modified)"
obj.BLOBVALUE = "A short BLOB (modified)"
self.cursor.execute("insert into TestObjects (IntCol, ObjectCol) " \
"values (5, :obj)", obj = obj)
self.cursor.execute("""
select IntCol, ObjectCol, ArrayCol
from TestObjects
where IntCol = 5""")
self.__TestData(5, (5, 'A string', 'Fixed str ', 'A NCHAR string',
'Fixed N ', b'Raw Value', 27, 13, 184.875, 1.375, 23.75,
14.25, 29.1625, cx_Oracle.Timestamp(2017, 5, 9, 0, 0, 0),
cx_Oracle.Timestamp(2017, 5, 9, 9, 41, 13),
cx_Oracle.Timestamp(1986, 8, 2, 15, 27, 38),
cx_Oracle.Timestamp(1999, 11, 12, 23, 5, 2),
'A short CLOB (modified)', 'A short NCLOB (modified)',
b'A short BLOB (modified)',
(23, 'Substring value'), None), None)
self.connection.rollback() self.connection.rollback()
def testInvalidTypeObject(self): def testInvalidTypeObject(self):