oracledb 6.9.0 → 7.0.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 (100) 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.0-darwin-arm64.node +0 -0
  5. package/build/Release/oracledb-7.0.0-darwin-arm64.node-buildinfo.txt +1 -0
  6. package/build/Release/oracledb-7.0.0-js-buildinfo.txt +1 -0
  7. package/build/Release/oracledb-7.0.0-linux-arm64.node +0 -0
  8. package/build/Release/oracledb-7.0.0-linux-arm64.node-buildinfo.txt +1 -0
  9. package/build/Release/oracledb-7.0.0-linux-x64.node +0 -0
  10. package/build/Release/oracledb-7.0.0-linux-x64.node-buildinfo.txt +1 -0
  11. package/build/Release/oracledb-7.0.0-win32-x64.node +0 -0
  12. package/build/Release/oracledb-7.0.0-win32-x64.node-buildinfo.txt +1 -0
  13. package/eslint.config.js +39 -0
  14. package/lib/aqDeqOptions.js +18 -1
  15. package/lib/aqQueue.js +10 -6
  16. package/lib/connection.js +418 -39
  17. package/lib/dbObject.js +25 -4
  18. package/lib/endUserSecurityContext.js +176 -0
  19. package/lib/errors.js +99 -8
  20. package/lib/impl/aqDeqOptions.js +10 -1
  21. package/lib/impl/connection.js +76 -2
  22. package/lib/impl/datahandlers/buffer.js +68 -5
  23. package/lib/impl/datahandlers/oson.js +7 -2
  24. package/lib/impl/datahandlers/vector.js +25 -5
  25. package/lib/impl/lob.js +9 -0
  26. package/lib/impl/parserHelpers.js +443 -0
  27. package/lib/impl/resultset.js +1 -1
  28. package/lib/impl/sodaDocument.js +5 -14
  29. package/lib/lob.js +27 -14
  30. package/lib/obfuscation.js +97 -0
  31. package/lib/oracledb.js +163 -49
  32. package/lib/parser.js +204 -0
  33. package/lib/pipeline.js +113 -0
  34. package/lib/pool.js +203 -147
  35. package/lib/poolStatistics.js +1 -1
  36. package/lib/resultset.js +42 -21
  37. package/lib/settings.js +1 -0
  38. package/lib/sodaCollection.js +12 -8
  39. package/lib/sodaDatabase.js +35 -8
  40. package/lib/sodaDocument.js +24 -6
  41. package/lib/sodaOperation.js +7 -6
  42. package/lib/thin/aq.js +475 -0
  43. package/lib/thin/connection.js +518 -54
  44. package/lib/thin/dbObject.js +7 -1
  45. package/lib/thin/lob.js +20 -1
  46. package/lib/thin/pool.js +42 -62
  47. package/lib/thin/protocol/capabilities.js +21 -4
  48. package/lib/thin/protocol/constants.js +143 -2
  49. package/lib/thin/protocol/encryptDecrypt.js +45 -10
  50. package/lib/thin/protocol/messages/aqArray.js +238 -0
  51. package/lib/thin/protocol/messages/aqBase.js +305 -0
  52. package/lib/thin/protocol/messages/aqDeq.js +164 -0
  53. package/lib/thin/protocol/messages/aqEnq.js +135 -0
  54. package/lib/thin/protocol/messages/auth.js +18 -28
  55. package/lib/thin/protocol/messages/base.js +245 -4
  56. package/lib/thin/protocol/messages/dataType.js +8 -3
  57. package/lib/thin/protocol/messages/directPathLoadStream.js +377 -0
  58. package/lib/thin/protocol/messages/directPathOp.js +65 -0
  59. package/lib/thin/protocol/messages/directPathPrepare.js +158 -0
  60. package/lib/thin/protocol/messages/endPipeline.js +56 -0
  61. package/lib/thin/protocol/messages/execute.js +9 -7
  62. package/lib/thin/protocol/messages/index.js +9 -1
  63. package/lib/thin/protocol/messages/protocol.js +2 -2
  64. package/lib/thin/protocol/messages/withData.js +10 -142
  65. package/lib/thin/protocol/packet.js +120 -28
  66. package/lib/thin/protocol/protocol.js +110 -25
  67. package/lib/thin/protocol/utils.js +1 -26
  68. package/lib/thin/resultSet.js +13 -19
  69. package/lib/thin/sqlnet/ezConnectResolver.js +2 -2
  70. package/lib/thin/sqlnet/networkSession.js +63 -41
  71. package/lib/thin/sqlnet/ntTcp.js +24 -0
  72. package/lib/thin/sqlnet/nvStrToNvPair.js +50 -25
  73. package/lib/thin/sqlnet/packet.js +25 -4
  74. package/lib/thin/sqlnet/paramParser.js +10 -7
  75. package/lib/thin/statementCache.js +2 -4
  76. package/lib/traceHandler.js +59 -2
  77. package/lib/transformer.js +8 -3
  78. package/lib/types.js +36 -22
  79. package/lib/util.js +6 -19
  80. package/lib/version.js +3 -3
  81. package/package/install.js +5 -5
  82. package/package/prunebinaries.js +1 -1
  83. package/package.json +1 -1
  84. package/plugins/configProviders/awsCommon.js +125 -0
  85. package/plugins/configProviders/awss3/index.js +138 -0
  86. package/plugins/configProviders/awssecretsmanager/index.js +147 -0
  87. package/plugins/configProviders/azure/index.js +7 -5
  88. package/plugins/token/extensionAzure/index.js +0 -1
  89. package/plugins/token/extensionOci/index.js +0 -1
  90. package/build/Release/oracledb-6.9.0-darwin-arm64.node +0 -0
  91. package/build/Release/oracledb-6.9.0-darwin-arm64.node-buildinfo.txt +0 -1
  92. package/build/Release/oracledb-6.9.0-darwin-x64.node +0 -0
  93. package/build/Release/oracledb-6.9.0-darwin-x64.node-buildinfo.txt +0 -1
  94. package/build/Release/oracledb-6.9.0-js-buildinfo.txt +0 -1
  95. package/build/Release/oracledb-6.9.0-linux-arm64.node +0 -0
  96. package/build/Release/oracledb-6.9.0-linux-arm64.node-buildinfo.txt +0 -1
  97. package/build/Release/oracledb-6.9.0-linux-x64.node +0 -0
  98. package/build/Release/oracledb-6.9.0-linux-x64.node-buildinfo.txt +0 -1
  99. package/build/Release/oracledb-6.9.0-win32-x64.node +0 -0
  100. package/build/Release/oracledb-6.9.0-win32-x64.node-buildinfo.txt +0 -1
