oracledb 6.4.0 → 6.5.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.5.0-darwin-x64.node +0 -0
- package/build/Release/oracledb-6.5.0-darwin-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.5.0-js-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.5.0-linux-arm64.node +0 -0
- package/build/Release/oracledb-6.5.0-linux-arm64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.5.0-linux-x64.node +0 -0
- package/build/Release/oracledb-6.5.0-linux-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.5.0-win32-x64.node +0 -0
- package/build/Release/oracledb-6.5.0-win32-x64.node-buildinfo.txt +1 -0
- package/lib/aqQueue.js +1 -1
- package/lib/connection.js +11 -14
- package/lib/errors.js +24 -2
- package/lib/impl/connection.js +2 -1
- package/lib/impl/datahandlers/constants.js +6 -5
- package/lib/impl/datahandlers/oson.js +301 -150
- package/lib/impl/datahandlers/vector.js +3 -22
- package/lib/oracledb.js +11 -1
- package/lib/pool.js +7 -1
- package/lib/settings.js +1 -0
- package/lib/thin/connection.js +23 -52
- package/lib/thin/pool.js +62 -6
- package/lib/thin/protocol/capabilities.js +17 -5
- package/lib/thin/protocol/constants.js +14 -2
- package/lib/thin/protocol/messages/auth.js +1 -1
- package/lib/thin/protocol/messages/base.js +8 -10
- package/lib/thin/protocol/messages/dataType.js +1 -0
- package/lib/thin/protocol/messages/execute.js +5 -1
- package/lib/thin/protocol/messages/{connectionCookie.js → fastAuth.js} +18 -16
- package/lib/thin/protocol/messages/fetch.js +4 -0
- package/lib/thin/protocol/messages/index.js +2 -2
- package/lib/thin/protocol/messages/protocol.js +9 -1
- package/lib/thin/protocol/messages/withData.js +2 -5
- package/lib/thin/protocol/packet.js +35 -4
- package/lib/thin/protocol/protocol.js +10 -5
- package/lib/thin/protocol/utils.js +11 -18
- package/lib/thin/sqlnet/constants.js +5 -2
- package/lib/thin/sqlnet/ezConnectResolver.js +9 -5
- package/lib/thin/sqlnet/navNodes.js +4 -3
- package/lib/thin/sqlnet/networkSession.js +14 -3
- package/lib/thin/sqlnet/packet.js +2 -5
- package/lib/thin/statement.js +36 -0
- package/lib/thin/statementCache.js +34 -11
- package/lib/thin/util.js +2 -2
- package/lib/transformer.js +9 -3
- package/lib/types.js +9 -1
- package/lib/util.js +1 -1
- package/lib/version.js +1 -1
- package/package.json +1 -1
- package/build/Release/oracledb-6.4.0-darwin-x64.node +0 -0
- package/build/Release/oracledb-6.4.0-darwin-x64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.4.0-js-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.4.0-linux-arm64.node +0 -0
- package/build/Release/oracledb-6.4.0-linux-arm64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.4.0-linux-x64.node +0 -0
- package/build/Release/oracledb-6.4.0-linux-x64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.4.0-win32-x64.node +0 -0
- package/build/Release/oracledb-6.4.0-win32-x64.node-buildinfo.txt +0 -1
|
@@ -37,12 +37,12 @@ const PingMessage = require('./ping.js');
|
|
|
37
37
|
const ProtocolMessage = require('./protocol.js');
|
|
38
38
|
const RollbackMessage = require('./rollback.js');
|
|
39
39
|
const SessionReleaseMessage = require('./sessionRelease.js');
|
|
40
|
-
const
|
|
40
|
+
const FastAuthMessage = require('./fastAuth.js');
|
|
41
41
|
|
|
42
42
|
module.exports = {
|
|
43
43
|
AuthMessage,
|
|
44
44
|
CommitMessage,
|
|
45
|
-
|
|
45
|
+
FastAuthMessage,
|
|
46
46
|
DataTypeMessage,
|
|
47
47
|
ExecuteMessage,
|
|
48
48
|
FetchMessage,
|
|
@@ -53,6 +53,7 @@ class ProtocolMessage extends Message {
|
|
|
53
53
|
processMessage(buf, messageType) {
|
|
54
54
|
if (messageType === constants.TNS_MSG_TYPE_PROTOCOL) {
|
|
55
55
|
this.processProtocolInfo(buf);
|
|
56
|
+
this.endOfResponse = !this.connection.nscon.endOfRequestSupport;
|
|
56
57
|
} else {
|
|
57
58
|
super.processMessage(buf, messageType);
|
|
58
59
|
}
|
|
@@ -75,7 +76,14 @@ class ProtocolMessage extends Message {
|
|
|
75
76
|
const serverCompileCaps = buf.readBytesWithLength();
|
|
76
77
|
if (serverCompileCaps) {
|
|
77
78
|
this.serverCompileCaps = Buffer.from(serverCompileCaps);
|
|
78
|
-
buf.caps.adjustForServerCompileCaps(this.serverCompileCaps);
|
|
79
|
+
buf.caps.adjustForServerCompileCaps(this.serverCompileCaps, this.connection.nscon);
|
|
80
|
+
|
|
81
|
+
// Set the maximum OSON field name size
|
|
82
|
+
if (buf.caps.ttcFieldVersion >= constants.TNS_CCAP_FIELD_VERSION_23_1) {
|
|
83
|
+
this.connection._osonMaxFieldNameSize = 65535;
|
|
84
|
+
} else {
|
|
85
|
+
this.connection._osonMaxFieldNameSize = 255;
|
|
86
|
+
}
|
|
79
87
|
}
|
|
80
88
|
const serverRunTimeCaps = buf.readBytesWithLength();
|
|
81
89
|
if (serverRunTimeCaps) {
|
|
@@ -85,6 +85,7 @@ class MessageWithData extends Message {
|
|
|
85
85
|
this.processIOVector(buf);
|
|
86
86
|
} else if (messageType === constants.TNS_MSG_TYPE_FLUSH_OUT_BINDS) {
|
|
87
87
|
this.flushOutBinds = true;
|
|
88
|
+
this.endOfResponse = true;
|
|
88
89
|
} else if (messageType === constants.TNS_MSG_TYPE_ERROR) {
|
|
89
90
|
this.processErrorInfo(buf);
|
|
90
91
|
} else {
|
|
@@ -92,10 +93,6 @@ class MessageWithData extends Message {
|
|
|
92
93
|
}
|
|
93
94
|
}
|
|
94
95
|
|
|
95
|
-
hasMoreData() {
|
|
96
|
-
return !this.processedError && !this.flushOutBinds;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
96
|
processErrorInfo(buf) {
|
|
100
97
|
super.processErrorInfo(buf);
|
|
101
98
|
if (this.errorInfo.cursorId !== 0) {
|
|
@@ -852,7 +849,7 @@ class MessageWithData extends Message {
|
|
|
852
849
|
} else if ([constants.TNS_DATA_TYPE_ROWID, constants.TNS_DATA_TYPE_UROWID].includes(oraTypeNum)) {
|
|
853
850
|
buf.writeBytesWithLength(Buffer.from(value));
|
|
854
851
|
} else if (oraTypeNum === constants.TNS_DATA_TYPE_JSON) {
|
|
855
|
-
buf.writeOson(value);
|
|
852
|
+
buf.writeOson(value, this.connection._osonMaxFieldNameSize);
|
|
856
853
|
} else if (oraTypeNum === constants.TNS_DATA_TYPE_VECTOR) {
|
|
857
854
|
buf.writeVector(value);
|
|
858
855
|
} else if (oraTypeNum === constants.TNS_DATA_TYPE_INT_NAMED) {
|
|
@@ -35,6 +35,9 @@ const vector = require('../../impl/datahandlers/vector.js');
|
|
|
35
35
|
const errors = require("../../errors.js");
|
|
36
36
|
|
|
37
37
|
const TNS_BASE64_ALPHABET_ARRAY = Buffer.from("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", 'utf8');
|
|
38
|
+
const FAST_AUTH_END_OF_RPC_VALUE = 0x800;
|
|
39
|
+
const FAST_AUTH_END_OF_RPC_OFFSET = 0x8;
|
|
40
|
+
const MSG_TYPE_OFFSET = 11;
|
|
38
41
|
|
|
39
42
|
/**
|
|
40
43
|
* Class used for byte chunks used in the ChunkedBytesBuffer.
|
|
@@ -290,14 +293,38 @@ class ReadPacket extends BaseBuffer {
|
|
|
290
293
|
this.packetNum = packet.num;
|
|
291
294
|
}
|
|
292
295
|
|
|
293
|
-
|
|
294
|
-
|
|
296
|
+
/**
|
|
297
|
+
* Read packets from network.
|
|
298
|
+
* If checkRequestBoundary is passed as true, it
|
|
299
|
+
* would read all packets until end of request
|
|
300
|
+
* boundary is seen in nwk header.
|
|
301
|
+
*/
|
|
302
|
+
async waitForPackets(checkRequestBoundary = false) {
|
|
303
|
+
let packet = await this.nsi.recvPacket();
|
|
295
304
|
if (!this.savedPackets) {
|
|
296
305
|
this.savedPackets = [packet];
|
|
297
306
|
this.savedPacketPos = 0;
|
|
298
307
|
} else {
|
|
299
308
|
this.savedPackets.push(packet);
|
|
300
309
|
}
|
|
310
|
+
if (checkRequestBoundary && this.nsi.endOfRequestSupport) {
|
|
311
|
+
while (packet.type === constants.TNS_PACKET_TYPE_DATA) {
|
|
312
|
+
// End Marker
|
|
313
|
+
if ((packet.buf.readUInt16BE(8) &
|
|
314
|
+
constants.TNS_DATA_FLAGS_END_OF_REQUEST)) {
|
|
315
|
+
break;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// Single Byte 1D packet
|
|
319
|
+
if (packet.buf.length === MSG_TYPE_OFFSET &&
|
|
320
|
+
packet.buf[MSG_TYPE_OFFSET - 1] ===
|
|
321
|
+
constants.TNS_MSG_TYPE_END_OF_REQUEST) {
|
|
322
|
+
break;
|
|
323
|
+
}
|
|
324
|
+
packet = await this.nsi.recvPacket();
|
|
325
|
+
this.savedPackets.push(packet);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
301
328
|
this.startPacket(this.savedPackets[this.savedPacketPos++]);
|
|
302
329
|
}
|
|
303
330
|
|
|
@@ -495,6 +522,10 @@ class WritePacket extends BaseBuffer {
|
|
|
495
522
|
if (!finalPacket) {
|
|
496
523
|
buf = Buffer.from(buf);
|
|
497
524
|
this.startPacket();
|
|
525
|
+
} else {
|
|
526
|
+
// Write End of RPC bit in last packet used only for fastAuth Message.
|
|
527
|
+
this.buf.writeUInt16BE(FAST_AUTH_END_OF_RPC_VALUE,
|
|
528
|
+
FAST_AUTH_END_OF_RPC_OFFSET);
|
|
498
529
|
}
|
|
499
530
|
if (!this.nsi.ntAdapter) {
|
|
500
531
|
errors.throwErr(errors.ERR_INVALID_CONNECTION);
|
|
@@ -545,9 +576,9 @@ class WritePacket extends BaseBuffer {
|
|
|
545
576
|
* Encodes a JavaScript object into OSON and then writes it (QLocator
|
|
546
577
|
* followed by data) to the buffer.
|
|
547
578
|
*/
|
|
548
|
-
writeOson(value) {
|
|
579
|
+
writeOson(value, osonMaxFieldSize) {
|
|
549
580
|
const encoder = new oson.OsonEncoder();
|
|
550
|
-
const buf = encoder.encode(value);
|
|
581
|
+
const buf = encoder.encode(value, osonMaxFieldSize);
|
|
551
582
|
this.writeQLocator(buf.length);
|
|
552
583
|
this.writeBytesWithLength(buf);
|
|
553
584
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright (c) 2022,
|
|
1
|
+
// Copyright (c) 2022, 2024, Oracle and/or its affiliates.
|
|
2
2
|
|
|
3
3
|
//-----------------------------------------------------------------------------
|
|
4
4
|
//
|
|
@@ -49,7 +49,7 @@ class Protocol {
|
|
|
49
49
|
* Compile and Runtime capabilities negotiated with Server
|
|
50
50
|
* @type {object}
|
|
51
51
|
*/
|
|
52
|
-
this.caps = new Capabilities(conn.nscon
|
|
52
|
+
this.caps = new Capabilities(conn.nscon);
|
|
53
53
|
this.writeBuf = new WritePacket(conn.nscon, this.caps, this);
|
|
54
54
|
this.readBuf = new ReadPacket(conn.nscon, this.caps);
|
|
55
55
|
this.callTimeout = 0;
|
|
@@ -67,11 +67,11 @@ class Protocol {
|
|
|
67
67
|
*/
|
|
68
68
|
async _decodeMessage(message) {
|
|
69
69
|
message.preProcess();
|
|
70
|
-
await this.readBuf.waitForPackets();
|
|
70
|
+
await this.readBuf.waitForPackets(true);
|
|
71
71
|
while (true) { // eslint-disable-line
|
|
72
72
|
if (this.nsi.isBreak) {
|
|
73
73
|
await this.resetMessage();
|
|
74
|
-
delete this.readBuf.
|
|
74
|
+
delete this.readBuf.savedPackets;
|
|
75
75
|
await this.readBuf.waitForPackets();
|
|
76
76
|
}
|
|
77
77
|
try {
|
|
@@ -164,7 +164,12 @@ class Protocol {
|
|
|
164
164
|
if (message.flushOutBinds) {
|
|
165
165
|
await this.flushOutBindMessage(message);
|
|
166
166
|
}
|
|
167
|
-
this.txnInProgress = message.callStatus & constants.
|
|
167
|
+
this.txnInProgress = Boolean(message.callStatus & constants.TNS_EOCS_FLAGS_TXN_IN_PROGRESS);
|
|
168
|
+
// processes the call status flags returned by the server.
|
|
169
|
+
if (message.callStatus & constants.TNS_EOCS_FLAGS_SESS_RELEASE) {
|
|
170
|
+
message.connection.statementCache.clearCursors();
|
|
171
|
+
}
|
|
172
|
+
|
|
168
173
|
if (message.errorOccurred) {
|
|
169
174
|
if (callTimeoutExpired) {
|
|
170
175
|
errors.throwErr(errors.ERR_CALL_TIMEOUT_EXCEEDED, this.callTimeout);
|
|
@@ -52,30 +52,23 @@ function encodeRowID(rowID) {
|
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
// obfuscate value
|
|
56
|
-
// and are possible to stay longer
|
|
55
|
+
// obfuscate value
|
|
57
56
|
function setObfuscatedValue(value) {
|
|
58
|
-
const
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
const arr = [];
|
|
63
|
-
for (let i = 0; i < len; i++) {
|
|
64
|
-
arr.push(buf[i] ^ bytes[i]);
|
|
57
|
+
const valueBytes = Buffer.from(value);
|
|
58
|
+
const obfuscatedBytes = crypto.randomBytes(valueBytes.length);
|
|
59
|
+
for (let i = 0; i < valueBytes.length; i++) {
|
|
60
|
+
valueBytes[i] = obfuscatedBytes[i] ^ valueBytes[i];
|
|
65
61
|
}
|
|
66
|
-
|
|
67
|
-
return {obfuscatedValue: buf, value: arr};
|
|
62
|
+
return {obfuscatedValue: obfuscatedBytes, value: valueBytes};
|
|
68
63
|
}
|
|
69
64
|
|
|
70
|
-
// returns the
|
|
65
|
+
// returns the deobfuscated value, after removing the obfuscation
|
|
71
66
|
// and clear memory of temporary Buffers coming from Buffer pool
|
|
72
|
-
function getDeobfuscatedValue(
|
|
73
|
-
const
|
|
74
|
-
for (let i = 0; i <
|
|
75
|
-
|
|
67
|
+
function getDeobfuscatedValue(valueBytes, obfuscatedBytes) {
|
|
68
|
+
const buf = Buffer.from(valueBytes);
|
|
69
|
+
for (let i = 0; i < valueBytes.length; i++) {
|
|
70
|
+
buf[i] = valueBytes[i] ^ obfuscatedBytes[i];
|
|
76
71
|
}
|
|
77
|
-
const buf = Buffer.from(arr);
|
|
78
|
-
arr.fill(0);
|
|
79
72
|
const retVal = buf.toString();
|
|
80
73
|
buf.fill(0);
|
|
81
74
|
return retVal;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright (c) 2022,
|
|
1
|
+
// Copyright (c) 2022, 2024, Oracle and/or its affiliates.
|
|
2
2
|
|
|
3
3
|
//-----------------------------------------------------------------------------
|
|
4
4
|
//
|
|
@@ -107,7 +107,8 @@ module.exports = {
|
|
|
107
107
|
NSGRAW: 0x1000, // I/O is direct to/from transport
|
|
108
108
|
TNS_VERSION_DESIRED: 319,
|
|
109
109
|
TNS_VERSION_MINIMUM: 300,
|
|
110
|
-
|
|
110
|
+
TNS_VERSION_MIN_DATA_FLAGS: 318,
|
|
111
|
+
TNS_VERSION_MIN_END_OF_RESPONSE: 319,
|
|
111
112
|
TNS_UUID_OFFSET: 45,
|
|
112
113
|
|
|
113
114
|
/* Accept Packet */
|
|
@@ -143,6 +144,8 @@ module.exports = {
|
|
|
143
144
|
// Accept flag2
|
|
144
145
|
NSPACOOB: 0x00000001, // OOB support check at connection time
|
|
145
146
|
NSGPCHKSCMD: 0x01000000, // Support for Poll and Check logic
|
|
147
|
+
TNS_ACCEPT_FLAG_HAS_END_OF_REQUEST: 0x02000000,
|
|
148
|
+
TNS_ACCEPT_FLAG_FAST_AUTH: 0x10000000, // Support Fast Auth
|
|
146
149
|
|
|
147
150
|
/* Redirect packet */
|
|
148
151
|
NSPRDLEN: 8, // Length of redirect data
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright (c) 2022,
|
|
1
|
+
// Copyright (c) 2022, 2024, Oracle and/or its affiliates.
|
|
2
2
|
|
|
3
3
|
//-----------------------------------------------------------------------------
|
|
4
4
|
//
|
|
@@ -164,6 +164,7 @@ class EZConnectResolver {
|
|
|
164
164
|
const poolConnectionClass = this.urlProps.get("POOL_CONNECTION_CLASS");
|
|
165
165
|
const poolPurity = this.urlProps.get("POOL_PURITY");
|
|
166
166
|
const serviceTag = this.urlProps.get("SERVICE_TAG");
|
|
167
|
+
const poolBoundary = this.urlProps.get("POOL_BOUNDARY");
|
|
167
168
|
|
|
168
169
|
const parts = [];
|
|
169
170
|
if (serviceName)
|
|
@@ -182,6 +183,8 @@ class EZConnectResolver {
|
|
|
182
183
|
parts.push(`(SERVICE_TAG=${serviceTag})`);
|
|
183
184
|
if (connectionIdPrefix)
|
|
184
185
|
parts.push(`(CONNECTION_ID_PREFIX=${connectionIdPrefix})`);
|
|
186
|
+
if (poolBoundary)
|
|
187
|
+
parts.push(`(POOL_BOUNDARY=${poolBoundary})`);
|
|
185
188
|
return `(CONNECT_DATA=${parts.join("")})`;
|
|
186
189
|
}
|
|
187
190
|
|
|
@@ -211,17 +214,17 @@ class EZConnectResolver {
|
|
|
211
214
|
let naddr = 0;
|
|
212
215
|
// ; groups the user into a ADDRESS_LIST
|
|
213
216
|
const addressLists = hostInfo.split(";");
|
|
214
|
-
for (const addressList
|
|
217
|
+
for (const addressList of addressLists) {
|
|
215
218
|
let addressNodeCount = 0;
|
|
216
219
|
const addressListBuilder = new Array();
|
|
217
|
-
for (const match of
|
|
220
|
+
for (const match of addressList.matchAll(HOSTNAMES_PATTERN)) {
|
|
218
221
|
const hostnames = (match.groups.hostnames).split(',');
|
|
219
222
|
let port = match.groups.port;
|
|
220
223
|
if (port == null) {
|
|
221
224
|
port = '1521'; //default port
|
|
222
225
|
}
|
|
223
|
-
for (const hname
|
|
224
|
-
addressListBuilder.push(this.getAddrStr(
|
|
226
|
+
for (const hname of hostnames) {
|
|
227
|
+
addressListBuilder.push(this.getAddrStr(hname, port, protocol, proxyInfo));
|
|
225
228
|
addressNodeCount++;
|
|
226
229
|
}
|
|
227
230
|
}
|
|
@@ -455,6 +458,7 @@ class EZConnectResolver {
|
|
|
455
458
|
aliasMap.set("pool_purity", "POOL_PURITY");
|
|
456
459
|
aliasMap.set("service_tag", "SERVICE_TAG");
|
|
457
460
|
aliasMap.set("connection_id_prefix", "CONNECTION_ID_PREFIX");
|
|
461
|
+
aliasMap.set("pool_boundary", "POOL_BOUNDARY");
|
|
458
462
|
return aliasMap;
|
|
459
463
|
}
|
|
460
464
|
}module.exports = EZConnectResolver;
|
|
@@ -486,7 +486,7 @@ class NavAddress extends Address {
|
|
|
486
486
|
if (!net.isIP(this.host)) {
|
|
487
487
|
try {
|
|
488
488
|
addresses = await dnsPromises.lookup(this.host, options);
|
|
489
|
-
for (const addr
|
|
489
|
+
for (const addr of addresses) {
|
|
490
490
|
const co = new ConnOption();
|
|
491
491
|
co.hostname = this.host;
|
|
492
492
|
co.port = this.port;
|
|
@@ -499,7 +499,7 @@ class NavAddress extends Address {
|
|
|
499
499
|
co.CNdata.push('(address=(protocol=' + this.prot + ')(host=' + this.host + ')(port=' + this.port + '))');
|
|
500
500
|
else
|
|
501
501
|
co.CNdata.push(this.toString());
|
|
502
|
-
co.host =
|
|
502
|
+
co.host = addr.address;
|
|
503
503
|
co.addr = this.addr;
|
|
504
504
|
cs.getcurrentDescription().addConnectOption(co);
|
|
505
505
|
}
|
|
@@ -777,7 +777,8 @@ class NavDescription extends Description {
|
|
|
777
777
|
if (this.connectData == null) {
|
|
778
778
|
this.connectData = "(SERVICE_NAME=)";
|
|
779
779
|
}
|
|
780
|
-
const
|
|
780
|
+
const pgmName = "\"'" + cInfo.program + "'\"";
|
|
781
|
+
const cid = `(CID=(PROGRAM=${pgmName})(HOST=${cInfo.hostName})(USER=${cInfo.userName}))`;
|
|
781
782
|
cOpts[i].CNdata.push(NavSchemaObject.CD);
|
|
782
783
|
cOpts[i].CNdata.push(this.connectData);
|
|
783
784
|
cOpts[i].CNdata.push(cid);
|
|
@@ -59,7 +59,7 @@ async function getConnectionInfo(userConfig) {
|
|
|
59
59
|
const sid = findValue(nvpair, ["DESCRIPTION", "CONNECT_DATA", "SID"]);
|
|
60
60
|
const poolPurity = findValue(nvpair, ["DESCRIPTION", "CONNECT_DATA", "POOL_PURITY"]);
|
|
61
61
|
|
|
62
|
-
return [serverVal, connClass, svcname, poolPurity, sid, addressNode
|
|
62
|
+
return [serverVal, connClass, svcname, poolPurity, sid, addressNode];
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
/**
|
|
@@ -83,6 +83,12 @@ async function resolveConnectStr(connectString, configDir) {
|
|
|
83
83
|
resolvedVal = p.get(connStr.toUpperCase());
|
|
84
84
|
if (!resolvedVal)
|
|
85
85
|
errors.throwErr(errors.ERR_TNS_ENTRY_NOT_FOUND, connStr, configDir ? configDir + '/tnsnames.ora' : process.env.TNS_ADMIN + '/tnsnames.ora');
|
|
86
|
+
if (resolvedVal.rhsType == 1) {
|
|
87
|
+
const rString = resolvedVal.atom;
|
|
88
|
+
if ((rString.indexOf(':') != -1) || (rString.indexOf('/') != -1)) {
|
|
89
|
+
return new EzConnect(rString).getResolvedUrl();
|
|
90
|
+
}
|
|
91
|
+
}
|
|
86
92
|
resolvedVal = resolvedVal.getListElement(0);
|
|
87
93
|
}
|
|
88
94
|
|
|
@@ -354,8 +360,13 @@ class NetworkSession {
|
|
|
354
360
|
break;
|
|
355
361
|
case constants.NSPTAC: /* ACCEPT */
|
|
356
362
|
Packet.AcceptPacket(packet, this.sAtts);
|
|
357
|
-
this.
|
|
358
|
-
|
|
363
|
+
if (this.sAtts.version >= constants.TNS_VERSION_MIN_END_OF_RESPONSE
|
|
364
|
+
&& (packet.flags & constants.TNS_ACCEPT_FLAG_HAS_END_OF_REQUEST)) {
|
|
365
|
+
this.endOfRequestSupport = true;
|
|
366
|
+
}
|
|
367
|
+
if (packet.flags & constants.TNS_ACCEPT_FLAG_FAST_AUTH) {
|
|
368
|
+
this.supportsFastAuth = true;
|
|
369
|
+
}
|
|
359
370
|
break;
|
|
360
371
|
case constants.NSPTRF: /* REFUSE */
|
|
361
372
|
this.refusePkt = new Packet.RefusePacket(packet);
|
|
@@ -246,11 +246,8 @@ function AcceptPacket(packet, sAtts) {
|
|
|
246
246
|
this.flag0 = packet.buf.readUInt8(constants.NSPACFL0);
|
|
247
247
|
this.flag1 = packet.buf.readUInt8(constants.NSPACFL1);
|
|
248
248
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
packet.dbUUID = packet.buf.subarray(constants.TNS_UUID_OFFSET,
|
|
252
|
-
constants.TNS_UUID_OFFSET + 16);
|
|
253
|
-
packet.dbUUID = packet.dbUUID.toString('base64');
|
|
249
|
+
if (sAtts.version >= constants.TNS_VERSION_MIN_DATA_FLAGS) {
|
|
250
|
+
packet.flags = packet.buf.readUInt32BE(constants.NSPACFL2);
|
|
254
251
|
}
|
|
255
252
|
}
|
|
256
253
|
|
package/lib/thin/statement.js
CHANGED
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
|
|
29
29
|
const { Buffer } = require('buffer');
|
|
30
30
|
const constants = require('../constants');
|
|
31
|
+
const errors = require('../errors');
|
|
31
32
|
|
|
32
33
|
/**
|
|
33
34
|
* It is used to cache the metadata about bind information
|
|
@@ -359,6 +360,7 @@ class Statement {
|
|
|
359
360
|
this.inUse = false;
|
|
360
361
|
this.bufferRowIndex = 0;
|
|
361
362
|
this.bufferRowCount = 0;
|
|
363
|
+
this.pendingClear = false;
|
|
362
364
|
this.statementType = constants.STMT_TYPE_UNKNOWN;
|
|
363
365
|
}
|
|
364
366
|
|
|
@@ -495,6 +497,12 @@ class Statement {
|
|
|
495
497
|
const info = new BindInfo(name, this.isReturning);
|
|
496
498
|
this.bindInfoList.push(info);
|
|
497
499
|
if (this.bindInfoDict.has(info.bindName)) {
|
|
500
|
+
if (this.isReturning) {
|
|
501
|
+
const origInfo = this.bindInfoDict.get(info.bindName)[0];
|
|
502
|
+
if (!origInfo.isReturnBind) {
|
|
503
|
+
errors.throwErr(errors.ERR_DML_RETURNING_DUP_BINDS, name);
|
|
504
|
+
}
|
|
505
|
+
}
|
|
498
506
|
this.bindInfoDict.get(info.bindName).push(info);
|
|
499
507
|
} else {
|
|
500
508
|
this.bindInfoDict.set(info.bindName, [info]);
|
|
@@ -528,6 +536,34 @@ class Statement {
|
|
|
528
536
|
|
|
529
537
|
bindInfo.bindVar = variable;
|
|
530
538
|
}
|
|
539
|
+
|
|
540
|
+
//---------------------------------------------------------------------------
|
|
541
|
+
// _clearAllState
|
|
542
|
+
//
|
|
543
|
+
// clear all state associated with the cursor
|
|
544
|
+
//---------------------------------------------------------------------------
|
|
545
|
+
_clearAllState() {
|
|
546
|
+
this.cursorId = 0;
|
|
547
|
+
this.requiresDefine = false;
|
|
548
|
+
this.noPrefetch = false;
|
|
549
|
+
this.requiresFullExecute = false;
|
|
550
|
+
this.queryVars = [];
|
|
551
|
+
this.numQueryVars = 0;
|
|
552
|
+
this.bufferRowCount = 0;
|
|
553
|
+
this.bufferRowIndex = 0;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
//---------------------------------------------------------------------------
|
|
557
|
+
// _clearState
|
|
558
|
+
//
|
|
559
|
+
// clear some state associated with the cursor
|
|
560
|
+
//---------------------------------------------------------------------------
|
|
561
|
+
_clearState() {
|
|
562
|
+
this.cursorId = 0;
|
|
563
|
+
this.requiresDefine = false;
|
|
564
|
+
this.noPrefetch = false;
|
|
565
|
+
this.requiresFullExecute = false;
|
|
566
|
+
}
|
|
531
567
|
}
|
|
532
568
|
|
|
533
569
|
module.exports.Statement = Statement;
|
|
@@ -71,20 +71,37 @@ class StatementCache {
|
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
//---------------------------------------------------------------------------
|
|
74
|
-
//
|
|
74
|
+
//clearCursors() {
|
|
75
75
|
// Clears the list of open cursors and removes the list of cursors that
|
|
76
76
|
// need to be closed. This is required when a DRCP session change has
|
|
77
77
|
// taken place as the cursor ID values are invalidated.
|
|
78
78
|
//---------------------------------------------------------------------------
|
|
79
|
-
|
|
79
|
+
clearCursors() {
|
|
80
80
|
const newOpenCursors = new Set();
|
|
81
81
|
for (const stmt of this._openCursors) {
|
|
82
|
-
stmt.
|
|
83
|
-
|
|
82
|
+
if (stmt.inUse || stmt.returnToCache) {
|
|
83
|
+
stmt.pendingClear = true;
|
|
84
84
|
newOpenCursors.add(stmt);
|
|
85
85
|
}
|
|
86
|
+
stmt._clearState();
|
|
86
87
|
}
|
|
87
88
|
this._openCursors = newOpenCursors;
|
|
89
|
+
this._cursorsToClose.clear();
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
//---------------------------------------------------------------------------
|
|
93
|
+
//clearPendingState() {
|
|
94
|
+
// Clears state for statment with pending clear flag set and not in use.
|
|
95
|
+
// This will clear all state for open cursors.
|
|
96
|
+
// Called after rows processing is completed.
|
|
97
|
+
//---------------------------------------------------------------------------
|
|
98
|
+
clearPendingStatus() {
|
|
99
|
+
for (const stmt of this._openCursors) {
|
|
100
|
+
if (stmt.pendingClear && !stmt.inUse) {
|
|
101
|
+
stmt._clearAllState();
|
|
102
|
+
stmt.pendingClear = false;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
88
105
|
}
|
|
89
106
|
|
|
90
107
|
//---------------------------------------------------------------------------
|
|
@@ -94,14 +111,10 @@ class StatementCache {
|
|
|
94
111
|
// supposed to be cached, a copy will be made (and not returned to the
|
|
95
112
|
// cache).
|
|
96
113
|
//---------------------------------------------------------------------------
|
|
97
|
-
getStatement(sql, cacheStatement = false) {
|
|
114
|
+
getStatement(sql, cacheStatement = false, forceNew = false) {
|
|
98
115
|
let stmt = null;
|
|
99
116
|
if (sql) {
|
|
100
117
|
stmt = this._cachedStatements.get(sql);
|
|
101
|
-
if (!cacheStatement) {
|
|
102
|
-
this._openCursors.add(stmt);
|
|
103
|
-
this._cachedStatements.delete(sql);
|
|
104
|
-
}
|
|
105
118
|
}
|
|
106
119
|
if (!stmt) {
|
|
107
120
|
stmt = new Statement();
|
|
@@ -114,13 +127,21 @@ class StatementCache {
|
|
|
114
127
|
this._adjustCache();
|
|
115
128
|
}
|
|
116
129
|
this._openCursors.add(stmt);
|
|
117
|
-
} else if (stmt.inUse
|
|
130
|
+
} else if (forceNew || stmt.inUse) {
|
|
131
|
+
if (!cacheStatement) {
|
|
132
|
+
this._addCursorToClose(stmt);
|
|
133
|
+
this._cachedStatements.delete(sql);
|
|
134
|
+
}
|
|
118
135
|
stmt = stmt._copy();
|
|
119
136
|
this._openCursors.add(stmt);
|
|
137
|
+
} else if (!cacheStatement) {
|
|
138
|
+
this._cachedStatements.delete(sql);
|
|
139
|
+
stmt.returnToCache = false;
|
|
120
140
|
} else {
|
|
121
141
|
this._cachedStatements.delete(sql);
|
|
122
142
|
this._cachedStatements.set(sql, stmt);
|
|
123
143
|
}
|
|
144
|
+
this._openCursors.add(stmt);
|
|
124
145
|
stmt.inUse = true;
|
|
125
146
|
return stmt;
|
|
126
147
|
}
|
|
@@ -146,9 +167,11 @@ class StatementCache {
|
|
|
146
167
|
}
|
|
147
168
|
if (statement.returnToCache) {
|
|
148
169
|
statement.inUse = false;
|
|
149
|
-
} else
|
|
170
|
+
} else {
|
|
150
171
|
this._addCursorToClose(statement);
|
|
151
172
|
}
|
|
173
|
+
// clear all state for statement which is having flag set and not in use
|
|
174
|
+
this.clearPendingStatus();
|
|
152
175
|
}
|
|
153
176
|
|
|
154
177
|
//---------------------------------------------------------------------------
|
package/lib/thin/util.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright (c) 2022,
|
|
1
|
+
// Copyright (c) 2022, 2024, Oracle and/or its affiliates.
|
|
2
2
|
|
|
3
3
|
//-----------------------------------------------------------------------------
|
|
4
4
|
//
|
|
@@ -254,5 +254,5 @@ module.exports = {
|
|
|
254
254
|
getOutBinds,
|
|
255
255
|
checkProxyUserValidity,
|
|
256
256
|
checkCredentials,
|
|
257
|
-
normalizePrivateKey
|
|
257
|
+
normalizePrivateKey,
|
|
258
258
|
};
|
package/lib/transformer.js
CHANGED
|
@@ -89,7 +89,7 @@ function transformJsonValue(value) {
|
|
|
89
89
|
if (value === undefined || value === null ||
|
|
90
90
|
typeof value === 'number' || typeof value === 'string' ||
|
|
91
91
|
typeof value === 'boolean' || Buffer.isBuffer(value) ||
|
|
92
|
-
util.isDate(value) || nodbUtil.isVectorValue(value))
|
|
92
|
+
util.types.isDate(value) || nodbUtil.isVectorValue(value))
|
|
93
93
|
return value;
|
|
94
94
|
|
|
95
95
|
// arrays are transformed to a new array with processed values
|
|
@@ -105,6 +105,12 @@ function transformJsonValue(value) {
|
|
|
105
105
|
if (value instanceof BaseDbObject)
|
|
106
106
|
return {fields: [], values: []};
|
|
107
107
|
|
|
108
|
+
// JsonId is a special type to represent autogenerated id
|
|
109
|
+
// for SODA documents.
|
|
110
|
+
if (value instanceof types.JsonId) {
|
|
111
|
+
return value;
|
|
112
|
+
}
|
|
113
|
+
|
|
108
114
|
// all other objects are transformed to an object with two arrays (fields
|
|
109
115
|
// and values)
|
|
110
116
|
const outValue = {};
|
|
@@ -166,7 +172,7 @@ function transformValueIn(info, value, options) {
|
|
|
166
172
|
return value;
|
|
167
173
|
|
|
168
174
|
// handle numbers
|
|
169
|
-
} else if (typeof value === 'number') {
|
|
175
|
+
} else if (typeof value === 'number' || typeof value === 'bigint') {
|
|
170
176
|
checkType(info, options,
|
|
171
177
|
types.DB_TYPE_NUMBER,
|
|
172
178
|
types.DB_TYPE_BINARY_INTEGER,
|
|
@@ -183,7 +189,7 @@ function transformValueIn(info, value, options) {
|
|
|
183
189
|
return value;
|
|
184
190
|
|
|
185
191
|
// handle dates
|
|
186
|
-
} else if (util.isDate(value)) {
|
|
192
|
+
} else if (util.types.isDate(value)) {
|
|
187
193
|
checkType(info, options,
|
|
188
194
|
types.DB_TYPE_TIMESTAMP,
|
|
189
195
|
types.DB_TYPE_TIMESTAMP_TZ,
|
package/lib/types.js
CHANGED
|
@@ -332,6 +332,13 @@ dbTypeByColumnTypeName.set("SMALLINT", DB_TYPE_NUMBER);
|
|
|
332
332
|
dbTypeByColumnTypeName.set("TIMESTAMP WITH LOCAL TZ", DB_TYPE_TIMESTAMP_LTZ);
|
|
333
333
|
dbTypeByColumnTypeName.set("TIMESTAMP WITH TZ", DB_TYPE_TIMESTAMP_TZ);
|
|
334
334
|
|
|
335
|
+
// It abstracts the autogenerated SODA Document key.
|
|
336
|
+
class JsonId extends Uint8Array {
|
|
337
|
+
toJSON() {
|
|
338
|
+
return (Buffer.from(this.buffer).toString('hex'));
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
335
342
|
module.exports = {
|
|
336
343
|
DbType,
|
|
337
344
|
DB_TYPE_BFILE,
|
|
@@ -368,5 +375,6 @@ module.exports = {
|
|
|
368
375
|
DB_TYPE_XMLTYPE,
|
|
369
376
|
getTypeByColumnTypeName,
|
|
370
377
|
getTypeByNum,
|
|
371
|
-
getTypeByOraTypeNum
|
|
378
|
+
getTypeByOraTypeNum,
|
|
379
|
+
JsonId
|
|
372
380
|
};
|
package/lib/util.js
CHANGED
|
@@ -231,7 +231,7 @@ function isShardingKey(value) {
|
|
|
231
231
|
const element = value[i];
|
|
232
232
|
const ok = typeof element === 'string' ||
|
|
233
233
|
typeof element === 'number' || Buffer.isBuffer(element) ||
|
|
234
|
-
util.isDate(element);
|
|
234
|
+
util.types.isDate(element);
|
|
235
235
|
if (!ok)
|
|
236
236
|
return false;
|
|
237
237
|
}
|
package/lib/version.js
CHANGED
package/package.json
CHANGED
|
Binary file
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
oracledb-6.4.0-darwin-x64.node v18.17.0 df971fa2503fcf9ab4a63f2f2508f5fb5780c0e1 31cd3b6682f32ad860df63d1dd06e3bf1c5e62aa Thu, 29 Feb 2024 13:53:47 GMT
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
df971fa2503fcf9ab4a63f2f2508f5fb5780c0e1
|
|
Binary file
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
oracledb-6.4.0-linux-arm64.node v18.19.0 df971fa2503fcf9ab4a63f2f2508f5fb5780c0e1 31cd3b6682f32ad860df63d1dd06e3bf1c5e62aa Thu, 29 Feb 2024 15:01:23 GMT
|
|
Binary file
|