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,
dpiShardingKeyColumn *column, cxoBuffer *buffer)
{
dpiNativeTypeNum nativeTypeNum;
cxoTransformNum transformNum;
transformNum = cxoTransform_getNumFromValue(value, 0);
if (cxoTransform_fromPython(transformNum, value, &column->value, buffer,
params->encoding, params->nencoding, NULL, 0) < 0)
if (cxoTransform_fromPython(transformNum, &nativeTypeNum, value,
&column->value, buffer, params->encoding, params->nencoding, NULL,
0) < 0)
return -1;
cxoTransform_getTypeInfo(transformNum, &column->oracleTypeNum,
&column->nativeTypeNum);

View File

@ -504,7 +504,8 @@ cxoSodaOperation *cxoSodaOperation_new(cxoSodaCollection *collection);
void cxoSubscr_callback(cxoSubscr *subscr, dpiSubscrMessage *message);
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,
const char *nencoding, cxoVar *var, uint32_t arrayPos);
cxoTransformNum cxoTransform_getNumFromDataTypeInfo(dpiDataTypeInfo *info);

View File

@ -176,7 +176,8 @@ static int cxoObject_convertFromPython(cxoObject *obj, PyObject *value,
// convert the different Python types
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.nencoding, NULL, 0) < 0)
return -1;

View File

@ -193,7 +193,8 @@ PyObject *cxoTransform_dateFromTicks(PyObject *args)
// cxoTransform_fromPython()
// 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,
const char *nencoding, cxoVar *var, uint32_t arrayPos)
{
@ -242,12 +243,18 @@ int cxoTransform_fromPython(cxoTransformNum transformNum, PyObject *pyValue,
encoding = nencoding;
if (cxoBuffer_fromObject(buffer, pyValue, encoding) < 0)
return -1;
if (var) {
Py_BEGIN_ALLOW_THREADS
status = dpiLob_setFromBytes(dbValue->asLOB, buffer->ptr,
buffer->size);
Py_END_ALLOW_THREADS
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;
case CXO_TRANSFORM_NATIVE_INT:
#if PY_MAJOR_VERSION < 3

View File

@ -601,6 +601,7 @@ static int cxoVar_setSingleValue(cxoVar *var, uint32_t arrayPos,
{
dpiDataBuffer tempDbValue, *dbValue;
PyObject *convertedValue = NULL;
dpiNativeTypeNum nativeTypeNum;
cxoBuffer buffer;
int result = 0;
dpiData *data;
@ -632,8 +633,9 @@ static int cxoVar_setSingleValue(cxoVar *var, uint32_t arrayPos,
if (var->type->size > 0)
dbValue = &tempDbValue;
else dbValue = &data->value;
result = cxoTransform_fromPython(var->type->transformNum, value,
dbValue, &buffer, var->connection->encodingInfo.encoding,
result = cxoTransform_fromPython(var->type->transformNum,
&nativeTypeNum, value, dbValue, &buffer,
var->connection->encodingInfo.encoding,
var->connection->encodingInfo.nencoding, var, arrayPos);
if (result == 0 && var->type->size > 0)
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),
'A short CLOB', 'A short NCLOB', b'A short BLOB',
(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()
def testInvalidTypeObject(self):