Skip to content

Commit 1eba9d5

Browse files
Use dpiData_*() functions to simplify setting data; correct handling of
timestamp with time zone attributes.
1 parent df102db commit 1eba9d5

File tree

3 files changed

+39
-29
lines changed

3 files changed

+39
-29
lines changed

src/Object.c

Lines changed: 19 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -189,9 +189,7 @@ static int Object_ConvertFromPython(udt_Object *obj, PyObject *value,
189189
dpiNativeTypeNum *nativeTypeNum, dpiData *data, udt_Buffer *buffer)
190190
{
191191
PyObject *textValue, *valueType;
192-
dpiTimestamp *timestamp;
193192
udt_Object *otherObj;
194-
dpiBytes *bytes;
195193
udt_LOB *lob;
196194
int status;
197195

@@ -221,51 +219,45 @@ static int Object_ConvertFromPython(udt_Object *obj, PyObject *value,
221219
return -1;
222220
}
223221
*nativeTypeNum = DPI_NATIVE_TYPE_BYTES;
224-
bytes = &data->value.asBytes;
225-
bytes->ptr = (char*) buffer->ptr;
226-
bytes->length = buffer->size;
222+
dpiData_setBytes(data, (char*) buffer->ptr, buffer->size);
227223
} else if (PyBool_Check(value)) {
228224
*nativeTypeNum = DPI_NATIVE_TYPE_BOOLEAN;
229-
data->value.asBoolean = (value == Py_True);
225+
dpiData_setBool(data, (value == Py_True));
230226
#if PY_MAJOR_VERSION < 3
231227

232228
} else if (PyInt_Check(value)) {
233229
*nativeTypeNum = DPI_NATIVE_TYPE_INT64;
234-
data->value.asInt64 = PyInt_AS_LONG(value);
230+
dpiData_setInt64(data, PyInt_AS_LONG(value));
235231
#endif
236232
} else if (PyLong_Check(value)) {
237233
*nativeTypeNum = DPI_NATIVE_TYPE_INT64;
238-
data->value.asInt64 = PyLong_AsLong(value);
234+
dpiData_setInt64(data, PyLong_AsLong(value));
239235
if (PyErr_Occurred())
240236
return -1;
241237
} else if (PyFloat_Check(value)) {
242238
*nativeTypeNum = DPI_NATIVE_TYPE_DOUBLE;
243-
data->value.asDouble = PyFloat_AS_DOUBLE(value);
244-
} else if (PyDateTime_Check(value) || PyDate_Check(value)) {
239+
dpiData_setDouble(data, PyFloat_AS_DOUBLE(value));
240+
} else if (PyDateTime_Check(value)) {
245241
*nativeTypeNum = DPI_NATIVE_TYPE_TIMESTAMP;
246-
timestamp = &data->value.asTimestamp;
247-
timestamp->year = PyDateTime_GET_YEAR(value);
248-
timestamp->month = PyDateTime_GET_MONTH(value);
249-
timestamp->day = PyDateTime_GET_DAY(value);
250-
if (PyDateTime_Check(value)) {
251-
timestamp->hour = PyDateTime_DATE_GET_HOUR(value);
252-
timestamp->minute = PyDateTime_DATE_GET_MINUTE(value);
253-
timestamp->second = PyDateTime_DATE_GET_SECOND(value);
254-
timestamp->fsecond = PyDateTime_DATE_GET_MICROSECOND(value) * 1000;
255-
} else {
256-
timestamp->hour = 0;
257-
timestamp->minute = 0;
258-
timestamp->second = 0;
259-
timestamp->fsecond = 0;
260-
}
242+
dpiData_setTimestamp(data, PyDateTime_GET_YEAR(value),
243+
PyDateTime_GET_MONTH(value), PyDateTime_GET_DAY(value),
244+
PyDateTime_DATE_GET_HOUR(value),
245+
PyDateTime_DATE_GET_MINUTE(value),
246+
PyDateTime_DATE_GET_SECOND(value),
247+
PyDateTime_DATE_GET_MICROSECOND(value) * 1000, 0, 0);
248+
} else if (PyDate_Check(value)) {
249+
*nativeTypeNum = DPI_NATIVE_TYPE_TIMESTAMP;
250+
dpiData_setTimestamp(data, PyDateTime_GET_YEAR(value),
251+
PyDateTime_GET_MONTH(value), PyDateTime_GET_DAY(value),
252+
0, 0, 0, 0, 0, 0);
261253
} else if (Py_TYPE(value) == &g_ObjectType) {
262254
*nativeTypeNum = DPI_NATIVE_TYPE_OBJECT;
263255
otherObj = (udt_Object*) value;
264-
data->value.asObject = otherObj->handle;
256+
dpiData_setObject(data, otherObj->handle);
265257
} else if (Py_TYPE(value) == &g_LOBType) {
266258
*nativeTypeNum = DPI_NATIVE_TYPE_LOB;
267259
lob = (udt_LOB*) value;
268-
data->value.asLOB = lob->handle;
260+
dpiData_setLOB(data, lob->handle);
269261
} else {
270262
PyErr_Format(g_NotSupportedErrorException,
271263
"Object_ConvertFromPython(): unhandled value type");

test/ObjectVar.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@ def testFetchData(self):
125125
'N First ', 2, 5, 12.5, 25.25, 50.125,
126126
cx_Oracle.Timestamp(2007, 3, 6, 0, 0, 0),
127127
cx_Oracle.Timestamp(2008, 9, 12, 16, 40),
128+
cx_Oracle.Timestamp(2009, 10, 13, 17, 50),
129+
cx_Oracle.Timestamp(2010, 11, 14, 18, 55),
128130
'Short CLOB value', 'Short NCLOB Value', b'Short BLOB value',
129131
(11, 'Sub object 1'),
130132
[(5, 'first element'), (6, 'second element')]),
@@ -134,6 +136,8 @@ def testFetchData(self):
134136
'N Third ', 4, 10, 43.25, 86.5, 192.125,
135137
cx_Oracle.Timestamp(2007, 6, 21, 0, 0, 0),
136138
cx_Oracle.Timestamp(2007, 12, 13, 7, 30, 45),
139+
cx_Oracle.Timestamp(2017, 6, 21, 23, 18, 45),
140+
cx_Oracle.Timestamp(2017, 7, 21, 8, 27, 13),
137141
'Another short CLOB value', 'Another short NCLOB Value',
138142
b'Yet another short BLOB value',
139143
(13, 'Sub object 3'),
@@ -150,8 +154,8 @@ def testGetObjectType(self):
150154
"FIXEDCHARVALUE", "NSTRINGVALUE", "NFIXEDCHARVALUE",
151155
"INTVALUE", "SMALLINTVALUE", "FLOATVALUE", "BINARYFLOATVALUE",
152156
"BINARYDOUBLEVALUE", "DATEVALUE", "TIMESTAMPVALUE",
153-
"CLOBVALUE", "NCLOBVALUE", "BLOBVALUE", "SUBOBJECTVALUE",
154-
"SUBOBJECTARRAY"]
157+
"TIMESTAMPTZVALUE", "TIMESTAMPLTZVALUE", "CLOBVALUE",
158+
"NCLOBVALUE", "BLOBVALUE", "SUBOBJECTVALUE", "SUBOBJECTARRAY"]
155159
actualAttributeNames = [a.name for a in typeObj.attributes]
156160
self.assertEqual(actualAttributeNames, expectedAttributeNames)
157161
typeObj = self.connection.gettype("UDT_OBJECTARRAY")
@@ -201,6 +205,8 @@ def testRoundTripObject(self):
201205
obj.FLOATVALUE = 23.75
202206
obj.DATEVALUE = datetime.date(2017, 5, 9)
203207
obj.TIMESTAMPVALUE = datetime.datetime(2017, 5, 9, 9, 41, 13)
208+
obj.TIMESTAMPTZVALUE = datetime.datetime(1986, 8, 2, 15, 27, 38)
209+
obj.TIMESTAMPLTZVALUE = datetime.datetime(1999, 11, 12, 23, 5, 2)
204210
obj.BINARYFLOATVALUE = 14.25
205211
obj.BINARYDOUBLEVALUE = 29.1625
206212
obj.CLOBVALUE = clob
@@ -221,6 +227,8 @@ def testRoundTripObject(self):
221227
'Fixed N ', 27, 13, 23.75, 14.25, 29.1625,
222228
cx_Oracle.Timestamp(2017, 5, 9, 0, 0, 0),
223229
cx_Oracle.Timestamp(2017, 5, 9, 9, 41, 13),
230+
cx_Oracle.Timestamp(1986, 8, 2, 15, 27, 38),
231+
cx_Oracle.Timestamp(1999, 11, 12, 23, 5, 2),
224232
'A short CLOB', 'A short NCLOB', b'A short BLOB',
225233
(23, 'Substring value'), None), None)
226234
self.connection.rollback()

