Skip to content

Commit 10c45fc

Browse files
committed
Added JsonId class to to represent JSON ID values returned by SODA in Oracle Database 23ai and higher in the _id attribute of documents stored in native SODA collections
1 parent 63d8bb5 commit 10c45fc

File tree

14 files changed

+177
-4
lines changed

14 files changed

+177
-4
lines changed

doc/src/release_notes.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@ For deprecated and desupported features, see :ref:`Deprecations and desupported
1010
node-oracledb `v6.5.0 <https://github.com/oracle/node-oracledb/compare/v6.4.0...v6.5.0>`__ (TBD)
1111
--------------------------------------------------------------------------------------------------------
1212

13+
Common Changes
14+
++++++++++++++
15+
16+
#) Added class :ref:`oracledb.JsonId <jsonid>` to represent JSON ID values
17+
returned by SODA in Oracle Database 23.4 and higher in the ``_id``
18+
attribute of documents stored in native collections.
19+
1320
Thin Mode Changes
1421
++++++++++++++++++
1522

lib/impl/datahandlers/constants.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ module.exports = {
7979
TNS_JSON_TYPE_ARRAY: 0xc0,
8080
TNS_JSON_TYPE_EXTENDED: 0x7b,
8181
TNS_JSON_TYPE_VECTOR: 0x01,
82+
TNS_JSON_TYPE_ID: 0x7e,
8283

8384
// timezone offsets
8485
TZ_HOUR_OFFSET: 20,

lib/impl/datahandlers/oson.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,11 @@ class OsonDecoder extends BaseBuffer {
143143
return this.readBytes(this.readUInt32BE()).toString();
144144
} else if (nodeType === constants.TNS_JSON_TYPE_NUMBER_LENGTH_UINT8) {
145145
return parseFloat(this.readOracleNumber());
146+
} else if (nodeType === constants.TNS_JSON_TYPE_ID) {
147+
const buf = this.readBytes(this.readUInt8());
148+
const jsonId = new types.JsonId(buf.length);
149+
buf.copy(jsonId);
150+
return jsonId;
146151
} else if (nodeType === constants.TNS_JSON_TYPE_BINARY_LENGTH_UINT16) {
147152
return Buffer.from(this.readBytes(this.readUInt16BE()));
148153
} else if (nodeType === constants.TNS_JSON_TYPE_BINARY_LENGTH_UINT32) {
@@ -562,6 +567,11 @@ class OsonTreeSegment extends GrowableBuffer {
562567
this.writeUInt32BE(buf.length);
563568
this.writeBytes(buf);
564569

570+
} else if (value instanceof types.JsonId) {
571+
this.writeUInt8(constants.TNS_JSON_TYPE_ID);
572+
this.writeUInt8(value.length);
573+
this.writeBytes(Buffer.from(value.buffer));
574+
565575
// handle objects
566576
} else {
567577
this._encodeObject(value, fnamesSeg);

lib/oracledb.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -832,6 +832,7 @@ module.exports = {
832832
AqQueue,
833833
BaseDbObject,
834834
Connection,
835+
JsonId: types.JsonId,
835836
Lob,
836837
Pool,
837838
PoolStatistics,

lib/settings.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ class Settings {
6363
this.thinDriverInitialized = false;
6464
this.createFetchTypeMap(this.fetchAsString, this.fetchAsBuffer);
6565
this.fetchTypeHandler = undefined;
66+
this._JsonId = types.JsonId;
6667
}
6768

6869
//---------------------------------------------------------------------------

lib/transformer.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,12 @@ function transformJsonValue(value) {
105105
if (value instanceof BaseDbObject)
106106
return {fields: [], values: []};
107107

108+
// JsonId is a special type to represent autogenerated id
109+
// for SODA documents.
110+
if (value instanceof types.JsonId) {
111+
return value;
112+
}
113+
108114
// all other objects are transformed to an object with two arrays (fields
109115
// and values)
110116
const outValue = {};

lib/types.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,13 @@ dbTypeByColumnTypeName.set("SMALLINT", DB_TYPE_NUMBER);
332332
dbTypeByColumnTypeName.set("TIMESTAMP WITH LOCAL TZ", DB_TYPE_TIMESTAMP_LTZ);
333333
dbTypeByColumnTypeName.set("TIMESTAMP WITH TZ", DB_TYPE_TIMESTAMP_TZ);
334334

335+
// It abstracts the autogenerated SODA Document key.
336+
class JsonId extends Uint8Array {
337+
toJSON() {
338+
return (Buffer.from(this.buffer).toString('hex'));
339+
}
340+
}
341+
335342
module.exports = {
336343
DbType,
337344
DB_TYPE_BFILE,
@@ -368,5 +375,6 @@ module.exports = {
368375
DB_TYPE_XMLTYPE,
369376
getTypeByColumnTypeName,
370377
getTypeByNum,
371-
getTypeByOraTypeNum
378+
getTypeByOraTypeNum,
379+
JsonId
372380
};

src/njsBaton.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -426,9 +426,11 @@ bool njsBaton_getJsonNodeValue(njsBaton *baton, dpiJsonNode *node,
426426
napi_value key, temp;
427427
dpiJsonArray *array;
428428
dpiJsonObject *obj;
429+
void *destData = NULL;
430+
size_t byteLength = 0;
429431
double temp_double;
430432
uint32_t i;
431-
napi_value global, vectorBytes;
433+
napi_value global, vectorBytes, arrBuf;
432434

433435
// null is a special case
434436
if (node->nativeTypeNum == DPI_NATIVE_TYPE_NULL) {
@@ -493,6 +495,15 @@ bool njsBaton_getJsonNodeValue(njsBaton *baton, dpiJsonNode *node,
493495
NJS_CHECK_NAPI(env, napi_call_function(env, global,
494496
baton->jsDecodeVectorFn, 1, &vectorBytes, value))
495497
return true;
498+
case DPI_ORACLE_TYPE_JSON_ID:
499+
byteLength = node->value->asBytes.length;
500+
NJS_CHECK_NAPI(env, napi_create_arraybuffer(env,
501+
byteLength, &destData, &arrBuf))
502+
memcpy(destData, node->value->asBytes.ptr, byteLength);
503+
NJS_CHECK_NAPI(env, napi_new_instance(env,
504+
baton->jsJsonIdConstructor, 1, &arrBuf, value))
505+
return true;
506+
496507
default:
497508
break;
498509
}
@@ -807,6 +818,10 @@ bool njsBaton_setJsValues(njsBaton *baton, napi_env env)
807818
NJS_CHECK_NAPI(env, napi_get_reference_value(env,
808819
baton->globals->jsEncodeVectorFn, &baton->jsEncodeVectorFn))
809820

821+
// acquire the JsonId constructor
822+
NJS_CHECK_NAPI(env, napi_get_reference_value(env,
823+
baton->globals->jsJsonIdConstructor, &baton->jsJsonIdConstructor))
824+
810825
return true;
811826
}
812827

src/njsJsonBuffer.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,9 +243,16 @@ static bool njsJsonBuffer_populateNode(njsJsonBuffer *buf, dpiJsonNode *node,
243243
// handle buffers
244244
NJS_CHECK_NAPI(env, napi_is_buffer(env, value, &check))
245245
if (check) {
246+
NJS_CHECK_NAPI(env, napi_instanceof(env, value,
247+
baton->jsJsonIdConstructor, &check))
246248
NJS_CHECK_NAPI(env, napi_get_buffer_info(env, value,
247249
(void**) &tempBuffer, &tempBufferLength))
248-
node->oracleTypeNum = DPI_ORACLE_TYPE_RAW;
250+
if (check) {
251+
// Handle JsonId
252+
node->oracleTypeNum = DPI_ORACLE_TYPE_JSON_ID;
253+
} else {
254+
node->oracleTypeNum = DPI_ORACLE_TYPE_RAW;
255+
}
249256
node->nativeTypeNum = DPI_NATIVE_TYPE_BYTES;
250257
node->value->asBytes.ptr = tempBuffer;
251258
node->value->asBytes.length = (uint32_t) tempBufferLength;

src/njsModule.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ static void njsModule_finalizeGlobals(napi_env env, void *finalize_data,
126126
NJS_DELETE_REF_AND_CLEAR(globals->jsMakeDateFn);
127127
NJS_DELETE_REF_AND_CLEAR(globals->jsDecodeVectorFn);
128128
NJS_DELETE_REF_AND_CLEAR(globals->jsEncodeVectorFn);
129+
NJS_DELETE_REF_AND_CLEAR(globals->jsJsonIdConstructor);
129130
free(globals);
130131
}
131132

@@ -189,6 +190,12 @@ static bool njsModule_populateGlobals(napi_env env, napi_value module,
189190
&globals->jsSodaOperationConstructor))
190191
return false;
191192

193+
// get the JsonId class
194+
NJS_CHECK_NAPI(env, napi_get_named_property(env, settings, "_JsonId",
195+
&temp))
196+
NJS_CHECK_NAPI(env, napi_create_reference(env, temp, 1,
197+
&globals->jsJsonIdConstructor))
198+
192199
// store a reference to the _makeDate() function
193200
NJS_CHECK_NAPI(env, napi_get_named_property(env, settings,
194201
"_getDateComponents", &temp))
@@ -267,6 +274,7 @@ static bool njsModule_initDPI(napi_env env, napi_value *args,
267274

268275
// initialize structure
269276
memset(&params, 0, sizeof(params));
277+
params.useJsonId = 1; // Enable JSONID
270278
if (*libDirLength > 0)
271279
params.oracleClientLibDir = *libDir;
272280
if (*configDirLength > 0)

0 commit comments

Comments
 (0)