Skip to content

Commit 242dc1c

Browse files
committed
Improve date handling in DB objects for Thick mode
1 parent d05c22c commit 242dc1c

File tree

6 files changed

+60
-68
lines changed

6 files changed

+60
-68
lines changed

src/njsDbObject.c

Lines changed: 28 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,9 @@ static bool njsDbObject_transformFromOracle(njsDbObject *obj, napi_env env,
100100
njsDataTypeInfo *typeInfo, dpiData *data, napi_value *value,
101101
njsDbObjectAttr *attr, njsModuleGlobals *globals);
102102
static bool njsDbObject_transformToOracle(njsDbObject *obj, napi_env env,
103-
napi_value value, dpiNativeTypeNum *nativeTypeNum, dpiData *data,
104-
char **strBuffer, njsDbObjectAttr *attr, njsModuleGlobals *globals);
103+
napi_value value, dpiOracleTypeNum oracleTypeNum,
104+
dpiNativeTypeNum *nativeTypeNum, dpiData *data, char **strBuffer,
105+
njsDbObjectAttr *attr, njsModuleGlobals *globals);
105106
static bool njsDbObjectType_populate(njsDbObjectType *objType,
106107
dpiObjectType *objectTypeHandle, napi_env env, napi_value jsObjectType,
107108
dpiObjectTypeInfo *info, njsBaton *baton);
@@ -124,8 +125,9 @@ NJS_NAPI_METHOD_IMPL_SYNC(njsDbObject_append, 1, &njsClassDefDbObject)
124125
int status;
125126

126127
nativeTypeNum = obj->type->elementTypeInfo.nativeTypeNum;
127-
if (!njsDbObject_transformToOracle(obj, env, args[0], &nativeTypeNum,
128-
&data, &str, NULL, globals))
128+
if (!njsDbObject_transformToOracle(obj, env, args[0],
129+
obj->type->elementTypeInfo.oracleTypeNum, &nativeTypeNum, &data,
130+
&str, NULL, globals))
129131
return false;
130132
status = dpiObject_appendElement(obj->handle, nativeTypeNum, &data);
131133
if (str)
@@ -547,8 +549,9 @@ NJS_NAPI_METHOD_IMPL_SYNC(njsDbObject_setAttrValue, 2, &njsClassDefDbObject)
547549

548550
// transform to value required by ODPI-C
549551
nativeTypeNum = attr->typeInfo.nativeTypeNum;
550-
if (!njsDbObject_transformToOracle(obj, env, args[1], &nativeTypeNum,
551-
&data, &str, attr, globals))
552+
if (!njsDbObject_transformToOracle(obj, env, args[1],
553+
attr->typeInfo.oracleTypeNum, &nativeTypeNum, &data, &str, attr,
554+
globals))
552555
return false;
553556

554557
// set value
@@ -578,8 +581,9 @@ NJS_NAPI_METHOD_IMPL_SYNC(njsDbObject_setElement, 2, &njsClassDefDbObject)
578581

