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