Fixed bug that throws the NJS-111 internal error, on the second SELECT call issued after the first SELECT call on an empty table with LOBs

This commit is contained in:
Sharad Chandran R 2023-07-06 13:10:16 +05:30
parent 8abee4c661
commit bae7dd19bd
6 changed files with 86 additions and 5 deletions

View File

@ -11,6 +11,10 @@ node-oracledb `v6.0.3 <https://github.com/oracle/node-oracledb/compare/v6.0.2...
Thin Mode Changes
+++++++++++++++++
#) Fixed bug that throws the NJS-111 internal error, on the second
select SQL issued after first select SQL is done on an empty
table involving LOB types.
#) Avoid throwing errors when calls to ``os.userInfo()`` fail.
`Issue #1564 <https://github.com/oracle/node-oracledb/issues/1564>`__.

View File

@ -77,21 +77,21 @@ class ExecuteMessage extends MessageWithData {
dmlOptions = constants.TNS_EXEC_OPTION_IMPLICIT_RESULTSET;
options |= constants.TNS_EXEC_OPTION_EXECUTE;
}
if (stmt.cursorId == 0 || stmt.isDdl) {
if (stmt.cursorId === 0 || stmt.isDdl) {
options |= constants.TNS_EXEC_OPTION_PARSE;
}
if (stmt.isQuery) {
if (this.parseOnly) {
options |= constants.TNS_EXEC_OPTION_DESCRIBE;
} else {
if (this.options.prefetchRows > 0) {
options |= constants.TNS_EXEC_OPTION_FETCH;
}
if (stmt.cursorId === 0 || stmt.requiresDefine) {
numIters = this.options.prefetchRows;
} else {
numIters = this.options.fetchArraySize;
}
if (numIters > 0 && !stmt.noPrefetch) {
options |= constants.TNS_EXEC_OPTION_FETCH;
}
}
}
if (!stmt.isPlSql && !this.parseOnly) {
@ -276,7 +276,7 @@ class ExecuteMessage extends MessageWithData {
if (this.currentRow === 0) {
let stmt = this.statement;
if (stmt.cursorId !== 0 && !stmt.requiresFullExecute && !this.parseOnly && !stmt.requiresDefine && !stmt.isDdl && !this.batchErrors) {
if (stmt.isQuery && !stmt.requiresDefine && this.options.prefetchRows > 0) {
if (stmt.isQuery && !stmt.requiresDefine && !stmt.noPrefetch && this.options.prefetchRows > 0) {
this.functionCode = constants.TNS_FUNC_REEXECUTE_AND_FETCH;
} else {
this.functionCode = constants.TNS_FUNC_REEXECUTE;

View File

@ -547,6 +547,7 @@ class MessageWithData extends Message {
variable.maxSize = constants.TNS_MAX_LONG_LENGTH;
}
resultSet.statement.requiresDefine = true;
resultSet.statement.noPrefetch = true;
}
}
}

View File

@ -93,6 +93,7 @@ class Statement {
this.queryVars = [];
this.bindInfoDict = new Map();
this.requiresFullExecute = false;
this.noPrefetch = false;
this.returnToCache = false;
this.numColumns = 0;
this.lastRowIndex;

View File

@ -42,6 +42,7 @@ const fs = require('fs');
const assert = require('assert');
const dbConfig = require('./dbconfig.js');
const assist = require('./dataTypeAssist.js');
const testsUtil = require('./testsUtil.js');
let inFileName = 'test/clobexample.txt'; // the file with text to be inserted into the database
let outFileName = 'test/clobstreamout.txt'; // output file with the stream out data
@ -170,4 +171,43 @@ describe('40. dataTypeClob.js', function() {
await assist.verifyNullValues(connection, tableName);
});
});
describe('40.3 Read CLOB data on meta data change', function() {
let connection = null;
const tableNameCLOB = 'nodb_myclobs_re_create';
const sqlCreateQuery = `
CREATE TABLE ${tableNameCLOB} (
num NUMBER,
content CLOB
)`;
const sqlDrop = testsUtil.sqlDropTable(tableNameCLOB);
const sqlCreate = testsUtil.sqlCreateTable(tableNameCLOB, sqlCreateQuery);
const insertSql = `INSERT INTO ${tableNameCLOB} (num, content) ` +
`VALUES (:n, 'CLOB')`;
const selectSql = `SELECT content FROM ${tableNameCLOB} WHERE num = 1`;
before(async function() {
oracledb.fetchAsString = [oracledb.CLOB];
connection = await oracledb.getConnection(dbConfig);
await connection.execute(sqlCreate);
await connection.execute(insertSql, { n: 1 }, { autoCommit: false });
});
after(async function() {
oracledb.fetchAsString = [];
await connection.execute(sqlDrop);
await connection.close();
});
it('40.3.1 Recreate table after CLOB column is read and statement is in statement cache',
async function() {
await connection.execute(selectSql, {}, { keepInStmtCache: true });
await connection.execute(sqlDrop);
await connection.execute(sqlCreate);
await connection.execute(insertSql, { n: 1 }, { autoCommit: false });
await connection.execute(selectSql);
});
});
});

View File

@ -36,6 +36,7 @@ const fs = require('fs');
const fsPromises = require('fs/promises');
const assert = require('assert');
const dbConfig = require('./dbconfig.js');
const testsUtil = require('./testsUtil.js');
describe("72. lobBind2.js", function() {
@ -539,4 +540,38 @@ describe("72. lobBind2.js", function() {
}); // 72.3
describe('72.4 Create Table with CLOB and Number columns and do select with empty rows and select after rows insertion', function() {
let connection = null;
const tableNameCLOB = 'nodb_myclobs_num_table';
const sqlCreateQuery = `
CREATE TABLE ${tableNameCLOB} (
F1 NUMBER,
F2 CLOB,
F3 CLOB
)`;
const sqlDrop = testsUtil.sqlDropTable(tableNameCLOB);
const sqlCreate = testsUtil.sqlCreateTable(tableNameCLOB, sqlCreateQuery);
const insertSql = `INSERT INTO ${tableNameCLOB} (F1, F2, F3) ` +
`VALUES (:1, :2, :3)`;
const selectSql = `SELECT * FROM ${tableNameCLOB} `;
before(async function() {
oracledb.fetchAsString = [oracledb.CLOB];
connection = await oracledb.getConnection(dbConfig);
await connection.execute(sqlCreate);
await connection.execute(selectSql, {}, {keepInStmtCache: true});
await connection.execute(insertSql, [1, 'CLOB1', 'CLOB2']);
});
after(async function() {
oracledb.fetchAsString = [];
await connection.execute(sqlDrop);
await connection.close();
});
it('72.4.1 Read both CLOB and Number with statement being in statement cache', async function() {
await connection.execute(selectSql, {}, {keepInStmtCache: true});
});
});
});