579582
NJS_CHECK_NAPI(env, napi_get_value_int32(env, args[0], &index))
580583
nativeTypeNum = obj->type->elementTypeInfo.nativeTypeNum;
581-
if (!njsDbObject_transformToOracle(obj, env, args[1], &nativeTypeNum,
582-
&data, &str, NULL, globals))
584+
if (!njsDbObject_transformToOracle(obj, env, args[1],
585+
obj->type->elementTypeInfo.oracleTypeNum, &nativeTypeNum, &data,
586+
&str, NULL, globals))
583587
return false;
584588
status = dpiObject_setElementValueByIndex(obj->handle, index,
585589
nativeTypeNum, &data);
@@ -600,7 +604,7 @@ static bool njsDbObject_transformFromOracle(njsDbObject *obj, napi_env env,
600604
njsDataTypeInfo *typeInfo, dpiData *data, napi_value *value,
601605
njsDbObjectAttr *attr, njsModuleGlobals *globals)
602606
{
603-
napi_value global, constructor, jsDbObjectType, temp;
607+
napi_value jsDbObjectType, makeDateFn, temp;
604608
njsLobBuffer lobBuffer;
605609
bool ok;
606610

@@ -650,14 +654,10 @@ static bool njsDbObject_transformFromOracle(njsDbObject *obj, napi_env env,
650654
case DPI_ORACLE_TYPE_TIMESTAMP:
651655
case DPI_ORACLE_TYPE_TIMESTAMP_TZ:
652656
case DPI_ORACLE_TYPE_TIMESTAMP_LTZ:
653-
NJS_CHECK_NAPI(env, napi_get_global(env, &global))
654-
NJS_CHECK_NAPI(env, napi_get_named_property(env, global, "Date",
655-
&constructor))
656-
NJS_CHECK_NAPI(env, napi_create_double(env, data->value.asDouble,
657-
&temp))
658-
NJS_CHECK_NAPI(env, napi_new_instance(env, constructor, 1, &temp,
659-
value))
660-
return true;
657+
NJS_CHECK_NAPI(env, napi_get_reference_value(env,
658+
globals->jsMakeDateFn, &makeDateFn))
659+
return njsUtils_getDateValue(typeInfo->oracleTypeNum, env,
660+
makeDateFn, &data->value.asTimestamp, value);
661661
case DPI_ORACLE_TYPE_CLOB:
662662
case DPI_ORACLE_TYPE_NCLOB:
663663
case DPI_ORACLE_TYPE_BLOB:
@@ -700,10 +700,11 @@ static bool njsDbObject_transformFromOracle(njsDbObject *obj, napi_env env,
700700
// Transforms a JavaScript value into the value that ODPI-C expects.
701701
//-----------------------------------------------------------------------------
702702
static bool njsDbObject_transformToOracle(njsDbObject *obj, napi_env env,
703-
napi_value value, dpiNativeTypeNum *nativeTypeNum, dpiData *data,
704-
char **strBuffer, njsDbObjectAttr *attr, njsModuleGlobals *globals)
703+
napi_value value, dpiOracleTypeNum oracleTypeNum,
704+
dpiNativeTypeNum *nativeTypeNum, dpiData *data, char **strBuffer,
705+
njsDbObjectAttr *attr, njsModuleGlobals *globals)
705706
{
706-
napi_value global, constructor, asNumber;
707+
napi_value constructor, getComponentsFn;
707708
napi_valuetype valueType;
708709
njsDbObject *valueObj;
709710
bool check, tempBool;
@@ -734,9 +735,7 @@ static bool njsDbObject_transformToOracle(njsDbObject *obj, napi_env env,
734735
case napi_number:
735736
NJS_CHECK_NAPI(env, napi_get_value_double(env, value,
736737
&data->value.asDouble));
737-
if (*nativeTypeNum != DPI_NATIVE_TYPE_TIMESTAMP) {
738-
*nativeTypeNum = DPI_NATIVE_TYPE_DOUBLE;
739-
}
738+
*nativeTypeNum = DPI_NATIVE_TYPE_DOUBLE;
740739
return true;
741740

742741
// handle booleans
@@ -750,18 +749,13 @@ static bool njsDbObject_transformToOracle(njsDbObject *obj, napi_env env,
750749
case napi_object:
751750

752751
// handle dates
753-
NJS_CHECK_NAPI(env, napi_get_global(env, &global))
754-
NJS_CHECK_NAPI(env, napi_get_named_property(env, global, "Date",
755-
&constructor))
756-
NJS_CHECK_NAPI(env, napi_instanceof(env, value, constructor,
757-
&check))
752+
NJS_CHECK_NAPI(env, napi_is_date(env, value, &check))
758753
if (check) {
759-
NJS_CHECK_NAPI(env, napi_coerce_to_number(env, value,
760-
&asNumber))
761-
NJS_CHECK_NAPI(env, napi_get_value_double(env, asNumber,
762-
&data->value.asDouble))
763-
*nativeTypeNum = DPI_NATIVE_TYPE_DOUBLE;
764-
return true;
754+
*nativeTypeNum = DPI_NATIVE_TYPE_TIMESTAMP;
755+
NJS_CHECK_NAPI(env, napi_get_reference_value(env,
756+
globals->jsGetDateComponentsFn, &getComponentsFn))
757+
return njsUtils_setDateValue(oracleTypeNum, env, value,
758+
getComponentsFn, &data->value.asTimestamp);
765759
}
766760

767761
// handle buffers
@@ -1004,12 +998,6 @@ static bool njsDbObjectType_populateTypeInfo(njsDataTypeInfo *info,
1004998

1005999
info->oracleTypeNum = sourceInfo->oracleTypeNum;
10061000
info->nativeTypeNum = sourceInfo->defaultNativeTypeNum;
1007-
if (info->oracleTypeNum == DPI_ORACLE_TYPE_DATE ||
1008-
info->oracleTypeNum == DPI_ORACLE_TYPE_TIMESTAMP ||
1009-
info->oracleTypeNum == DPI_ORACLE_TYPE_TIMESTAMP_TZ ||
1010-
info->oracleTypeNum == DPI_ORACLE_TYPE_TIMESTAMP_LTZ) {
1011-
info->nativeTypeNum = DPI_NATIVE_TYPE_DOUBLE;
1012-
}
10131001
if (sourceInfo->objectType) {
10141002
return njsDbObject_getSubClass(baton, sourceInfo->objectType, env,
10151003
&temp, &info->objectType);

src/njsJsonBuffer.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ static bool njsJsonBuffer_populateNode(njsJsonBuffer *buf, dpiJsonNode *node,
214214
node->oracleTypeNum = DPI_ORACLE_TYPE_TIMESTAMP;
215215
node->nativeTypeNum = DPI_NATIVE_TYPE_TIMESTAMP;
216216
return njsUtils_setDateValue(DPI_ORACLE_TYPE_TIMESTAMP, env, value,
217-
baton, &node->value->asTimestamp);
217+
baton->jsGetDateComponentsFn, &node->value->asTimestamp);
218218
}
219219

220220
// handle buffers

src/njsModule.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -856,8 +856,8 @@ bool njsUtils_genericNew(napi_env env, const njsClassDef *classDef,
856856
napi_ref constructorRef, napi_value *instanceObj, void **instance);
857857
bool njsUtils_genericThrowError(napi_env env, const char *fileName,
858858
int lineNum);
859-
bool njsUtils_getDateValue(uint32_t varTypeNum, napi_env env, njsBaton *baton,
860-
dpiTimestamp *timestamp, napi_value *value);
859+
bool njsUtils_getDateValue(uint32_t varTypeNum, napi_env env,
860+
napi_value makeDateFn, dpiTimestamp *timestamp, napi_value *value);
861861
bool njsUtils_getError(napi_env env, dpiErrorInfo *errorInfo,
862862
const char *buffer, napi_value *error);
863863
bool njsUtils_getNamedProperty(napi_env env, napi_value value,
@@ -883,7 +883,7 @@ bool njsUtils_getNamedPropertyUnsignedIntArray(napi_env env, napi_value value,
883883
bool njsUtils_getXid(napi_env env, napi_value xidObj, dpiXid **xid);
884884
bool njsUtils_isInstance(napi_env env, napi_value value, const char *name);
885885
bool njsUtils_setDateValue(uint32_t varTypeNum, napi_env env, napi_value value,
886-
njsBaton *baton, dpiTimestamp *timestamp);
886+
napi_value getComponentsFn, dpiTimestamp *timestamp);
887887
bool njsUtils_throwErrorDPI(napi_env env, njsModuleGlobals *globals);
888888
bool njsUtils_throwInsufficientMemory(napi_env env);
889889
bool njsUtils_throwUnsupportedDataType(napi_env env, uint32_t oracleTypeNum,

src/njsUtils.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -587,8 +587,8 @@ bool njsUtils_getXid(napi_env env, napi_value value, dpiXid **xid)
587587
// an absolute JS date for TIMESTAMP WITH TIME ZONE and TIMESTAMP WITH LOCAL
588588
// TIME ZONE.
589589
//-----------------------------------------------------------------------------
590-
bool njsUtils_getDateValue(uint32_t varTypeNum, napi_env env, njsBaton *baton,
591-
dpiTimestamp *timestamp, napi_value *value)
590+
bool njsUtils_getDateValue(uint32_t varTypeNum, napi_env env,
591+
napi_value makeDateFn, dpiTimestamp *timestamp, napi_value *value)
592592
{
593593
napi_value global, args[9];
594594
int32_t tzOffset = 0;
@@ -616,8 +616,8 @@ bool njsUtils_getDateValue(uint32_t varTypeNum, napi_env env, njsBaton *baton,
616616
}
617617
NJS_CHECK_NAPI(env, napi_create_int32(env, tzOffset,
618618
&args[8]))
619-
NJS_CHECK_NAPI(env, napi_call_function(env, global,
620-
baton->jsMakeDateFn, 9, args, value))
619+
NJS_CHECK_NAPI(env, napi_call_function(env, global, makeDateFn, 9, args,
620+
value))
621621
return true;
622622
}
623623

@@ -632,7 +632,7 @@ bool njsUtils_getDateValue(uint32_t varTypeNum, napi_env env, njsBaton *baton,
632632
// native format).
633633
//-----------------------------------------------------------------------------
634634
bool njsUtils_setDateValue(uint32_t varTypeNum, napi_env env, napi_value value,
635-
njsBaton *baton, dpiTimestamp *timestamp)
635+
napi_value getComponentsFn, dpiTimestamp *timestamp)
636636
{
637637
napi_value args[2], global, array, temp;
638638
uint32_t temp_unsigned;
@@ -645,8 +645,8 @@ bool njsUtils_setDateValue(uint32_t varTypeNum, napi_env env, napi_value value,
645645
NJS_CHECK_NAPI(env, napi_get_global(env, &global))
646646
NJS_CHECK_NAPI(env, napi_get_boolean(env, useLocalTime, &args[0]))
647647
args[1] = value;
648-
NJS_CHECK_NAPI(env, napi_call_function(env, global,
649-
baton->jsGetDateComponentsFn, 2, args, &array))
648+
NJS_CHECK_NAPI(env, napi_call_function(env, global, getComponentsFn, 2,
649+
args, &array))
650650

651651
// store year
652652
NJS_CHECK_NAPI(env, napi_get_element(env, array, 0, &temp))

src/njsVariable.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -367,8 +367,8 @@ static bool njsVariable_getJsonNodeValue(njsBaton *baton, dpiJsonNode *node,
367367
return true;
368368
case DPI_ORACLE_TYPE_DATE:
369369
case DPI_ORACLE_TYPE_TIMESTAMP:
370-
return njsUtils_getDateValue(node->oracleTypeNum, env, baton,
371-
&node->value->asTimestamp, value);
370+
return njsUtils_getDateValue(node->oracleTypeNum, env,
371+
baton->jsMakeDateFn, &node->value->asTimestamp, value);
372372
case DPI_ORACLE_TYPE_BOOLEAN:
373373
NJS_CHECK_NAPI(env, napi_get_boolean(env, node->value->asBoolean,
374374
value))
@@ -416,8 +416,8 @@ bool njsVariable_getScalarValue(njsVariable *var, njsConnection *conn,
416416
value))
417417
break;
418418
case DPI_NATIVE_TYPE_TIMESTAMP:
419-
if (!njsUtils_getDateValue(var->varTypeNum, env, baton,
420-
&data->value.asTimestamp, value))
419+
if (!njsUtils_getDateValue(var->varTypeNum, env,
420+
baton->jsMakeDateFn, &data->value.asTimestamp, value))
421421
return false;
422422
break;
423423
case DPI_NATIVE_TYPE_DOUBLE:
@@ -813,8 +813,8 @@ bool njsVariable_setScalarValue(njsVariable *var, uint32_t pos, napi_env env,
813813
// handle binding dates
814814
NJS_CHECK_NAPI(env, napi_is_date(env, value, &check))
815815
if (check) {
816-
return njsUtils_setDateValue(var->varTypeNum, env, value, baton,
817-
&data->value.asTimestamp);
816+
return njsUtils_setDateValue(var->varTypeNum, env, value,
817+
baton->jsGetDateComponentsFn, &data->value.asTimestamp);
818818
}
819819

820820
// handle binding cursors

test/dbObject5.js

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,8 @@ describe('204. dbObject5.js', () => {
110110
const seq = 101;
111111
let sql = `INSERT INTO ${TABLE} VALUES (:1, :2)`;
112112

113-
const date1 = new Date (1986, 8, 18);
114-
const date2 = new Date (1989, 3, 4);
113+
const date1 = new Date(1986, 8, 18);
114+
const date2 = new Date(1989, 3, 4);
115115
const objData = {
116116
ENTRY: date1,
117117
EXIT : date2
@@ -121,14 +121,19 @@ describe('204. dbObject5.js', () => {
121121

122122
let result = await conn.execute(sql, [seq, testObj]);
123123
assert.strictEqual(result.rowsAffected, 1);
124+
125+
sql = `INSERT INTO ${TABLE} values (:1, ${TYPE}(:2, :3))`;
126+
await conn.execute(sql, [seq, date1, date2]);
124127
await conn.commit();
125128

126129
sql = `SELECT * FROM ${TABLE} WHERE num = ${seq}`;
127130
result = await conn.execute(sql);
128131

129-
assert.strictEqual(result.rows[0][1]['ENTRY'].getTime(), date1.getTime());
130-
assert.strictEqual(result.rows[0][1]['EXIT'].getTime(), date2.getTime());
131-
assert.strictEqual(result.rows[0][0], seq);
132+
for (const row of result.rows) {
133+
assert.strictEqual(row[0], seq);
134+
assert.strictEqual(row[1]['ENTRY'].getTime(), date1.getTime());
135+
assert.strictEqual(row[1]['EXIT'].getTime(), date2.getTime());
136+
}
132137
}); // 204.1
133138

134139
it('204.2 insert null value for DATE type attribute', async () => {
@@ -206,13 +211,12 @@ describe('204. dbObject5.js', () => {
206211
}
207212
);
208213

209-
let resultSet = await result.outBinds.p_cur1.getRows();
210-
assert.equal(resultSet.length, 4);
211-
result.outBinds.p_cur1.close();
214+
const rows1 = await result.outBinds.p_cur1.getRows();
215+
await result.outBinds.p_cur1.close();
212216

213-
resultSet = await result.outBinds.p_cur2.getRows();
214-
assert.equal(resultSet.length, 4);
215-
result.outBinds.p_cur2.close();
217+
const rows2 = await result.outBinds.p_cur2.getRows();
218+
await result.outBinds.p_cur2.close();
219+
assert.deepStrictEqual(rows1, rows2);
216220
}); // 204.5;
217221

218222
});

0 commit comments

Comments
 (0)