oracledb 6.0.3 → 6.1.0

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 (61) hide show
  1. package/README.md +2 -2
  2. package/build/Release/oracledb-6.1.0-darwin-x64.node +0 -0
  3. package/build/Release/oracledb-6.1.0-darwin-x64.node-buildinfo.txt +1 -0
  4. package/build/Release/oracledb-6.1.0-js-buildinfo.txt +1 -0
  5. package/build/Release/oracledb-6.1.0-linux-arm64.node +0 -0
  6. package/build/Release/oracledb-6.1.0-linux-arm64.node-buildinfo.txt +1 -0
  7. package/build/Release/oracledb-6.1.0-linux-x64.node +0 -0
  8. package/build/Release/oracledb-6.1.0-linux-x64.node-buildinfo.txt +1 -0
  9. package/build/Release/oracledb-6.1.0-win32-x64.node +0 -0
  10. package/build/Release/oracledb-6.1.0-win32-x64.node-buildinfo.txt +1 -0
  11. package/examples/example.js +0 -1
  12. package/lib/aqQueue.js +40 -26
  13. package/lib/connection.js +15 -3
  14. package/lib/errors.js +10 -6
  15. package/lib/impl/connection.js +9 -0
  16. package/lib/impl/resultset.js +7 -4
  17. package/lib/oracledb.js +15 -12
  18. package/lib/pool.js +7 -1
  19. package/lib/sodaCollection.js +1 -1
  20. package/lib/thin/connection.js +92 -30
  21. package/lib/thin/pool.js +153 -68
  22. package/lib/thin/protocol/buffer.js +19 -1
  23. package/lib/thin/protocol/constants.js +3 -14
  24. package/lib/thin/protocol/encryptDecrypt.js +17 -17
  25. package/lib/thin/protocol/messages/auth.js +21 -23
  26. package/lib/thin/protocol/messages/base.js +22 -45
  27. package/lib/thin/protocol/messages/connectionCookie.js +76 -0
  28. package/lib/thin/protocol/messages/dataType.js +13 -9
  29. package/lib/thin/protocol/messages/execute.js +7 -7
  30. package/lib/thin/protocol/messages/index.js +2 -0
  31. package/lib/thin/protocol/messages/protocol.js +31 -20
  32. package/lib/thin/protocol/messages/withData.js +49 -43
  33. package/lib/thin/protocol/oson.js +4 -4
  34. package/lib/thin/protocol/packet.js +31 -10
  35. package/lib/thin/protocol/utils.js +2 -2
  36. package/lib/thin/resultSet.js +6 -6
  37. package/lib/thin/sqlnet/connStrategy.js +130 -5
  38. package/lib/thin/sqlnet/constants.js +2 -0
  39. package/lib/thin/sqlnet/ezConnectResolver.js +20 -19
  40. package/lib/thin/sqlnet/navNodes.js +32 -25
  41. package/lib/thin/sqlnet/networkSession.js +35 -30
  42. package/lib/thin/sqlnet/ntTcp.js +30 -14
  43. package/lib/thin/sqlnet/nvStrToNvPair.js +16 -16
  44. package/lib/thin/sqlnet/packet.js +9 -2
  45. package/lib/thin/sqlnet/paramParser.js +9 -9
  46. package/lib/thin/sqlnet/sessionAtts.js +4 -0
  47. package/lib/thin/statement.js +3 -3
  48. package/lib/thin/util.js +7 -8
  49. package/lib/transformer.js +3 -1
  50. package/lib/util.js +0 -13
  51. package/lib/version.js +2 -2
  52. package/package.json +1 -1
  53. package/build/Release/oracledb-6.0.3-darwin-x64.node +0 -0
  54. package/build/Release/oracledb-6.0.3-darwin-x64.node-buildinfo.txt +0 -1
  55. package/build/Release/oracledb-6.0.3-js-buildinfo.txt +0 -1
  56. package/build/Release/oracledb-6.0.3-linux-arm64.node +0 -0
  57. package/build/Release/oracledb-6.0.3-linux-arm64.node-buildinfo.txt +0 -1
  58. package/build/Release/oracledb-6.0.3-linux-x64.node +0 -0
  59. package/build/Release/oracledb-6.0.3-linux-x64.node-buildinfo.txt +0 -1
  60. package/build/Release/oracledb-6.0.3-win32-x64.node +0 -0
  61. package/build/Release/oracledb-6.0.3-win32-x64.node-buildinfo.txt +0 -1
package/README.md CHANGED
@@ -1,10 +1,10 @@
1
- # node-oracledb version 6.0.3
1
+ # node-oracledb version 6.1.0
2
2
 
3
3
  The node-oracledb add-on for Node.js powers high performance Oracle Database
4
4
  applications. Applications can be written in TypeScript, or directly in
5
5
  JavaScript.
6
6
 
