Skip to content

Commit 94ad326

Browse files
committed
Fixed bug which throws NJS-112 error during fetching of JSON and Vector columns as string after table recreation with statement caching
1 parent f6c8f6c commit 94ad326

File tree

5 files changed

+161
-1
lines changed

5 files changed

+161
-1
lines changed

doc/src/release_notes.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,16 @@ node-oracledb Release Notes
77

88
For deprecated and desupported features, see :ref:`Deprecations and desupported features <deprecations>`.
99

10+
node-oracledb `v6.6.0 <https://github.com/oracle/node-oracledb/compare/v6.5.1...v6.6.0>`__ (TBD)
11+
---------------------------------------------------------------------------------------------------------
12+
13+
Thin Mode Changes
14+
+++++++++++++++++
15+
16+
#) Fixed bug which throws an `NJS-112` error during fetching of JSON and
17+
vector columns after table recreation. This is similar to the
18+
fix provided for GitHub issue #1565.
19+
1020
node-oracledb `v6.5.1 <https://github.com/oracle/node-oracledb/compare/v6.5.0...v6.5.1>`__ (23 May 2024)
1121
---------------------------------------------------------------------------------------------------------
1222

lib/thin/protocol/messages/withData.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,11 @@ class MessageWithData extends Message {
140140
if ((cVar.fetchInfo.dbType._oraTypeNum === constants.TNS_DATA_TYPE_CLOB
141141
&& pVar.fetchInfo.fetchType._oraTypeNum === constants.TNS_DATA_TYPE_LONG)
142142
|| (cVar.fetchInfo.dbType._oraTypeNum === constants.TNS_DATA_TYPE_BLOB
143-
&& pVar.fetchInfo.fetchType._oraTypeNum === constants.TNS_DATA_TYPE_LONG_RAW)) {
143+
&& pVar.fetchInfo.fetchType._oraTypeNum === constants.TNS_DATA_TYPE_LONG_RAW)
144+
|| (cVar.fetchInfo.dbType._oraTypeNum === constants.TNS_DATA_TYPE_JSON
145+
&& pVar.fetchInfo.fetchType._oraTypeNum === constants.TNS_DATA_TYPE_VARCHAR)
146+
|| (cVar.fetchInfo.dbType._oraTypeNum === constants.TNS_DATA_TYPE_VECTOR
147+
&& pVar.fetchInfo.fetchType._oraTypeNum === constants.TNS_DATA_TYPE_LONG)) {
144148
cVar.type = pVar.fetchInfo.fetchType;
145149
cVar.maxSize = pVar.maxSize;
146150
}

test/dataTypeJson.js

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1026,4 +1026,98 @@ describe('244.dataTypeJson.js', function() {
10261026

10271027
}); // 244.12
10281028

1029+
describe('244.13 Read JSON data on meta data change', function() {
1030+
1031+
const tableNameJSON = 'nodb_myjson_recreate';
1032+
let sequence = 1;
1033+
const sqlCreate = " CREATE TABLE " + tableNameJSON + " ( \n" +
1034+
" id NUMBER, \n" +
1035+
" content JSON \n" +
1036+
" )";
1037+
1038+
before('create table, insert data', async function() {
1039+
if (!isRunnable) {
1040+
this.skip();
1041+
}
1042+
await testsUtil.createTable(connection, tableNameJSON, sqlCreate);
1043+
}); // before()
1044+
1045+
after(async function() {
1046+
if (!isRunnable) {
1047+
this.skip();
1048+
}
1049+
oracledb.stmtCacheSize = default_stmtCacheSize;
1050+
oracledb.fetchAsString = [];
1051+
await testsUtil.dropTable(connection, tableNameJSON);
1052+
}); // after()
1053+
1054+
async function recreateTable() {
1055+
await testsUtil.dropTable(connection, tableNameJSON);
1056+
await testsUtil.createTable(connection, tableNameJSON, sqlCreate);
1057+
}
1058+
1059+
const testInsertAndFetch = async function(seq, jsonVal, resultStr, selectOpts) {
1060+
let sql = "insert into " + tableNameJSON + " ( id, content ) values (:i, :c)";
1061+
const binds = [
1062+
{ val: seq, type: oracledb.NUMBER, dir: oracledb.BIND_IN },
1063+
{ val: jsonVal, type: oracledb.DB_TYPE_JSON, dir: oracledb.BIND_IN }
1064+
];
1065+
1066+
await connection.execute(sql, binds);
1067+
sql = "select content as C from " + tableNameJSON + " where id = " + seq;
1068+
const result = await connection.execute(sql, [], selectOpts);
1069+
assert.strictEqual(result.rows[0][0], resultStr);
1070+
};
1071+
1072+
it('244.13.1 table recreate - with oracledb.fetchAsString', async function() {
1073+
oracledb.fetchAsString = [ oracledb.DB_TYPE_JSON ];
1074+
const jsonVals = [{ "key5": "2018/11/01 18:30:00" }];
1075+
const resultStr = ["{\"key5\":\"2018/11/01 18:30:00\"}"];
1076+
1077+
// Add the JSON Field with Long Field Name to the JSON Values Array
1078+
// for Oracle DB 23.4 (and Oracle Client 23.4)
1079+
if (isOracle_23_4) {
1080+
const longFieldName = 'A'.repeat(1000);
1081+
const jsonVal = {};
1082+
jsonVal[longFieldName] = "2018/11/01 18:30:00";
1083+
jsonVals.push(jsonVal);
1084+
resultStr.push(`{"${longFieldName}":"2018/11/01 18:30:00"}`);
1085+
}
1086+
1087+
for (let i = 0; i < jsonVals.length; i++) {
1088+
await testInsertAndFetch(sequence, jsonVals[i], resultStr[i], {});
1089+
sequence++;
1090+
}
1091+
1092+
await recreateTable();
1093+
sequence = 1;
1094+
1095+
for (let i = 0; i < jsonVals.length; i++) {
1096+
await testInsertAndFetch(sequence, jsonVals[i], resultStr[i], {});
1097+
sequence++;
1098+
}
1099+
1100+
}); // 244.13.1
1101+
1102+
it('244.13.2 table recreate - with fetchInfo oracledb.STRING', async function() {
1103+
oracledb.fetchAsString = [];
1104+
const jsonVal = { "key5": "2018/11/01 18:30:00" };
1105+
const resultStr = "{\"key5\":\"2018/11/01 18:30:00\"}";
1106+
1107+
const options = {
1108+
fetchInfo: { C: { type: oracledb.STRING } }
1109+
};
1110+
1111+
// Test Insert and Fetch of JSON Data
1112+
await testInsertAndFetch(sequence, jsonVal, resultStr, options);
1113+
// Recreate the same table
1114+
await recreateTable();
1115+
// Test Insert and Fetch of JSON Data again
1116+
await testInsertAndFetch(sequence, jsonVal, resultStr, options);
1117+
sequence++;
1118+
1119+
}); // 244.13.2
1120+
1121+
}); // 244.13
1122+
10291123
});

