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.
- package/LICENSE.txt +1 -1
- package/NOTICE.txt +1 -1
- package/README.md +9 -9
- package/build/Release/oracledb-7.0.0-darwin-arm64.node +0 -0
- package/build/Release/oracledb-7.0.0-darwin-arm64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-7.0.0-js-buildinfo.txt +1 -0
- package/build/Release/oracledb-7.0.0-linux-arm64.node +0 -0
- package/build/Release/oracledb-7.0.0-linux-arm64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-7.0.0-linux-x64.node +0 -0
- package/build/Release/oracledb-7.0.0-linux-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-7.0.0-win32-x64.node +0 -0
- package/build/Release/oracledb-7.0.0-win32-x64.node-buildinfo.txt +1 -0
- package/eslint.config.js +39 -0
- package/lib/aqDeqOptions.js +18 -1
- package/lib/aqQueue.js +10 -6
- package/lib/connection.js +418 -39
- package/lib/dbObject.js +25 -4
- package/lib/endUserSecurityContext.js +176 -0
- package/lib/errors.js +99 -8
- package/lib/impl/aqDeqOptions.js +10 -1
- package/lib/impl/connection.js +76 -2
- package/lib/impl/datahandlers/buffer.js +68 -5
- package/lib/impl/datahandlers/oson.js +7 -2
- package/lib/impl/datahandlers/vector.js +25 -5
- package/lib/impl/lob.js +9 -0
- package/lib/impl/parserHelpers.js +443 -0
- package/lib/impl/resultset.js +1 -1
- package/lib/impl/sodaDocument.js +5 -14
- package/lib/lob.js +27 -14
- package/lib/obfuscation.js +97 -0
- package/lib/oracledb.js +163 -49
- package/lib/parser.js +204 -0
- package/lib/pipeline.js +113 -0
- package/lib/pool.js +203 -147
- package/lib/poolStatistics.js +1 -1
- package/lib/resultset.js +42 -21
- package/lib/settings.js +1 -0
- package/lib/sodaCollection.js +12 -8
- package/lib/sodaDatabase.js +35 -8
- package/lib/sodaDocument.js +24 -6
- package/lib/sodaOperation.js +7 -6
- package/lib/thin/aq.js +475 -0
- package/lib/thin/connection.js +518 -54
- package/lib/thin/dbObject.js +7 -1
- package/lib/thin/lob.js +20 -1
- package/lib/thin/pool.js +42 -62
- package/lib/thin/protocol/capabilities.js +21 -4
- package/lib/thin/protocol/constants.js +143 -2
- package/lib/thin/protocol/encryptDecrypt.js +45 -10
- package/lib/thin/protocol/messages/aqArray.js +238 -0
- package/lib/thin/protocol/messages/aqBase.js +305 -0
- package/lib/thin/protocol/messages/aqDeq.js +164 -0
- package/lib/thin/protocol/messages/aqEnq.js +135 -0
- package/lib/thin/protocol/messages/auth.js +18 -28
- package/lib/thin/protocol/messages/base.js +245 -4
- package/lib/thin/protocol/messages/dataType.js +8 -3
- package/lib/thin/protocol/messages/directPathLoadStream.js +377 -0
- package/lib/thin/protocol/messages/directPathOp.js +65 -0
- package/lib/thin/protocol/messages/directPathPrepare.js +158 -0
- package/lib/thin/protocol/messages/endPipeline.js +56 -0
- package/lib/thin/protocol/messages/execute.js +9 -7
- package/lib/thin/protocol/messages/index.js +9 -1
- package/lib/thin/protocol/messages/protocol.js +2 -2
- package/lib/thin/protocol/messages/withData.js +10 -142
- package/lib/thin/protocol/packet.js +120 -28
- package/lib/thin/protocol/protocol.js +110 -25
- package/lib/thin/protocol/utils.js +1 -26
- package/lib/thin/resultSet.js +13 -19
- package/lib/thin/sqlnet/ezConnectResolver.js +2 -2
- package/lib/thin/sqlnet/networkSession.js +63 -41
- package/lib/thin/sqlnet/ntTcp.js +24 -0
- package/lib/thin/sqlnet/nvStrToNvPair.js +50 -25
- package/lib/thin/sqlnet/packet.js +25 -4
- package/lib/thin/sqlnet/paramParser.js +10 -7
- package/lib/thin/statementCache.js +2 -4
- package/lib/traceHandler.js +59 -2
- package/lib/transformer.js +8 -3
- package/lib/types.js +36 -22
- package/lib/util.js +6 -19
- package/lib/version.js +3 -3
- package/package/install.js +5 -5
- package/package/prunebinaries.js +1 -1
- package/package.json +1 -1
- package/plugins/configProviders/awsCommon.js +125 -0
- package/plugins/configProviders/awss3/index.js +138 -0
- package/plugins/configProviders/awssecretsmanager/index.js +147 -0
- package/plugins/configProviders/azure/index.js +7 -5
- package/plugins/token/extensionAzure/index.js +0 -1
- package/plugins/token/extensionOci/index.js +0 -1
- package/build/Release/oracledb-6.9.0-darwin-arm64.node +0 -0
- package/build/Release/oracledb-6.9.0-darwin-arm64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.9.0-darwin-x64.node +0 -0
- package/build/Release/oracledb-6.9.0-darwin-x64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.9.0-js-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.9.0-linux-arm64.node +0 -0
- package/build/Release/oracledb-6.9.0-linux-arm64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.9.0-linux-x64.node +0 -0
- package/build/Release/oracledb-6.9.0-linux-x64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.9.0-win32-x64.node +0 -0
- package/build/Release/oracledb-6.9.0-win32-x64.node-buildinfo.txt +0 -1
package/lib/impl/sodaDocument.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright (c) 2022,
|
|
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
|
-
//
|
|
34
|
+
// getContent()
|
|
35
35
|
//
|
|
36
|
-
// Returns the document content
|
|
36
|
+
// Returns the document content.
|
|
37
37
|
//---------------------------------------------------------------------------
|
|
38
|
-
|
|
39
|
-
errors.throwNotImplemented("getting doc content
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
299
|
+
return this._impl?.getPieceSize();
|
|
287
300
|
}
|
|
288
301
|
|
|
289
302
|
set pieceSize(value) {
|
|
290
|
-
errors.assertPropValue(Number.
|
|
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,
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
981
|
-
|
|
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
|
|
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
|
-
|
|
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 &&
|
|
1003
|
-
const
|
|
1004
|
-
|
|
1015
|
+
if (configProviderCache && (cachedConfigEntry = configProviderCache.get(url))) {
|
|
1016
|
+
const config = cachedConfigEntry.cacheOpts;
|
|
1017
|
+
if (config.configTTL)
|
|
1018
|
+
cacheEntriesDuration = config.configTTL * 1000;
|
|
1005
1019
|
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
secondOpts.password = protocolUtil.getDeobfuscatedValue(secondOpts.password.value, secondOpts.password.obfuscatedValue);
|
|
1020
|
+
if ((Date.now() - cachedConfigEntry.timeAdded) < cacheEntriesDuration) {
|
|
1021
|
+
secondOpts = { ...config};
|
|
1009
1022
|
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1023
|
+
//deobfuscate password
|
|
1024
|
+
if (secondOpts.password instanceof ObfuscatedValue) {
|
|
1025
|
+
secondOpts.password = secondOpts.password.get();
|
|
1026
|
+
}
|
|
1013
1027
|
|
|
1014
|
-
|
|
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 =
|
|
1070
|
+
cacheOpts.password = new ObfuscatedValue(secondOpts.password);
|
|
1051
1071
|
if (secondOpts.walletContent)
|
|
1052
|
-
cacheOpts.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
|
};
|