7
- Use node-oracledb 6.0.3 to connect Node.js 14.6, or later, to Oracle
7
+ Use node-oracledb 6.1.0 to connect Node.js 14.6, or later, to Oracle
8
8
  Database. Older versions of node-oracledb may work with older versions of
9
9
  Node.js.
10
10
 
@@ -0,0 +1 @@
1
+ oracledb-6.1.0-darwin-x64.node v18.17.1 98df02823e1fc31b0e57044cd1fb2358dfc620ed 20785f251426f274f4216369b9259908a103384d Mon, 21 Aug 2023 05:58:15 GMT
@@ -0,0 +1 @@
1
+ 98df02823e1fc31b0e57044cd1fb2358dfc620ed
@@ -0,0 +1 @@
1
+ oracledb-6.1.0-linux-arm64.node v18.15.0 98df02823e1fc31b0e57044cd1fb2358dfc620ed 20785f251426f274f4216369b9259908a103384d Mon, 21 Aug 2023 07:05:34 GMT
@@ -0,0 +1 @@
1
+ oracledb-6.1.0-linux-x64.node v16.20.0 98df02823e1fc31b0e57044cd1fb2358dfc620ed 20785f251426f274f4216369b9259908a103384d Mon, 21 Aug 2023 05:55:55 GMT
@@ -0,0 +1 @@
1
+ oracledb-6.1.0-win32-x64.node v16.19.0 98df02823e1fc31b0e57044cd1fb2358dfc620ed 20785f251426f274f4216369b9259908a103384d Mon, 21 Aug 2023 09:35:54 GMT
@@ -127,7 +127,6 @@ async function run() {
127
127
  // For a complete list of options see the documentation.
128
128
  options = {
129
129
  outFormat: oracledb.OUT_FORMAT_OBJECT, // query result format
130
- // extendedMetaData: true, // get extra metadata
131
130
  // fetchArraySize: 100 // internal buffer allocation size for tuning
132
131
  };
133
132
 
package/lib/aqQueue.js CHANGED
@@ -27,13 +27,14 @@
27
27
  'use strict';
28
28
 
29
29
  const { Buffer } = require('buffer');
30
- const constants = require('./constants.js');
31
30
  const errors = require('./errors.js');
32
31
  const nodbUtil = require('./util.js');
33
32
  const AqDeqOptions = require('./aqDeqOptions.js');
34
33
  const AqEnqOptions = require('./aqEnqOptions.js');
35
34
  const AqMessage = require('./aqMessage.js');
36
35
  const BaseDbObject = require('./dbObject.js');
36
+ const transformer = require('./transformer.js');
37
+ const types = require('./types.js');
37
38
 
38
39
  class AqQueue {
39
40
 
@@ -47,6 +48,19 @@ class AqQueue {
47
48
  value instanceof BaseDbObject);
48
49
  }
49
50
 
51
+ //---------------------------------------------------------------------------
52
+ // _makeMessage()
53
+ //
54
+ // For enqOne()/deqOne()/enqMany()/deqMany(), wrap the return value with JS
55
+ // layer object.
56
+ //---------------------------------------------------------------------------
57
+ _makeMessage(msgImpl) {
58
+ const msg = new AqMessage();
59
+ msg._impl = msgImpl;
60
+ msg._payloadTypeClass = this._payloadTypeClass;
61
+ return msg;
62
+ }
63
+
50
64
  //---------------------------------------------------------------------------
51
65
  // _verifyMessage()
52
66
  //
@@ -64,7 +78,7 @@ class AqQueue {
64
78
  message = {};
65
79
  } else {
66
80
  message = {...message};
67
- if (this._isPayload(message.payload)) {
81
+ if (this._isJson || this._isPayload(message.payload)) {
68
82
  payload = message.payload;
69
83
  } else if (this._payloadTypeClass) {
70
84
  payload = new this._payloadTypeClass(message.payload);
@@ -74,7 +88,9 @@ class AqQueue {
74
88
  }
75
89
 
76
90
  // validate payload
77
- if (typeof payload === 'string') {
91
+ if (this._isJson) {
92
+ message.payload = transformer.transformJsonValue(payload);
93
+ } else if (typeof payload === 'string') {
78
94
  message.payload = Buffer.from(payload);
79
95
  } else if (Buffer.isBuffer(payload)) {
80
96
  message.payload = payload;
@@ -116,8 +132,17 @@ class AqQueue {
116
132
  // Creates the queue and populates some internal attributes.
117
133
  //---------------------------------------------------------------------------
118
134
  async create(conn, name, options) {
119
- if (options.payloadType) {
120
- if (typeof options.payloadType == 'string') {
135
+ if (options.payloadType === types.DB_TYPE_JSON) {
136
+ this._isJson = true;
137
+ this._payloadType = types.DB_TYPE_JSON;
138
+ this._payloadTypeName = "JSON";
139
+ } else if (options.payloadType === undefined ||
140
+ options.payloadType === types.DB_TYPE_RAW) {
141
+ this._payloadType = types.DB_TYPE_RAW;
142
+ this._payloadTypeName = "RAW";
143
+ } else {
144
+ if (typeof options.payloadType === 'string') {
145
+ // DB Object type
121
146
  const cls = await conn._getDbObjectClassForName(options.payloadType);
122
147
  this._payloadTypeClass = cls;
123
148
  options.payloadType = cls;
@@ -126,14 +151,12 @@ class AqQueue {
126
151
  options.payloadType.prototype instanceof BaseDbObject, 2, "payloadType");
127
152
  this._payloadTypeClass = options.payloadType;
128
153
  }
129
- this._payloadType = constants.DB_TYPE_OBJECT;
154
+ this._payloadType = types.DB_TYPE_OBJECT;
130
155
  this._payloadTypeName = this._payloadTypeClass.prototype.name;
131
- } else {
132
- this._payloadType = constants.DB_TYPE_RAW;
133
- this._payloadTypeName = "RAW";
134
156
  }
135
157
  this._name = name;
136
- this._impl = await conn._impl.getQueue(name, options);
158
+ this._impl = await conn._impl.getQueue(name, this._payloadTypeClass,
159
+ this._payloadType);
137
160
  }
138
161
 
139
162
  //---------------------------------------------------------------------------
@@ -147,14 +170,7 @@ class AqQueue {
147
170
  errors.assertParamValue(Number.isInteger(maxMessages) && maxMessages > 0,
148
171
  1);
149
172
  const msgImpls = await this._impl.deqMany(maxMessages);
150
- const messages = new Array(msgImpls.length);
151
- for (let i = 0; i < msgImpls.length; i++) {
152
- const msg = new AqMessage();
153
- msg._impl = msgImpls[i];
154
- msg._payloadTypeClass = this._payloadTypeClass;
155
- messages[i] = msg;
156
- }
157
- return messages;
173
+ return msgImpls.map(i => this._makeMessage(i));
158
174
  }
159
175
 
160
176
  //---------------------------------------------------------------------------
@@ -165,12 +181,8 @@ class AqQueue {
165
181
  async deqOne() {
166
182
  errors.assertArgCount(arguments, 0, 0);
167
183
  const msgImpl = await this._impl.deqOne();
168
- if (msgImpl) {
169
- const msg = new AqMessage();
170
- msg._impl = msgImpl;
171
- msg._payloadTypeClass = this._payloadTypeClass;
172
- return msg;
173
- }
184
+ if (msgImpl)
185
+ return this._makeMessage(msgImpl);
174
186
  }
175
187
 
176
188
  //---------------------------------------------------------------------------
@@ -200,7 +212,8 @@ class AqQueue {
200
212
  for (let i = 0; i < messages.length; i++) {
201
213
  verifiedMessages[i] = this._verifyMessage(messages[i]);
202
214
  }
203
- return await this._impl.enqMany(verifiedMessages);
215
+ const msgImpls = await this._impl.enqMany(verifiedMessages);
216
+ return msgImpls.map(i => this._makeMessage(i));
204
217
  }
205
218
 
206
219
  //---------------------------------------------------------------------------
@@ -211,7 +224,8 @@ class AqQueue {
211
224
  async enqOne(message) {
212
225
  errors.assertArgCount(arguments, 1, 1);
213
226
  message = this._verifyMessage(message);
214
- return await this._impl.enqOne(message);
227
+ const msgImpl = await this._impl.enqOne(message);
228
+ return this._makeMessage(msgImpl);
215
229
  }
216
230
 
217
231
  //---------------------------------------------------------------------------
package/lib/connection.js CHANGED
@@ -1039,6 +1039,19 @@ class Connection extends EventEmitter {
1039
1039
  return info;
1040
1040
  }
1041
1041
 
1042
+ //---------------------------------------------------------------------------
1043
+ // instanceName
1044
+ //
1045
+ // Returns the Oracle Database instance name associated with the connection.
1046
+ // This is the equivalent of the SQL expression:
1047
+ // sys_context('userenv', 'instance_name')
1048
+ //---------------------------------------------------------------------------
1049
+ get instanceName() {
1050
+ if (this._impl)
1051
+ return this._impl.getInstanceName();
1052
+ return undefined;
1053
+ }
1054
+
1042
1055
  //---------------------------------------------------------------------------
1043
1056
  // internalName
1044
1057
  //
@@ -1227,7 +1240,7 @@ class Connection extends EventEmitter {
1227
1240
  errors.assertArgCount(arguments, 2, 2);
1228
1241
  errors.assertParamValue(typeof name === 'string', 1);
1229
1242
  errors.assertParamValue(nodbUtil.isObject(options), 2);
1230
- options = {...options};
1243
+ options = {name: name, ...options};
1231
1244
  errors.assertParamPropUnsignedInt(options, 2, "namespace");
1232
1245
  if (options.namespace === undefined)
1233
1246
  options.namespace = constants.SUBSCR_NAMESPACE_DBCHANGE;
@@ -1253,14 +1266,13 @@ class Connection extends EventEmitter {
1253
1266
  errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
1254
1267
 
1255
1268
  const inSubscr = _subscriptions.get(name);
1256
- let outValue = await this._impl.subscribe(inSubscr, options);
1269
+ const outValue = await this._impl.subscribe(inSubscr, options);
1257
1270
  let subscription;
1258
1271
  if (options.namespace === constants.SUBSCR_NAMESPACE_DBCHANGE) {
1259
1272
  subscription = outValue.subscription;
1260
1273
  delete outValue.subscription;
1261
1274
  } else {
1262
1275
  subscription = outValue;
1263
- outValue = undefined;
1264
1276
  }
1265
1277
  _subscriptions.set(name, subscription);
1266
1278
  return outValue;
package/lib/errors.js CHANGED
@@ -116,7 +116,6 @@ const ERR_UNEXPECTED_DATA = 113;
116
116
  const ERR_OSON_FIELD_NAME_LIMITATION = 114;
117
117
  const ERR_ORACLE_NUMBER_NO_REPR = 115;
118
118
  const ERR_UNSUPPORTED_VERIFIER_TYPE = 116;
119
- const ERR_INVALID_PRIVATE_KEY = 117;
120
119
  const ERR_THIN_CONNECTION_ALREADY_CREATED = 118;
121
120
  const ERR_UNSUPPORTED_CONVERSION = 119;
122
121
  const ERR_FETCH_TYPE_HANDLER_RETURN_VALUE = 120;
@@ -178,7 +177,6 @@ adjustErrorXref.set("OCI-22165", [ERR_INVALID_COLL_INDEX_SET, /index \[([0-9]+)\
178
177
  adjustErrorXref.set("ORA-00028", ERR_CONNECTION_CLOSED);
179
178
  adjustErrorXref.set("ORA-00600", ERR_CONNECTION_CLOSED);
180
179
  adjustErrorXref.set("ORA-24338", ERR_INVALID_REF_CURSOR);
181
- adjustErrorXref.set("ORA-24422", ERR_POOL_HAS_BUSY_CONNECTIONS);
182
180
  adjustErrorXref.set("ORA-25708", ERR_TOKEN_HAS_EXPIRED);
183
181
 
184
182
  // define mapping for error messages
@@ -355,8 +353,6 @@ messages.set(ERR_ORACLE_NUMBER_NO_REPR, // NJS-115
355
353
  'value cannot be represented as an Oracle Database number');
356
354
  messages.set(ERR_UNSUPPORTED_VERIFIER_TYPE, // NJS-116
357
355
  'password verifier type 0x%s is not supported by node-oracledb in Thin mode');
358
- messages.set(ERR_INVALID_PRIVATE_KEY, // NJS-117
359
- 'invalid private key. Headers and footers are not allowed');
360
356
  messages.set(ERR_THIN_CONNECTION_ALREADY_CREATED, // NJS-118
361
357
  'node-oracledb Thick mode cannot be enabled because a Thin mode connection has already been created');
362
358
  messages.set(ERR_UNSUPPORTED_CONVERSION, // NJS-119
@@ -612,10 +608,19 @@ function transformErr(err, fnOpt) {
612
608
  const pos = err.message.indexOf(":");
613
609
  if (pos > 0) {
614
610
  err.code = err.message.substr(0, pos);
611
+ /* add Oracle Database Error Help Portal URL for database error
612
+ messages, but only in thin mode since this is done
613
+ automatically in thick mode with Oracle Client 23c and higher
614
+ */
615
+ const settings = require('./settings.js');
616
+ if (err.errorNum && settings.thin) {
617
+ err.message += '\n' + 'Help: https://docs.oracle.com/error-help/db/ora-' +
618
+ `${err.errorNum.toString().padStart(5, '0')}/`;
619
+ }
615
620
  if (adjustErrorXref.has(err.code)) {
616
621
  let args = [];
617
622
  let driverErrorNum;
618
- let driverErrorInfo = adjustErrorXref.get(err.code);
623
+ const driverErrorInfo = adjustErrorXref.get(err.code);
619
624
  if (typeof driverErrorInfo === 'number') {
620
625
  driverErrorNum = driverErrorInfo;
621
626
  } else {
@@ -748,7 +753,6 @@ module.exports = {
748
753
  ERR_UNEXPECTED_DATA,
749
754
  ERR_OSON_FIELD_NAME_LIMITATION,
750
755
  ERR_OSON_VERSION_NOT_SUPPORTED,
751
- ERR_INVALID_PRIVATE_KEY,
752
756
  ERR_THIN_CONNECTION_ALREADY_CREATED,
753
757
  ERR_UNSUPPORTED_CONVERSION,
754
758
  ERR_FETCH_TYPE_HANDLER_RETURN_VALUE,
@@ -226,6 +226,15 @@ class ConnectionImpl {
226
226
  errors.throwNotImplemented("getting the external name");
227
227
  }
228
228
 
229
+ //---------------------------------------------------------------------------
230
+ // getInstanceName()
231
+ //
232
+ // Returns the Oracle Database instance name associated with the connection.
233
+ //---------------------------------------------------------------------------
234
+ getInstanceName() {
235
+ errors.throwNotImplemented("getting the Oracle Database instance name.");
236
+ }
237
+
229
238
  //---------------------------------------------------------------------------
230
239
  // getInternalName()
231
240
  //
@@ -111,14 +111,17 @@ class ResultSetImpl {
111
111
  if (metadata.dbType === types.DB_TYPE_NUMBER &&
112
112
  metadata.fetchType === types.DB_TYPE_NUMBER) {
113
113
  converter = (v) => (v === null) ? null : parseFloat(v);
114
- } else if (metadata.fetchType === types.DB_TYPE_VARCHAR &&
115
- (metadata.dbType === types.DB_TYPE_BINARY_DOUBLE ||
114
+ } else if (metadata.fetchType === types.DB_TYPE_VARCHAR) {
115
+ if (metadata.dbType === types.DB_TYPE_BINARY_DOUBLE ||
116
116
  metadata.dbType === types.DB_TYPE_BINARY_FLOAT ||
117
117
  metadata.dbType === types.DB_TYPE_DATE ||
118
118
  metadata.dbType === types.DB_TYPE_TIMESTAMP ||
119
119
  metadata.dbType === types.DB_TYPE_TIMESTAMP_LTZ ||
120
- metadata.dbType === types.DB_TYPE_TIMESTAMP_TZ)) {
121
- converter = (v) => (v === null) ? null : v.toString();
120
+ metadata.dbType === types.DB_TYPE_TIMESTAMP_TZ) {
121
+ converter = (v) => (v === null) ? null : v.toString();
122
+ } else if (metadata.dbType === types.DB_TYPE_RAW) {
123
+ converter = (v) => (v === null) ? null : v.toString('hex').toUpperCase();
124
+ }
122
125
  }
123
126
  if (userConverter && converter) {
124
127
  const internalConverter = converter;
package/lib/oracledb.js CHANGED
@@ -67,7 +67,6 @@ const defaultPoolAlias = 'default';
67
67
 
68
68
  // save arguments for call to initOracleClient()
69
69
  let _initOracleClientArgs;
70
- let _thinDriverInitialized = false;
71
70
 
72
71
  // Load the Oracledb binary
73
72
  function _initCLib() {
@@ -248,6 +247,12 @@ async function _verifyOptions(options, inCreatePool) {
248
247
  outOptions.sslServerDNMatch = options.sslServerDNMatch;
249
248
  }
250
249
 
250
+ // sslAllowWeakDNMatch must be a boolean
251
+ if (options.sslAllowWeakDNMatch !== undefined) {
252
+ errors.assertParamPropValue(typeof options.sslAllowWeakDNMatch === 'boolean',
253
+ 1, "sslAllowWeakDNMatch");
254
+ outOptions.sslAllowWeakDNMatch = options.sslAllowWeakDNMatch;
255
+ }
251
256
  // httpsProxy must be a string
252
257
  if (options.httpsProxy !== undefined) {
253
258
  errors.assertParamPropValue(typeof options.httpsProxy === 'string',
@@ -472,8 +477,10 @@ async function _verifyOptions(options, inCreatePool) {
472
477
  errors.assert(nodbUtil.isTokenValid(accessToken),
473
478
  errors.ERR_TOKEN_HAS_EXPIRED);
474
479
  if (accessToken.privateKey !== undefined) {
475
- errors.assert(nodbUtil.isPrivateKeyValid(accessToken),
476
- errors.ERR_INVALID_PRIVATE_KEY);
480
+ errors.assert(typeof accessToken.privateKey === 'string', errors.ERR_TOKEN_BASED_AUTH);
481
+ accessToken.privateKey = accessToken.privateKey.replace(/\n/g, '');
482
+ accessToken.privateKey = accessToken.privateKey.replace('-----BEGIN PRIVATE KEY-----', '');
483
+ accessToken.privateKey = accessToken.privateKey.replace('-----END PRIVATE KEY-----', '');
477
484
  }
478
485
 
479
486
  // store token and privatekey
@@ -546,7 +553,7 @@ async function createPool(options) {
546
553
  }
547
554
 
548
555
  // initialize the Oracle client, if necessary
549
- if (_initOracleClientArgs === undefined && !_thinDriverInitialized) {
556
+ if (_initOracleClientArgs === undefined && !settings.thinDriverInitialized) {
550
557
  _initializeThinDriver();
551
558
  }
552
559
 
@@ -579,6 +586,9 @@ async function createPool(options) {
579
586
  delete poolCache[pool.poolAlias];
580
587
  }
581
588
  });
589
+ if (_initOracleClientArgs === undefined) {
590
+ settings.thinDriverInitialized = true;
591
+ }
582
592
 
583
593
  return pool;
584
594
  }
@@ -638,7 +648,6 @@ async function getConnection(a1) {
638
648
  // Returns a pool for the given alias.
639
649
  //-----------------------------------------------------------------------------
640
650
  function getPool(poolAlias) {
641
- let pool;
642
651
 
643
652
  errors.assertArgCount(arguments, 0, 1);
644
653
 
@@ -649,7 +658,7 @@ function getPool(poolAlias) {
649
658
 
650
659
  poolAlias = poolAlias || defaultPoolAlias;
651
660
 
652
- pool = poolCache[poolAlias];
661
+ const pool = poolCache[poolAlias];
653
662
 
654
663
  if (!pool) {
655
664
  errors.throwErr(errors.ERR_POOL_WITH_ALIAS_NOT_FOUND, poolAlias);
@@ -1053,16 +1062,10 @@ module.exports = {
1053
1062
  },
1054
1063
 
1055
1064
  get oracleClientVersion() {
1056
- if (_initOracleClientArgs === undefined) {
1057
- errors.throwNotImplemented("getting the Oracle Client version");
1058
- }
1059
1065
  return settings.oracleClientVersion;
1060
1066
  },
1061
1067
 
1062
1068
  get oracleClientVersionString() {
1063
- if (_initOracleClientArgs === undefined) {
1064
- errors.throwNotImplemented("getting the Oracle Client version");
1065
- }
1066
1069
  return settings.oracleClientVersionString;
1067
1070
  },
1068
1071
 
package/lib/pool.js CHANGED
@@ -279,8 +279,14 @@ class Pool extends EventEmitter {
279
279
  });
280
280
  }
281
281
 
282
+ // if any connections are still out and the pool is not being force closed,
283
+ // throw an exception
284
+ if (!forceClose && this._connectionsOut > 0) {
285
+ errors.throwErr(errors.ERR_POOL_HAS_BUSY_CONNECTIONS);
286
+ }
287
+
282
288
  // close the pool
283
- await this._impl.close({forceClose: forceClose});
289
+ await this._impl.close();
284
290
  this._status = constants.POOL_STATUS_CLOSED;
285
291
  this.emit('_afterPoolClose');
286
292
 
@@ -109,7 +109,7 @@ class SodaCollection {
109
109
  errors.assertArgCount(arguments, 1, 1);
110
110
  errors.assertParamValue(Array.isArray(docs) && docs.length > 0, 1);
111
111
 
112
- let actualDocs = Array(docs.length);
112
+ const actualDocs = Array(docs.length);
113
113
  for (let i = 0; i < docs.length; i++) {
114
114
  actualDocs[i] = nodbUtil.verifySodaDoc(docs[i]);
115
115
  }
@@ -32,7 +32,7 @@ const ThinResultSetImpl = require('./resultSet.js');
32
32
  const ThinLobImpl = require("./lob.js");
33
33
  const Protocol = require("./protocol/protocol.js");
34
34
  const { BaseBuffer } = require('./protocol/buffer.js');
35
- const {NetworkSession:nsi, getConnectionInfo} = require("./sqlnet/networkSession.js");
35
+ const {NetworkSession:nsi} = require("./sqlnet/networkSession.js");
36
36
  const { Statement } = require("./statement");
37
37
  const thinUtil = require('./util');
38
38
  const sqlNetConstants = require('./sqlnet/constants.js');
@@ -49,6 +49,8 @@ const finalizationRegistry = new global.FinalizationRegistry((heldValue) => {
49
49
  class TDSBuffer extends BaseBuffer {
50
50
  }
51
51
 
52
+ const connectionCookies = new Map();
53
+
52
54
  class ThinConnectionImpl extends ConnectionImpl {
53
55
 
54
56
  /**
@@ -443,10 +445,6 @@ class ThinConnectionImpl extends ConnectionImpl {
443
445
  await this._protocol.breakMessage();
444
446
  }
445
447
 
446
- _healthStatus() {
447
- return this.nscon.recvInbandNotif();
448
- }
449
-
450
448
  isHealthy() {
451
449
  try {
452
450
  if (this.nscon.recvInbandNotif() === 0)
@@ -461,6 +459,26 @@ class ThinConnectionImpl extends ConnectionImpl {
461
459
  return (this._pool) ? true : false;
462
460
  }
463
461
 
462
+ //---------------------------------------------------------------------------
463
+ // getConnectionCookieByUUID()
464
+ //
465
+ // It fetches from map which keeps keyname as UUID+ServiceName.
466
+ // UUID identifies the CDB instance and ServiceName identifies the
467
+ // entity within a PDB which uniquely identifies a pdb instance.
468
+ //---------------------------------------------------------------------------
469
+ getConnectionCookieByUUID(uuid) {
470
+ let cookie;
471
+ if (uuid) {
472
+ const key = uuid + ((this.serviceName) ? this.serviceName : this.sid);
473
+ cookie = connectionCookies.get(key);
474
+ if (!cookie) {
475
+ cookie = {};
476
+ connectionCookies.set(key, cookie);
477
+ }
478
+ }
479
+ return cookie;
480
+ }
481
+
464
482
  /**
465
483
  *
466
484
  * @param {object} params Configuration of the connection
@@ -499,22 +517,32 @@ class ThinConnectionImpl extends ConnectionImpl {
499
517
  this._clientInfoModified = false;
500
518
  this._module = "";
501
519
  this._moduleModified = false;
520
+ this._drcpEnabled = false;
502
521
  this.serviceName = '';
503
522
  this.remoteAddress = '';
504
- this.privilege = params.privilege;
505
523
  this.comboKey = null; // used in changePassword API
506
524
 
507
525
  this.nscon = new nsi();
508
526
  finalizationRegistry.register(this, this.nscon);
509
527
  await this.nscon.connect(params);
510
528
 
511
- this._connInfo = (this.isPooled()) ? params._connInfo.map((x) => x) :
512
- await getConnectionInfo(params);
513
- this._drcpEnabled = String(this._connInfo[0]).toLowerCase() === 'pooled';
514
- this.serviceName = this._connInfo[2];
515
- this.purity = this._connInfo[3] | constants.PURITY_DEFAULT;
529
+ let serverType;
530
+ if (this.isPooled()) {
531
+ serverType = params._connInfo[0];
532
+ this.serviceName = params._connInfo[2];
533
+ this.purity = params._connInfo[3] | constants.PURITY_DEFAULT;
534
+ this.sid = params._connInfo[4];
535
+ } else {
536
+ serverType = this.nscon.getOption(sqlNetConstants.SERVERTYPE);
537
+ this.serviceName = this.nscon.getOption(sqlNetConstants.SVCNAME);
538
+ this.sid = this.nscon.getOption(sqlNetConstants.SID);
539
+ this.purity = this.nscon.getOption(sqlNetConstants.PURITY) | constants.PURITY_DEFAULT;
540
+ }
541
+ if (serverType) {
542
+ this._drcpEnabled = serverType.toLowerCase() === 'pooled';
543
+ }
516
544
  this.remoteAddress = this.nscon.getOption(sqlNetConstants.REMOTEADDR);
517
- this.connClass = params.connectionClass;
545
+ this.connectionClass = params.connectionClass;
518
546
 
519
547
  /*
520
548
  * if drcp is used, use purity = NEW as the default purity for
@@ -538,13 +566,41 @@ class ThinConnectionImpl extends ConnectionImpl {
538
566
  }
539
567
 
540
568
  try {
541
- let message = new messages.ProtocolMessage(this);
542
- await this._protocol._processMessage(message);
543
- message = new messages.DataTypeMessage(this);
544
- await this._protocol._processMessage(message);
545
- message = new messages.AuthMessage(this, params);
546
- await this._protocol._processMessage(message); // OSESSKEY
547
- await this._protocol._processMessage(message); // OAUTH
569
+ const cookie = this.getConnectionCookieByUUID(this.nscon.dbUUID);
570
+ this.nscon.dbUUID = null;
571
+ const protocolMessage = new messages.ProtocolMessage(this);
572
+ const dataTypeMessage = new messages.DataTypeMessage(this);
573
+ const authMessage = new messages.AuthMessage(this, params);
574
+ let sentCookie = false;
575
+ if (cookie && cookie.populated) {
576
+ const cookieMessage = new messages.ConnectionCookieMessage(this);
577
+ cookieMessage.cookie = cookie;
578
+ cookieMessage.protocolMessage = protocolMessage;
579
+ cookieMessage.dataTypeMessage = dataTypeMessage;
580
+ cookieMessage.authMessage = authMessage;
581
+ await this._protocol._processMessage(cookieMessage);
582
+ sentCookie = true;
583
+ } else {
584
+ await this._protocol._processMessage(protocolMessage);
585
+ }
586
+ if (!sentCookie || !cookie.populated) {
587
+ await this._protocol._processMessage(dataTypeMessage);
588
+ // Does OSESSKEY for non-token Authentication else OAUTH
589
+ await this._protocol._processMessage(authMessage);
590
+ if (cookie && !cookie.populated) {
591
+ cookie.protocolVersion = protocolMessage.serverVersion;
592
+ cookie.serverBanner = protocolMessage.serverBanner;
593
+ cookie.charsetID = this._protocol.caps.charSetID;
594
+ cookie.ncharsetID = this._protocol.caps.nCharsetId;
595
+ cookie.flags = protocolMessage.serverFlags;
596
+ cookie.compileCaps = Buffer.from(protocolMessage.serverCompileCaps);
597
+ cookie.runtimeCaps = Buffer.from(protocolMessage.serverRunTimeCaps);
598
+ cookie.populated = true;
599
+ }
600
+ }
601
+ if (!params.token) { // non-token Authentication
602
+ await this._protocol._processMessage(authMessage); // OAUTH
603
+ }
548
604
  } catch (err) {
549
605
  this.nscon.disconnect();
550
606
  throw err;
@@ -614,7 +670,7 @@ class ThinConnectionImpl extends ConnectionImpl {
614
670
  // option is true
615
671
  //---------------------------------------------------------------------------
616
672
  _prepare(sql, options) {
617
- let statement = this._getStatement(sql, options.keepInStmtCache);
673
+ const statement = this._getStatement(sql, options.keepInStmtCache);
618
674
  statement.bufferRowIndex = 0;
619
675
  statement.bufferRowCount = 0;
620
676
  statement.lastRowIndex = 0;
@@ -626,8 +682,8 @@ class ThinConnectionImpl extends ConnectionImpl {
626
682
  // Binds the values by user to the statement object
627
683
  //---------------------------------------------------------------------------
628
684
  async _bind(stmt, variable, pos = 0) {
629
- let bindInfoDict = stmt.bindInfoDict;
630
- let bindInfoList = stmt.bindInfoList;
685
+ const bindInfoDict = stmt.bindInfoDict;
686
+ const bindInfoList = stmt.bindInfoList;
631
687
 
632
688
  /*
633
689
  * For PL/SQL blocks, if the size of a string or bytes object exceeds
@@ -650,8 +706,8 @@ class ThinConnectionImpl extends ConnectionImpl {
650
706
  if (val === null) {
651
707
  return null;
652
708
  }
653
- let data = await val.getData();
654
- let len = val._length;
709
+ const data = await val.getData();
710
+ const len = val._length;
655
711
  if (data && len > maxSize) {
656
712
  errors.throwErr(errors.ERR_INSUFFICIENT_BUFFER_FOR_BINDS);
657
713
  }
@@ -662,7 +718,7 @@ class ThinConnectionImpl extends ConnectionImpl {
662
718
  if (variable.type === types.DB_TYPE_CLOB ||
663
719
  variable.type === types.DB_TYPE_NCLOB ||
664
720
  variable.type === types.DB_TYPE_BLOB) {
665
- for (let [index, val] of variable.values.entries()) {
721
+ for (const [index, val] of variable.values.entries()) {
666
722
  if (!(val instanceof ThinLobImpl)) {
667
723
  if (val && val.length > 0) {
668
724
  const lobImpl = new ThinLobImpl();
@@ -693,7 +749,7 @@ class ThinConnectionImpl extends ConnectionImpl {
693
749
  stmt._setVariable(bindInfo, variable);
694
750
  });
695
751
  } else {
696
- let bindInfo = bindInfoList[pos - 1];
752
+ const bindInfo = bindInfoList[pos - 1];
697
753
  stmt._setVariable(bindInfo, variable);
698
754
  }
699
755
  }
@@ -739,7 +795,7 @@ class ThinConnectionImpl extends ConnectionImpl {
739
795
  //---------------------------------------------------------------------------
740
796
  // Clears the statement cache for the connection
741
797
  //---------------------------------------------------------------------------
742
- resetStatmentCache() {
798
+ resetStatementCache() {
743
799
  this.statementCache.clear();
744
800
  this._cursorsToClose.clear();
745
801
  }
@@ -761,9 +817,9 @@ class ThinConnectionImpl extends ConnectionImpl {
761
817
  // information for a statment.
762
818
  //---------------------------------------------------------------------------
763
819
  async getStatementInfo(sql) {
764
- let options = {};
765
- let result = {};
766
- let statement = await this._prepareAndBind(sql, null, options, true);
820
+ const options = {};
821
+ const result = {};
822
+ const statement = await this._prepareAndBind(sql, null, options, true);
767
823
  options.connection = this;
768
824
  // parse the statement (but not for DDL which doesn't support it)
769
825
  if (!statement.isDdl) {
@@ -1038,6 +1094,12 @@ class ThinConnectionImpl extends ConnectionImpl {
1038
1094
  return '';
1039
1095
  }
1040
1096
 
1097
+ //---------------------------------------------------------------------------
1098
+ // Returns the Oracle Database instance name associated with the connection.
1099
+ //---------------------------------------------------------------------------
1100
+ getInstanceName() {
1101
+ return this.instanceName;
1102
+ }
1041
1103
  }
1042
1104
 
1043
1105
  module.exports = ThinConnectionImpl;