test/dataTypeVector1.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1897,4 +1897,52 @@ describe('294. dataTypeVector1.js', function() {
18971897
);
18981898
}
18991899
}); // 294.72
1900+
1901+
it('294.73 fetch VECTOR column as string with table recreate', async function() {
1902+
oracledb.fetchTypeHandler = function() {
1903+
return {type: oracledb.STRING};
1904+
};
1905+
1906+
const table = 'nodb_vectorDbTable1';
1907+
const sqlCreate = `CREATE TABLE IF NOT EXISTS ${table} (
1908+
IntCol NUMBER,
1909+
Vector64Col vector(10, float64)
1910+
)`;
1911+
let plsqlCreate = testsUtil.sqlCreateTable(table, sqlCreate);
1912+
await connection.execute(plsqlCreate);
1913+
1914+
// Create a Float64Array
1915+
const float64Array = new Float64Array(
1916+
[-999999.12345, 987654.321, -12345.6789, 56789.0123,
1917+
-314159.2654, 291828.1828, -99999.9999, 43210.9876, -87654.321, 65432.1098]);
1918+
1919+
const sqlInsert = `INSERT INTO ${table} (IntCol, Vector64Col) VALUES(:id, :vec64)`;
1920+
const bindOpts = {
1921+
id: 2,
1922+
vec64: float64Array
1923+
};
1924+
await connection.execute(sqlInsert, bindOpts);
1925+
1926+
let result = await connection.execute(`SELECT Vector64Col FROM ${table}`);
1927+
1928+
// Convert the vector data returned as a string back to Float64Array
1929+
const resultFloat64Array1 = new Float64Array(JSON.parse(result.rows[0][0]));
1930+
1931+
assert.deepStrictEqual(resultFloat64Array1, float64Array);
1932+
await connection.execute(testsUtil.sqlDropTable(table));
1933+
1934+
// Recreate the table with same data and redo the fetch
1935+
plsqlCreate = testsUtil.sqlCreateTable(table, sqlCreate);
1936+
await connection.execute(plsqlCreate);
1937+
await connection.execute(sqlInsert, bindOpts);
1938+
1939+
result = await connection.execute(`SELECT Vector64Col FROM ${table}`);
1940+
1941+
// Convert the vector data returned as a string back to Float64Array
1942+
const resultFloat64Array2 = new Float64Array(JSON.parse(result.rows[0][0]));
1943+
1944+
assert.deepStrictEqual(resultFloat64Array2, float64Array);
1945+
await connection.execute(testsUtil.sqlDropTable(table));
1946+
1947+
}); // 294.73
19001948
});

test/list.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4940,6 +4940,9 @@ oracledb.OUT_FORMAT_OBJECT and resultSet = true
49404940
244.11.3 fetch JSON with relative offsets and shared fields, not values
49414941
244.12 Verify auto-generated SODA document key
49424942
244.12.1 Verify Json Id on select
4943+
244.13 Read JSON data on meta data change
4944+
244.13.1 table recreate - with oracledb.fetchAsString
4945+
244.13.2 table recreate - with fetchInfo oracledb.STRING
49434946

49444947
245. fetchLobAsStrBuf.js
49454948
245.1 CLOB,BLOB Insert
@@ -5775,6 +5778,7 @@ oracledb.OUT_FORMAT_OBJECT and resultSet = true
57755778
294.70 typed arrays with undefined value
57765779
294.71 typed arrays with null values
57775780
294.72 inserting empty vector in Fixed and Flex vector columns
5781+
294.73 fetch VECTOR column as string with table recreate
57785782

57795783
295. dataTypeVector2.js
57805784
295.1 verify fetch information for older clients

0 commit comments

Comments
 (0)