oracledb 6.10.0 → 7.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.txt +1 -1
- package/NOTICE.txt +1 -1
- package/README.md +9 -9
- package/build/Release/oracledb-7.0.1-darwin-arm64.node +0 -0
- package/build/Release/oracledb-7.0.1-darwin-arm64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-7.0.1-js-buildinfo.txt +1 -0
- package/build/Release/oracledb-7.0.1-linux-arm64.node +0 -0
- package/build/Release/oracledb-7.0.1-linux-arm64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-7.0.1-linux-x64.node +0 -0
- package/build/Release/oracledb-7.0.1-linux-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-7.0.1-win32-x64.node +0 -0
- package/build/Release/oracledb-7.0.1-win32-x64.node-buildinfo.txt +1 -0
- package/lib/aqDeqOptions.js +4 -4
- package/lib/aqEnqOptions.js +2 -2
- package/lib/aqQueue.js +11 -6
- package/lib/connection.js +407 -40
- package/lib/endUserSecurityContext.js +169 -0
- package/lib/errors.js +108 -5
- package/lib/impl/connection.js +76 -2
- package/lib/impl/datahandlers/buffer.js +19 -5
- package/lib/impl/datahandlers/vector.js +25 -5
- package/lib/impl/lob.js +9 -0
- package/lib/impl/parserHelpers.js +447 -0
- package/lib/impl/resultset.js +1 -1
- package/lib/lob.js +27 -14
- package/lib/obfuscation.js +97 -0
- package/lib/oracledb.js +148 -43
- package/lib/parser.js +204 -0
- package/lib/pipeline.js +113 -0
- package/lib/pool.js +16 -1
- package/lib/resultset.js +42 -21
- package/lib/settings.js +1 -0
- package/lib/thin/connection.js +461 -53
- package/lib/thin/dbObject.js +10 -4
- package/lib/thin/lob.js +20 -1
- package/lib/thin/pool.js +43 -63
- package/lib/thin/protocol/capabilities.js +18 -3
- package/lib/thin/protocol/constants.js +82 -2
- package/lib/thin/protocol/encryptDecrypt.js +43 -8
- package/lib/thin/protocol/messages/aqArray.js +2 -2
- package/lib/thin/protocol/messages/aqBase.js +2 -2
- package/lib/thin/protocol/messages/auth.js +6 -1
- package/lib/thin/protocol/messages/base.js +246 -5
- package/lib/thin/protocol/messages/dataType.js +8 -3
- package/lib/thin/protocol/messages/directPathLoadStream.js +377 -0
- package/lib/thin/protocol/messages/directPathOp.js +65 -0
- package/lib/thin/protocol/messages/directPathPrepare.js +158 -0
- package/lib/thin/protocol/messages/endPipeline.js +56 -0
- package/lib/thin/protocol/messages/execute.js +9 -7
- package/lib/thin/protocol/messages/index.js +9 -1
- package/lib/thin/protocol/messages/protocol.js +2 -2
- package/lib/thin/protocol/messages/withData.js +10 -143
- package/lib/thin/protocol/packet.js +115 -24
- package/lib/thin/protocol/protocol.js +110 -25
- package/lib/thin/protocol/utils.js +1 -26
- package/lib/thin/resultSet.js +13 -19
- package/lib/thin/sqlnet/ezConnectResolver.js +4 -4
- package/lib/thin/sqlnet/navNodes.js +4 -2
- package/lib/thin/sqlnet/networkSession.js +78 -50
- package/lib/thin/sqlnet/ntTcp.js +24 -0
- package/lib/thin/sqlnet/nvStrToNvPair.js +50 -25
- package/lib/thin/sqlnet/packet.js +49 -8
- package/lib/thin/sqlnet/paramParser.js +10 -7
- package/lib/thin/sqlnet/sessionAtts.js +2 -2
- package/lib/thin/statementCache.js +2 -4
- package/lib/traceHandler.js +59 -2
- package/lib/transformer.js +8 -3
- package/lib/types.js +35 -21
- package/lib/util.js +6 -6
- package/lib/version.js +4 -4
- package/package/install.js +5 -5
- package/package/prunebinaries.js +1 -1
- package/package.json +1 -1
- package/plugins/configProviders/awsCommon.js +125 -0
- package/plugins/configProviders/awss3/index.js +138 -0
- package/plugins/configProviders/awssecretsmanager/index.js +147 -0
- package/plugins/configProviders/azure/index.js +4 -5
- package/plugins/token/extensionAzure/index.js +0 -1
- package/plugins/token/extensionOci/index.js +0 -1
- package/build/Release/oracledb-6.10.0-darwin-arm64.node +0 -0
- package/build/Release/oracledb-6.10.0-darwin-arm64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.10.0-darwin-x64.node +0 -0
- package/build/Release/oracledb-6.10.0-darwin-x64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.10.0-js-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.10.0-linux-arm64.node +0 -0
- package/build/Release/oracledb-6.10.0-linux-arm64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.10.0-linux-x64.node +0 -0
- package/build/Release/oracledb-6.10.0-linux-x64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.10.0-win32-x64.node +0 -0
- package/build/Release/oracledb-6.10.0-win32-x64.node-buildinfo.txt +0 -1
package/lib/thin/connection.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright (c) 2022,
|
|
1
|
+
// Copyright (c) 2022, 2026, Oracle and/or its affiliates.
|
|
2
2
|
|
|
3
3
|
//-----------------------------------------------------------------------------
|
|
4
4
|
//
|
|
@@ -53,6 +53,29 @@ class TDSBuffer extends BaseBuffer {
|
|
|
53
53
|
|
|
54
54
|
class ThinConnectionImpl extends ConnectionImpl {
|
|
55
55
|
|
|
56
|
+
static _createNamespace(nameSpaceName) {
|
|
57
|
+
return {
|
|
58
|
+
nameSpaceName,
|
|
59
|
+
keyValues: [],
|
|
60
|
+
pendingClear: false
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
static _mergeKeyValues(namespace, keyValues) {
|
|
65
|
+
const mergedKeyValues = namespace.keyValues.slice();
|
|
66
|
+
for (const entry of keyValues) {
|
|
67
|
+
const entryKey = Object.keys(entry)[0];
|
|
68
|
+
const existingIndex = mergedKeyValues.findIndex((existingEntry) =>
|
|
69
|
+
Object.prototype.hasOwnProperty.call(existingEntry, entryKey));
|
|
70
|
+
if (existingIndex !== -1) {
|
|
71
|
+
mergedKeyValues.splice(existingIndex, 1);
|
|
72
|
+
}
|
|
73
|
+
mergedKeyValues.push(entry);
|
|
74
|
+
}
|
|
75
|
+
namespace.keyValues = mergedKeyValues;
|
|
76
|
+
namespace.pendingClear = false;
|
|
77
|
+
}
|
|
78
|
+
|
|
56
79
|
/**
|
|
57
80
|
* Terminates the connection
|
|
58
81
|
*
|
|
@@ -60,6 +83,7 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
60
83
|
*/
|
|
61
84
|
async close() {
|
|
62
85
|
try {
|
|
86
|
+
this.clearEndUserSecurityContext();
|
|
63
87
|
if (this._protocol.txnInProgress) {
|
|
64
88
|
if (this.tpcContext) {
|
|
65
89
|
const message = this.createTpcRollbackMessage();
|
|
@@ -82,7 +106,7 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
82
106
|
}
|
|
83
107
|
this.nscon.disconnect();
|
|
84
108
|
}
|
|
85
|
-
} catch
|
|
109
|
+
} catch {
|
|
86
110
|
// immediate close of open socket on failure
|
|
87
111
|
// exception won't be thrown to user
|
|
88
112
|
this.nscon.disconnect(sqlNetConstants.NSFIMM);
|
|
@@ -166,12 +190,8 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
166
190
|
}
|
|
167
191
|
}
|
|
168
192
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
//
|
|
172
|
-
// Calls the RPC that executes a SQL statement and returns the results.
|
|
173
|
-
//---------------------------------------------------------------------------
|
|
174
|
-
async _execute(statement, numIters, binds, options, executeManyFlag, internalTempLobs = []) {
|
|
193
|
+
async _getExecuteMessage(statement, numIters, binds, options,
|
|
194
|
+
executeManyFlag, internalTempLobs = []) {
|
|
175
195
|
|
|
176
196
|
// Throw error if executeMany is not called on a DML statement or PL/SQL
|
|
177
197
|
if (executeManyFlag && statement.isQuery) {
|
|
@@ -206,6 +226,18 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
206
226
|
message.numExecs = numIters;
|
|
207
227
|
message.arrayDmlRowCounts = options.dmlRowCounts;
|
|
208
228
|
message.batchErrors = options.batchErrors;
|
|
229
|
+
return message;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
//---------------------------------------------------------------------------
|
|
233
|
+
// _execute()
|
|
234
|
+
//
|
|
235
|
+
// Calls the RPC that executes a SQL statement and returns the results.
|
|
236
|
+
//---------------------------------------------------------------------------
|
|
237
|
+
async _execute(statement, numIters, binds, options, executeManyFlag, internalTempLobs = []) {
|
|
238
|
+
|
|
239
|
+
const message = await this._getExecuteMessage(statement, numIters, binds,
|
|
240
|
+
options, executeManyFlag, internalTempLobs);
|
|
209
241
|
|
|
210
242
|
// if a PL/SQL statement requires a full execute, perform only a single
|
|
211
243
|
// iteration in order to allow the determination of input/output binds
|
|
@@ -227,14 +259,124 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
227
259
|
}
|
|
228
260
|
|
|
229
261
|
// if a define is required, send an additional request to the database
|
|
230
|
-
|
|
231
|
-
statement.requiresFullExecute = true;
|
|
232
|
-
await this._protocol._processMessage(message);
|
|
233
|
-
statement.requiresFullExecute = false;
|
|
234
|
-
statement.requiresDefine = false;
|
|
235
|
-
}
|
|
262
|
+
await this._handleDefines(statement, message);
|
|
236
263
|
|
|
237
264
|
// process results
|
|
265
|
+
return this._processExecuteResult(statement, numIters, options,
|
|
266
|
+
executeManyFlag, message);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
//---------------------------------------------------------------------------
|
|
270
|
+
// _sendMessagesForPipeline()
|
|
271
|
+
//
|
|
272
|
+
// Sends the messages for the pipeline to the database for processing.
|
|
273
|
+
// This is async function only because of await adapter.pauseWrite()
|
|
274
|
+
// which is used to slow down writing to network socket.
|
|
275
|
+
//---------------------------------------------------------------------------
|
|
276
|
+
async _sendMessagesForPipeline(messages, continueOnError) {
|
|
277
|
+
for (const messageObj of messages) {
|
|
278
|
+
if (messageObj.pipelineResultImpl.error)
|
|
279
|
+
continue;
|
|
280
|
+
const message = messageObj.message;
|
|
281
|
+
const opType = messageObj.pipelineResultImpl.op.opType;
|
|
282
|
+
try {
|
|
283
|
+
if (['execute', 'executeMany', 'fetchOne', 'fetchMany',
|
|
284
|
+
'fetchAll'].includes(opType)) {
|
|
285
|
+
const statement = messageObj.statement;
|
|
286
|
+
if (statement.isPlSql && (statement.cursorId === 0 ||
|
|
287
|
+
statement.requiresFullExecute)) {
|
|
288
|
+
message.numExecs = 1;
|
|
289
|
+
message.noImplicitRelease = true;
|
|
290
|
+
await this._protocol._encodeMessage(message);
|
|
291
|
+
message.requiresSingleExecute = true;
|
|
292
|
+
} else if (message.numExecs > 0) {
|
|
293
|
+
await this._protocol._encodeMessage(message);
|
|
294
|
+
}
|
|
295
|
+
} else if (opType === 'commit')
|
|
296
|
+
await this._protocol._encodeMessage(message);
|
|
297
|
+
} catch (err) {
|
|
298
|
+
this._returnStatement(messageObj.statement);
|
|
299
|
+
if (!continueOnError) {
|
|
300
|
+
throw (err);
|
|
301
|
+
}
|
|
302
|
+
messageObj.pipelineResultImpl.error = err;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
//---------------------------------------------------------------------------
|
|
308
|
+
// _createMessagesForPipelineOp()
|
|
309
|
+
//
|
|
310
|
+
// Creates a single message for a pipeline operation.
|
|
311
|
+
//---------------------------------------------------------------------------
|
|
312
|
+
async _createMessagesForPipelineOp(conn, operation) {
|
|
313
|
+
const opType = operation.opType;
|
|
314
|
+
if (opType === 'commit') {
|
|
315
|
+
errors.assert(conn._impl, errors.ERR_INVALID_CONNECTION);
|
|
316
|
+
return { message: new messages.CommitMessage(this) };
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
let processedArgs;
|
|
320
|
+
switch (opType) {
|
|
321
|
+
case 'execute':
|
|
322
|
+
processedArgs = await conn._processExecuteArgs(operation.statement,
|
|
323
|
+
operation.parameters, operation.options);
|
|
324
|
+
break;
|
|
325
|
+
case 'executeMany':
|
|
326
|
+
processedArgs = await conn._processExecuteManyArgs(operation.statement,
|
|
327
|
+
operation.parameters, operation.options);
|
|
328
|
+
break;
|
|
329
|
+
case 'fetchOne':
|
|
330
|
+
case 'fetchMany':
|
|
331
|
+
case 'fetchAll': {
|
|
332
|
+
const options = {
|
|
333
|
+
...operation.options,
|
|
334
|
+
fetchTypeHandler: conn._createFetchTypeHandler(operation.fetchLobs)
|
|
335
|
+
};
|
|
336
|
+
processedArgs = await conn._processExecuteArgs(operation.statement,
|
|
337
|
+
operation.parameters, options);
|
|
338
|
+
break;
|
|
339
|
+
}
|
|
340
|
+
default:
|
|
341
|
+
errors.throwErr(errors.ERR_PIPELINE_OPERATION_NOT_SUPPORTED, opType);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
const {sql, numIters, binds, options, executeManyFlag} = processedArgs;
|
|
345
|
+
return await this._prepareForExecute(sql, numIters, binds, options,
|
|
346
|
+
executeManyFlag);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
//---------------------------------------------------------------------------
|
|
350
|
+
// _createMessagesForPipeline()
|
|
351
|
+
//
|
|
352
|
+
// Creates a list of messages for the pipeline and returns them after they
|
|
353
|
+
// have been submitted to the database for processing.
|
|
354
|
+
//---------------------------------------------------------------------------
|
|
355
|
+
async _createMessagesForPipeline(conn, resultsImpl, continueOnError) {
|
|
356
|
+
const messagesForPipeline = [];
|
|
357
|
+
let tokenNum = 1;
|
|
358
|
+
for (const resultImpl of resultsImpl) {
|
|
359
|
+
let messageObj;
|
|
360
|
+
try {
|
|
361
|
+
messageObj = await this._createMessagesForPipelineOp(conn,
|
|
362
|
+
resultImpl.op);
|
|
363
|
+
} catch (err) {
|
|
364
|
+
if (!continueOnError)
|
|
365
|
+
throw (err);
|
|
366
|
+
resultImpl.error = err;
|
|
367
|
+
continue;
|
|
368
|
+
}
|
|
369
|
+
messageObj.message.pipelineMessage = true;
|
|
370
|
+
messageObj.pipelineResultImpl = resultImpl;
|
|
371
|
+
messageObj.message.tokenNum = tokenNum;
|
|
372
|
+
tokenNum++;
|
|
373
|
+
messagesForPipeline.push(messageObj);
|
|
374
|
+
}
|
|
375
|
+
return messagesForPipeline;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
_processExecuteResult(statement, numIters, options, executeManyFlag,
|
|
379
|
+
message) {
|
|
238
380
|
const result = {};
|
|
239
381
|
if (message.warning) {
|
|
240
382
|
result.warning = message.warning;
|
|
@@ -284,6 +426,164 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
284
426
|
return result;
|
|
285
427
|
}
|
|
286
428
|
|
|
429
|
+
//---------------------------------------------------------------------------
|
|
430
|
+
// _completePipelineOp()
|
|
431
|
+
//
|
|
432
|
+
// Completes a particular pipeline operation.
|
|
433
|
+
//---------------------------------------------------------------------------
|
|
434
|
+
async _completePipelineOp(messageObj, conn) {
|
|
435
|
+
const message = messageObj.message;
|
|
436
|
+
const opType = messageObj.pipelineResultImpl.op.opType;
|
|
437
|
+
|
|
438
|
+
// Post-processing of pipeline message happen once after reading response
|
|
439
|
+
// of all the operations is completed in the first phase.
|
|
440
|
+
await message.postProcess();
|
|
441
|
+
await this._protocol._processCallStatus(message);
|
|
442
|
+
|
|
443
|
+
if (opType === 'commit')
|
|
444
|
+
return;
|
|
445
|
+
|
|
446
|
+
if (['execute', 'executeMany', 'fetchOne', 'fetchMany',
|
|
447
|
+
'fetchAll'].includes(opType)) {
|
|
448
|
+
const statement = messageObj.statement;
|
|
449
|
+
const numIters = messageObj.numIters;
|
|
450
|
+
const options = messageObj.options;
|
|
451
|
+
const executeManyFlag = messageObj.executeManyFlag;
|
|
452
|
+
try {
|
|
453
|
+
|
|
454
|
+
// for PL/SQL blocks that required a single execute, perform any
|
|
455
|
+
// remaining executes now
|
|
456
|
+
if (message.requiresSingleExecute) {
|
|
457
|
+
statement.requiresFullExecute = false;
|
|
458
|
+
message.numExecs = numIters - 1;
|
|
459
|
+
message.offset = 1;
|
|
460
|
+
message.noImplicitRelease = false;
|
|
461
|
+
if (message.numExecs > 0) {
|
|
462
|
+
await this._protocol._processMessage(message);
|
|
463
|
+
statement.requiresFullExecute = false;
|
|
464
|
+
}
|
|
465
|
+
message.requiresSingleExecute = false;
|
|
466
|
+
} else {
|
|
467
|
+
statement.requiresFullExecute = false;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
// resend the message if that is required (for operations that fetch
|
|
471
|
+
// LOBS, for example)
|
|
472
|
+
await this._handleDefines(statement, message);
|
|
473
|
+
|
|
474
|
+
// process results
|
|
475
|
+
messageObj.resultTemp = this._processExecuteResult(statement, numIters,
|
|
476
|
+
options, executeManyFlag, message);
|
|
477
|
+
} catch (err) {
|
|
478
|
+
this._returnStatement(messageObj.statement);
|
|
479
|
+
throw (err);
|
|
480
|
+
} finally {
|
|
481
|
+
for (const lob of messageObj.internalTempLobs) {
|
|
482
|
+
this._tempLobsToClose.push(lob._locator);
|
|
483
|
+
this._tempLobsTotalSize += lob._locator.length;
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
if (opType === 'executeMany')
|
|
487
|
+
await conn._transformExecuteManyResult(messageObj.resultTemp,
|
|
488
|
+
messageObj.options);
|
|
489
|
+
else if (opType === 'execute') {
|
|
490
|
+
await conn._handleFetchForExecuteInPipeline(messageObj.resultTemp, messageObj.options);
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
if (['fetchOne', 'fetchMany', 'fetchAll'].includes(opType)) {
|
|
494
|
+
// fetch rows
|
|
495
|
+
await conn._transformExecuteResult(messageObj.resultTemp,
|
|
496
|
+
messageObj.options, messageObj.pipelineResultImpl.op);
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
//---------------------------------------------------------------------------
|
|
502
|
+
// _completePipelineOps()
|
|
503
|
+
//
|
|
504
|
+
// Completes any pipeline operations that have not actually completed.
|
|
505
|
+
// This could be due to the fact that LOBs were fetched or a fetch all
|
|
506
|
+
// operation has more rows to fetch.
|
|
507
|
+
//---------------------------------------------------------------------------
|
|
508
|
+
async _completePipelineOps(messagesForPipeline, conn, continueOnError) {
|
|
509
|
+
for (const messageObj of messagesForPipeline) {
|
|
510
|
+
const resultImpl = messageObj.pipelineResultImpl;
|
|
511
|
+
if (resultImpl.error)
|
|
512
|
+
continue;
|
|
513
|
+
try {
|
|
514
|
+
await this._completePipelineOp(messageObj, conn);
|
|
515
|
+
if (!messageObj.pipelineResultImpl.error) {
|
|
516
|
+
messageObj.pipelineResultImpl.result = messageObj.resultTemp;
|
|
517
|
+
}
|
|
518
|
+
} catch (err) {
|
|
519
|
+
this._returnStatement(messageObj.statement);
|
|
520
|
+
if (!continueOnError) {
|
|
521
|
+
throw (err);
|
|
522
|
+
}
|
|
523
|
+
messageObj.pipelineResultImpl.error = err;
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
// Returns whether the connection supports pipelining. Currently this is
|
|
529
|
+
// only supported with Oracle Database 23ai and later.
|
|
530
|
+
supportsPipelining() {
|
|
531
|
+
return this.nscon.pipeliningSupport;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
//---------------------------------------------------------------------------
|
|
535
|
+
// runPipelineWithPipelining()
|
|
536
|
+
//
|
|
537
|
+
// Run the pipeline with pipelining when the database supports it.
|
|
538
|
+
//---------------------------------------------------------------------------
|
|
539
|
+
async runPipelineWithPipelining(conn, resultsImpl, continueOnError) {
|
|
540
|
+
this.pipelineMode = continueOnError ?
|
|
541
|
+
constants.TNS_PIPELINE_MODE_CONTINUE_ON_ERROR :
|
|
542
|
+
constants.TNS_PIPELINE_MODE_ABORT_ON_ERROR;
|
|
543
|
+
this.nscon.pipelineEnabled = true;
|
|
544
|
+
|
|
545
|
+
// Create all pipeline messages
|
|
546
|
+
const messagesForPipeline = await this._createMessagesForPipeline(conn,
|
|
547
|
+
resultsImpl, continueOnError);
|
|
548
|
+
try {
|
|
549
|
+
this._protocol.readBuf.resetPackets();
|
|
550
|
+
|
|
551
|
+
// Encode all messages
|
|
552
|
+
await this._sendMessagesForPipeline(messagesForPipeline,
|
|
553
|
+
continueOnError);
|
|
554
|
+
|
|
555
|
+
// endPipeline message
|
|
556
|
+
const endMessage = new messages.EndPipelineMessage(this);
|
|
557
|
+
|
|
558
|
+
// Decode responses for all operation messages, then process the final
|
|
559
|
+
// end-pipeline response and cleanup any remaining response packets.
|
|
560
|
+
await this._protocol.endPipeline(messagesForPipeline,
|
|
561
|
+
endMessage, this, continueOnError);
|
|
562
|
+
|
|
563
|
+
// Complete post processing of results (and deferred operations in
|
|
564
|
+
// non-pipeline mode)
|
|
565
|
+
await this._completePipelineOps(messagesForPipeline, conn,
|
|
566
|
+
continueOnError);
|
|
567
|
+
|
|
568
|
+
return conn._buildPipelineResults(resultsImpl);
|
|
569
|
+
} finally {
|
|
570
|
+
this.pipelineMode = 0;
|
|
571
|
+
this.nscon.pipelineEnabled = false;
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
//---------------------------------------------------------------------------
|
|
576
|
+
// runPipelineWithoutPipelining()
|
|
577
|
+
//
|
|
578
|
+
// Run the pipeline without pipelining when the database doesn't support
|
|
579
|
+
// pipelining. Call timeouts are disabled for consistency with when
|
|
580
|
+
// run with pipelining.
|
|
581
|
+
//---------------------------------------------------------------------------
|
|
582
|
+
async runPipelineWithoutPipelining(conn, resultsImpl, continueOnError) {
|
|
583
|
+
return await conn._runPipelineWithoutPipelining(resultsImpl,
|
|
584
|
+
continueOnError);
|
|
585
|
+
}
|
|
586
|
+
|
|
287
587
|
//---------------------------------------------------------------------------
|
|
288
588
|
// _parseTDSAttr()
|
|
289
589
|
//
|
|
@@ -789,7 +1089,8 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
789
1089
|
let portUpdateNum;
|
|
790
1090
|
|
|
791
1091
|
this.dbDomain = authMessage.sessionData['AUTH_SC_DB_DOMAIN'];
|
|
792
|
-
this.dbName = authMessage.sessionData['
|
|
1092
|
+
this.dbName = authMessage.sessionData['AUTH_SC_DBUNIQUE_NAME'];
|
|
1093
|
+
this.dbUniqueName = authMessage.sessionData['AUTH_SC_REAL_DBUNIQUE_NAME'];
|
|
793
1094
|
this.maxOpenCursors = Number(authMessage.sessionData['AUTH_MAX_OPEN_CURSORS'] || 0);
|
|
794
1095
|
this.serviceName = authMessage.sessionData['AUTH_SC_SERVICE_NAME'];
|
|
795
1096
|
this.instanceName = authMessage.sessionData['AUTH_INSTANCENAME'];
|
|
@@ -810,6 +1111,11 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
810
1111
|
}
|
|
811
1112
|
this.serverVersionString = versionNum + '.' + releaseNum + '.' + updateNum + '.' + portReleaseNum + '.' + portUpdateNum;
|
|
812
1113
|
this.serverVersion = versionNum * 100000000 + releaseNum * 1000000 + updateNum * 10000 + portReleaseNum * 100 + portUpdateNum * 1;
|
|
1114
|
+
|
|
1115
|
+
// Set pdbName only from Oracle Database version 12.2 onwards.
|
|
1116
|
+
if (this.serverVersion >= 1202000000) {
|
|
1117
|
+
this.pdbName = authMessage.sessionData.AUTH_DBNAME;
|
|
1118
|
+
}
|
|
813
1119
|
}
|
|
814
1120
|
|
|
815
1121
|
/**
|
|
@@ -853,51 +1159,52 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
853
1159
|
this.comboKey = null; // used in changePassword API
|
|
854
1160
|
this.tpcContext = null;
|
|
855
1161
|
this._sessionlessData = null;
|
|
1162
|
+
this._nameSpaceMap = new Map();
|
|
856
1163
|
|
|
857
1164
|
this.nscon = new nsi();
|
|
858
1165
|
finalizationRegistry.register(this, this.nscon);
|
|
859
1166
|
await this.nscon.connect(params);
|
|
860
1167
|
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
serverType = params._connInfo[0];
|
|
864
|
-
this.serviceName = params._connInfo[2];
|
|
865
|
-
this.purity = params._connInfo[3] | constants.PURITY_DEFAULT;
|
|
866
|
-
this.sid = params._connInfo[4];
|
|
867
|
-
} else {
|
|
868
|
-
serverType = this.nscon.getOption(sqlNetConstants.SERVERTYPE);
|
|
869
|
-
this.serviceName = this.nscon.getOption(sqlNetConstants.SVCNAME);
|
|
870
|
-
this.sid = this.nscon.getOption(sqlNetConstants.SID);
|
|
871
|
-
this.purity = this.nscon.getOption(sqlNetConstants.PURITY) | constants.PURITY_DEFAULT;
|
|
872
|
-
}
|
|
873
|
-
if (serverType) {
|
|
874
|
-
this._drcpEnabled = serverType.toLowerCase() === 'pooled';
|
|
875
|
-
}
|
|
876
|
-
this.remoteAddress = this.nscon.getOption(sqlNetConstants.REMOTEADDR);
|
|
877
|
-
this.connectionClass = params.connectionClass;
|
|
878
|
-
|
|
879
|
-
/*
|
|
880
|
-
* if drcp is used, use purity = NEW as the default purity for
|
|
881
|
-
* standalone connections and purity = SELF for connections that belong
|
|
882
|
-
* to a pool
|
|
883
|
-
*/
|
|
884
|
-
if (this.purity === constants.PURITY_DEFAULT && this._drcpEnabled) {
|
|
1168
|
+
try {
|
|
1169
|
+
let serverType;
|
|
885
1170
|
if (this.isPooled()) {
|
|
886
|
-
|
|
1171
|
+
serverType = params._connInfo[0];
|
|
1172
|
+
this.serviceName = params._connInfo[2];
|
|
1173
|
+
this.purity = params._connInfo[3] | constants.PURITY_DEFAULT;
|
|
1174
|
+
this.sid = params._connInfo[4];
|
|
887
1175
|
} else {
|
|
888
|
-
|
|
1176
|
+
serverType = this.nscon.getOption(sqlNetConstants.SERVERTYPE);
|
|
1177
|
+
this.serviceName = this.nscon.getOption(sqlNetConstants.SVCNAME);
|
|
1178
|
+
this.sid = this.nscon.getOption(sqlNetConstants.SID);
|
|
1179
|
+
this.purity = this.nscon.getOption(sqlNetConstants.PURITY) | constants.PURITY_DEFAULT;
|
|
1180
|
+
}
|
|
1181
|
+
if (serverType) {
|
|
1182
|
+
this._drcpEnabled = serverType.toLowerCase() === 'pooled';
|
|
1183
|
+
}
|
|
1184
|
+
this.remoteAddress = this.nscon.getOption(sqlNetConstants.REMOTEADDR);
|
|
1185
|
+
this.connectionClass = params.connectionClass;
|
|
1186
|
+
|
|
1187
|
+
/*
|
|
1188
|
+
* if drcp is used, use purity = NEW as the default purity for
|
|
1189
|
+
* standalone connections and purity = SELF for connections that belong
|
|
1190
|
+
* to a pool
|
|
1191
|
+
*/
|
|
1192
|
+
if (this.purity === constants.PURITY_DEFAULT && this._drcpEnabled) {
|
|
1193
|
+
if (this.isPooled()) {
|
|
1194
|
+
this.purity = constants.PURITY_SELF;
|
|
1195
|
+
} else {
|
|
1196
|
+
this.purity = constants.PURITY_NEW;
|
|
1197
|
+
}
|
|
889
1198
|
}
|
|
890
|
-
}
|
|
891
1199
|
|
|
892
|
-
|
|
1200
|
+
this._protocol = new Protocol(this);
|
|
893
1201
|
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
1202
|
+
// check if the protocol version supported by the database is high
|
|
1203
|
+
// enough; if not, reject the connection immediately
|
|
1204
|
+
if (this._protocol.caps.protocolVersion < constants.TNS_VERSION_MIN_ACCEPTED) {
|
|
1205
|
+
errors.throwErr(errors.ERR_SERVER_VERSION_NOT_SUPPORTED);
|
|
1206
|
+
}
|
|
899
1207
|
|
|
900
|
-
try {
|
|
901
1208
|
const protocolMessage = new messages.ProtocolMessage(this);
|
|
902
1209
|
const dataTypeMessage = new messages.DataTypeMessage(this);
|
|
903
1210
|
const authMessage = new messages.AuthMessage(this, params);
|
|
@@ -956,7 +1263,8 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
956
1263
|
// option is true
|
|
957
1264
|
//---------------------------------------------------------------------------
|
|
958
1265
|
_prepare(sql, options) {
|
|
959
|
-
const
|
|
1266
|
+
const forceNew = Boolean(options.fetchTypeMap);
|
|
1267
|
+
const statement = this._getStatement(sql, options.keepInStmtCache, forceNew);
|
|
960
1268
|
statement.bufferRowIndex = 0;
|
|
961
1269
|
statement.bufferRowCount = 0;
|
|
962
1270
|
statement.lastRowIndex = 0;
|
|
@@ -978,6 +1286,8 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
978
1286
|
* the user expects to get it
|
|
979
1287
|
*/
|
|
980
1288
|
if (stmt.isPlSql && variable.maxSize > 32767) {
|
|
1289
|
+
if (this.pipelineMode)
|
|
1290
|
+
errors.throwErr(errors.ERR_PIPELINE_LARGE_BUFFERS_NOT_SUPPORTED);
|
|
981
1291
|
if (variable.type === types.DB_TYPE_RAW ||
|
|
982
1292
|
variable.type === types.DB_TYPE_LONG_RAW) {
|
|
983
1293
|
variable.type = types.DB_TYPE_BLOB;
|
|
@@ -1097,6 +1407,15 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
1097
1407
|
}
|
|
1098
1408
|
}
|
|
1099
1409
|
|
|
1410
|
+
async _handleDefines(statement, message) {
|
|
1411
|
+
if (statement.requiresDefine && statement.sql) {
|
|
1412
|
+
statement.requiresFullExecute = true;
|
|
1413
|
+
await this._protocol._processMessage(message);
|
|
1414
|
+
statement.requiresDefine = false;
|
|
1415
|
+
statement.requiresFullExecute = false;
|
|
1416
|
+
}
|
|
1417
|
+
}
|
|
1418
|
+
|
|
1100
1419
|
//---------------------------------------------------------------------------
|
|
1101
1420
|
// execute()
|
|
1102
1421
|
//
|
|
@@ -1120,6 +1439,15 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
1120
1439
|
}
|
|
1121
1440
|
}
|
|
1122
1441
|
|
|
1442
|
+
async _prepareForExecute(sql, numIters, binds, options, executeManyFlag) {
|
|
1443
|
+
const statement = this._prepare(sql, options);
|
|
1444
|
+
const internalTempLobs = [];
|
|
1445
|
+
const message = await this._getExecuteMessage(statement, numIters, binds,
|
|
1446
|
+
options, executeManyFlag, internalTempLobs);
|
|
1447
|
+
return {statement, numIters, options, executeManyFlag, internalTempLobs,
|
|
1448
|
+
message};
|
|
1449
|
+
}
|
|
1450
|
+
|
|
1123
1451
|
//---------------------------------------------------------------------------
|
|
1124
1452
|
// Get the statement object from the statement cache for the SQL if it exists
|
|
1125
1453
|
// else prepare a new statement object for the SQL. If a statement is already
|
|
@@ -1129,9 +1457,9 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
1129
1457
|
// cache) since it is unknown at this point whether the original session or a
|
|
1130
1458
|
// new session is going to be used.
|
|
1131
1459
|
//---------------------------------------------------------------------------
|
|
1132
|
-
_getStatement(sql, cacheStatement = false) {
|
|
1460
|
+
_getStatement(sql, cacheStatement = false, forceNew = false) {
|
|
1133
1461
|
return this.statementCache.getStatement(sql, cacheStatement,
|
|
1134
|
-
this._drcpEstablishSession);
|
|
1462
|
+
forceNew || this._drcpEstablishSession);
|
|
1135
1463
|
}
|
|
1136
1464
|
|
|
1137
1465
|
//---------------------------------------------------------------------------
|
|
@@ -1455,6 +1783,20 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
1455
1783
|
return this.dbName;
|
|
1456
1784
|
}
|
|
1457
1785
|
|
|
1786
|
+
//---------------------------------------------------------------------------
|
|
1787
|
+
// Returns the name of a container associated with the connection.
|
|
1788
|
+
//---------------------------------------------------------------------------
|
|
1789
|
+
getPdbName() {
|
|
1790
|
+
return this.pdbName;
|
|
1791
|
+
}
|
|
1792
|
+
|
|
1793
|
+
//---------------------------------------------------------------------------
|
|
1794
|
+
// Returns the Oracle Database unique name associated with the connection.
|
|
1795
|
+
//---------------------------------------------------------------------------
|
|
1796
|
+
getDbUniqueName() {
|
|
1797
|
+
return this.dbUniqueName;
|
|
1798
|
+
}
|
|
1799
|
+
|
|
1458
1800
|
//---------------------------------------------------------------------------
|
|
1459
1801
|
// Returns maximum number of cursors that can be opened in one session.
|
|
1460
1802
|
//---------------------------------------------------------------------------
|
|
@@ -1499,6 +1841,72 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
1499
1841
|
getQueue(name, payloadTypeClass, payloadType) {
|
|
1500
1842
|
return new ThinQueueImpl(this, name, payloadTypeClass, payloadType);
|
|
1501
1843
|
}
|
|
1502
|
-
}
|
|
1503
1844
|
|
|
1845
|
+
// Queue key/value pairs to be sent to the server.
|
|
1846
|
+
// If the namespace already has pending entries, merge and replace by key.
|
|
1847
|
+
appContext(namespaceName, keyValues) {
|
|
1848
|
+
const existingNamespace = this._nameSpaceMap.get(namespaceName);
|
|
1849
|
+
|
|
1850
|
+
// If namespace doesn't exist or was cleared, just initialize it
|
|
1851
|
+
if (!existingNamespace || existingNamespace.pendingClear) {
|
|
1852
|
+
const ns = existingNamespace || ThinConnectionImpl._createNamespace(namespaceName);
|
|
1853
|
+
ns.pendingClear = false;
|
|
1854
|
+
ns.keyValues = keyValues;
|
|
1855
|
+
this._nameSpaceMap.set(namespaceName, ns);
|
|
1856
|
+
return;
|
|
1857
|
+
}
|
|
1858
|
+
|
|
1859
|
+
ThinConnectionImpl._mergeKeyValues(existingNamespace, keyValues);
|
|
1860
|
+
}
|
|
1861
|
+
|
|
1862
|
+
// This will clear all context on the server.
|
|
1863
|
+
// If the nameSpaceName exists , it updates else creates a new entry with clear flag set.
|
|
1864
|
+
clearAppContext(namespaceName) {
|
|
1865
|
+
const ns = ThinConnectionImpl._createNamespace(namespaceName);
|
|
1866
|
+
ns.pendingClear = true;
|
|
1867
|
+
this._nameSpaceMap.set(namespaceName, ns);
|
|
1868
|
+
}
|
|
1869
|
+
|
|
1870
|
+
//---------------------------------------------------------------------------
|
|
1871
|
+
// directPathLoad()
|
|
1872
|
+
// Implements direct path loading into a table.
|
|
1873
|
+
//---------------------------------------------------------------------------
|
|
1874
|
+
async directPathLoad(schemaName, tableName, columnNames, data) {
|
|
1875
|
+
const prepareMessage = new messages.DirectPathPrepareMessage(this);
|
|
1876
|
+
prepareMessage.schemaName = schemaName;
|
|
1877
|
+
prepareMessage.tableName = tableName;
|
|
1878
|
+
prepareMessage.columnNames = columnNames;
|
|
1879
|
+
await this._protocol._processMessage(prepareMessage);
|
|
1880
|
+
|
|
1881
|
+
const opMessage = new messages.DirectPathOpMessage(this);
|
|
1882
|
+
opMessage.prepare(prepareMessage.cursorId, constants.TNS_DP_OP_ABORT);
|
|
1883
|
+
|
|
1884
|
+
try {
|
|
1885
|
+
const loadMessage = new messages.DirectPathLoadStreamMessage(this);
|
|
1886
|
+
loadMessage.prepare(prepareMessage.cursorId, data, prepareMessage.columnMetadata);
|
|
1887
|
+
await this._protocol._processMessage(loadMessage);
|
|
1888
|
+
opMessage.opCode = constants.TNS_DP_OP_FINISH;
|
|
1889
|
+
} finally {
|
|
1890
|
+
await this._protocol._processMessage(opMessage);
|
|
1891
|
+
}
|
|
1892
|
+
}
|
|
1893
|
+
|
|
1894
|
+
//---------------------------------------------------------------------------
|
|
1895
|
+
// setEndUserSecurityContext()
|
|
1896
|
+
//
|
|
1897
|
+
// Set the End Security Context.
|
|
1898
|
+
//---------------------------------------------------------------------------
|
|
1899
|
+
setEndUserSecurityContext(context) {
|
|
1900
|
+
if (!this._protocol.caps.supportsEndUserSecurityContext) {
|
|
1901
|
+
errors.throwErr(errors.ERR_UNSUPPORTED_DEEP_DATA_SECURITY_FEATURE);
|
|
1902
|
+
}
|
|
1903
|
+
|
|
1904
|
+
this.securityContext = context;
|
|
1905
|
+
}
|
|
1906
|
+
|
|
1907
|
+
clearEndUserSecurityContext() {
|
|
1908
|
+
this.securityContext = null;
|
|
1909
|
+
}
|
|
1910
|
+
|
|
1911
|
+
}
|
|
1504
1912
|
module.exports = ThinConnectionImpl;
|