Skip to content

Commit 04f0a0e

Browse files
committed
Optimization with PL/SQL usage in executeMany with Implicit Connection Pooling
1 parent e190a3d commit 04f0a0e

File tree

5 files changed

+49
-21
lines changed

5 files changed

+49
-21
lines changed

lib/errors.js

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,6 @@ const ERR_VECTOR_FORMAT_NOT_SUPPORTED = 144;
144144
const ERR_VECTOR_VERSION_NOT_SUPPORTED = 145;
145145
const ERR_OBJECT_IS_NOT_A_COLLECTION = 146;
146146
const ERR_CURSOR_HAS_BEEN_CLOSED = 147;
147-
const ERR_INVALID_POOL_BOUNDARY = 148;
148147

149148
// Oracle Net layer errors start from 500
150149
const ERR_CONNECTION_CLOSED = 500;
@@ -190,7 +189,6 @@ adjustErrorXref.set("ORA-00600", ERR_CONNECTION_CLOSED);
190189
adjustErrorXref.set("ORA-24338", ERR_INVALID_REF_CURSOR);
191190
adjustErrorXref.set("ORA-25708", ERR_TOKEN_HAS_EXPIRED);
192191
adjustErrorXref.set("ORA-24344", WRN_COMPILATION_CREATE);
193-
adjustErrorXref.set("ORA-24510", ERR_INVALID_POOL_BOUNDARY);
194192

195193
// define mapping for error messages
196194
const messages = new Map();
@@ -422,8 +420,6 @@ messages.set(ERR_OBJECT_IS_NOT_A_COLLECTION, // NJS-146
422420
'object %s is not a collection');
423421
messages.set(ERR_CURSOR_HAS_BEEN_CLOSED, // NJS-147
424422
'cursor has been closed by the database');
425-
messages.set(ERR_INVALID_POOL_BOUNDARY, // NJS-148
426-
'invalid value of POOL_BOUNDARY in connect string');
427423

428424
// Oracle Net layer errors
429425

