oracledb 6.4.0 → 6.5.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 (60) hide show
  1. package/README.md +2 -2
  2. package/build/Release/oracledb-6.5.1-darwin-x64.node +0 -0
  3. package/build/Release/oracledb-6.5.1-darwin-x64.node-buildinfo.txt +1 -0
  4. package/build/Release/oracledb-6.5.1-js-buildinfo.txt +1 -0
  5. package/build/Release/oracledb-6.5.1-linux-arm64.node +0 -0
  6. package/build/Release/oracledb-6.5.1-linux-arm64.node-buildinfo.txt +1 -0
  7. package/build/Release/oracledb-6.5.1-linux-x64.node +0 -0
  8. package/build/Release/oracledb-6.5.1-linux-x64.node-buildinfo.txt +1 -0
  9. package/build/Release/oracledb-6.5.1-win32-x64.node +0 -0
  10. package/build/Release/oracledb-6.5.1-win32-x64.node-buildinfo.txt +1 -0
  11. package/examples/README.md +2 -0
  12. package/lib/aqQueue.js +1 -1
  13. package/lib/connection.js +11 -14
  14. package/lib/errors.js +36 -2
  15. package/lib/impl/connection.js +2 -1
  16. package/lib/impl/datahandlers/buffer.js +2 -2
  17. package/lib/impl/datahandlers/constants.js +6 -5
  18. package/lib/impl/datahandlers/oson.js +301 -150
  19. package/lib/impl/datahandlers/vector.js +3 -22
  20. package/lib/oracledb.js +8 -25
  21. package/lib/pool.js +14 -1
  22. package/lib/settings.js +1 -0
  23. package/lib/thin/connection.js +23 -52
  24. package/lib/thin/pool.js +62 -6
  25. package/lib/thin/protocol/capabilities.js +17 -5
  26. package/lib/thin/protocol/constants.js +15 -2
  27. package/lib/thin/protocol/messages/auth.js +1 -1
  28. package/lib/thin/protocol/messages/base.js +8 -10
  29. package/lib/thin/protocol/messages/dataType.js +1 -0
  30. package/lib/thin/protocol/messages/execute.js +5 -1
  31. package/lib/thin/protocol/messages/{connectionCookie.js → fastAuth.js} +18 -16
  32. package/lib/thin/protocol/messages/fetch.js +4 -0
  33. package/lib/thin/protocol/messages/index.js +2 -2
  34. package/lib/thin/protocol/messages/protocol.js +9 -1
  35. package/lib/thin/protocol/messages/withData.js +13 -7
  36. package/lib/thin/protocol/packet.js +35 -4
  37. package/lib/thin/protocol/protocol.js +14 -5
  38. package/lib/thin/protocol/utils.js +11 -18
  39. package/lib/thin/sqlnet/constants.js +5 -2
  40. package/lib/thin/sqlnet/ezConnectResolver.js +9 -5
  41. package/lib/thin/sqlnet/navNodes.js +4 -3
  42. package/lib/thin/sqlnet/networkSession.js +14 -3
  43. package/lib/thin/sqlnet/packet.js +5 -6
  44. package/lib/thin/statement.js +40 -0
  45. package/lib/thin/statementCache.js +39 -11
  46. package/lib/thin/util.js +2 -2
  47. package/lib/transformer.js +9 -3
  48. package/lib/types.js +9 -1
  49. package/lib/util.js +29 -1
  50. package/lib/version.js +2 -2
  51. package/package.json +1 -1
  52. package/build/Release/oracledb-6.4.0-darwin-x64.node +0 -0
  53. package/build/Release/oracledb-6.4.0-darwin-x64.node-buildinfo.txt +0 -1
  54. package/build/Release/oracledb-6.4.0-js-buildinfo.txt +0 -1
  55. package/build/Release/oracledb-6.4.0-linux-arm64.node +0 -0
  56. package/build/Release/oracledb-6.4.0-linux-arm64.node-buildinfo.txt +0 -1
  57. package/build/Release/oracledb-6.4.0-linux-x64.node +0 -0
  58. package/build/Release/oracledb-6.4.0-linux-x64.node-buildinfo.txt +0 -1
  59. package/build/Release/oracledb-6.4.0-win32-x64.node +0 -0
  60. package/build/Release/oracledb-6.4.0-win32-x64.node-buildinfo.txt +0 -1
