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.
Files changed (90) hide show
  1. package/LICENSE.txt +1 -1
  2. package/NOTICE.txt +1 -1
  3. package/README.md +9 -9
  4. package/build/Release/oracledb-7.0.1-darwin-arm64.node +0 -0
  5. package/build/Release/oracledb-7.0.1-darwin-arm64.node-buildinfo.txt +1 -0
  6. package/build/Release/oracledb-7.0.1-js-buildinfo.txt +1 -0
  7. package/build/Release/oracledb-7.0.1-linux-arm64.node +0 -0
  8. package/build/Release/oracledb-7.0.1-linux-arm64.node-buildinfo.txt +1 -0
  9. package/build/Release/oracledb-7.0.1-linux-x64.node +0 -0
  10. package/build/Release/oracledb-7.0.1-linux-x64.node-buildinfo.txt +1 -0
  11. package/build/Release/oracledb-7.0.1-win32-x64.node +0 -0
  12. package/build/Release/oracledb-7.0.1-win32-x64.node-buildinfo.txt +1 -0
  13. package/lib/aqDeqOptions.js +4 -4
  14. package/lib/aqEnqOptions.js +2 -2
  15. package/lib/aqQueue.js +11 -6
  16. package/lib/connection.js +407 -40
  17. package/lib/endUserSecurityContext.js +169 -0
  18. package/lib/errors.js +108 -5
  19. package/lib/impl/connection.js +76 -2
  20. package/lib/impl/datahandlers/buffer.js +19 -5
  21. package/lib/impl/datahandlers/vector.js +25 -5
  22. package/lib/impl/lob.js +9 -0
  23. package/lib/impl/parserHelpers.js +447 -0
  24. package/lib/impl/resultset.js +1 -1
  25. package/lib/lob.js +27 -14
  26. package/lib/obfuscation.js +97 -0
  27. package/lib/oracledb.js +148 -43
  28. package/lib/parser.js +204 -0
  29. package/lib/pipeline.js +113 -0
  30. package/lib/pool.js +16 -1
  31. package/lib/resultset.js +42 -21
  32. package/lib/settings.js +1 -0
  33. package/lib/thin/connection.js +461 -53
  34. package/lib/thin/dbObject.js +10 -4
  35. package/lib/thin/lob.js +20 -1
  36. package/lib/thin/pool.js +43 -63
  37. package/lib/thin/protocol/capabilities.js +18 -3
  38. package/lib/thin/protocol/constants.js +82 -2
  39. package/lib/thin/protocol/encryptDecrypt.js +43 -8
  40. package/lib/thin/protocol/messages/aqArray.js +2 -2
  41. package/lib/thin/protocol/messages/aqBase.js +2 -2
  42. package/lib/thin/protocol/messages/auth.js +6 -1
  43. package/lib/thin/protocol/messages/base.js +246 -5
  44. package/lib/thin/protocol/messages/dataType.js +8 -3
  45. package/lib/thin/protocol/messages/directPathLoadStream.js +377 -0
  46. package/lib/thin/protocol/messages/directPathOp.js +65 -0
  47. package/lib/thin/protocol/messages/directPathPrepare.js +158 -0
  48. package/lib/thin/protocol/messages/endPipeline.js +56 -0
  49. package/lib/thin/protocol/messages/execute.js +9 -7
  50. package/lib/thin/protocol/messages/index.js +9 -1
  51. package/lib/thin/protocol/messages/protocol.js +2 -2
  52. package/lib/thin/protocol/messages/withData.js +10 -143
  53. package/lib/thin/protocol/packet.js +115 -24
  54. package/lib/thin/protocol/protocol.js +110 -25
  55. package/lib/thin/protocol/utils.js +1 -26
  56. package/lib/thin/resultSet.js +13 -19
  57. package/lib/thin/sqlnet/ezConnectResolver.js +4 -4
  58. package/lib/thin/sqlnet/navNodes.js +4 -2
  59. package/lib/thin/sqlnet/networkSession.js +78 -50
  60. package/lib/thin/sqlnet/ntTcp.js +24 -0
  61. package/lib/thin/sqlnet/nvStrToNvPair.js +50 -25
  62. package/lib/thin/sqlnet/packet.js +49 -8
  63. package/lib/thin/sqlnet/paramParser.js +10 -7
  64. package/lib/thin/sqlnet/sessionAtts.js +2 -2
  65. package/lib/thin/statementCache.js +2 -4
  66. package/lib/traceHandler.js +59 -2
  67. package/lib/transformer.js +8 -3
  68. package/lib/types.js +35 -21
  69. package/lib/util.js +6 -6
  70. package/lib/version.js +4 -4
  71. package/package/install.js +5 -5
  72. package/package/prunebinaries.js +1 -1
  73. package/package.json +1 -1
  74. package/plugins/configProviders/awsCommon.js +125 -0
  75. package/plugins/configProviders/awss3/index.js +138 -0
  76. package/plugins/configProviders/awssecretsmanager/index.js +147 -0
  77. package/plugins/configProviders/azure/index.js +4 -5
  78. package/plugins/token/extensionAzure/index.js +0 -1
  79. package/plugins/token/extensionOci/index.js +0 -1
  80. package/build/Release/oracledb-6.10.0-darwin-arm64.node +0 -0
  81. package/build/Release/oracledb-6.10.0-darwin-arm64.node-buildinfo.txt +0 -1
  82. package/build/Release/oracledb-6.10.0-darwin-x64.node +0 -0
  83. package/build/Release/oracledb-6.10.0-darwin-x64.node-buildinfo.txt +0 -1
  84. package/build/Release/oracledb-6.10.0-js-buildinfo.txt +0 -1
  85. package/build/Release/oracledb-6.10.0-linux-arm64.node +0 -0
  86. package/build/Release/oracledb-6.10.0-linux-arm64.node-buildinfo.txt +0 -1
  87. package/build/Release/oracledb-6.10.0-linux-x64.node +0 -0
  88. package/build/Release/oracledb-6.10.0-linux-x64.node-buildinfo.txt +0 -1
  89. package/build/Release/oracledb-6.10.0-win32-x64.node +0 -0
  90. package/build/Release/oracledb-6.10.0-win32-x64.node-buildinfo.txt +0 -1
@@ -1,4 +1,4 @@
1
- // Copyright (c) 2022, 2025, Oracle and/or its affiliates.
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 (err) {
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
- // _execute()
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
- if (statement.requiresDefine && statement.sql) {
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['AUTH_DBNAME'];
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
- let serverType;
862
- if (this.isPooled()) {
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
- this.purity = constants.PURITY_SELF;
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
- this.purity = constants.PURITY_NEW;
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
- this._protocol = new Protocol(this);
1200
+ this._protocol = new Protocol(this);
893
1201
 
894
- // check if the protocol version supported by the database is high
895
- // enough; if not, reject the connection immediately
896
- if (this._protocol.caps.protocolVersion < constants.TNS_VERSION_MIN_ACCEPTED) {
897
- errors.throwErr(errors.ERR_SERVER_VERSION_NOT_SUPPORTED);
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 statement = this._getStatement(sql, options.keepInStmtCache);
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;