oracledb 6.3.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/LICENSE.txt +1 -1
- package/NOTICE.txt +1 -1
- package/README.md +3 -3
- 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/examples/README.md +3 -0
- package/lib/aqQueue.js +8 -8
- package/lib/connection.js +65 -22
- package/lib/constants.js +7 -1
- package/lib/dbObject.js +72 -1
- package/lib/errors.js +51 -10
- package/lib/impl/connection.js +2 -1
- package/lib/{thin/protocol → impl/datahandlers}/buffer.js +36 -32
- package/lib/impl/datahandlers/constants.js +106 -0
- package/lib/{thin/protocol → impl/datahandlers}/oson.js +320 -151
- package/lib/impl/datahandlers/vector.js +137 -0
- package/lib/impl/pool.js +9 -0
- package/lib/impl/resultset.js +34 -17
- package/lib/lob.js +22 -6
- package/lib/oracledb.js +35 -1
- package/lib/pool.js +17 -2
- package/lib/poolStatistics.js +3 -1
- package/lib/settings.js +31 -6
- package/lib/sodaDocCursor.js +14 -1
- package/lib/thin/connection.js +120 -193
- package/lib/thin/dbObject.js +4 -2
- package/lib/thin/lob.js +6 -6
- package/lib/thin/pool.js +84 -10
- package/lib/thin/protocol/capabilities.js +20 -6
- package/lib/thin/protocol/constants.js +34 -54
- package/lib/thin/protocol/messages/auth.js +2 -2
- package/lib/thin/protocol/messages/base.js +28 -27
- package/lib/thin/protocol/messages/dataType.js +4 -2
- 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 +40 -11
- package/lib/thin/protocol/packet.js +93 -8
- 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 +27 -4
- package/lib/thin/sqlnet/packet.js +2 -5
- package/lib/thin/statement.js +43 -7
- package/lib/thin/statementCache.js +190 -0
- package/lib/thin/util.js +2 -2
- package/lib/transformer.js +21 -6
- package/lib/types.js +21 -3
- package/lib/util.js +30 -1
- package/lib/version.js +2 -2
- package/package.json +1 -1
- package/build/Release/oracledb-6.3.0-darwin-x64.node +0 -0
- package/build/Release/oracledb-6.3.0-darwin-x64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.3.0-js-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.3.0-linux-arm64.node +0 -0
- package/build/Release/oracledb-6.3.0-linux-arm64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.3.0-linux-x64.node +0 -0
- package/build/Release/oracledb-6.3.0-linux-x64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.3.0-win32-x64.node +0 -0
- package/build/Release/oracledb-6.3.0-win32-x64.node-buildinfo.txt +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright (c) 2023 Oracle and/or its affiliates.
|
|
1
|
+
// Copyright (c) 2023, 2024, Oracle and/or its affiliates.
|
|
2
2
|
|
|
3
3
|
//-----------------------------------------------------------------------------
|
|
4
4
|
//
|
|
@@ -31,46 +31,48 @@ const Message = require("./base.js");
|
|
|
31
31
|
|
|
32
32
|
/**
|
|
33
33
|
* Executes a Fast Negotiation RPC function.
|
|
34
|
-
* It sends Protocol Negotiation,
|
|
34
|
+
* It sends Protocol Negotiation, Datatype Negotiation
|
|
35
35
|
* and OSESS Key RPC in single round trip.
|
|
36
36
|
*
|
|
37
|
-
* @class
|
|
37
|
+
* @class FastAuthMessage
|
|
38
38
|
* @extends {Message}
|
|
39
39
|
*/
|
|
40
|
-
class
|
|
40
|
+
class FastAuthMessage extends Message {
|
|
41
41
|
|
|
42
42
|
/**
|
|
43
|
-
* Serializes the
|
|
43
|
+
* Serializes the FastAuthMessage function arguments
|
|
44
44
|
*
|
|
45
45
|
* @param {object} buf input arguments
|
|
46
46
|
*/
|
|
47
47
|
encode(buf) {
|
|
48
|
+
buf.writeUInt8(constants.TNS_MSG_TYPE_FAST_AUTH);
|
|
49
|
+
buf.writeUInt8(1); // Fast Auth version
|
|
50
|
+
buf.writeUInt8(constants.TNS_SERVER_CONVERTS_CHARS); // flag 1
|
|
51
|
+
buf.writeUInt8(0); // flag 2
|
|
48
52
|
this.protocolMessage.encode(buf);
|
|
49
|
-
buf.
|
|
50
|
-
buf.writeUInt8(
|
|
51
|
-
buf.
|
|
52
|
-
buf.
|
|
53
|
-
buf.writeUInt8(
|
|
54
|
-
buf.writeUInt16LE(this.cookie.ncharsetID);
|
|
55
|
-
buf.writeBytesWithLength(this.cookie.serverBanner);
|
|
56
|
-
buf.writeBytesWithLength(this.cookie.compileCaps);
|
|
57
|
-
buf.writeBytesWithLength(this.cookie.runtimeCaps);
|
|
53
|
+
buf.writeUInt16BE(0); // server charset (unused)
|
|
54
|
+
buf.writeUInt8(0); // server charset flag (unused)
|
|
55
|
+
buf.writeUInt16BE(0); // server ncharset (unused)
|
|
56
|
+
buf.caps.ttcFieldVersion = constants.TNS_CCAP_FIELD_VERSION_19_1_EXT_1;
|
|
57
|
+
buf.writeUInt8(buf.caps.ttcFieldVersion);
|
|
58
58
|
this.dataTypeMessage.encode(buf);
|
|
59
59
|
this.authMessage.encode(buf);
|
|
60
|
+
buf.caps.ttcFieldVersion = constants.TNS_CCAP_FIELD_VERSION_MAX;
|
|
60
61
|
}
|
|
61
62
|
|
|
62
63
|
processMessage(buf, messageType) {
|
|
63
64
|
if (messageType === constants.TNS_MSG_TYPE_RENEGOTIATE) {
|
|
64
|
-
this.
|
|
65
|
+
this.reNegotiate = true;
|
|
65
66
|
} else if (messageType === constants.TNS_MSG_TYPE_PROTOCOL) {
|
|
66
67
|
this.protocolMessage.processMessage(buf, messageType);
|
|
67
68
|
} else if (messageType === constants.TNS_MSG_TYPE_DATA_TYPES) {
|
|
68
69
|
this.dataTypeMessage.processMessage(buf, messageType);
|
|
69
70
|
} else {
|
|
70
71
|
this.authMessage.processMessage(buf, messageType);
|
|
72
|
+
this.endOfResponse = this.authMessage.endOfResponse;
|
|
71
73
|
}
|
|
72
74
|
}
|
|
73
75
|
|
|
74
76
|
}
|
|
75
77
|
|
|
76
|
-
module.exports =
|
|
78
|
+
module.exports = FastAuthMessage;
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
|
|
29
29
|
const constants = require("../constants.js");
|
|
30
30
|
const MessageWithData = require("./withData.js");
|
|
31
|
+
const errors = require("../../../errors.js");
|
|
31
32
|
|
|
32
33
|
/**
|
|
33
34
|
* Executes OFETCH RPC
|
|
@@ -51,6 +52,9 @@ class FetchMessage extends MessageWithData {
|
|
|
51
52
|
//-------------------------------------------------------------------------
|
|
52
53
|
encode(buf) {
|
|
53
54
|
this.writeFunctionHeader(buf);
|
|
55
|
+
if (this.statement.cursorId === 0) {
|
|
56
|
+
errors.throwErr(errors.ERR_CURSOR_HAS_BEEN_CLOSED);
|
|
57
|
+
}
|
|
54
58
|
buf.writeUB4(this.statement.cursorId);
|
|
55
59
|
buf.writeUB4(this.options.fetchArraySize);
|
|
56
60
|
}
|
|
@@ -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) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright (c) 2022,
|
|
1
|
+
// Copyright (c) 2022, 2024, Oracle and/or its affiliates.
|
|
2
2
|
|
|
3
3
|
//-----------------------------------------------------------------------------
|
|
4
4
|
//
|
|
@@ -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) {
|
|
@@ -117,7 +114,7 @@ class MessageWithData extends Message {
|
|
|
117
114
|
this.errorOccurred = false;
|
|
118
115
|
this.statement.moreRowsToFetch = false;
|
|
119
116
|
} else if (this.errorInfo.num !== 0 && this.errorInfo.cursorId !== 0) {
|
|
120
|
-
this.connection.statementCache.delete(this.statement.sql);
|
|
117
|
+
this.connection.statementCache._cachedStatements.delete(this.statement.sql);
|
|
121
118
|
this.statement.returnToCache = false;
|
|
122
119
|
}
|
|
123
120
|
if (this.errorInfo.batchErrors) {
|
|
@@ -148,15 +145,16 @@ class MessageWithData extends Message {
|
|
|
148
145
|
buf.skipUB1();
|
|
149
146
|
}
|
|
150
147
|
resultSet.metadata = [];
|
|
148
|
+
const metadata = [];
|
|
149
|
+
const queryVars = [];
|
|
151
150
|
for (let i = 0; i < statement.numQueryVars; i++) {
|
|
152
151
|
const variable = this.processColumnInfo(buf, i + 1);
|
|
153
152
|
if (prevQueryVars && i < prevQueryVars.length) {
|
|
154
153
|
this._adjustFetchType(prevQueryVars[i], variable);
|
|
155
154
|
}
|
|
156
|
-
|
|
157
|
-
|
|
155
|
+
queryVars.push(variable);
|
|
156
|
+
metadata.push(variable.fetchInfo);
|
|
158
157
|
}
|
|
159
|
-
|
|
160
158
|
let numBytes = buf.readUB4();
|
|
161
159
|
if (numBytes > 0) {
|
|
162
160
|
buf.skipBytesChunked(); // current date
|
|
@@ -170,6 +168,13 @@ class MessageWithData extends Message {
|
|
|
170
168
|
buf.skipBytesChunked();
|
|
171
169
|
}
|
|
172
170
|
|
|
171
|
+
/*
|
|
172
|
+
* The message state(resultSet) and statement state(queryVars) is modified
|
|
173
|
+
* at end of the DescribeInfo function so that an OutOfPacketsError
|
|
174
|
+
* won't cause partial information state to be stored.
|
|
175
|
+
*/
|
|
176
|
+
resultSet.metadata = metadata;
|
|
177
|
+
statement.queryVars = queryVars;
|
|
173
178
|
this.resultSetsToSetup.push(resultSet);
|
|
174
179
|
}
|
|
175
180
|
|
|
@@ -223,6 +228,7 @@ class MessageWithData extends Message {
|
|
|
223
228
|
nullable: nullable
|
|
224
229
|
};
|
|
225
230
|
fetchInfo.isJson = Boolean(udsFlags & constants.TNS_UDS_FLAGS_IS_JSON);
|
|
231
|
+
fetchInfo.isOson = Boolean(udsFlags & constants.TNS_UDS_FLAGS_IS_OSON);
|
|
226
232
|
if (buf.caps.ttcFieldVersion >= constants.TNS_CCAP_FIELD_VERSION_23_1) {
|
|
227
233
|
numBytes = buf.readUB4();
|
|
228
234
|
if (numBytes > 0) {
|
|
@@ -254,6 +260,19 @@ class MessageWithData extends Message {
|
|
|
254
260
|
buf.skipUB4(); // flags
|
|
255
261
|
}
|
|
256
262
|
}
|
|
263
|
+
if (buf.caps.ttcFieldVersion >= constants.TNS_CCAP_FIELD_VERSION_23_4) {
|
|
264
|
+
const dimensions = buf.readUB4();
|
|
265
|
+
const vectorFormat = buf.readUInt8();
|
|
266
|
+
const vectorFlags = buf.readUInt8();
|
|
267
|
+
if (fetchInfo.dbType === types.DB_TYPE_VECTOR) {
|
|
268
|
+
if (!(vectorFlags & constants.VECTOR_META_FLAG_FLEXIBLE_DIM)) {
|
|
269
|
+
fetchInfo.vectorDimensions = dimensions;
|
|
270
|
+
}
|
|
271
|
+
if (vectorFormat !== constants.VECTOR_FORMAT_FLEX) {
|
|
272
|
+
fetchInfo.vectorFormat = vectorFormat;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
257
276
|
|
|
258
277
|
switch (fetchInfo.dbType) {
|
|
259
278
|
case types.DB_TYPE_VARCHAR:
|
|
@@ -481,6 +500,8 @@ class MessageWithData extends Message {
|
|
|
481
500
|
}
|
|
482
501
|
} else if (oraTypeNum === constants.TNS_DATA_TYPE_JSON) {
|
|
483
502
|
colValue = buf.readOson();
|
|
503
|
+
} else if (oraTypeNum === constants.TNS_DATA_TYPE_VECTOR) {
|
|
504
|
+
colValue = buf.readVector();
|
|
484
505
|
} else if (oraTypeNum === constants.TNS_DATA_TYPE_INT_NAMED) {
|
|
485
506
|
const obj = buf.readDbObject();
|
|
486
507
|
if (obj.packedData) {
|
|
@@ -589,7 +610,8 @@ class MessageWithData extends Message {
|
|
|
589
610
|
if (variable.type === types.DB_TYPE_CLOB ||
|
|
590
611
|
variable.type === types.DB_TYPE_NCLOB ||
|
|
591
612
|
variable.type === types.DB_TYPE_BLOB ||
|
|
592
|
-
variable.type === types.DB_TYPE_JSON
|
|
613
|
+
variable.type === types.DB_TYPE_JSON ||
|
|
614
|
+
variable.type === types.DB_TYPE_VECTOR) {
|
|
593
615
|
if (variable.type !== variable.fetchInfo.fetchType) {
|
|
594
616
|
variable.type = variable.fetchInfo.fetchType;
|
|
595
617
|
variable.maxSize = constants.TNS_MAX_LONG_LENGTH;
|
|
@@ -674,6 +696,9 @@ class MessageWithData extends Message {
|
|
|
674
696
|
} else if (variable.type === types.DB_TYPE_JSON) {
|
|
675
697
|
contFlag = constants.TNS_LOB_PREFETCH_FLAG;
|
|
676
698
|
maxSize = lobPrefetchLength = constants.TNS_JSON_MAX_LENGTH;
|
|
699
|
+
} else if (variable.type === types.DB_TYPE_VECTOR) {
|
|
700
|
+
contFlag = constants.TNS_LOB_PREFETCH_FLAG;
|
|
701
|
+
maxSize = lobPrefetchLength = constants.TNS_VECTOR_MAX_LENGTH;
|
|
677
702
|
}
|
|
678
703
|
buf.writeUInt8(oraTypeNum);
|
|
679
704
|
buf.writeUInt8(flag);
|
|
@@ -794,8 +819,10 @@ class MessageWithData extends Message {
|
|
|
794
819
|
) {
|
|
795
820
|
buf.writeOracleDate(value, variable.type);
|
|
796
821
|
} else if (oraTypeNum === constants.TNS_DATA_TYPE_BINARY_DOUBLE) {
|
|
822
|
+
buf.writeUInt8(8);
|
|
797
823
|
buf.writeBinaryDouble(value);
|
|
798
824
|
} else if (oraTypeNum === constants.TNS_DATA_TYPE_BINARY_FLOAT) {
|
|
825
|
+
buf.writeUInt8(4);
|
|
799
826
|
buf.writeBinaryFloat(value);
|
|
800
827
|
} else if (oraTypeNum === constants.TNS_DATA_TYPE_CURSOR) {
|
|
801
828
|
let cursor = value;
|
|
@@ -822,7 +849,9 @@ class MessageWithData extends Message {
|
|
|
822
849
|
} else if ([constants.TNS_DATA_TYPE_ROWID, constants.TNS_DATA_TYPE_UROWID].includes(oraTypeNum)) {
|
|
823
850
|
buf.writeBytesWithLength(Buffer.from(value));
|
|
824
851
|
} else if (oraTypeNum === constants.TNS_DATA_TYPE_JSON) {
|
|
825
|
-
buf.writeOson(value);
|
|
852
|
+
buf.writeOson(value, this.connection._osonMaxFieldNameSize);
|
|
853
|
+
} else if (oraTypeNum === constants.TNS_DATA_TYPE_VECTOR) {
|
|
854
|
+
buf.writeVector(value);
|
|
826
855
|
} else if (oraTypeNum === constants.TNS_DATA_TYPE_INT_NAMED) {
|
|
827
856
|
buf.writeDbObject(value);
|
|
828
857
|
} else {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright (c) 2022,
|
|
1
|
+
// Copyright (c) 2022, 2024, Oracle and/or its affiliates.
|
|
2
2
|
|
|
3
3
|
//-----------------------------------------------------------------------------
|
|
4
4
|
//
|
|
@@ -26,14 +26,18 @@
|
|
|
26
26
|
|
|
27
27
|
'use strict';
|
|
28
28
|
|
|
29
|
-
const { BaseBuffer } = require('
|
|
29
|
+
const { BaseBuffer } = require('../../impl/datahandlers/buffer.js');
|
|
30
30
|
const { Buffer } = require('buffer');
|
|
31
|
-
const constants = require(
|
|
32
|
-
const oson = require('
|
|
31
|
+
const constants = require('./constants.js');
|
|
32
|
+
const oson = require('../../impl/datahandlers/oson.js');
|
|
33
33
|
const utils = require('./utils.js');
|
|
34
|
+
const vector = require('../../impl/datahandlers/vector.js');
|
|
34
35
|
const errors = require("../../errors.js");
|
|
35
36
|
|
|
36
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;
|
|
37
41
|
|
|
38
42
|
/**
|
|
39
43
|
* Class used for byte chunks used in the ChunkedBytesBuffer.
|
|
@@ -289,14 +293,38 @@ class ReadPacket extends BaseBuffer {
|
|
|
289
293
|
this.packetNum = packet.num;
|
|
290
294
|
}
|
|
291
295
|
|
|
292
|
-
|
|
293
|
-
|
|
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();
|
|
294
304
|
if (!this.savedPackets) {
|
|
295
305
|
this.savedPackets = [packet];
|
|
296
306
|
this.savedPacketPos = 0;
|
|
297
307
|
} else {
|
|
298
308
|
this.savedPackets.push(packet);
|
|
299
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
|
+
}
|
|
300
328
|
this.startPacket(this.savedPackets[this.savedPacketPos++]);
|
|
301
329
|
}
|
|
302
330
|
|
|
@@ -395,6 +423,22 @@ class ReadPacket extends BaseBuffer {
|
|
|
395
423
|
return {rba, partitionID, blockNum, slotNum};
|
|
396
424
|
}
|
|
397
425
|
|
|
426
|
+
/**
|
|
427
|
+
* Reads VECTOR data (QLocator followed by data) and decodes it into a
|
|
428
|
+
* JavaScript object.
|
|
429
|
+
*/
|
|
430
|
+
readVector() {
|
|
431
|
+
const numBytes = this.readUB4();
|
|
432
|
+
if (numBytes === 0) {
|
|
433
|
+
return null;
|
|
434
|
+
}
|
|
435
|
+
this.skipUB8(); // size (unused)
|
|
436
|
+
this.skipUB4(); // chunk size (unused)
|
|
437
|
+
const decoder = new vector.VectorDecoder(this.readBytesWithLength());
|
|
438
|
+
this.skipBytesChunked(); // locator (unused)
|
|
439
|
+
return decoder.decode();
|
|
440
|
+
}
|
|
441
|
+
|
|
398
442
|
skipBytesChunked() {
|
|
399
443
|
const numBytes = this.readUInt8();
|
|
400
444
|
if (numBytes === 0 || numBytes === constants.TNS_NULL_LENGTH_INDICATOR) {
|
|
@@ -478,6 +522,13 @@ class WritePacket extends BaseBuffer {
|
|
|
478
522
|
if (!finalPacket) {
|
|
479
523
|
buf = Buffer.from(buf);
|
|
480
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);
|
|
529
|
+
}
|
|
530
|
+
if (!this.nsi.ntAdapter) {
|
|
531
|
+
errors.throwErr(errors.ERR_INVALID_CONNECTION);
|
|
481
532
|
}
|
|
482
533
|
this.nsi.ntAdapter.send(buf);
|
|
483
534
|
}
|
|
@@ -525,9 +576,9 @@ class WritePacket extends BaseBuffer {
|
|
|
525
576
|
* Encodes a JavaScript object into OSON and then writes it (QLocator
|
|
526
577
|
* followed by data) to the buffer.
|
|
527
578
|
*/
|
|
528
|
-
writeOson(value) {
|
|
579
|
+
writeOson(value, osonMaxFieldSize) {
|
|
529
580
|
const encoder = new oson.OsonEncoder();
|
|
530
|
-
const buf = encoder.encode(value);
|
|
581
|
+
const buf = encoder.encode(value, osonMaxFieldSize);
|
|
531
582
|
this.writeQLocator(buf.length);
|
|
532
583
|
this.writeBytesWithLength(buf);
|
|
533
584
|
}
|
|
@@ -537,6 +588,40 @@ class WritePacket extends BaseBuffer {
|
|
|
537
588
|
this.protocol.sequenceId = (this.protocol.sequenceId + 1) % 256;
|
|
538
589
|
}
|
|
539
590
|
|
|
591
|
+
/**
|
|
592
|
+
* Encodes a JavaScript object into VECTOR data and then writes it (QLocator
|
|
593
|
+
* followed by data) to the buffer.
|
|
594
|
+
*/
|
|
595
|
+
writeVector(value) {
|
|
596
|
+
const encoder = new vector.VectorEncoder();
|
|
597
|
+
const buf = encoder.encode(value);
|
|
598
|
+
this.writeQLocator(buf.length);
|
|
599
|
+
this.writeBytesWithLength(buf);
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
//---------------------------------------------------------------------------
|
|
603
|
+
// writeQLocator()
|
|
604
|
+
//
|
|
605
|
+
// Writes a QLocator. QLocators are always 40 bytes in length.
|
|
606
|
+
//---------------------------------------------------------------------------
|
|
607
|
+
writeQLocator(numBytes) {
|
|
608
|
+
this.writeUB4(40); // QLocator length
|
|
609
|
+
this.writeUInt8(40); // repeated length
|
|
610
|
+
this.writeUInt16BE(38); // internal length
|
|
611
|
+
this.writeUInt16BE(constants.TNS_LOB_QLOCATOR_VERSION);
|
|
612
|
+
this.writeUInt8(constants.TNS_LOB_LOC_FLAGS_VALUE_BASED |
|
|
613
|
+
constants.TNS_LOB_LOC_FLAGS_BLOB | constants.TNS_LOB_LOC_FLAGS_ABSTRACT);
|
|
614
|
+
this.writeUInt8(constants.TNS_LOB_LOC_FLAGS_INIT);
|
|
615
|
+
this.writeUInt16BE(0); // additional flags
|
|
616
|
+
this.writeUInt16BE(1); // byt1
|
|
617
|
+
this.writeUInt64BE(numBytes);
|
|
618
|
+
this.writeUInt16BE(0); // unused
|
|
619
|
+
this.writeUInt16BE(0); // csid
|
|
620
|
+
this.writeUInt16BE(0); // unused
|
|
621
|
+
this.writeUInt64BE(0); // unused
|
|
622
|
+
this.writeUInt64BE(0); // unused
|
|
623
|
+
}
|
|
624
|
+
|
|
540
625
|
}
|
|
541
626
|
|
|
542
627
|
module.exports = {
|
|
@@ -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);
|