@@ -54,14 +54,7 @@ class VectorDecoder extends BaseBuffer {
54
54
  errors.throwErr(errors.ERR_VECTOR_VERSION_NOT_SUPPORTED, version);
55
55
  const flags = this.readUInt16BE();
56
56
  const vectorFormat = this.readUInt8();
57
- let numElements;
58
- if (flags & constants.TNS_VECTOR_FLAG_DIM_UINT8) {
59
- numElements = this.readUInt8();
60
- } else if (flags & constants.TNS_VECTOR_FLAG_DIM_UINT32) {
61
- numElements = this.readUInt32BE();
62
- } else {
63
- numElements = this.readUInt16BE();
64
- }
57
+ const numElements = this.readUInt32BE();
65
58
  let elementSize, result;
66
59
  if (vectorFormat === constants.VECTOR_FORMAT_FLOAT32) {
67
60
  elementSize = 4;
@@ -117,27 +110,15 @@ class VectorEncoder extends GrowableBuffer {
117
110
  }
118
111
 
119
112
  // Let server generate the norm (TNS_VECTOR_FLAG_NORMSRC)
120
- let flags = constants.TNS_VECTOR_FLAG_NORM
113
+ const flags = constants.TNS_VECTOR_FLAG_NORM
121
114
  | constants.TNS_VECTOR_FLAG_NORMSRC;
122
- const numElements = value.length;
123
- if (numElements < 256) {
124
- flags |= constants.TNS_VECTOR_FLAG_DIM_UINT8;
125
- } else if (numElements > 65535) {
126
- flags |= constants.TNS_VECTOR_FLAG_DIM_UINT32;
127
- }
128
115
 
129
116
  // write header
130
117
  this.writeUInt8(constants.TNS_VECTOR_MAGIC_BYTE);
131
118
  this.writeUInt8(constants.TNS_VECTOR_VERSION);
132
119
  this.writeUInt16BE(flags);
133
120
  this.writeUInt8(vectorFormat);
134
- if (numElements < 256) {
135
- this.writeUInt8(numElements);
136
- } else if (numElements < 65536) {
137
- this.writeUInt16BE(numElements);
138
- } else {
139
- this.writeUInt32BE(numElements);
140
- }
121
+ this.writeUInt32BE(value.length);
141
122
  this.reserveBytes(8);
142
123
 
143
124
  // write data
package/lib/oracledb.js CHANGED
@@ -118,24 +118,6 @@ function _initializeThinDriver() {
118
118
  require('./thin');
119
119
  }
120
120
 
121
- //---------------------------------------------------------------------------
122
- // _isPrivilege()
123
- //
124
- // Returns a boolean indicating if the supplied value is a valid privilege.
125
- //---------------------------------------------------------------------------
126
- function _isPrivilege(value) {
127
- return (
128
- value === constants.SYSASM ||
129
- value === constants.SYSBACKUP ||
130
- value === constants.SYSDBA ||
131
- value === constants.SYSDG ||
132
- value === constants.SYSKM ||
133
- value === constants.SYSOPER ||
134
- value === constants.SYSPRELIM ||
135
- value === constants.SYSRAC
136
- );
137
- }
138
-
139
121
  //-----------------------------------------------------------------------------
140
122
  // _verifyOptions()
141
123
  //
@@ -322,6 +304,13 @@ async function _verifyOptions(options, inCreatePool) {
322
304
  outOptions.connectionIdPrefix = options.connectionIdPrefix;
323
305
  }
324
306
 
307
+ // privilege must be one of a set of named constants
308
+ if (options.privilege !== undefined) {
309
+ errors.assertParamPropValue(nodbUtil.isPrivilege(options.privilege), 1,
310
+ "privilege");
311
+ outOptions.privilege = options.privilege;
312
+ }
313
+
325
314
  // check pool specific options
326
315
  if (inCreatePool) {
327
316
 
@@ -435,13 +424,6 @@ async function _verifyOptions(options, inCreatePool) {
435
424
  outOptions.newPassword = options.newPassword;
436
425
  }
437
426
 
438
- // privilege must be one of a set of named constants
439
- if (options.privilege !== undefined) {
440
- errors.assertParamPropValue(_isPrivilege(options.privilege), 1,
441
- "privilege");
442
- outOptions.privilege = options.privilege;
443
- }
444
-
445
427
  // shardingKey must be an array of values
446
428
  if (options.shardingKey !== undefined) {
447
429
  const value = options.shardingKey;
@@ -832,6 +814,7 @@ module.exports = {
832
814
  AqQueue,
833
815
  BaseDbObject,
834
816
  Connection,
817
+ JsonId: types.JsonId,
835
818
  Lob,
836
819
  Pool,
837
820
  PoolStatistics,
package/lib/pool.js CHANGED
@@ -238,6 +238,13 @@ class Pool extends EventEmitter {
238
238
  outOptions.superShardingKey = options.superShardingKey;
239
239
  }
240
240
 
241
+ // privilege must be one of a set of named constants
242
+ if (options.privilege !== undefined) {
243
+ errors.assertParamPropValue(nodbUtil.isPrivilege(options.privilege), 1,
244
+ "privilege");
245
+ outOptions.privilege = options.privilege;
246
+ }
247
+
241
248
  return outOptions;
242
249
  }
243
250
 
@@ -681,7 +688,7 @@ class Pool extends EventEmitter {
681
688
  errors.assertParamPropBool(options, 1, "enableStatistics");
682
689
  errors.assertParamPropBool(options, 1, "resetStatistics");
683
690
  errors.assertParamPropUnsignedInt(options, 1, "poolMin");
684
- errors.assertParamPropUnsignedInt(options, 1, "poolMax");
691
+ errors.assertParamPropUnsignedIntNonZero(options, 1, "poolMax");
685
692
  errors.assertParamPropUnsignedInt(options, 1, "poolMaxPerShard");
686
693
  errors.assertParamPropUnsignedInt(options, 1, "poolIncrement");
687
694
  errors.assertParamPropInt(options, 1, "poolPingInterval");
@@ -689,6 +696,12 @@ class Pool extends EventEmitter {
689
696
  errors.assertParamPropUnsignedInt(options, 1, "stmtCacheSize");
690
697
  errors.assertParamPropBool(options, 1, "sodaMetaDataCache");
691
698
 
699
+ // poolMax must be greater than or equal to poolMin
700
+ if (options.poolMin > options.poolMax) {
701
+ errors.throwErr(errors.ERR_INVALID_NUMBER_OF_CONNECTIONS, options.poolMax,
702
+ options.poolMin);
703
+ }
704
+
692
705
  // reconfiguration can happen only when status is OPEN
693
706
  this._checkPoolOpen(false);
694
707
 
package/lib/settings.js CHANGED
@@ -63,6 +63,7 @@ class Settings {
63
63
  this.thinDriverInitialized = false;
64
64
  this.createFetchTypeMap(this.fetchAsString, this.fetchAsBuffer);
65
65
  this.fetchTypeHandler = undefined;
66
+ this._JsonId = types.JsonId;
66
67
  }
67
68
 
68
69
  //---------------------------------------------------------------------------
@@ -50,8 +50,6 @@ const finalizationRegistry = new global.FinalizationRegistry((heldValue) => {
50
50
  class TDSBuffer extends BaseBuffer {
51
51
  }
52
52
 
53
- const connectionCookies = new Map();
54
-
55
53
  class ThinConnectionImpl extends ConnectionImpl {
56
54
 
57
55
  /**
@@ -183,12 +181,20 @@ class ThinConnectionImpl extends ConnectionImpl {
183
181
  message.numExecs = numIters;
184
182
  message.arrayDmlRowCounts = options.dmlRowCounts;
185
183
  message.batchErrors = options.batchErrors;
186
- if (statement.isPlSql && statement.requiresFullExecute) {
184
+
185
+ // if a PL/SQL statement requires a full execute, perform only a single
186
+ // iteration in order to allow the determination of input/output binds
187
+ // to be completed; after that, an execution of the remaining iterations
188
+ // can be performed.
189
+ if (statement.isPlSql && (statement.cursorId === 0 ||
190
+ statement.requiresFullExecute)) {
187
191
  message.numExecs = 1;
192
+ message.noImplicitRelease = true;
188
193
  await this._protocol._processMessage(message);
189
194
  statement.requiresFullExecute = false;
190
195
  message.numExecs = numIters - 1;
191
196
  message.offset = 1;
197
+ message.noImplicitRelease = false;
192
198
  }
193
199
  if (message.numExecs > 0) {
194
200
  await this._protocol._processMessage(message);
@@ -588,26 +594,6 @@ class ThinConnectionImpl extends ConnectionImpl {
588
594
  return (this._pool) ? true : false;
589
595
  }
590
596
 
591
- //---------------------------------------------------------------------------
592
- // getConnectionCookieByUUID()
593
- //
594
- // It fetches from map which keeps keyname as UUID+ServiceName.
595
- // UUID identifies the CDB instance and ServiceName identifies the
596
- // entity within a PDB which uniquely identifies a pdb instance.
597
- //---------------------------------------------------------------------------
598
- getConnectionCookieByUUID(uuid) {
599
- let cookie;
600
- if (uuid) {
601
- const key = uuid + ((this.serviceName) ? this.serviceName : this.sid);
602
- cookie = connectionCookies.get(key);
603
- if (!cookie) {
604
- cookie = {};
605
- connectionCookies.set(key, cookie);
606
- }
607
- }
608
- return cookie;
609
- }
610
-
611
597
  /**
612
598
  *
613
599
  * @param {object} params Configuration of the connection
@@ -692,37 +678,24 @@ class ThinConnectionImpl extends ConnectionImpl {
692
678
  }
693
679
 
694
680
  try {
695
- const cookie = this.getConnectionCookieByUUID(this.nscon.dbUUID);
696
- this.nscon.dbUUID = null;
697
681
  const protocolMessage = new messages.ProtocolMessage(this);
698
682
  const dataTypeMessage = new messages.DataTypeMessage(this);
699
683
  const authMessage = new messages.AuthMessage(this, params);
700
- let sentCookie = false;
701
- if (cookie && cookie.populated) {
702
- const cookieMessage = new messages.ConnectionCookieMessage(this);
703
- cookieMessage.cookie = cookie;
704
- cookieMessage.protocolMessage = protocolMessage;
705
- cookieMessage.dataTypeMessage = dataTypeMessage;
706
- cookieMessage.authMessage = authMessage;
707
- await this._protocol._processMessage(cookieMessage);
708
- sentCookie = true;
684
+ if (this.nscon.supportsFastAuth) {
685
+ const fastAuthMessage = new messages.FastAuthMessage(this);
686
+ fastAuthMessage.protocolMessage = protocolMessage;
687
+ fastAuthMessage.dataTypeMessage = dataTypeMessage;
688
+ fastAuthMessage.authMessage = authMessage;
689
+ await this._protocol._processMessage(fastAuthMessage);
690
+ if (fastAuthMessage.reNegotiate) {
691
+ // Fast Authentication failed.
692
+ await this._protocol._processMessage(dataTypeMessage);
693
+ await this._protocol._processMessage(authMessage);
694
+ }
709
695
  } else {
710
696
  await this._protocol._processMessage(protocolMessage);
711
- }
712
- if (!sentCookie || !cookie.populated) {
713
697
  await this._protocol._processMessage(dataTypeMessage);
714
- // Does OSESSKEY for non-token Authentication else OAUTH
715
698
  await this._protocol._processMessage(authMessage);
716
- if (cookie && !cookie.populated) {
717
- cookie.protocolVersion = protocolMessage.serverVersion;
718
- cookie.serverBanner = protocolMessage.serverBanner;
719
- cookie.charsetID = this._protocol.caps.charSetID;
720
- cookie.ncharsetID = this._protocol.caps.nCharsetId;
721
- cookie.flags = protocolMessage.serverFlags;
722
- cookie.compileCaps = Buffer.from(protocolMessage.serverCompileCaps);
723
- cookie.runtimeCaps = Buffer.from(protocolMessage.serverRunTimeCaps);
724
- cookie.populated = true;
725
- }
726
699
  }
727
700
  if (!params.token) { // non-token Authentication
728
701
  await this._protocol._processMessage(authMessage); // OAUTH
@@ -922,10 +895,8 @@ class ThinConnectionImpl extends ConnectionImpl {
922
895
  // new session is going to be used.
923
896
  //---------------------------------------------------------------------------
924
897
  _getStatement(sql, cacheStatement = false) {
925
- if (this._drcpEstablishSession) {
926
- cacheStatement = false;
927
- }
928
- return this.statementCache.getStatement(sql, cacheStatement);
898
+ return this.statementCache.getStatement(sql, cacheStatement,
899
+ this._drcpEstablishSession);
929
900
  }
930
901
 
931
902
  //---------------------------------------------------------------------------
@@ -1077,7 +1048,7 @@ class ThinConnectionImpl extends ConnectionImpl {
1077
1048
  // Returns boolean based on this._protocol.txnInProgress value.
1078
1049
  //---------------------------------------------------------------------------
1079
1050
  getTransactionInProgress() {
1080
- return this._protocol.txnInProgress === constants.TNS_TXN_IN_PROGRESS;
1051
+ return this._protocol.txnInProgress;
1081
1052
  }
1082
1053
 
1083
1054
  //---------------------------------------------------------------------------
package/lib/thin/pool.js CHANGED
@@ -105,6 +105,7 @@ class ThinPoolImpl extends PoolImpl {
105
105
  this._accessTokenFn = params.accessTokenFn;
106
106
  this._accessTokenConfig = params.accessTokenConfig;
107
107
  this._isDRCPEnabled = false;
108
+ this._implicitPool = null;
108
109
  this.eventEmitter = new EventEmitter();
109
110
  // listener to remove dead or idle connections
110
111
  this.eventEmitter.on('_removePoolConnection', async (connImpl) => {
@@ -385,11 +386,11 @@ class ThinPoolImpl extends PoolImpl {
385
386
  }
386
387
 
387
388
  //---------------------------------------------------------------------------
388
- // _getNumConns()
389
+ // _getNumConnsToCreate()
389
390
  //
390
391
  // get number of connections need to be created
391
392
  //---------------------------------------------------------------------------
392
- _getNumConns() {
393
+ _getNumConnsToCreate() {
393
394
  const usedConns = this._freeConnectionList.length + this._usedConnectionList.size;
394
395
  // less connections in the pool than poolMin? restore to poolMin
395
396
  if (usedConns < this._poolMin) {
@@ -415,11 +416,19 @@ class ThinPoolImpl extends PoolImpl {
415
416
 
416
417
  // continue until a close request is received
417
418
  while (!this._poolCloseWaiter) {
418
- // get count for connections to be created
419
- const numConns = this._getNumConns();
419
+ // eliminate connections that exceed the poolMax (this should only happen
420
+ // after a reconfiguration has taken place where the maximum number of
421
+ // connections is reduced)
422
+ let numToDestroy = this._poolMax - this.getConnectionsOpen();
423
+ while (numToDestroy > 0 && this._freeConnectionList.length > 0) {
424
+ const connToBeRemoved = this._freeConnectionList.shift();
425
+ this.eventEmitter.emit('_removePoolConnection', connToBeRemoved);
426
+ numToDestroy--;
427
+ }
420
428
 
429
+ const numToCreate = this._getNumConnsToCreate();
421
430
  // connection creation is going on serially and not concurrently
422
- for (let i = 0; i < numConns; i++) {
431
+ for (let i = 0; i < numToCreate; i++) {
423
432
  try {
424
433
  // get deobfuscated value
425
434
  const config = await this._getConnAttrs();
@@ -564,8 +573,14 @@ class ThinPoolImpl extends PoolImpl {
564
573
  if (conn.nscon.connected) {
565
574
  conn._lastTimeUsed = Date.now();
566
575
  conn._newSession = false;
567
- this._freeConnectionList.push(conn);
576
+ if ((this._freeConnectionList.length + this._usedConnectionList.size)
577
+ < this._poolMax) {
578
+ this._freeConnectionList.push(conn);
579
+ } else {
580
+ this.eventEmitter.emit('_removePoolConnection', conn);
581
+ }
568
582
  }
583
+
569
584
  this._setScheduler();
570
585
  }
571
586
 
@@ -578,6 +593,47 @@ class ThinPoolImpl extends PoolImpl {
578
593
  this._userConfig.connectionClass = crypto.randomBytes(16).toString('base64');
579
594
  this._userConfig.connectionClass = "NJS:" + this._userConfig.connectionClass;
580
595
  }
596
+
597
+ //---------------------------------------------------------------------------
598
+ // reconfigure()
599
+ //
600
+ // Reconfigures the pool with new parameters
601
+ //---------------------------------------------------------------------------
602
+ reconfigure(params) {
603
+ if (params.poolIncrement !== undefined) {
604
+ this._poolIncrement = params.poolIncrement;
605
+ }
606
+
607
+ if (params.poolTimeout !== undefined &&
608
+ this._poolTimeout !== params.poolTimeout) {
609
+ this._poolTimeout = params.poolTimeout;
610
+ // clear scheduled job
611
+ if (this._schedulerJob) {
612
+ clearTimeout(this._schedulerJob);
613
+ this._schedulerJob = null;
614
+ }
615
+ }
616
+
617
+ if (params.poolPingInterval !== undefined) {
618
+ this._poolPingInterval = params.poolPingInterval;
619
+ }
620
+
621
+ if (params.stmtCacheSize !== undefined) {
622
+ this._stmtCacheSize = params.stmtCacheSize;
623
+ }
624
+
625
+ if (params.poolMax !== undefined) {
626
+ this._poolMax = params.poolMax;
627
+ }
628
+
629
+ if (params.poolMin !== undefined) {
630
+ this._poolMin = params.poolMin;
631
+ }
632
+
633
+ if (this.bgWaiter) {
634
+ this.bgWaiter();
635
+ }
636
+ }
581
637
  }
582
638
 
583
639
  module.exports = ThinPoolImpl;
@@ -36,25 +36,32 @@ const errors = require('../../errors');
36
36
  */
37
37
  class Capabilities {
38
38
 
39
- constructor(protocolVersion) {
40
- this.protocolVersion = protocolVersion;
39
+ constructor(nscon) {
40
+ this.protocolVersion = nscon.sAtts.version;
41
41
  this.ttcFieldVersion = constants.TNS_CCAP_FIELD_VERSION_MAX;
42
42
  this.supports12cLogon = true;
43
43
  this.supportsOob = false;
44
44
  this.nCharsetId = constants.TNS_CHARSET_UTF16;
45
45
  this.compileCaps = Buffer.alloc(constants.TNS_CCAP_MAX);
46
46
  this.runtimeCaps = Buffer.alloc(constants.TNS_RCAP_MAX);
47
- this.initCompileCaps();
47
+ this.initCompileCaps(nscon);
48
48
  this.initRuntimeCaps();
49
49
  this.maxStringSize = 0;
50
50
  }
51
51
 
52
- adjustForServerCompileCaps(serverCaps) {
52
+ adjustForServerCompileCaps(serverCaps, nscon) {
53
53
  if (serverCaps[constants.TNS_CCAP_FIELD_VERSION] < this.ttcFieldVersion) {
54
54
  this.ttcFieldVersion = serverCaps[constants.TNS_CCAP_FIELD_VERSION];
55
55
  this.compileCaps[constants.TNS_CCAP_FIELD_VERSION] =
56
56
  this.ttcFieldVersion;
57
57
  }
58
+ if ((this.ttcFieldVersion < constants.TNS_CCAP_FIELD_VERSION_23_4
59
+ && nscon.endOfRequestSupport)) {
60
+ // endOfRequestSupport used only from 23.4 onwards and not for 23.3
61
+ this.compileCaps[constants.TNS_CCAP_TTC4]
62
+ ^= constants.TNS_CCAP_END_OF_REQUEST;
63
+ nscon.endOfRequestSupport = false;
64
+ }
58
65
  }
59
66
 
60
67
  adjustForServerRuntimeCaps(serverCaps) {
@@ -65,7 +72,7 @@ class Capabilities {
65
72
  }
66
73
  }
67
74
 
68
- initCompileCaps() {
75
+ initCompileCaps(nscon) {
69
76
  this.compileCaps[constants.TNS_CCAP_SQL_VERSION] =
70
77
  constants.TNS_CCAP_SQL_VERSION_MAX;
71
78
  this.compileCaps[constants.TNS_CCAP_LOGON_TYPES] =
@@ -104,6 +111,11 @@ class Capabilities {
104
111
  constants.TNS_CCAP_CLIENT_FN_MAX;
105
112
  this.compileCaps[constants.TNS_CCAP_TTC4] =
106
113
  constants.TNS_CCAP_INBAND_NOTIFICATION;
114
+ if (nscon.endOfRequestSupport) {
115
+ this.compileCaps[constants.TNS_CCAP_TTC4] |= constants.TNS_CCAP_END_OF_REQUEST;
116
+ }
117
+ this.compileCaps[constants.TNS_CCAP_CTB_FEATURE_BACKPORT] =
118
+ constants.TNS_CCAP_CTB_IMPLICIT_POOL;
107
119
  this.compileCaps[constants.TNS_CCAP_TTC5] =
108
120
  constants.TNS_CCAP_VECTOR_SUPPORT;
109
121
  }
@@ -433,7 +433,8 @@ module.exports = {
433
433
  TNS_MSG_TYPE_ONEWAY_FN: 26,
434
434
  TNS_MSG_TYPE_IMPLICIT_RESULTSET: 27,
435
435
  TNS_MSG_TYPE_RENEGOTIATE: 28,
436
- TNS_MSG_TYPE_COOKIE: 30,
436
+ TNS_MSG_TYPE_END_OF_REQUEST: 29,
437
+ TNS_MSG_TYPE_FAST_AUTH: 34,
437
438
 
438
439
  // parameter keyword numbers,
439
440
  TNS_KEYWORD_NUM_CURRENT_SCHEMA: 168,
@@ -464,6 +465,7 @@ module.exports = {
464
465
  TNS_EXEC_OPTION_DESCRIBE: 0x20000,
465
466
  TNS_EXEC_OPTION_NO_COMPRESSED_FETCH: 0x40000,
466
467
  TNS_EXEC_OPTION_BATCH_ERRORS: 0x80000,
468
+ TNS_EXEC_OPTION_NO_IMPL_REL: 0x200000,
467
469
 
468
470
  // server side piggyback op codes
469
471
  TNS_SERVER_PIGGYBACK_QUERY_CACHE_INVALIDATION: 1,
@@ -558,6 +560,7 @@ module.exports = {
558
560
  // compile time capability indices
559
561
  TNS_CCAP_SQL_VERSION: 0,
560
562
  TNS_CCAP_LOGON_TYPES: 4,
563
+ TNS_CCAP_CTB_FEATURE_BACKPORT: 5,
561
564
  TNS_CCAP_FIELD_VERSION: 7,
562
565
  TNS_CCAP_SERVER_DEFINE_CONV: 8,
563
566
  TNS_CCAP_TTC1: 15,
@@ -625,9 +628,11 @@ module.exports = {
625
628
  TNS_CCAP_DRCP: 0x10,
626
629
  TNS_CCAP_ZLNP: 0x04,
627
630
  TNS_CCAP_INBAND_NOTIFICATION: 0x04,
631
+ TNS_CCAP_END_OF_REQUEST: 0x20,
628
632
  TNS_CCAP_CLIENT_FN_MAX: 12,
629
633
  TNS_CCAP_LOB2_QUASI: 0x01,
630
634
  TNS_CCAP_LOB2_2GB_PREFETCH: 0x04,
635
+ TNS_CCAP_CTB_IMPLICIT_POOL: 0x08,
631
636
  TNS_CCAP_VECTOR_SUPPORT: 0x08,
632
637
 
633
638
  // runtime capability indices
@@ -651,6 +656,10 @@ module.exports = {
651
656
  TNS_UDS_FLAGS_IS_JSON: 0x00000100,
652
657
  TNS_UDS_FLAGS_IS_OSON: 0x00000800,
653
658
 
659
+ // end of call status flags
660
+ TNS_EOCS_FLAGS_TXN_IN_PROGRESS: 0x00000002,
661
+ TNS_EOCS_FLAGS_SESS_RELEASE: 0x00008000,
662
+
654
663
  // other constants
655
664
  TNS_ESCAPE_CHAR: 253,
656
665
  TNS_LONG_LENGTH_INDICATOR: dataHandlerConstants.TNS_LONG_LENGTH_INDICATOR,
@@ -660,9 +669,9 @@ module.exports = {
660
669
  TNS_MAX_LONG_LENGTH: 0x7fffffff,
661
670
  TNS_SDU: 8192,
662
671
  TNS_TDU: 65535,
663
- TNS_TXN_IN_PROGRESS: 0x00000002,
664
672
  TNS_MAX_CONNECT_DATA: 230,
665
673
  TNS_MAX_UROWID_LENGTH: 3950,
674
+ TNS_SERVER_CONVERTS_CHARS: 0x01, // server does charset conversion
666
675
 
667
676
  // drcp release mode
668
677
  DRCP_DEAUTHENTICATE: 0x00000002,
@@ -715,6 +724,7 @@ module.exports = {
715
724
  TNS_XML_TYPE_FLAG_SKIP_NEXT_4: 0x100000,
716
725
 
717
726
  // errors
727
+ TNS_ERR_INCONSISTENT_DATA_TYPES: 932,
718
728
  TNS_ERR_VAR_NOT_IN_SELECT_LIST: 1007,
719
729
  TNS_ERR_INBAND_MESSAGE: 12573,
720
730
  TNS_ERR_INVALID_SERVICE_NAME: 12514,
@@ -735,6 +745,9 @@ module.exports = {
735
745
  NUMBER_AS_TEXT_CHARS: 172,
736
746
  CHUNKED_BYTES_CHUNK_SIZE: 65536,
737
747
 
748
+ // Network Header flags for Data packet
749
+ TNS_DATA_FLAGS_END_OF_REQUEST: 0x2000,
750
+
738
751
  TNS_BASE64_ALPHABET_ARRAY: Buffer.from('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'),
739
752
  TNS_EXTENT_OID: Buffer.from('00000000000000000000000000010001', 'hex')
740
753
  };
@@ -181,7 +181,7 @@ class AuthMessage extends Message {
181
181
  if (this.userByteLen > 0) {
182
182
  buf.writeBytesWithLength(Buffer.from(this.username));
183
183
  }
184
- buf.writeKeyValue("AUTH_TERMINAL", "unknown");
184
+ buf.writeKeyValue("AUTH_TERMINAL", cInfo.terminal);
185
185
  buf.writeKeyValue("AUTH_PROGRAM_NM", cInfo.program);
186
186
  buf.writeKeyValue("AUTH_MACHINE", cInfo.hostName);
187
187
  buf.writeKeyValue("AUTH_PID", cInfo.pid);
@@ -42,10 +42,9 @@ class Message {
42
42
  this.functionCode = 0;
43
43
  this.callStatus = 0;
44
44
  this.flushOutBinds = false;
45
+ this.endOfResponse = false;
45
46
  this.endToEndSeqNum = 0;
46
47
  this.errorOccurred = false;
47
- this.flushOutBinds = false;
48
- this.processedError = false;
49
48
  this.warning = undefined;
50
49
  }
51
50
 
@@ -161,7 +160,7 @@ class Message {
161
160
  */
162
161
  this.errorInfo.message = this.errorInfo.message.trim();
163
162
  }
164
- this.processedError = true;
163
+ this.endOfResponse = !this.connection.nscon.endOfRequestSupport;
165
164
  }
166
165
 
167
166
  processReturnParameter() { }
@@ -178,22 +177,18 @@ class Message {
178
177
  }
179
178
  }
180
179
 
181
- hasMoreData(buf) {
182
- return buf.numBytesLeft() > 0 && !this.flushOutBinds;
183
- }
184
-
185
180
  decode(buf) {
186
181
  this.process(buf);
187
182
  }
188
183
 
189
184
  process(buf) {
185
+ this.endOfResponse = false;
190
186
  this.flushOutBinds = false;
191
- this.processedError = false;
192
187
  do {
193
188
  this.savePoint(buf);
194
189
  const messageType = buf.readUInt8();
195
190
  this.processMessage(buf, messageType);
196
- } while (this.hasMoreData(buf));
191
+ } while (!this.endOfResponse);
197
192
  }
198
193
 
199
194
  savePoint(buf) {
@@ -208,10 +203,13 @@ class Message {
208
203
  } else if (messageType === constants.TNS_MSG_TYPE_STATUS) {
209
204
  this.callStatus = buf.readUB4();
210
205
  this.endToEndSeqNum = buf.readUB2();
206
+ this.endOfResponse = !this.connection.nscon.endOfRequestSupport;
211
207
  } else if (messageType === constants.TNS_MSG_TYPE_PARAMETER) {
212
208
  this.processReturnParameter(buf);
213
209
  } else if (messageType === constants.TNS_MSG_TYPE_SERVER_SIDE_PIGGYBACK) {
214
210
  this.processServerSidePiggyBack(buf);
211
+ } else if (messageType === constants.TNS_MSG_TYPE_END_OF_REQUEST) {
212
+ this.endOfResponse = true;
215
213
  } else {
216
214
  errors.throwErr(errors.ERR_UNEXPECTED_MESSAGE_TYPE, messageType, buf.pos, buf.packetNum);
217
215
  }
@@ -282,7 +280,7 @@ class Message {
282
280
  const flags = buf.readUB4(); // session flags
283
281
  if (flags & constants.TNS_SESSGET_SESSION_CHANGED) {
284
282
  if (this.connection._drcpEstablishSession) {
285
- this.connection.statementCache.clearOpenCursors();
283
+ this.connection.statementCache.clearCursors();
286
284
  }
287
285
  }
288
286
  this.connection._drcpEstablishSession = false;
@@ -48,6 +48,7 @@ class DataTypeMessage extends Message {
48
48
  if (convDataType !== 0)
49
49
  buf.skipBytes(4);
50
50
  }
51
+ this.endOfResponse = !this.connection.nscon.endOfRequestSupport;
51
52
  } else {
52
53
  super.processMessage(buf, messageType);
53
54
  }
@@ -68,13 +68,17 @@ class ExecuteMessage extends MessageWithData {
68
68
  const stmt = this.statement;
69
69
  const params = stmt.bindInfoList;
70
70
 
71
+ if (this.noImplicitRelease) {
72
+ dmlOptions |= constants.TNS_EXEC_OPTION_NO_IMPL_REL;
73
+ }
74
+
71
75
  if (!stmt.requiresDefine && !this.parseOnly && params) {
72
76
  numParams = params.length;
73
77
  }
74
78
  if (stmt.requiresDefine) {
75
79
  options |= constants.TNS_EXEC_OPTION_DEFINE;
76
80
  } else if (!this.parseOnly && stmt.sql) {
77
- dmlOptions = constants.TNS_EXEC_OPTION_IMPLICIT_RESULTSET;
81
+ dmlOptions |= constants.TNS_EXEC_OPTION_IMPLICIT_RESULTSET;
78
82
  options |= constants.TNS_EXEC_OPTION_EXECUTE;
79
83
  }
80
84
  if (stmt.cursorId === 0 || stmt.isDdl) {