oracledb 6.7.2 → 6.9.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 +39 -3
- package/build/Release/oracledb-6.9.0-darwin-arm64.node +0 -0
- package/build/Release/oracledb-6.9.0-darwin-arm64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.9.0-darwin-x64.node +0 -0
- package/build/Release/oracledb-6.9.0-darwin-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.9.0-js-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.9.0-linux-arm64.node +0 -0
- package/build/Release/oracledb-6.9.0-linux-arm64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.9.0-linux-x64.node +0 -0
- package/build/Release/oracledb-6.9.0-linux-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.9.0-win32-x64.node +0 -0
- package/build/Release/oracledb-6.9.0-win32-x64.node-buildinfo.txt +1 -0
- package/lib/aqMessage.js +10 -1
- package/lib/configProviders/file.js +72 -0
- package/lib/connection.js +153 -4
- package/lib/dbObject.js +51 -10
- package/lib/errors.js +144 -36
- package/lib/impl/connection.js +24 -1
- package/lib/impl/datahandlers/buffer.js +92 -1
- package/lib/impl/datahandlers/constants.js +2 -0
- package/lib/impl/datahandlers/oson.js +15 -1
- package/lib/impl/datahandlers/vector.js +72 -27
- package/lib/impl/pool.js +10 -1
- package/lib/impl/resultset.js +5 -4
- package/lib/lob.js +9 -1
- package/lib/oracledb.js +209 -20
- package/lib/pool.js +12 -1
- package/lib/poolStatistics.js +3 -1
- package/lib/settings.js +5 -1
- package/lib/thin/connection.js +130 -12
- package/lib/thin/dbObject.js +46 -13
- package/lib/thin/lob.js +2 -3
- package/lib/thin/pool.js +112 -31
- package/lib/thin/protocol/capabilities.js +8 -4
- package/lib/thin/protocol/constants.js +31 -1
- package/lib/thin/protocol/messages/auth.js +42 -6
- package/lib/thin/protocol/messages/base.js +98 -9
- package/lib/thin/protocol/messages/dataType.js +2 -1
- package/lib/thin/protocol/messages/execute.js +46 -4
- package/lib/thin/protocol/messages/fastAuth.js +6 -1
- package/lib/thin/protocol/messages/lobOp.js +5 -22
- package/lib/thin/protocol/messages/logOff.js +0 -1
- package/lib/thin/protocol/messages/sessionRelease.js +0 -1
- package/lib/thin/protocol/messages/transactionSwitch.js +12 -4
- package/lib/thin/protocol/messages/withData.js +10 -1
- package/lib/thin/protocol/packet.js +1 -1
- package/lib/thin/protocol/protocol.js +2 -1
- package/lib/thin/sqlnet/ANO.js +438 -0
- package/lib/thin/sqlnet/connStrategy.js +2 -1
- package/lib/thin/sqlnet/constants.js +5 -1
- package/lib/thin/sqlnet/ezConnectResolver.js +4 -2
- package/lib/thin/sqlnet/navNodes.js +22 -3
- package/lib/thin/sqlnet/networkSession.js +94 -16
- package/lib/thin/sqlnet/ntTcp.js +50 -3
- package/lib/thin/sqlnet/packet.js +32 -4
- package/lib/thin/sqlnet/sessionAtts.js +24 -2
- package/lib/thin/util.js +3 -8
- package/lib/transformer.js +13 -2
- package/lib/types.js +220 -8
- package/lib/util.js +77 -3
- package/lib/version.js +2 -2
- package/package/install.js +3 -3
- package/package/prunebinaries.js +6 -12
- package/package.json +2 -2
- package/{lib/configProviders/azure.js → plugins/configProviders/azure/index.js} +70 -63
- package/plugins/configProviders/azurevault/index.js +84 -0
- package/{lib → plugins}/configProviders/base.js +13 -3
- package/{lib/configProviders/ociobject.js → plugins/configProviders/ociobject/index.js} +43 -78
- package/plugins/configProviders/ocivault/index.js +100 -0
- package/plugins/token/extensionAzure/index.js +101 -0
- package/plugins/token/extensionOci/index.js +210 -0
- package/build/Release/oracledb-6.7.2-darwin-arm64.node +0 -0
- package/build/Release/oracledb-6.7.2-darwin-arm64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.7.2-darwin-x64.node +0 -0
- package/build/Release/oracledb-6.7.2-darwin-x64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.7.2-js-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.7.2-linux-arm64.node +0 -0
- package/build/Release/oracledb-6.7.2-linux-arm64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.7.2-linux-x64.node +0 -0
- package/build/Release/oracledb-6.7.2-linux-x64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.7.2-win32-x64.node +0 -0
- package/build/Release/oracledb-6.7.2-win32-x64.node-buildinfo.txt +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright (c) 2024, Oracle and/or its affiliates.
|
|
1
|
+
// Copyright (c) 2024, 2025, Oracle and/or its affiliates.
|
|
2
2
|
|
|
3
3
|
//-----------------------------------------------------------------------------
|
|
4
4
|
//
|
|
@@ -30,6 +30,7 @@ const { BaseBuffer, GrowableBuffer } = require('./buffer.js');
|
|
|
30
30
|
const { Buffer } = require('buffer');
|
|
31
31
|
const constants = require("./constants.js");
|
|
32
32
|
const errors = require("../../errors.js");
|
|
33
|
+
const types = require("../../types.js");
|
|
33
34
|
|
|
34
35
|
/**
|
|
35
36
|
* Class used for decoding
|
|
@@ -50,68 +51,83 @@ class VectorDecoder extends BaseBuffer {
|
|
|
50
51
|
errors.throwErr(errors.ERR_UNEXPECTED_DATA,
|
|
51
52
|
Buffer.from([magicByte]).toString('hex'));
|
|
52
53
|
const version = this.readUInt8();
|
|
53
|
-
if (version > constants.
|
|
54
|
+
if (version > constants.TNS_VECTOR_VERSION_WITH_SPARSE)
|
|
54
55
|
errors.throwErr(errors.ERR_VECTOR_VERSION_NOT_SUPPORTED, version);
|
|
55
56
|
const flags = this.readUInt16BE();
|
|
56
57
|
const vectorFormat = this.readUInt8();
|
|
57
58
|
let numElements = this.readUInt32BE();
|
|
58
|
-
let elementSize,
|
|
59
|
+
let elementSize, value, sparseValue;
|
|
60
|
+
|
|
61
|
+
// For binary vector, NORM will never be present but space for NORM is reserved to keep
|
|
62
|
+
// same header lengh across the different vector formats.
|
|
63
|
+
if (vectorFormat === constants.VECTOR_FORMAT_BINARY || flags & constants.TNS_VECTOR_FLAG_NORM)
|
|
64
|
+
this.skipBytes(8);
|
|
65
|
+
|
|
66
|
+
let sparseFormat;
|
|
67
|
+
if (flags & constants.TNS_VECTOR_FLAG_SPARSE) {
|
|
68
|
+
sparseFormat = true;
|
|
69
|
+
sparseValue = {};
|
|
70
|
+
sparseValue.numDimensions = numElements; // vector dimensions.
|
|
71
|
+
numElements = this.readUInt16BE(); // actual elements.
|
|
72
|
+
sparseValue.indices = new Uint32Array(numElements);
|
|
73
|
+
for (let i = 0; i < numElements; i++) {
|
|
74
|
+
sparseValue.indices[i] = this.readUInt32BE();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
59
78
|
if (vectorFormat === constants.VECTOR_FORMAT_FLOAT32) {
|
|
60
79
|
elementSize = 4;
|
|
61
|
-
|
|
80
|
+
value = new Float32Array(numElements);
|
|
62
81
|
} else if (vectorFormat === constants.VECTOR_FORMAT_FLOAT64) {
|
|
63
82
|
elementSize = 8;
|
|
64
|
-
|
|
83
|
+
value = new Float64Array(numElements);
|
|
65
84
|
} else if (vectorFormat === constants.VECTOR_FORMAT_INT8) {
|
|
66
85
|
elementSize = 1;
|
|
67
|
-
|
|
86
|
+
value = new Int8Array(numElements);
|
|
68
87
|
} else if (vectorFormat === constants.VECTOR_FORMAT_BINARY) {
|
|
69
88
|
elementSize = 1;
|
|
70
89
|
// The number of dimensions are assumed to be multiple of 8.
|
|
71
90
|
numElements = numElements / 8;
|
|
72
|
-
|
|
91
|
+
value = new Uint8Array(numElements);
|
|
73
92
|
} else {
|
|
74
93
|
errors.throwErr(errors.ERR_VECTOR_FORMAT_NOT_SUPPORTED, vectorFormat);
|
|
75
94
|
}
|
|
76
95
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
this.skipBytes(8);
|
|
96
|
+
if (sparseFormat) {
|
|
97
|
+
sparseValue.values = value;
|
|
98
|
+
}
|
|
81
99
|
|
|
82
100
|
// parse data
|
|
101
|
+
let res;
|
|
83
102
|
for (let i = 0; i < numElements; i++) {
|
|
84
103
|
const buf = this.readBytes(elementSize);
|
|
85
104
|
if (vectorFormat === constants.VECTOR_FORMAT_FLOAT32) {
|
|
86
|
-
|
|
105
|
+
res = this.parseBinaryFloat(buf);
|
|
87
106
|
} else if (vectorFormat === constants.VECTOR_FORMAT_FLOAT64) {
|
|
88
|
-
|
|
107
|
+
res = this.parseBinaryDouble(buf);
|
|
89
108
|
} else {
|
|
90
|
-
|
|
109
|
+
res = buf[0];
|
|
91
110
|
}
|
|
111
|
+
value[i] = res;
|
|
92
112
|
}
|
|
93
113
|
|
|
94
|
-
return
|
|
114
|
+
return sparseFormat ? types.SparseVector.create(sparseValue) : value;
|
|
95
115
|
}
|
|
96
116
|
|
|
97
117
|
}
|
|
98
118
|
|
|
99
119
|
class VectorEncoder extends GrowableBuffer {
|
|
100
120
|
|
|
101
|
-
|
|
102
|
-
//
|
|
103
|
-
//
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
// determine some basic information about the vector
|
|
109
|
-
let vectorFormat = constants.VECTOR_FORMAT_FLOAT32;
|
|
110
|
-
let writeFn = this.writeBinaryFloat.bind(this);
|
|
121
|
+
// Writes Header from value.
|
|
122
|
+
// It returns function to serialize the value.
|
|
123
|
+
// sparseVal is provided for SparseVector.
|
|
124
|
+
_updateVectorHeader(value, sparseVal) {
|
|
125
|
+
let flags = constants.TNS_VECTOR_FLAG_NORMSRC
|
|
126
|
+
| constants.TNS_VECTOR_FLAG_NORM; // NORM is present and reserve space.
|
|
111
127
|
let numElements = value.length;
|
|
112
128
|
let vectorVersion = constants.TNS_VECTOR_VERSION_BASE;
|
|
113
|
-
let
|
|
114
|
-
|
|
129
|
+
let vectorFormat = constants.VECTOR_FORMAT_FLOAT32;
|
|
130
|
+
let writeFn = this.writeBinaryFloat.bind(this);
|
|
115
131
|
|
|
116
132
|
if (Array.isArray(value) || value instanceof Float64Array) {
|
|
117
133
|
vectorFormat = constants.VECTOR_FORMAT_FLOAT64;
|
|
@@ -127,6 +143,11 @@ class VectorEncoder extends GrowableBuffer {
|
|
|
127
143
|
flags = constants.TNS_VECTOR_FLAG_NORMSRC; // only space is reserved.
|
|
128
144
|
writeFn = this.writeUInt8.bind(this);
|
|
129
145
|
}
|
|
146
|
+
if (sparseVal && sparseVal instanceof types.SparseVector) {
|
|
147
|
+
vectorVersion = constants.TNS_VECTOR_VERSION_WITH_SPARSE;
|
|
148
|
+
numElements = sparseVal.numDimensions;
|
|
149
|
+
flags |= constants.TNS_VECTOR_FLAG_SPARSE;
|
|
150
|
+
}
|
|
130
151
|
|
|
131
152
|
// write header
|
|
132
153
|
this.writeUInt8(constants.TNS_VECTOR_MAGIC_BYTE);
|
|
@@ -135,6 +156,30 @@ class VectorEncoder extends GrowableBuffer {
|
|
|
135
156
|
this.writeUInt8(vectorFormat);
|
|
136
157
|
this.writeUInt32BE(numElements);
|
|
137
158
|
this.reserveBytes(8);
|
|
159
|
+
return writeFn;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
//---------------------------------------------------------------------------
|
|
163
|
+
// encode()
|
|
164
|
+
//
|
|
165
|
+
// Encodes the value as OSON and returns a buffer containing the OSON bytes.
|
|
166
|
+
//---------------------------------------------------------------------------
|
|
167
|
+
encode(value) {
|
|
168
|
+
let writeFn;
|
|
169
|
+
|
|
170
|
+
if (value instanceof types.SparseVector) {
|
|
171
|
+
writeFn = this._updateVectorHeader(value.values, value);
|
|
172
|
+
const numElements = value.indices.length;
|
|
173
|
+
this.writeUInt16BE(numElements);
|
|
174
|
+
|
|
175
|
+
// Write indices
|
|
176
|
+
value.indices.forEach((element) => {
|
|
177
|
+
this.writeUInt32BE(element);
|
|
178
|
+
});
|
|
179
|
+
value = value.values;
|
|
180
|
+
} else {
|
|
181
|
+
writeFn = this._updateVectorHeader(value);
|
|
182
|
+
}
|
|
138
183
|
|
|
139
184
|
// write data
|
|
140
185
|
value.forEach((element) => {
|
package/lib/impl/pool.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright (c) 2022, Oracle and/or its affiliates.
|
|
1
|
+
// Copyright (c) 2022, 2025, Oracle and/or its affiliates.
|
|
2
2
|
|
|
3
3
|
//-----------------------------------------------------------------------------
|
|
4
4
|
//
|
|
@@ -165,6 +165,15 @@ class PoolImpl {
|
|
|
165
165
|
errors.throwNotImplemented("getting the pool timeout");
|
|
166
166
|
}
|
|
167
167
|
|
|
168
|
+
//---------------------------------------------------------------------------
|
|
169
|
+
// getMaxLifetimeSession()
|
|
170
|
+
//
|
|
171
|
+
// Returns the pool max lifetime for a session.
|
|
172
|
+
//---------------------------------------------------------------------------
|
|
173
|
+
getMaxLifetimeSession() {
|
|
174
|
+
errors.throwNotImplemented("getting the pool max lifetime");
|
|
175
|
+
}
|
|
176
|
+
|
|
168
177
|
//---------------------------------------------------------------------------
|
|
169
178
|
// getStmtCacheSize()
|
|
170
179
|
//
|
package/lib/impl/resultset.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
|
//
|
|
@@ -43,8 +43,9 @@ class ResultSetImpl extends BaseImpl {
|
|
|
43
43
|
// _determineFetchType()
|
|
44
44
|
//
|
|
45
45
|
// Determine the fetch type to use for the specified metadata.
|
|
46
|
+
// Param rowsetMetaData includes metadata of all the columns fetched.
|
|
46
47
|
//---------------------------------------------------------------------------
|
|
47
|
-
_determineFetchType(metadata, options) {
|
|
48
|
+
_determineFetchType(metadata, options, rowsetMetaData) {
|
|
48
49
|
|
|
49
50
|
// clear any previous fetch type and converter functions that may have been
|
|
50
51
|
// retained
|
|
@@ -54,7 +55,7 @@ class ResultSetImpl extends BaseImpl {
|
|
|
54
55
|
// if a fetch type handler is specified, call it; if no value (undefined)
|
|
55
56
|
// is returned, the normal processing takes place
|
|
56
57
|
if (options.fetchTypeHandler) {
|
|
57
|
-
const result = options.fetchTypeHandler(metadata);
|
|
58
|
+
const result = options.fetchTypeHandler(metadata, rowsetMetaData);
|
|
58
59
|
if (result !== undefined) {
|
|
59
60
|
errors.assert(typeof result === 'object',
|
|
60
61
|
errors.ERR_FETCH_TYPE_HANDLER_RETURN_VALUE);
|
|
@@ -232,7 +233,7 @@ class ResultSetImpl extends BaseImpl {
|
|
|
232
233
|
info.dbTypeClass = cls;
|
|
233
234
|
}
|
|
234
235
|
nodbUtil.addTypeProperties(info, "dbType");
|
|
235
|
-
this._determineFetchType(info, options);
|
|
236
|
+
this._determineFetchType(info, options, metaData);
|
|
236
237
|
if (info.fetchType === types.DB_TYPE_CURSOR) {
|
|
237
238
|
this.nestedCursorIndices.push(i);
|
|
238
239
|
} else if (info.fetchType === types.DB_TYPE_CLOB ||
|
package/lib/lob.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright (c) 2016,
|
|
1
|
+
// Copyright (c) 2016, 2025, Oracle and/or its affiliates.
|
|
2
2
|
|
|
3
3
|
//-----------------------------------------------------------------------------
|
|
4
4
|
//
|
|
@@ -246,6 +246,14 @@ class Lob extends Duplex {
|
|
|
246
246
|
this._checkIsBfile();
|
|
247
247
|
errors.assertArgCount(arguments, 1, 1);
|
|
248
248
|
errors.assertParamValue(nodbUtil.isObject(a1), 1);
|
|
249
|
+
errors.assertParamValue(Object.hasOwn(a1, "dirName"), 1);
|
|
250
|
+
errors.assertParamValue(Object.hasOwn(a1, "fileName"), 1);
|
|
251
|
+
errors.assertPropValue(
|
|
252
|
+
a1.dirName != "" && a1.dirName != null, "dirName"
|
|
253
|
+
);
|
|
254
|
+
errors.assertPropValue(
|
|
255
|
+
a1.fileName != "" && a1.fileName != null, "fileName"
|
|
256
|
+
);
|
|
249
257
|
this._impl.setDirFileName(a1);
|
|
250
258
|
}
|
|
251
259
|
|
package/lib/oracledb.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright (c) 2015,
|
|
1
|
+
// Copyright (c) 2015, 2025, Oracle and/or its affiliates.
|
|
2
2
|
|
|
3
3
|
//-----------------------------------------------------------------------------
|
|
4
4
|
//
|
|
@@ -34,15 +34,15 @@ const impl = require('./impl');
|
|
|
34
34
|
const process = require('process');
|
|
35
35
|
const util = require('util');
|
|
36
36
|
|
|
37
|
-
// This version of node-oracledb works with Node.js 14.
|
|
37
|
+
// This version of node-oracledb works with Node.js 14.17 or later.
|
|
38
38
|
// Note: the checked version is the minimum required for Node-API
|
|
39
39
|
// compatibility. When new Node.js versions are released, older Node.js
|
|
40
40
|
// versions are dropped from the node-oracledb test plan.
|
|
41
41
|
//
|
|
42
42
|
// Keep this code in sync with package/install.js
|
|
43
43
|
const vs = process.version.substring(1).split(".").map(Number);
|
|
44
|
-
errors.assert(vs[0] > 14 || (vs[0] === 14 && vs[1] >=
|
|
45
|
-
errors.ERR_NODE_TOO_OLD, nodbUtil.PACKAGE_JSON_VERSION, "14.
|
|
44
|
+
errors.assert(vs[0] > 14 || (vs[0] === 14 && vs[1] >= 17),
|
|
45
|
+
errors.ERR_NODE_TOO_OLD, nodbUtil.PACKAGE_JSON_VERSION, "14.17");
|
|
46
46
|
|
|
47
47
|
const AqDeqOptions = require('./aqDeqOptions.js');
|
|
48
48
|
const AqEnqOptions = require('./aqEnqOptions.js');
|
|
@@ -67,6 +67,8 @@ const SodaOperation = require('./sodaOperation.js');
|
|
|
67
67
|
const poolCache = {};
|
|
68
68
|
const tempUsedPoolAliases = {};
|
|
69
69
|
const defaultPoolAlias = 'default';
|
|
70
|
+
const registeredHooks = [];
|
|
71
|
+
const registeredConfigProviderHooks = new Map();
|
|
70
72
|
let configProviderCache;
|
|
71
73
|
|
|
72
74
|
// save arguments for call to initOracleClient()
|
|
@@ -188,6 +190,18 @@ async function _verifyOptions(options, inCreatePool) {
|
|
|
188
190
|
"walletLocation");
|
|
189
191
|
outOptions.walletLocation = options.walletLocation;
|
|
190
192
|
}
|
|
193
|
+
if (options.networkCompression !== undefined) {
|
|
194
|
+
errors.assertParamPropValue(typeof options.networkCompression === 'boolean', 1,
|
|
195
|
+
"networkCompression");
|
|
196
|
+
outOptions.networkCompression = options.networkCompression;
|
|
197
|
+
outOptions.networkCompressionLevels = [];
|
|
198
|
+
outOptions.networkCompressionLevels.push('high');
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
if (options.networkCompressionThreshold !== undefined) {
|
|
202
|
+
errors.assertParamPropValue(Number.isInteger(options.networkCompressionThreshold), 1, "networkCompressionThreshold");
|
|
203
|
+
outOptions.networkCompressionThreshold = options.networkCompressionThreshold;
|
|
204
|
+
}
|
|
191
205
|
|
|
192
206
|
//wallet content must be a string
|
|
193
207
|
if (options.walletContent !== undefined) {
|
|
@@ -362,6 +376,22 @@ async function _verifyOptions(options, inCreatePool) {
|
|
|
362
376
|
outOptions.terminal = options.terminal;
|
|
363
377
|
}
|
|
364
378
|
|
|
379
|
+
// useSNI must be a boolean
|
|
380
|
+
if (options.useSNI !== undefined) {
|
|
381
|
+
errors.assertParamPropValue(typeof options.useSNI === 'boolean', 1,
|
|
382
|
+
"useSNI");
|
|
383
|
+
outOptions.useSNI = options.useSNI;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// appContext must be an array of array values. The element arrays should
|
|
387
|
+
// have 3 string values (namespace, name and value).
|
|
388
|
+
if (options.appContext !== undefined) {
|
|
389
|
+
const value = options.appContext;
|
|
390
|
+
errors.assertParamPropValue(nodbUtil.isAppContext(value), 1,
|
|
391
|
+
"appContext");
|
|
392
|
+
outOptions.appContext = options.appContext;
|
|
393
|
+
}
|
|
394
|
+
|
|
365
395
|
// check pool specific options
|
|
366
396
|
if (inCreatePool) {
|
|
367
397
|
|
|
@@ -415,6 +445,13 @@ async function _verifyOptions(options, inCreatePool) {
|
|
|
415
445
|
outOptions.poolPingTimeout = options.poolPingTimeout;
|
|
416
446
|
}
|
|
417
447
|
|
|
448
|
+
// maxLifeTime must be an unsigned integer
|
|
449
|
+
if (options.maxLifetimeSession !== undefined) {
|
|
450
|
+
errors.assertParamPropValue(Number.isInteger(options.maxLifetimeSession) &&
|
|
451
|
+
options.maxLifetimeSession >= 0, 1, "maxLifetimeSession");
|
|
452
|
+
outOptions.maxLifetimeSession = options.maxLifetimeSession;
|
|
453
|
+
}
|
|
454
|
+
|
|
418
455
|
// homogeneous must be a boolean (and defaults to True)
|
|
419
456
|
outOptions.homogeneous = true;
|
|
420
457
|
if (options.homogeneous !== undefined) {
|
|
@@ -513,9 +550,13 @@ async function _verifyOptions(options, inCreatePool) {
|
|
|
513
550
|
if (typeof options.accessToken === 'function') {
|
|
514
551
|
outOptions.accessTokenFn = options.accessToken;
|
|
515
552
|
outOptions.accessTokenConfig = options.accessTokenConfig;
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
553
|
+
try {
|
|
554
|
+
accessToken = await options.accessToken(false, outOptions.accessTokenConfig);
|
|
555
|
+
if (!nodbUtil.isTokenValid(accessToken)) {
|
|
556
|
+
accessToken = await options.accessToken(true, outOptions.accessTokenConfig);
|
|
557
|
+
}
|
|
558
|
+
} catch (error) {
|
|
559
|
+
errors.throwWrapErr(error, errors.ERR_ACCESS_TOKEN);
|
|
519
560
|
}
|
|
520
561
|
} else {
|
|
521
562
|
accessToken = options.accessToken;
|
|
@@ -568,6 +609,18 @@ async function createPool(options) {
|
|
|
568
609
|
// check arguments
|
|
569
610
|
errors.assertArgCount(arguments, 1, 1);
|
|
570
611
|
errors.assertParamValue(nodbUtil.isObject(options), 1);
|
|
612
|
+
|
|
613
|
+
// this will invoke hookFn() written in application side.
|
|
614
|
+
// for token based auth it will generate access token and save it in options.
|
|
615
|
+
for (const hookFn of registeredHooks) {
|
|
616
|
+
// eslint-disable-next-line no-useless-catch
|
|
617
|
+
try {
|
|
618
|
+
await hookFn(options);
|
|
619
|
+
} catch (error) {
|
|
620
|
+
errors.throwWrapErr(error, errors.ERR_CALLOUT_FN);
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
|
|
571
624
|
options = await _verifyOptions(options, true);
|
|
572
625
|
const sessionCallback = options.sessionCallback;
|
|
573
626
|
if (typeof sessionCallback === 'function')
|
|
@@ -700,6 +753,17 @@ async function getConnection(a1) {
|
|
|
700
753
|
return await pool.getConnection(options);
|
|
701
754
|
}
|
|
702
755
|
|
|
756
|
+
// this will invoke hookFn() written in application side.
|
|
757
|
+
// for token based auth it will generate access token and save it in options.
|
|
758
|
+
for (const hookFn of registeredHooks) {
|
|
759
|
+
// eslint-disable-next-line no-useless-catch
|
|
760
|
+
try {
|
|
761
|
+
await hookFn(options);
|
|
762
|
+
} catch (error) {
|
|
763
|
+
errors.throwWrapErr(error, errors.ERR_CALLOUT_FN);
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
|
|
703
767
|
// create a standalone connection
|
|
704
768
|
options = await _verifyOptions(options, false);
|
|
705
769
|
settings.addToOptions(options,
|
|
@@ -841,6 +905,84 @@ async function shutdown(a1, a2) {
|
|
|
841
905
|
await conn.close();
|
|
842
906
|
}
|
|
843
907
|
|
|
908
|
+
async function _setConfigParameters(obj, credential, configProvider) {
|
|
909
|
+
const configObject = {};
|
|
910
|
+
const pmSection = 'njs';
|
|
911
|
+
const params = obj[pmSection];
|
|
912
|
+
for (const key in params) {
|
|
913
|
+
const val = params[key];
|
|
914
|
+
configObject[key] = val;
|
|
915
|
+
}
|
|
916
|
+
configObject.connectString = obj.connect_descriptor;
|
|
917
|
+
if (!configObject.connectString)
|
|
918
|
+
errors.throwErr(errors.ERR_CONFIG_PROVIDER_FAILED_TO_RETRIEVE_CONFIG, 'connect_descriptor must be set');
|
|
919
|
+
|
|
920
|
+
configObject.user = obj.user;
|
|
921
|
+
if (obj.password) {
|
|
922
|
+
configObject.password = await _retrieveParamValueFromVault(obj['password'], credential, configProvider);
|
|
923
|
+
}
|
|
924
|
+
if (obj.wallet_location) {
|
|
925
|
+
// retrieve wallet_location
|
|
926
|
+
configObject.walletContent = await _retrieveParamValueFromVault(obj['wallet_location'], credential, configProvider);
|
|
927
|
+
//only Pem file supported
|
|
928
|
+
if (!nodbUtil.isPemFile(configObject.walletContent))
|
|
929
|
+
errors.throwErr(errors.ERR_WALLET_TYPE_NOT_SUPPORTED);
|
|
930
|
+
}
|
|
931
|
+
return configObject;
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
async function _retrieveParamValueFromVault(paramObj, credential, configProvider) {
|
|
935
|
+
const paramMap = new Map();
|
|
936
|
+
const auth = paramObj.authentication;
|
|
937
|
+
if (auth) {
|
|
938
|
+
for (const key in auth) {
|
|
939
|
+
if (key == 'method')
|
|
940
|
+
paramMap.set('authentication', auth[key]);
|
|
941
|
+
const val = auth[key];
|
|
942
|
+
paramMap.set(key.toLowerCase(), val);
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
const args = {};
|
|
946
|
+
if (paramObj.type == "base64") {
|
|
947
|
+
console.log("WARNING: Base64 Encoding in a JSON Password should only be used in development environments");
|
|
948
|
+
return Buffer.from(paramObj.value, "base64").toString("utf-8");
|
|
949
|
+
} else if (paramObj.type == "text") {
|
|
950
|
+
if (configProvider == 'azurevault' || configProvider == 'ocivault') {
|
|
951
|
+
console.log("WARNING: Plain Text in a JSON Password should only be used in development environments");
|
|
952
|
+
return paramObj.value;
|
|
953
|
+
} else
|
|
954
|
+
errors.throwErr(errors.ERR_CONFIG_PROVIDER_PARAM_TYPE, 'password type text is only allowed in ocivault and azurevault');
|
|
955
|
+
} else if (paramObj.type == "azurevault") {
|
|
956
|
+
paramMap.set('azuresecreturl', paramObj.value);
|
|
957
|
+
if (!(configProvider == 'azure' || configProvider == 'azurevault'))
|
|
958
|
+
credential = null;
|
|
959
|
+
const hookFn = registeredConfigProviderHooks['azurevault'];
|
|
960
|
+
if (hookFn == undefined)
|
|
961
|
+
errors.throwErr(errors.ERR_REGISTER_HOOKFN_CONFIGPROVIDER, 'azurevault');
|
|
962
|
+
args.credential = credential;
|
|
963
|
+
args.paramMap = paramMap;
|
|
964
|
+
const vaultReturn = await hookFn(args);
|
|
965
|
+
const paramValue = vaultReturn[0];
|
|
966
|
+
return paramValue;
|
|
967
|
+
|
|
968
|
+
} else if (paramObj.type == "ocivault") {
|
|
969
|
+
|
|
970
|
+
paramMap.set('ocidvault', paramObj.value);
|
|
971
|
+
if (!(configProvider == 'ociobject' || configProvider == 'ocivault'))
|
|
972
|
+
credential = null;
|
|
973
|
+
const hookFn = registeredConfigProviderHooks['ocivault'];
|
|
974
|
+
if (hookFn == undefined)
|
|
975
|
+
errors.throwErr(errors.ERR_REGISTER_HOOKFN_CONFIGPROVIDER, 'ocivault');
|
|
976
|
+
const args = {};
|
|
977
|
+
args.credential = credential;
|
|
978
|
+
args.paramMap = paramMap;
|
|
979
|
+
const vaultReturn = await hookFn(args);
|
|
980
|
+
const paramValue = vaultReturn[0];
|
|
981
|
+
return paramValue;
|
|
982
|
+
} else {
|
|
983
|
+
errors.throwErr(errors.ERR_CONFIG_PROVIDER_PARAM_TYPE, 'password/wallet_location');
|
|
984
|
+
}
|
|
985
|
+
}
|
|
844
986
|
//-----------------------------------------------------------------------------
|
|
845
987
|
// _checkConfigProvider()
|
|
846
988
|
//
|
|
@@ -881,23 +1023,27 @@ async function _checkConfigProvider(options) {
|
|
|
881
1023
|
if (match) {
|
|
882
1024
|
const provider = match.groups.provider;
|
|
883
1025
|
const provider_arg = match.groups.provider_arg;
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
try {
|
|
892
|
-
configProvider.init();
|
|
893
|
-
} catch (err) {
|
|
894
|
-
errors.throwErr(errors.ERR_CONFIG_PROVIDER_LOAD_FAILED, err.message);
|
|
895
|
-
}
|
|
1026
|
+
const hookFn = registeredConfigProviderHooks[provider];
|
|
1027
|
+
if (hookFn == undefined)
|
|
1028
|
+
errors.throwErr(errors.ERR_REGISTER_HOOKFN_CONFIGPROVIDER, provider);
|
|
1029
|
+
const args = {};
|
|
1030
|
+
args.provider_arg = provider_arg;
|
|
1031
|
+
args.urlExtendedPart = urlExtendedPart;
|
|
1032
|
+
|
|
896
1033
|
try {
|
|
1034
|
+
// hookFn returns an array with first element as the config stored in the configProvider
|
|
1035
|
+
// second being the credential to the configProvider
|
|
1036
|
+
const configProviderReturn = await hookFn(args);
|
|
1037
|
+
secondOpts = configProviderReturn[0];
|
|
897
1038
|
if (!configProviderCache) {
|
|
898
1039
|
configProviderCache = new Map();
|
|
899
1040
|
}
|
|
900
|
-
|
|
1041
|
+
if (!secondOpts) {
|
|
1042
|
+
errors.throwErr(errors.ERR_CONFIG_PROVIDER_FAILED_TO_RETRIEVE_CONFIG, 'no configuration found in ' + provider);
|
|
1043
|
+
}
|
|
1044
|
+
if (provider != 'azure')
|
|
1045
|
+
secondOpts = await _setConfigParameters(secondOpts, configProviderReturn[1], provider);
|
|
1046
|
+
|
|
901
1047
|
// obfuscate password & walletcontent and store config in the cache
|
|
902
1048
|
const cacheOpts = { ...secondOpts};
|
|
903
1049
|
if (secondOpts.password)
|
|
@@ -998,6 +1144,31 @@ async function startup(a1, a2) {
|
|
|
998
1144
|
await conn.close();
|
|
999
1145
|
}
|
|
1000
1146
|
|
|
1147
|
+
//-----------------------------------------------------------------------------
|
|
1148
|
+
// registerProcessConfigurationHook()
|
|
1149
|
+
//
|
|
1150
|
+
// Registers extension modules and registered modules will be called and
|
|
1151
|
+
// executed during pool and standalone connection creation.
|
|
1152
|
+
//-----------------------------------------------------------------------------
|
|
1153
|
+
function registerProcessConfigurationHook(fn) {
|
|
1154
|
+
errors.assertArgCount(arguments, 1, 1);
|
|
1155
|
+
errors.assertParamValue(typeof fn === 'function', 1);
|
|
1156
|
+
registeredHooks.push(fn);
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1159
|
+
//-----------------------------------------------------------------------------
|
|
1160
|
+
// registerConfigurationProviderHook()
|
|
1161
|
+
//
|
|
1162
|
+
// Registers Configuration Provider plugin modules and registered modules will
|
|
1163
|
+
// be called and executed during pool and standalone connection creation.
|
|
1164
|
+
//-----------------------------------------------------------------------------
|
|
1165
|
+
function registerConfigurationProviderHook(configProvider, fn) {
|
|
1166
|
+
errors.assertArgCount(arguments, 2, 2);
|
|
1167
|
+
errors.assertParamValue(typeof fn === 'function', 1);
|
|
1168
|
+
errors.assertParamValue(typeof configProvider === 'string', 1);
|
|
1169
|
+
registeredConfigProviderHooks[configProvider] = fn;
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1001
1172
|
// module exports
|
|
1002
1173
|
module.exports = {
|
|
1003
1174
|
|
|
@@ -1018,6 +1189,9 @@ module.exports = {
|
|
|
1018
1189
|
SodaDocCursor,
|
|
1019
1190
|
SodaDocument,
|
|
1020
1191
|
SodaOperation,
|
|
1192
|
+
SparseVector: types.SparseVector,
|
|
1193
|
+
IntervalYM: types.IntervalYM,
|
|
1194
|
+
IntervalDS: types.IntervalDS,
|
|
1021
1195
|
|
|
1022
1196
|
// top-level functions
|
|
1023
1197
|
getConnection: nodbUtil.callbackify(nodbUtil.wrapFn(getConnection)),
|
|
@@ -1025,6 +1199,8 @@ module.exports = {
|
|
|
1025
1199
|
getNetworkServiceNames: nodbUtil.callbackify(nodbUtil.wrapFn(getNetworkServiceNames)),
|
|
1026
1200
|
getPool,
|
|
1027
1201
|
initOracleClient,
|
|
1202
|
+
registerProcessConfigurationHook,
|
|
1203
|
+
registerConfigurationProviderHook,
|
|
1028
1204
|
shutdown: nodbUtil.callbackify(nodbUtil.wrapFn(shutdown)),
|
|
1029
1205
|
startup: nodbUtil.callbackify(nodbUtil.wrapFn(startup)),
|
|
1030
1206
|
|
|
@@ -1269,6 +1445,10 @@ module.exports = {
|
|
|
1269
1445
|
return settings.fetchTypeHandler;
|
|
1270
1446
|
},
|
|
1271
1447
|
|
|
1448
|
+
get dbObjectTypeHandler() {
|
|
1449
|
+
return settings.dbObjectTypeHandler;
|
|
1450
|
+
},
|
|
1451
|
+
|
|
1272
1452
|
get lobPrefetchSize() {
|
|
1273
1453
|
return settings.lobPrefetchSize;
|
|
1274
1454
|
},
|
|
@@ -1329,6 +1509,7 @@ module.exports = {
|
|
|
1329
1509
|
return settings.configProviderCacheTimeout;
|
|
1330
1510
|
},
|
|
1331
1511
|
|
|
1512
|
+
|
|
1332
1513
|
get thin() {
|
|
1333
1514
|
return settings.thin;
|
|
1334
1515
|
},
|
|
@@ -1413,6 +1594,13 @@ module.exports = {
|
|
|
1413
1594
|
settings.fetchTypeHandler = value;
|
|
1414
1595
|
},
|
|
1415
1596
|
|
|
1597
|
+
set dbObjectTypeHandler(value) {
|
|
1598
|
+
if (value !== undefined) {
|
|
1599
|
+
errors.assertPropValue(typeof value === 'function', "dbObjectTypeHandler");
|
|
1600
|
+
}
|
|
1601
|
+
settings.dbObjectTypeHandler = value;
|
|
1602
|
+
},
|
|
1603
|
+
|
|
1416
1604
|
set lobPrefetchSize(value) {
|
|
1417
1605
|
errors.assertPropValue(Number.isInteger(value) && value >= 0,
|
|
1418
1606
|
"lobPrefetchSize");
|
|
@@ -1509,6 +1697,7 @@ module.exports = {
|
|
|
1509
1697
|
errors.assertPropValue(typeof value === 'string', "terminal");
|
|
1510
1698
|
settings.terminal = value;
|
|
1511
1699
|
},
|
|
1700
|
+
|
|
1512
1701
|
set configProviderCacheTimeout(value) {
|
|
1513
1702
|
errors.assertPropValue(Number.isInteger(value) && value >= 0,
|
|
1514
1703
|
"configProviderCacheTimeout");
|
package/lib/pool.js
CHANGED
|
@@ -653,6 +653,15 @@ class Pool extends EventEmitter {
|
|
|
653
653
|
return this._impl.getPoolTimeout();
|
|
654
654
|
}
|
|
655
655
|
|
|
656
|
+
//---------------------------------------------------------------------------
|
|
657
|
+
// maxLifetimeSession
|
|
658
|
+
//
|
|
659
|
+
// Property for the max allowed lifetime of a session in the pool.
|
|
660
|
+
//---------------------------------------------------------------------------
|
|
661
|
+
get maxLifetimeSession() {
|
|
662
|
+
return this._impl.getMaxLifetimeSession();
|
|
663
|
+
}
|
|
664
|
+
|
|
656
665
|
//---------------------------------------------------------------------------
|
|
657
666
|
// queueMax
|
|
658
667
|
//
|
|
@@ -693,6 +702,7 @@ class Pool extends EventEmitter {
|
|
|
693
702
|
errors.assertParamPropUnsignedInt(options, 1, "poolIncrement");
|
|
694
703
|
errors.assertParamPropInt(options, 1, "poolPingInterval");
|
|
695
704
|
errors.assertParamPropUnsignedInt(options, 1, "poolTimeout");
|
|
705
|
+
errors.assertParamPropUnsignedInt(options, 1, "maxLifetimeSession");
|
|
696
706
|
errors.assertParamPropUnsignedInt(options, 1, "stmtCacheSize");
|
|
697
707
|
errors.assertParamPropBool(options, 1, "sodaMetaDataCache");
|
|
698
708
|
|
|
@@ -708,7 +718,8 @@ class Pool extends EventEmitter {
|
|
|
708
718
|
this._status = constants.POOL_STATUS_RECONFIGURING;
|
|
709
719
|
try {
|
|
710
720
|
// poolMin/poolMax/poolIncrement/poolPingInterval/poolTimeout/
|
|
711
|
-
// poolMaxPerShard/stmtCacheSize/sodaMetaDataCache
|
|
721
|
+
// poolMaxPerShard/stmtCacheSize/sodaMetaDataCache/maxLifetimeSession
|
|
722
|
+
// parameters
|
|
712
723
|
await this._impl.reconfigure(options);
|
|
713
724
|
|
|
714
725
|
// pool JS parameters: queueMax, queueTimeout, enableStatistics,
|
package/lib/poolStatistics.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright (c) 2021,
|
|
1
|
+
// Copyright (c) 2021, 2025, Oracle and/or its affiliates.
|
|
2
2
|
|
|
3
3
|
//-----------------------------------------------------------------------------
|
|
4
4
|
//
|
|
@@ -74,6 +74,7 @@ class PoolStatistics {
|
|
|
74
74
|
this.poolPingInterval = pool.poolPingInterval;
|
|
75
75
|
this.poolPingTimeout = pool.poolPingTimeout;
|
|
76
76
|
this.poolTimeout = pool.poolTimeout;
|
|
77
|
+
this.maxLifetimeSession = pool.maxLifetimeSession;
|
|
77
78
|
this.queueMax = pool.queueMax;
|
|
78
79
|
this.queueTimeout = pool.queueTimeout;
|
|
79
80
|
this.sodaMetaDataCache = pool.sodaMetaDataCache;
|
|
@@ -127,6 +128,7 @@ class PoolStatistics {
|
|
|
127
128
|
console.log('...poolPingInterval (seconds):', this.poolPingInterval);
|
|
128
129
|
console.log('...poolPingTimeout (milliseconds):', this.poolPingTimeout);
|
|
129
130
|
console.log('...poolTimeout (seconds):', this.poolTimeout);
|
|
131
|
+
console.log('...maxLifetimeSession (seconds):', this.maxLifetimeSession);
|
|
130
132
|
console.log('...queueMax:', this.queueMax);
|
|
131
133
|
console.log('...queueTimeout (milliseconds):', this.queueTimeout);
|
|
132
134
|
console.log('...sessionCallback:', this.sessionCallback);
|
package/lib/settings.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
|
//
|
|
@@ -64,7 +64,11 @@ class Settings {
|
|
|
64
64
|
this.thinDriverInitialized = false;
|
|
65
65
|
this.createFetchTypeMap(this.fetchAsString, this.fetchAsBuffer);
|
|
66
66
|
this.fetchTypeHandler = undefined;
|
|
67
|
+
this.dbObjectTypeHandler = undefined;
|
|
67
68
|
this._JsonId = types.JsonId;
|
|
69
|
+
this._SparseVector = types.SparseVector;
|
|
70
|
+
this._IntervalYM = types.IntervalYM;
|
|
71
|
+
this._IntervalDS = types.IntervalDS;
|
|
68
72
|
}
|
|
69
73
|
|
|
70
74
|
//---------------------------------------------------------------------------
|