@@ -816,7 +812,6 @@ module.exports = {
816812
ERR_VECTOR_VERSION_NOT_SUPPORTED,
817813
ERR_OBJECT_IS_NOT_A_COLLECTION,
818814
ERR_CURSOR_HAS_BEEN_CLOSED,
819-
ERR_INVALID_POOL_BOUNDARY,
820815
ERR_CONNECTION_CLOSED_CODE: `${ERR_PREFIX}-${ERR_CONNECTION_CLOSED}`,
821816
WRN_COMPILATION_CREATE,
822817
assert,

lib/thin/connection.js

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -187,22 +187,18 @@ class ThinConnectionImpl extends ConnectionImpl {
187187
// if a PL/SQL statement requires a full execute, perform only a single
188188
// iteration in order to allow the determination of input/output binds
189189
// to be completed; after that, an execution of the remaining iterations
190-
// can be performed (but only if the cursor remains intact)
191-
const countIters = numIters;
192-
if (statement.isPlSql && statement.requiresFullExecute) {
190+
// can be performed.
191+
if (statement.isPlSql && (statement.cursorId === 0 ||
192+
statement.requiresFullExecute)) {
193193
message.numExecs = 1;
194-
while (numIters > 0) {
195-
numIters -= 1;
196-
await this._protocol._processMessage(message);
197-
statement.requiresFullExecute = false;
198-
message.offset += 1;
199-
if (statement.cursorId != 0) {
200-
break;
201-
}
202-
}
194+
message.noImplicitRelease = true;
195+
await this._protocol._processMessage(message);
196+
statement.requiresFullExecute = false;
197+
message.numExecs = numIters - 1;
198+
message.offset = 1;
199+
message.noImplicitRelease = false;
203200
}
204-
if (numIters > 0) {
205-
message.numExecs = numIters;
201+
if (message.numExecs > 0) {
206202
await this._protocol._processMessage(message);
207203
statement.requiresFullExecute = false;
208204
}
@@ -224,7 +220,7 @@ class ThinConnectionImpl extends ConnectionImpl {
224220
result.resultSet = message.resultSet;
225221
} else {
226222
statement.bufferRowIndex = 0;
227-
const outBinds = thinUtil.getOutBinds(statement, countIters,
223+
const outBinds = thinUtil.getOutBinds(statement, numIters,
228224
executeManyFlag);
229225
if (outBinds) {
230226
result.outBinds = outBinds;

lib/thin/protocol/constants.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,7 @@ module.exports = {
464464
TNS_EXEC_OPTION_DESCRIBE: 0x20000,
465465
TNS_EXEC_OPTION_NO_COMPRESSED_FETCH: 0x40000,
466466
TNS_EXEC_OPTION_BATCH_ERRORS: 0x80000,
467+
TNS_EXEC_OPTION_NO_IMPL_REL: 0x200000,
467468

468469
// server side piggyback op codes
469470
TNS_SERVER_PIGGYBACK_QUERY_CACHE_INVALIDATION: 1,

lib/thin/protocol/messages/execute.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,17 @@ class ExecuteMessage extends MessageWithData {
6868
const stmt = this.statement;
6969
const params = stmt.bindInfoList;
7070

71+
if (this.noImplicitRelease) {
72+
dmlOptions |= constants.TNS_EXEC_OPTION_NO_IMPL_REL;
73+
}
74+
7175
if (!stmt.requiresDefine && !this.parseOnly && params) {
7276
numParams = params.length;
7377
}
7478
if (stmt.requiresDefine) {
7579
options |= constants.TNS_EXEC_OPTION_DEFINE;
7680
} else if (!this.parseOnly && stmt.sql) {
77-
dmlOptions = constants.TNS_EXEC_OPTION_IMPLICIT_RESULTSET;
81+
dmlOptions |= constants.TNS_EXEC_OPTION_IMPLICIT_RESULTSET;
7882
options |= constants.TNS_EXEC_OPTION_EXECUTE;
7983
}
8084
if (stmt.cursorId === 0 || stmt.isDdl) {

test/executeMany1.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,38 @@ describe('163. executeMany1.js', function() {
492492
await dotruncate();
493493
}); // 163.16
494494

495+
it('163.17 calls PL/SQL, with round trip count check', async function() {
496+
if (!dbConfig.test.DBA_PRIVILEGE) {
497+
this.skip();
498+
}
499+
await doCreateProc();
500+
const plsql = "BEGIN nodb_proc_em(:1, :2, :3); END;";
501+
const binds = [ [1], [2], [3], [4], [6]];
502+
const options = {
503+
bindDefs: [
504+
{ type: oracledb.NUMBER },
505+
{ type: oracledb.NUMBER, dir: oracledb.BIND_OUT },
506+
{ type: oracledb.STRING, dir: oracledb.BIND_OUT, maxSize: 20 }
507+
]
508+
};
509+
const sid = await testsUtil.getSid(conn);
510+
const rt1 = await testsUtil.getRoundTripCount(sid);
511+
await conn.executeMany(plsql, binds, options);
512+
const rt2 = await testsUtil.getRoundTripCount(sid);
513+
let result = false;
514+
// thick does OAL8 after each iterations. Round trip count increases
515+
// with each iteration.
516+
if (dbConfig.test.mode === 'thick' && rt2 - rt1 === 5) {
517+
result = true;
518+
}
519+
520+
if (dbConfig.test.mode === 'thin' && rt2 - rt1 < 3) {
521+
result = true;
522+
}
523+
assert.deepStrictEqual(result, true);
524+
await doDropProc();
525+
}); // 163.17
526+
495527
const doCreateProc = async function() {
496528
const proc = "CREATE OR REPLACE PROCEDURE nodb_proc_em (a_num IN NUMBER, " +
497529
" a_outnum OUT NUMBER, a_outstr OUT VARCHAR2) \n" +

0 commit comments

Comments
 (0)