Skip to content

Commit

Permalink
Fixed bug that throws the NJS-111 internal error, on the second SELEC…
Browse files Browse the repository at this point in the history
…T call issued after the first SELECT call on an empty table with LOBs
  • Loading branch information
sharadraju committed Jul 6, 2023
1 parent 8abee4c commit bae7dd1
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 5 deletions.
4 changes: 4 additions & 0 deletions doc/src/release_notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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>`__.

Expand Down
10 changes: 5 additions & 5 deletions lib/thin/protocol/messages/execute.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions lib/thin/protocol/messages/withData.js
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,7 @@ class MessageWithData extends Message {
variable.maxSize = constants.TNS_MAX_LONG_LENGTH;
}
resultSet.statement.requiresDefine = true;
resultSet.statement.noPrefetch = true;
}
}
}
Expand Down
1 change: 1 addition & 0 deletions lib/thin/statement.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
40 changes: 40 additions & 0 deletions test/dataTypeClob.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
});

});

});
35 changes: 35 additions & 0 deletions test/lobBind2.js
Original file line number Diff line number Diff line change
Expand Up @@ -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() {

Expand Down Expand Up @@ -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});
});

});
});

0 comments on commit bae7dd1

Please sign in to comment.