test/sql/SetupTest.sql

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ create type &main_user..udt_Object as object (
7171
BinaryDoubleValue binary_double,
7272
DateValue date,
7373
TimestampValue timestamp,
74+
TimestampTZValue timestamp with time zone,
75+
TimestampLTZValue timestamp with local time zone,
7476
CLOBValue clob,
7577
NCLOBValue nclob,
7678
BLOBValue blob,
@@ -298,6 +300,10 @@ insert into &main_user..TestObjects values (1,
298300
&main_user..udt_Object(1, 'First row', 'First', 'N First Row', 'N First',
299301
2, 5, 12.5, 25.25, 50.125, to_date(20070306, 'YYYYMMDD'),
300302
to_timestamp('20080912 16:40:00', 'YYYYMMDD HH24:MI:SS'),
303+
to_timestamp_tz('20091013 17:50:00 00:00',
304+
'YYYYMMDD HH24:MI:SS TZH:TZM'),
305+
to_timestamp_tz('20101114 18:55:00 00:00',
306+
'YYYYMMDD HH24:MI:SS TZH:TZM'),
301307
'Short CLOB value', 'Short NCLOB Value',
302308
utl_raw.cast_to_raw('Short BLOB value'),
303309
&main_user..udt_SubObject(11, 'Sub object 1'),
@@ -313,6 +319,10 @@ insert into &main_user..TestObjects values (3,
313319
&main_user..udt_Object(3, 'Third row', 'Third', 'N Third Row', 'N Third',
314320
4, 10, 43.25, 86.5, 192.125, to_date(20070621, 'YYYYMMDD'),
315321
to_timestamp('20071213 07:30:45', 'YYYYMMDD HH24:MI:SS'),
322+
to_timestamp_tz('20170621 23:18:45 00:00',
323+
'YYYYMMDD HH24:MI:SS TZH:TZM'),
324+
to_timestamp_tz('20170721 08:27:13 00:00',
325+
'YYYYMMDD HH24:MI:SS TZH:TZM'),
316326
'Another short CLOB value', 'Another short NCLOB Value',
317327
utl_raw.cast_to_raw('Yet another short BLOB value'),
318328
&main_user..udt_SubObject(13, 'Sub object 3'),

0 commit comments

Comments
 (0)