@@ -1,4 +1,4 @@
1
- // Copyright (c) 2022, 2023, Oracle and/or its affiliates.
1
+ // Copyright (c) 2022, 2025, Oracle and/or its affiliates.
2
2
 
3
3
  //-----------------------------------------------------------------------------
4
4
  //
@@ -31,21 +31,12 @@ const errors = require('../errors.js');
31
31
  class SodaDocumentImpl {
32
32
 
33
33
  //---------------------------------------------------------------------------
34
- // getContentAsBuffer()
34
+ // getContent()
35
35
  //
36
- // Returns the document content as a Buffer object.
36
+ // Returns the document content.
37
37
  //---------------------------------------------------------------------------
38
- getContentAsBuffer() {
39
- errors.throwNotImplemented("getting doc content as a buffer");
40
- }
41
-
42
- //---------------------------------------------------------------------------
43
- // getContentAsString()
44
- //
45
- // Returns the document content as a string.
46
- //---------------------------------------------------------------------------
47
- getContentAsString() {
48
- errors.throwNotImplemented("getting doc content as a string");
38
+ getContent() {
39
+ errors.throwNotImplemented("getting doc content");
49
40
  }
50
41
 
51
42
  //---------------------------------------------------------------------------
package/lib/lob.js CHANGED
@@ -117,12 +117,6 @@ class Lob extends Duplex {
117
117
  // called to associate a LOB implementation with this user facing object
118
118
  _setup(lobImpl, autoCloseLob) {
119
119
  this._impl = lobImpl;
120
- // chunk size is not defined for BFILE LOBs
121
- if (this.type !== types.DB_TYPE_BFILE) {
122
- this._chunkSize = lobImpl.getChunkSize();
123
- }
124
- this._pieceSize = lobImpl.getPieceSize();
125
- this._length = lobImpl.getLength();
126
120
  this._type = lobImpl.getType();
127
121
  if (typeof this._type === 'number') {
128
122
  this._type = types.getTypeByNum(this._type);
@@ -170,10 +164,11 @@ class Lob extends Duplex {
170
164
  // chunkSize
171
165
  //
172
166
  // Property for the chunk size of the LOB.
167
+ // returns undefined if the LOB is closed.
173
168
  //---------------------------------------------------------------------------
174
169
  get chunkSize() {
175
170
  this._checkNotBfile();
176
- return this._chunkSize;
171
+ return this._impl?.getChunkSize();
177
172
  }
178
173
 
179
174
  //---------------------------------------------------------------------------
@@ -218,12 +213,12 @@ class Lob extends Duplex {
218
213
  if (offset === undefined) {
219
214
  offset = 1;
220
215
  } else {
221
- errors.assertParamValue(Number.isInteger(offset) && offset > 0, 1);
216
+ errors.assertParamValue(Number.isSafeInteger(offset) && offset > 0, 1);
222
217
  }
223
218
  if (amount === undefined) {
224
219
  amount = 0;
225
220
  } else {
226
- errors.assertParamValue(Number.isInteger(amount) && amount > 0, 2);
221
+ errors.assertParamValue(Number.isSafeInteger(amount) && amount > 0, 2);
227
222
  }
228
223
  errors.assert(this._impl, errors.ERR_INVALID_LOB);
229
224
  return await this._impl.getData(offset, amount);
@@ -257,6 +252,22 @@ class Lob extends Duplex {
257
252
  this._impl.setDirFileName(a1);
258
253
  }
259
254
 
255
+ //---------------------------------------------------------------------------
256
+ // trim()
257
+ // trims non-BFILE LOBs to a smaller size as specified by the parameter.
258
+ //---------------------------------------------------------------------------
259
+ async trim(newSize) {
260
+ this._checkNotBfile();
261
+ errors.assertArgCount(arguments, 0, 1);
262
+ if (newSize === undefined) {
263
+ newSize = 0;
264
+ } else {
265
+ errors.assertParamValue(Number.isInteger(newSize) && newSize >= 0 &&
266
+ newSize < 2 ** 32, 1);
267
+ }
268
+ await this._impl.trim(newSize);
269
+ }
270
+
260
271
  //---------------------------------------------------------------------------
261
272
  // fileExists
262
273
  //
@@ -271,9 +282,10 @@ class Lob extends Duplex {
271
282
  // length
272
283
  //
273
284
  // Property for the length of the LOB.
285
+ // returns undefined if the LOB is closed.
274
286
  //---------------------------------------------------------------------------
275
287
  get length() {
276
- return this._length;
288
+ return this._impl?.getLength();
277
289
  }
278
290
 
279
291
  //---------------------------------------------------------------------------
@@ -281,16 +293,16 @@ class Lob extends Duplex {
281
293
  //
282
294
  // Property for the size to use for each piece that is transferred when
283
295
  // reading from the LOB.
296
+ // returns undefined if the LOB is closed.
284
297
  //---------------------------------------------------------------------------
285
298
  get pieceSize() {
286
- return this._pieceSize;
299
+ return this._impl?.getPieceSize();
287
300
  }
288
301
 
289
302
  set pieceSize(value) {
290
- errors.assertPropValue(Number.isInteger(value) && value >= 0, "pieceSize");
303
+ errors.assertPropValue(Number.isSafeInteger(value) && value >= 0, "pieceSize");
291
304
  errors.assert(this._impl, errors.ERR_INVALID_LOB);
292
305
  this._impl.setPieceSize(value);
293
- this._pieceSize = value;
294
306
  }
295
307
 
296
308
  //---------------------------------------------------------------------------
@@ -307,7 +319,8 @@ class Lob extends Duplex {
307
319
  nodbUtil.wrapFns(Lob.prototype, errors.ERR_BUSY_LOB,
308
320
  "close",
309
321
  "fileExists",
310
- "getData");
322
+ "getData",
323
+ "trim");
311
324
  Lob.prototype._serializedRead = nodbUtil.wrapFn(Lob.prototype._readData, true);
312
325
  Lob.prototype._serializedWrite =
313
326
  nodbUtil.wrapFn(Lob.prototype._writeData, true);
@@ -0,0 +1,97 @@
1
+ // Copyright (c) 2026, Oracle and/or its affiliates.
2
+
3
+ //-----------------------------------------------------------------------------
4
+ //
5
+ // This software is dual-licensed to you under the Universal Permissive License
6
+ // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License
7
+ // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose
8
+ // either license.
9
+ //
10
+ // If you elect to accept the software under the Apache License, Version 2.0,
11
+ // the following applies:
12
+ //
13
+ // Licensed under the Apache License, Version 2.0 (the "License");
14
+ // you may not use this file except in compliance with the License.
15
+ // You may obtain a copy of the License at
16
+ //
17
+ // https://www.apache.org/licenses/LICENSE-2.0
18
+ //
19
+ // Unless required by applicable law or agreed to in writing, software
20
+ // distributed under the License is distributed on an "AS IS" BASIS,
21
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22
+ // See the License for the specific language governing permissions and
23
+ // limitations under the License.
24
+ //
25
+ //-----------------------------------------------------------------------------
26
+
27
+ 'use strict';
28
+
29
+ const { Buffer } = require('buffer');
30
+ const crypto = require('crypto');
31
+
32
+ class ObfuscatedValue {
33
+
34
+ constructor(value, options = {}) {
35
+ this._valueBuffer = null;
36
+ this._maskBuffer = null;
37
+ this._defaultReturnBuffer =
38
+ options.returnBuffer ??
39
+ (value !== undefined && value !== null && Buffer.isBuffer(value));
40
+ if (value !== undefined && value !== null) {
41
+ this.set(value, options);
42
+ }
43
+ }
44
+
45
+ set(value, options = {}) {
46
+ if (value === undefined || value === null) {
47
+ this.clear();
48
+ return;
49
+ }
50
+ const returnBuffer = options.returnBuffer ??
51
+ (Buffer.isBuffer(value) || this._defaultReturnBuffer === true);
52
+ const source = Buffer.isBuffer(value)
53
+ ? Buffer.from(value)
54
+ : Buffer.from(String(value));
55
+ const mask = crypto.randomBytes(source.length);
56
+ for (let i = 0; i < source.length; i++) {
57
+ source[i] = source[i] ^ mask[i];
58
+ }
59
+ this.clear();
60
+ this._valueBuffer = source;
61
+ this._maskBuffer = mask;
62
+ this._defaultReturnBuffer = returnBuffer;
63
+ }
64
+
65
+ get(options = {}) {
66
+ if (!this._valueBuffer || !this._maskBuffer) {
67
+ return null;
68
+ }
69
+ const returnBuffer = options.returnBuffer ??
70
+ (this._defaultReturnBuffer === true);
71
+ const result = Buffer.allocUnsafe(this._valueBuffer.length);
72
+ for (let i = 0; i < this._valueBuffer.length; i++) {
73
+ result[i] = this._valueBuffer[i] ^ this._maskBuffer[i];
74
+ }
75
+ if (returnBuffer) {
76
+ return result;
77
+ }
78
+ const text = result.toString();
79
+ result.fill(0);
80
+ return text;
81
+ }
82
+
83
+ clear() {
84
+ if (this._valueBuffer) {
85
+ this._valueBuffer.fill(0);
86
+ this._valueBuffer = null;
87
+ }
88
+ if (this._maskBuffer) {
89
+ this._maskBuffer.fill(0);
90
+ this._maskBuffer = null;
91
+ }
92
+ }
93
+ }
94
+
95
+ module.exports = {
96
+ ObfuscatedValue
97
+ };
package/lib/oracledb.js CHANGED
@@ -1,4 +1,4 @@
1
- // Copyright (c) 2015, 2025, Oracle and/or its affiliates.
1
+ // Copyright (c) 2015, 2026, Oracle and/or its affiliates.
2
2
 
3
3
  //-----------------------------------------------------------------------------
4
4
  //
@@ -28,11 +28,14 @@
28
28
 
29
29
  const constants = require('./constants.js');
30
30
  const nodbUtil = require('./util.js');
31
+ const { ObfuscatedValue } = require('./obfuscation.js');
31
32
  const errors = require('./errors.js');
32
33
  const types = require('./types.js');
33
34
  const impl = require('./impl');
34
35
  const process = require('process');
35
36
  const util = require('util');
37
+ const parser = require('./parser.js');
38
+ const parserHelpers = require('./impl/parserHelpers.js');
36
39
 
37
40
  // This version of node-oracledb works with Node.js 14.17 or later.
38
41
  // Note: the checked version is the minimum required for Node-API
@@ -47,7 +50,6 @@ errors.assert(vs[0] > 14 || (vs[0] === 14 && vs[1] >= 17),
47
50
  const AqDeqOptions = require('./aqDeqOptions.js');
48
51
  const AqEnqOptions = require('./aqEnqOptions.js');
49
52
  const AqMessage = require('./aqMessage.js');
50
- const protocolUtil = require('./thin/protocol/utils.js');
51
53
  const AqQueue = require('./aqQueue.js');
52
54
  const future = require('./future.js');
53
55
  const traceHandler = require('./traceHandler.js');
@@ -57,12 +59,14 @@ const Lob = require('./lob.js');
57
59
  const Pool = require('./pool.js');
58
60
  const PoolStatistics = require('./poolStatistics.js');
59
61
  const ResultSet = require('./resultset.js');
62
+ const Pipeline = require('./pipeline.js');
60
63
  const settings = require('./settings.js');
61
64
  const SodaDatabase = require('./sodaDatabase.js');
62
65
  const SodaCollection = require('./sodaCollection.js');
63
66
  const SodaDocCursor = require('./sodaDocCursor.js');
64
67
  const SodaDocument = require('./sodaDocument.js');
65
68
  const SodaOperation = require('./sodaOperation.js');
69
+ const EndUserSecurityContext = require('./endUserSecurityContext.js');
66
70
 
67
71
  const poolCache = {};
68
72
  const tempUsedPoolAliases = {};
@@ -131,6 +135,27 @@ function _initializeThinDriver() {
131
135
  require('./thin');
132
136
  }
133
137
 
138
+ // validate external authentication credentials for token and non-token Authentications
139
+ function _validateExternalAuthCredentials(outOptions, inCreatePool, isTokenAuth = false) {
140
+ if (!outOptions.externalAuth) {
141
+ return;
142
+ }
143
+ if (outOptions.password !== undefined) {
144
+ errors.throwErr(isTokenAuth ? errors.ERR_TOKEN_BASED_AUTH
145
+ : errors.ERR_WRONG_CRED_FOR_EXTAUTH);
146
+ }
147
+ if (outOptions.user) {
148
+ if (inCreatePool && !settings.thin) {
149
+ // Thick mode currently does not allow proxy users to be specified
150
+ // during pool creation.
151
+ errors.throwErr(errors.ERR_WRONG_CRED_FOR_EXTAUTH);
152
+ } else if (outOptions.user[0] !== '[' || outOptions.user.slice(-1) !== ']') {
153
+ // username is not enclosed in [].
154
+ errors.throwErr(errors.ERR_WRONG_USER_FORMAT_EXTAUTH_PROXY);
155
+ }
156
+ }
157
+ }
158
+
134
159
  //-----------------------------------------------------------------------------
135
160
  // _verifyOptions()
136
161
  //
@@ -532,10 +557,7 @@ async function _verifyOptions(options, inCreatePool) {
532
557
 
533
558
  // check access token
534
559
  if (options.accessToken !== undefined) {
535
-
536
- // cannot set username or password for token based authentication
537
- errors.assert(outOptions.user === undefined &&
538
- outOptions.password === undefined, errors.ERR_TOKEN_BASED_AUTH);
560
+ _validateExternalAuthCredentials(outOptions, inCreatePool, true);
539
561
 
540
562
  // homogenous (for pool) and externalAuth (both) must be set
541
563
  if (inCreatePool) {
@@ -581,17 +603,7 @@ async function _verifyOptions(options, inCreatePool) {
581
603
  // Check external Auth config.
582
604
  // Allow Session User enclosed in [] for proxy authentication.
583
605
  if (outOptions.token === undefined && outOptions.externalAuth) {
584
- if (outOptions.password) {
585
- errors.throwErr(errors.ERR_WRONG_CRED_FOR_EXTAUTH);
586
- }
587
- if (outOptions.user) {
588
- if (inCreatePool) {
589
- errors.throwErr(errors.ERR_WRONG_CRED_FOR_EXTAUTH);
590
- } else if (outOptions.user[0] !== '[' || outOptions.user.slice(-1) !== ']') {
591
- // username is not enclosed in [].
592
- errors.throwErr(errors.ERR_WRONG_USER_FORMAT_EXTAUTH_PROXY);
593
- }
594
- }
606
+ _validateExternalAuthCredentials(outOptions, inCreatePool);
595
607
  }
596
608
 
597
609
  return outOptions;
@@ -613,15 +625,13 @@ async function createPool(options) {
613
625
  // this will invoke hookFn() written in application side.
614
626
  // for token based auth it will generate access token and save it in options.
615
627
  for (const hookFn of registeredHooks) {
616
- // eslint-disable-next-line no-useless-catch
617
628
  try {
618
629
  await hookFn(options);
619
630
  } catch (error) {
620
631
  errors.throwWrapErr(error, errors.ERR_CALLOUT_FN);
621
632
  }
622
633
  }
623
-
624
- options = await _verifyOptions(options, true);
634
+ options = await _updateUserOptionsFromConnectString(options, true);
625
635
  const sessionCallback = options.sessionCallback;
626
636
  if (typeof sessionCallback === 'function')
627
637
  delete options.sessionCallback;
@@ -684,6 +694,15 @@ async function createPool(options) {
684
694
  pool._impl._connectString = options.connectString;
685
695
  pool._impl._user = options.user;
686
696
  try {
697
+ // registers a callback poolEventReg having 'eventName' and 'arguments of the
698
+ // event' as its arguments. It is passed as part of options while creating impl
699
+ // pool, so that events emitted in impl pool can access the lib pool instance.
700
+ // For now, no argument is passed as args, but can be used later for future metrics.
701
+ options.poolEventReg = ((eventName, ...args) => {
702
+ if (traceHandler.isEnabled()) {
703
+ traceHandler.getTraceInstance()?.[eventName](pool, ...args);
704
+ }
705
+ });
687
706
  await pool._impl.create(options);
688
707
  } finally {
689
708
  if (poolAlias) {
@@ -756,16 +775,14 @@ async function getConnection(a1) {
756
775
  // this will invoke hookFn() written in application side.
757
776
  // for token based auth it will generate access token and save it in options.
758
777
  for (const hookFn of registeredHooks) {
759
- // eslint-disable-next-line no-useless-catch
760
778
  try {
761
779
  await hookFn(options);
762
780
  } catch (error) {
763
781
  errors.throwWrapErr(error, errors.ERR_CALLOUT_FN);
764
782
  }
765
783
  }
766
-
767
784
  // create a standalone connection
768
- options = await _verifyOptions(options, false);
785
+ options = await _updateUserOptionsFromConnectString(options, false);
769
786
  settings.addToOptions(options,
770
787
  "connectionClass",
771
788
  "driverName",
@@ -906,14 +923,11 @@ async function shutdown(a1, a2) {
906
923
  }
907
924
 
908
925
  async function _setConfigParameters(obj, credential, configProvider) {
909
- const configObject = {};
910
926
  const pmSection = 'njs';
911
927
  const params = obj[pmSection];
912
- for (const key in params) {
913
- const val = params[key];
914
- configObject[key] = val;
915
- }
928
+ const configObject = params ? { ...params } : {};
916
929
  configObject.connectString = obj.connect_descriptor;
930
+ configObject.configTTL = obj.config_time_to_live;
917
931
  if (!configObject.connectString)
918
932
  errors.throwErr(errors.ERR_CONFIG_PROVIDER_FAILED_TO_RETRIEVE_CONFIG, 'connect_descriptor must be set');
919
933
 
@@ -947,11 +961,11 @@ async function _retrieveParamValueFromVault(paramObj, credential, configProvider
947
961
  console.log("WARNING: Base64 Encoding in a JSON Password should only be used in development environments");
948
962
  return Buffer.from(paramObj.value, "base64").toString("utf-8");
949
963
  } else if (paramObj.type == "text") {
950
- if (configProvider == 'azurevault' || configProvider == 'ocivault') {
964
+ if (configProvider == 'azurevault' || configProvider == 'ocivault' || configProvider == 'awssecretsmanager') {
951
965
  console.log("WARNING: Plain Text in a JSON Password should only be used in development environments");
952
966
  return paramObj.value;
953
967
  } else
954
- errors.throwErr(errors.ERR_CONFIG_PROVIDER_PARAM_TYPE, 'password type text is only allowed in ocivault and azurevault');
968
+ errors.throwErr(errors.ERR_CONFIG_PROVIDER_PARAM_TYPE, 'password type text is only allowed in ocivault, azurevault and awssecretsmanager');
955
969
  } else if (paramObj.type == "azurevault") {
956
970
  paramMap.set('azuresecreturl', paramObj.value);
957
971
  if (!(configProvider == 'azure' || configProvider == 'azurevault'))
@@ -977,41 +991,47 @@ async function _retrieveParamValueFromVault(paramObj, credential, configProvider
977
991
  args.credential = credential;
978
992
  args.paramMap = paramMap;
979
993
  const vaultReturn = await hookFn(args);
980
- const paramValue = vaultReturn[0];
981
- return paramValue;
982
- } else {
994
+ return vaultReturn[0];
995
+ } else {
983
996
  errors.throwErr(errors.ERR_CONFIG_PROVIDER_PARAM_TYPE, 'password/wallet_location');
984
997
  }
985
998
  }
986
999
  //-----------------------------------------------------------------------------
987
1000
  // _checkConfigProvider()
988
1001
  //
989
- // Look for the config provider in the connection string and retreives
1002
+ // Look for the config provider in the connection string and retrieves
990
1003
  // object stored in the config Provider.
991
1004
  // Returns object based on precedence between input object and the one retrieved
992
1005
  // from Config Provider.
993
1006
  //-----------------------------------------------------------------------------
994
1007
  async function _checkConfigProvider(options) {
995
1008
  // Time for Cache entries to be deleted in milliseconds
996
- const cacheEntriesDuration = settings.configProviderCacheTimeout * 1000;
997
- let secondOpts;
1009
+ let cacheEntriesDuration = settings.configProviderCacheTimeout * 1000;
1010
+ let secondOpts, cachedConfigEntry;
998
1011
  const url = options.connectString || options.connectionString;
999
1012
  if (!url)
1000
1013
  return options;
1001
1014
 
1002
- if (configProviderCache && configProviderCache.has(url) && ((Date.now() - configProviderCache.get(url).timeAdded) < cacheEntriesDuration)) {
1003
- const cacheOpts1 = configProviderCache.get(url).cacheOpts;
1004
- secondOpts = { ...cacheOpts1};
1015
+ if (configProviderCache && (cachedConfigEntry = configProviderCache.get(url))) {
1016
+ const config = cachedConfigEntry.cacheOpts;
1017
+ if (config.configTTL)
1018
+ cacheEntriesDuration = config.configTTL * 1000;
1005
1019
 
1006
- //deobfuscate password
1007
- if (secondOpts.password)
1008
- secondOpts.password = protocolUtil.getDeobfuscatedValue(secondOpts.password.value, secondOpts.password.obfuscatedValue);
1020
+ if ((Date.now() - cachedConfigEntry.timeAdded) < cacheEntriesDuration) {
1021
+ secondOpts = { ...config};
1009
1022
 
1010
- //deobfuscate walletContent
1011
- if (secondOpts.walletContent)
1012
- secondOpts.walletContent = protocolUtil.getDeobfuscatedValue(secondOpts.walletContent.value, secondOpts.walletContent.obfuscatedValue);
1023
+ //deobfuscate password
1024
+ if (secondOpts.password instanceof ObfuscatedValue) {
1025
+ secondOpts.password = secondOpts.password.get();
1026
+ }
1013
1027
 
1014
- } else {
1028
+ //deobfuscate walletContent
1029
+ if (secondOpts.walletContent instanceof ObfuscatedValue) {
1030
+ secondOpts.walletContent = secondOpts.walletContent.get();
1031
+ }
1032
+ }
1033
+ }
1034
+ if (!secondOpts) {
1015
1035
  let parsedUrl = url;
1016
1036
  let urlExtendedPart;
1017
1037
  const baseRegex = new RegExp("^config-(?<provider>[A-Za-z0-9]+)(://)(?<provider_arg>[^?]+)");
@@ -1047,9 +1067,9 @@ async function _checkConfigProvider(options) {
1047
1067
  // obfuscate password & walletcontent and store config in the cache
1048
1068
  const cacheOpts = { ...secondOpts};
1049
1069
  if (secondOpts.password)
1050
- cacheOpts.password = protocolUtil.setObfuscatedValue(secondOpts.password);
1070
+ cacheOpts.password = new ObfuscatedValue(secondOpts.password);
1051
1071
  if (secondOpts.walletContent)
1052
- cacheOpts.walletContent = protocolUtil.setObfuscatedValue(secondOpts.walletContent);
1072
+ cacheOpts.walletContent = new ObfuscatedValue(secondOpts.walletContent);
1053
1073
  configProviderCache.set(url, { cacheOpts, timeAdded: Date.now()});
1054
1074
  } catch (err) {
1055
1075
  errors.throwErr(errors.ERR_CONFIG_PROVIDER_FAILED_TO_RETRIEVE_CONFIG, err.message);
@@ -1101,6 +1121,30 @@ function modifyOptionsPrecedence(cloudConfig, userConfig) {
1101
1121
  return userConfig;
1102
1122
 
1103
1123
  }
1124
+ async function _updateUserOptionsFromConnectString(options, inCreatePool) {
1125
+ let tempOptions;
1126
+ const hasConnectString = options.connectString || options.connectionString;
1127
+ if (!settings.thickModeDSNPassthrough && hasConnectString) {
1128
+ tempOptions = Object.create(Object.getPrototypeOf(options));
1129
+ Object.defineProperties(tempOptions, Object.getOwnPropertyDescriptors(options));
1130
+ const { connectString, resolver } = parserHelpers.getConnectDescriptorFromEZConnect(tempOptions.connectString || tempOptions.connectionString);
1131
+ if (tempOptions.connectString !== undefined) {
1132
+ tempOptions.connectString = connectString;
1133
+ } else if (tempOptions.connectionString != undefined) {
1134
+ tempOptions.connectionString = connectString;
1135
+ }
1136
+
1137
+ if (resolver) parserHelpers.mergeExtendedParams(tempOptions, resolver);
1138
+ } else {
1139
+ tempOptions = options;
1140
+ }
1141
+ options = await _verifyOptions(tempOptions, inCreatePool);
1142
+ if (!settings.thickModeDSNPassthrough && options.connectString) {
1143
+ await parserHelpers.applyConnectStringOverrides(options);
1144
+ }
1145
+ return options;
1146
+ }
1147
+
1104
1148
  //-----------------------------------------------------------------------------
1105
1149
  // startup()
1106
1150
  //
@@ -1169,6 +1213,62 @@ function registerConfigurationProviderHook(configProvider, fn) {
1169
1213
  registeredConfigProviderHooks[configProvider] = fn;
1170
1214
  }
1171
1215
 
1216
+ //-----------------------------------------------------------------------------
1217
+ // enquoteLiteral()
1218
+ //
1219
+ // Returns a quoted SQL literal with embedded single quotes doubled.
1220
+ //-----------------------------------------------------------------------------
1221
+ function enquoteLiteral(value) {
1222
+ errors.assertArgCount(arguments, 1, 1);
1223
+ errors.assertParamValue(typeof value === 'string', 1);
1224
+ return parser.enquoteLiteral(value);
1225
+ }
1226
+
1227
+ //-----------------------------------------------------------------------------
1228
+ // enquoteName()
1229
+ //
1230
+ // Returns a quoted SQL identifier. Embedded double quotes are rejected and the
1231
+ // value is converted to uppercase using locale-independent Unicode rules when
1232
+ // capitalize is true.
1233
+ //-----------------------------------------------------------------------------
1234
+ function enquoteName(name, capitalize = true) {
1235
+ errors.assertArgCount(arguments, 1, 2);
1236
+ errors.assertParamValue(typeof name === 'string', 1);
1237
+ if (arguments.length > 1)
1238
+ errors.assertParamValue(typeof capitalize === 'boolean', 2);
1239
+
1240
+ if (name.includes('"')) {
1241
+ errors.throwErr(errors.ERR_INVALID_SQL_NAME);
1242
+ }
1243
+ return `"${capitalize ? name.toUpperCase() : name}"`;
1244
+ }
1245
+
1246
+ //-----------------------------------------------------------------------------
1247
+ // isQualifiedSqlName()
1248
+ //
1249
+ // Returns whether the trimmed value is a qualified SQL name. Qualified names
1250
+ // are dotted simple SQL names with an optional trailing @ database link, and
1251
+ // the database link name can itself be dotted.
1252
+ //-----------------------------------------------------------------------------
1253
+ function isQualifiedSqlName(name) {
1254
+ errors.assertArgCount(arguments, 1, 1);
1255
+ errors.assertParamValue(typeof name === 'string', 1);
1256
+ const text = name.trim();
1257
+ return parser.parseQualifiedSqlName(text, 0) === text.length;
1258
+ }
1259
+
1260
+ //-----------------------------------------------------------------------------
1261
+ // isSimpleSqlName()
1262
+ //
1263
+ // Returns whether the trimmed value is a single simple SQL name.
1264
+ //-----------------------------------------------------------------------------
1265
+ function isSimpleSqlName(name) {
1266
+ errors.assertArgCount(arguments, 1, 1);
1267
+ errors.assertParamValue(typeof name === 'string', 1);
1268
+ const text = name.trim();
1269
+ return parser.parseSimpleSqlName(text, 0) === text.length;
1270
+ }
1271
+
1172
1272
  // module exports
1173
1273
  module.exports = {
1174
1274
 
@@ -1182,6 +1282,7 @@ module.exports = {
1182
1282
  JsonId: types.JsonId,
1183
1283
  Lob,
1184
1284
  Pool,
1285
+ Pipeline,
1185
1286
  PoolStatistics,
1186
1287
  ResultSet,
1187
1288
  SodaDatabase,
@@ -1192,13 +1293,18 @@ module.exports = {
1192
1293
  SparseVector: types.SparseVector,
1193
1294
  IntervalYM: types.IntervalYM,
1194
1295
  IntervalDS: types.IntervalDS,
1296
+ EndUserSecurityContext,
1195
1297
 
1196
1298
  // top-level functions
1299
+ enquoteLiteral,
1300
+ enquoteName,
1197
1301
  getConnection: nodbUtil.callbackify(nodbUtil.wrapFn(getConnection)),
1198
1302
  createPool: nodbUtil.callbackify(nodbUtil.wrapFn(createPool)),
1199
1303
  getNetworkServiceNames: nodbUtil.callbackify(nodbUtil.wrapFn(getNetworkServiceNames)),
1200
1304
  getPool,
1201
1305
  initOracleClient,
1306
+ isQualifiedSqlName,
1307
+ isSimpleSqlName,
1202
1308
  registerProcessConfigurationHook,
1203
1309
  registerConfigurationProviderHook,
1204
1310
  shutdown: nodbUtil.callbackify(nodbUtil.wrapFn(shutdown)),
@@ -1702,6 +1808,14 @@ module.exports = {
1702
1808
  errors.assertPropValue(Number.isInteger(value) && value >= 0,
1703
1809
  "configProviderCacheTimeout");
1704
1810
  settings.configProviderCacheTimeout = value;
1705
- }
1811
+ },
1706
1812
 
1813
+ get thickModeDSNPassthrough() {
1814
+ return settings.thickModeDSNPassthrough;
1815
+ },
1816
+
1817
+ set thickModeDSNPassthrough(value) {
1818
+ errors.assertPropValue(typeof value === 'boolean', "thickModeDSNPassthrough");
1819
+ settings.thickModeDSNPassthrough = value;
1820
+ },
1707
1821
  };