oracledb 7.0.0 → 26.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -6
- package/build/Release/oracledb-26.0.0-darwin-arm64.node +0 -0
- package/build/Release/oracledb-26.0.0-darwin-arm64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-26.0.0-js-buildinfo.txt +1 -0
- package/build/Release/oracledb-26.0.0-linux-arm64.node +0 -0
- package/build/Release/oracledb-26.0.0-linux-arm64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-26.0.0-linux-x64.node +0 -0
- package/build/Release/oracledb-26.0.0-linux-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-26.0.0-win32-x64.node +0 -0
- package/build/Release/oracledb-26.0.0-win32-x64.node-buildinfo.txt +1 -0
- package/lib/aqDeqOptions.js +4 -4
- package/lib/aqEnqOptions.js +2 -2
- package/lib/aqQueue.js +11 -6
- package/lib/connection.js +73 -18
- package/lib/constants.js +4 -0
- package/lib/endUserSecurityContext.js +30 -25
- package/lib/errors.js +92 -5
- package/lib/impl/connection.js +36 -0
- package/lib/impl/datahandlers/buffer.js +91 -18
- package/lib/impl/datahandlers/oson.js +3 -2
- package/lib/impl/parserHelpers.js +6 -2
- package/lib/impl/resultset.js +32 -11
- package/lib/oracledb.js +34 -0
- package/lib/pool.js +6 -2
- package/lib/queryStream.js +13 -5
- package/lib/resultset.js +10 -3
- package/lib/securityContextProvider.js +206 -0
- package/lib/thin/aq.js +2 -3
- package/lib/thin/connection.js +380 -24
- package/lib/thin/dbObject.js +20 -11
- package/lib/thin/pool.js +4 -3
- package/lib/thin/protocol/capabilities.js +37 -4
- package/lib/thin/protocol/constants.js +49 -1
- package/lib/thin/protocol/messages/aqArray.js +2 -2
- package/lib/thin/protocol/messages/aqBase.js +2 -2
- package/lib/thin/protocol/messages/auth.js +17 -6
- package/lib/thin/protocol/messages/base.js +75 -17
- package/lib/thin/protocol/messages/dataType.js +46 -0
- package/lib/thin/protocol/messages/directPathLoadStream.js +3 -2
- package/lib/thin/protocol/messages/execute.js +10 -4
- package/lib/thin/protocol/messages/index.js +4 -0
- package/lib/thin/protocol/messages/notification.js +281 -0
- package/lib/thin/protocol/messages/subscribe.js +181 -0
- package/lib/thin/protocol/messages/withData.js +23 -10
- package/lib/thin/protocol/packet.js +2 -4
- package/lib/thin/protocol/protocol.js +7 -4
- package/lib/thin/resultSet.js +40 -20
- package/lib/thin/sqlnet/ezConnectResolver.js +9 -2
- package/lib/thin/sqlnet/navNodes.js +7 -5
- package/lib/thin/sqlnet/networkSession.js +17 -11
- package/lib/thin/sqlnet/ntTcp.js +24 -8
- package/lib/thin/sqlnet/packet.js +24 -4
- package/lib/thin/sqlnet/sessionAtts.js +2 -2
- package/lib/thin/statement.js +6 -1
- package/lib/thin/statementCache.js +34 -6
- package/lib/thin/subscr.js +363 -0
- package/lib/transformer.js +60 -17
- package/lib/util.js +46 -8
- package/lib/version.js +1 -1
- package/package.json +1 -1
- package/plugins/configProviders/gcpstorage/index.js +121 -0
- package/plugins/configProviders/ociobject/index.js +1 -1
- package/plugins/token/cache.js +154 -0
- package/plugins/token/endUserSecurityProvider/index.js +377 -0
- package/plugins/token/extensionAzure/index.js +160 -28
- package/plugins/token/extensionOci/index.js +221 -16
- package/plugins/vectorsdk/OracleVecDB.js +346 -0
- package/plugins/vectorsdk/index.js +49 -0
- package/plugins/vectorsdk/utils.js +370 -0
- package/plugins/vectorsdk/vectorEmbedding.js +223 -0
- package/plugins/vectorsdk/vectorIndex.js +177 -0
- package/plugins/vectorsdk/vectorRecords.js +406 -0
- package/plugins/vectorsdk/vectorSchema.js +408 -0
- package/plugins/vectorsdk/vectorSearch.js +538 -0
- package/build/Release/oracledb-7.0.0-darwin-arm64.node +0 -0
- package/build/Release/oracledb-7.0.0-darwin-arm64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-7.0.0-js-buildinfo.txt +0 -1
- package/build/Release/oracledb-7.0.0-linux-arm64.node +0 -0
- package/build/Release/oracledb-7.0.0-linux-arm64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-7.0.0-linux-x64.node +0 -0
- package/build/Release/oracledb-7.0.0-linux-x64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-7.0.0-win32-x64.node +0 -0
- package/build/Release/oracledb-7.0.0-win32-x64.node-buildinfo.txt +0 -1
- package/eslint.config.js +0 -39
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright (c) 2022,
|
|
1
|
+
// Copyright (c) 2022, 2026, Oracle and/or its affiliates.
|
|
2
2
|
|
|
3
3
|
//-----------------------------------------------------------------------------
|
|
4
4
|
//
|
|
@@ -290,12 +290,15 @@ class EZConnectResolver {
|
|
|
290
290
|
// by default for TCPS protocol.
|
|
291
291
|
const serverDNMatch = this.urlProps.get("SSL_SERVER_DN_MATCH");
|
|
292
292
|
const serverCertDN = this.urlProps.get("SSL_SERVER_CERT_DN");
|
|
293
|
+
const allowWeakDNMatch = this.urlProps.get("SSL_ALLOW_WEAK_DN_MATCH");
|
|
293
294
|
const walletDir = this.urlProps.get("MY_WALLET_DIRECTORY");
|
|
294
295
|
if (serverDNMatch != null)
|
|
295
296
|
securityInfo.push(`(SSL_SERVER_DN_MATCH=${serverDNMatch})`);
|
|
296
297
|
if (serverCertDN != null)
|
|
297
298
|
securityInfo.push(`(SSL_SERVER_CERT_DN=${serverCertDN})`);
|
|
298
|
-
if (
|
|
299
|
+
if (allowWeakDNMatch != null)
|
|
300
|
+
securityInfo.push(`(SSL_ALLOW_WEAK_DN_MATCH=${allowWeakDNMatch})`);
|
|
301
|
+
if (walletDir != null && walletDir.toUpperCase() !== 'SYSTEM')
|
|
299
302
|
securityInfo.push(`(MY_WALLET_DIRECTORY=${walletDir})`);
|
|
300
303
|
}
|
|
301
304
|
if (securityInfo.length === 0)
|
|
@@ -454,6 +457,10 @@ class EZConnectResolver {
|
|
|
454
457
|
aliasMap.set("recv_timeout", "RECV_TIMEOUT");
|
|
455
458
|
aliasMap.set("ssl_server_cert_dn", "SSL_SERVER_CERT_DN");
|
|
456
459
|
aliasMap.set("ssl_server_dn_match", "SSL_SERVER_DN_MATCH");
|
|
460
|
+
aliasMap.set("tls_server_cert_dn", "SSL_SERVER_CERT_DN");
|
|
461
|
+
aliasMap.set("tls_server_dn_match", "SSL_SERVER_DN_MATCH");
|
|
462
|
+
aliasMap.set("ssl_allow_weak_dn_match", "SSL_ALLOW_WEAK_DN_MATCH");
|
|
463
|
+
aliasMap.set("tls_allow_weak_dn_match", "SSL_ALLOW_WEAK_DN_MATCH");
|
|
457
464
|
aliasMap.set("wallet_location", "MY_WALLET_DIRECTORY");
|
|
458
465
|
aliasMap.set("pool_connection_class", "POOL_CONNECTION_CLASS");
|
|
459
466
|
aliasMap.set("pool_purity", "POOL_PURITY");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright (c) 2022,
|
|
1
|
+
// Copyright (c) 2022, 2026, Oracle and/or its affiliates.
|
|
2
2
|
|
|
3
3
|
//-----------------------------------------------------------------------------
|
|
4
4
|
//
|
|
@@ -315,18 +315,20 @@ class Description {
|
|
|
315
315
|
let tmpnv;
|
|
316
316
|
for (let i = 0; i < listsize; i++) {
|
|
317
317
|
tmpnv = childnv.getListElement(i);
|
|
318
|
-
if (tmpnv.name.toUpperCase() == "SSL_SERVER_CERT_DN") {
|
|
318
|
+
if (tmpnv.name.toUpperCase() == "SSL_SERVER_CERT_DN" || tmpnv.name.toUpperCase() == "TLS_SERVER_CERT_DN") {
|
|
319
319
|
this.params.sslServerCertDN = tmpnv.valueToString();
|
|
320
|
-
} else if (tmpnv.name.toUpperCase() == "SSL_SERVER_DN_MATCH") {
|
|
320
|
+
} else if (tmpnv.name.toUpperCase() == "SSL_SERVER_DN_MATCH" || tmpnv.name.toUpperCase() == "TLS_SERVER_DN_MATCH") {
|
|
321
321
|
this.params.sslServerDNMatch = (tmpnv.atom.toLowerCase() == "yes"
|
|
322
322
|
|| tmpnv.atom.toLowerCase() == "on"
|
|
323
323
|
|| tmpnv.atom.toLowerCase() == "true");
|
|
324
|
-
} else if (tmpnv.name.toUpperCase() == "SSL_ALLOW_WEAK_DN_MATCH") {
|
|
324
|
+
} else if (tmpnv.name.toUpperCase() == "SSL_ALLOW_WEAK_DN_MATCH" || tmpnv.name.toUpperCase() == "TLS_ALLOW_WEAK_DN_MATCH") {
|
|
325
325
|
this.params.sslAllowWeakDNMatch = (tmpnv.atom.toLowerCase() == "yes"
|
|
326
326
|
|| tmpnv.atom.toLowerCase() == "on"
|
|
327
327
|
|| tmpnv.atom.toLowerCase() == "true");
|
|
328
328
|
} else if ((tmpnv.name.toUpperCase() == "WALLET_LOCATION") || (tmpnv.name.toUpperCase() == "MY_WALLET_DIRECTORY")) {
|
|
329
|
-
|
|
329
|
+
if (!(typeof tmpnv.atom === 'string' && tmpnv.atom.trim().toUpperCase() === 'SYSTEM')) {
|
|
330
|
+
this.params.walletLocation = tmpnv.atom;
|
|
331
|
+
}
|
|
330
332
|
}
|
|
331
333
|
}
|
|
332
334
|
}
|
|
@@ -157,14 +157,23 @@ class NetworkSession {
|
|
|
157
157
|
* Make the transport level connection
|
|
158
158
|
*/
|
|
159
159
|
async transportConnect(address) {
|
|
160
|
-
|
|
161
|
-
|
|
160
|
+
const protocol = address?.protocol ? address.protocol.toUpperCase() : undefined;
|
|
161
|
+
const effectiveHttpsProxy = address?.httpsProxy || this.sAtts?.nt?.httpsProxy;
|
|
162
|
+
|
|
163
|
+
// Enforce TCPS whenever an HTTPS proxy would be used (either at the address
|
|
164
|
+
// level or via the session-global proxy fallback in NTTCP).
|
|
165
|
+
if (protocol === 'TCP' && effectiveHttpsProxy) {
|
|
166
|
+
errors.throwErr(errors.ERR_INVALID_CONNECT_STRING_PARAMETERS,
|
|
167
|
+
'https proxy requires protocol as', 'tcps ');
|
|
162
168
|
}
|
|
163
|
-
|
|
169
|
+
|
|
170
|
+
if (protocol === 'TCP' || protocol === 'TCPS') {
|
|
164
171
|
this.ntAdapter = new NTTCP(this.sAtts.nt);
|
|
165
172
|
} else {
|
|
166
|
-
errors.throwErr(errors.ERR_INVALID_CONNECT_STRING_PARAMETERS,
|
|
173
|
+
errors.throwErr(errors.ERR_INVALID_CONNECT_STRING_PARAMETERS,
|
|
174
|
+
address.protocol + " protocol not supported");
|
|
167
175
|
}
|
|
176
|
+
|
|
168
177
|
await this.ntAdapter.connect(address);
|
|
169
178
|
this.ntAdapter.startRead();
|
|
170
179
|
this.sAtts.ntCha = this.ntAdapter.cha;
|
|
@@ -390,7 +399,7 @@ class NetworkSession {
|
|
|
390
399
|
} catch (err) {
|
|
391
400
|
if (err.code == 'ERR_BUFFER_TOO_LARGE') {
|
|
392
401
|
errors.throwErr(errors.ERR_INVALID_PACKET,
|
|
393
|
-
|
|
402
|
+
`Decompressed packet exceeds SDU ${maxPayload}`);
|
|
394
403
|
}
|
|
395
404
|
errors.throwErr(errors.ERR_DATA_COMPRESSION, err.message);
|
|
396
405
|
}
|
|
@@ -580,7 +589,7 @@ class NetworkSession {
|
|
|
580
589
|
if (this.isBreak) {
|
|
581
590
|
return;
|
|
582
591
|
}
|
|
583
|
-
let bytesCopied
|
|
592
|
+
let bytesCopied;
|
|
584
593
|
|
|
585
594
|
this.sndDatapkt.dataLen = this.sndDatapkt.offset;
|
|
586
595
|
if (this.sndDatapkt.dataLen < this.sndDatapkt.bufLen || !this.sndDatapkt.bufLen) {
|
|
@@ -724,10 +733,8 @@ class NetworkSession {
|
|
|
724
733
|
* returns 0 if healthy connection
|
|
725
734
|
*/
|
|
726
735
|
recvInbandNotif() {
|
|
727
|
-
let error = 0;
|
|
728
736
|
if (this.controlPkt.errno) { /* Control pkt already read */
|
|
729
|
-
|
|
730
|
-
return (error);
|
|
737
|
+
return this.controlPkt.errno;
|
|
731
738
|
} else if (!this.getOption(constants.HEALTHCHECK)) {
|
|
732
739
|
return errors.ERR_CONNECTION_CLOSED;
|
|
733
740
|
} else {
|
|
@@ -736,8 +743,7 @@ class NetworkSession {
|
|
|
736
743
|
|
|
737
744
|
if (packet.type == constants.NSPTCNL) {
|
|
738
745
|
this.controlPkt.fromPacket(packet);
|
|
739
|
-
|
|
740
|
-
return (error);
|
|
746
|
+
return this.controlPkt.errno;
|
|
741
747
|
} else {
|
|
742
748
|
this.ntAdapter.packets.unshift(packet); /* Push packet back */
|
|
743
749
|
return (0);
|
package/lib/thin/sqlnet/ntTcp.js
CHANGED
|
@@ -74,6 +74,7 @@ class NTTCP {
|
|
|
74
74
|
this.largeSDU = false;
|
|
75
75
|
this.streamNum = streamNum++;
|
|
76
76
|
this.packetNum = 1;
|
|
77
|
+
this.proxyReq = null; // track in-flight proxy CONNECT request for abort on timeout
|
|
77
78
|
this.doDNMatch = true;
|
|
78
79
|
}
|
|
79
80
|
|
|
@@ -157,7 +158,7 @@ class NTTCP {
|
|
|
157
158
|
address.port = DEFAULT_PORT;
|
|
158
159
|
}
|
|
159
160
|
|
|
160
|
-
let connectErrCause, proxyConnectErrCause
|
|
161
|
+
let connectErrCause, proxyConnectErrCause;
|
|
161
162
|
const httpsProxy = address.httpsProxy || this.atts.httpsProxy;
|
|
162
163
|
let httpsProxyPort = address.httpsProxyPort || this.atts.httpsProxyPort;
|
|
163
164
|
|
|
@@ -166,13 +167,13 @@ class NTTCP {
|
|
|
166
167
|
if (!httpsProxyPort) {
|
|
167
168
|
httpsProxyPort = DEFAULT_HTTPS_PROXY_PORT;
|
|
168
169
|
}
|
|
169
|
-
|
|
170
|
+
this.proxyReq = http.request({
|
|
170
171
|
host: httpsProxy,
|
|
171
172
|
port: httpsProxyPort,
|
|
172
173
|
method: 'CONNECT',
|
|
173
174
|
path: address.host + ':' + address.port,
|
|
174
175
|
});
|
|
175
|
-
|
|
176
|
+
this.proxyReq.once('connect', (res, socket) => {
|
|
176
177
|
if (res.statusCode == 200) {
|
|
177
178
|
this.connected = true;
|
|
178
179
|
this.stream = socket;
|
|
@@ -181,11 +182,11 @@ class NTTCP {
|
|
|
181
182
|
}
|
|
182
183
|
resolve();
|
|
183
184
|
});
|
|
184
|
-
|
|
185
|
+
this.proxyReq.once('error', (err) => {
|
|
185
186
|
proxyConnectErrCause = err.message;
|
|
186
187
|
resolve();
|
|
187
188
|
});
|
|
188
|
-
|
|
189
|
+
this.proxyReq.end();
|
|
189
190
|
} else {
|
|
190
191
|
this.stream = net.connect(address.port, address.host, () => {
|
|
191
192
|
this.connected = true;
|
|
@@ -197,8 +198,10 @@ class NTTCP {
|
|
|
197
198
|
});
|
|
198
199
|
}
|
|
199
200
|
});
|
|
200
|
-
if (
|
|
201
|
-
|
|
201
|
+
if (this.proxyReq) {
|
|
202
|
+
this.proxyReq.removeAllListeners();
|
|
203
|
+
this.proxyReq = null;
|
|
204
|
+
}
|
|
202
205
|
if (!this.connected) {
|
|
203
206
|
if (proxyConnectErrCause) {
|
|
204
207
|
errors.throwErr(errors.ERR_PROXY_CONNECTION_FAILURE, httpsProxy, httpsProxyPort, this.atts.connectionId, proxyConnectErrCause);
|
|
@@ -260,14 +263,27 @@ class NTTCP {
|
|
|
260
263
|
* @returns Promise
|
|
261
264
|
*/
|
|
262
265
|
disconnect(type) { /* Disconnect function for TCP sockets */
|
|
263
|
-
if
|
|
266
|
+
// Always tear down the socket if present, even if not yet connected
|
|
267
|
+
if (this.stream) {
|
|
264
268
|
if (type == constants.NSFIMM)
|
|
265
269
|
this.stream.destroy();
|
|
266
270
|
else
|
|
267
271
|
this.stream.end();
|
|
268
272
|
}
|
|
273
|
+
|
|
274
|
+
// Tear down any in-flight proxy CONNECT request after its socket. Keep an
|
|
275
|
+
// error listener for a socket error already pending when it is destroyed.
|
|
276
|
+
if (this.proxyReq) {
|
|
277
|
+
this.proxyReq.removeAllListeners();
|
|
278
|
+
this.proxyReq.once('error', () => {});
|
|
279
|
+
this.proxyReq.destroy();
|
|
280
|
+
this.proxyReq = null;
|
|
281
|
+
}
|
|
282
|
+
|
|
269
283
|
this.stream = null;
|
|
270
284
|
this.connected = false;
|
|
285
|
+
this.err = this.err || (type == constants.NSFIMM);
|
|
286
|
+
this._notifyWaiters();
|
|
271
287
|
this.drainWaiter = null;
|
|
272
288
|
this.readWaiter = null;
|
|
273
289
|
}
|
|
@@ -32,6 +32,20 @@ const errors = require("../../errors.js");
|
|
|
32
32
|
const MAX_CDATA_LEN = 230;
|
|
33
33
|
const NSPCNL = 74;
|
|
34
34
|
|
|
35
|
+
|
|
36
|
+
function validateAcceptDataUnits(sdu, tdu, largeSDU) {
|
|
37
|
+
const maxSdu = largeSDU ? constants.NSPABSSDULN : constants.NSPMXSDULN;
|
|
38
|
+
if (sdu < constants.NSPMNSDULN || sdu > maxSdu) {
|
|
39
|
+
const reason = `Negotiated SDU ${sdu} is outside the valid range ` +
|
|
40
|
+
`${constants.NSPMNSDULN} to ${maxSdu}`;
|
|
41
|
+
errors.throwErr(errors.ERR_INVALID_PACKET, reason);
|
|
42
|
+
}
|
|
43
|
+
if (tdu < constants.NSPMNTDULN || tdu > constants.NSPMXTDULN) {
|
|
44
|
+
const reason = `Negotiated TDU ${tdu} is outside the valid range ` +
|
|
45
|
+
`${constants.NSPMNTDULN} to ${constants.NSPMXTDULN}`;
|
|
46
|
+
errors.throwErr(errors.ERR_INVALID_PACKET, reason);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
35
49
|
/**
|
|
36
50
|
* Connect Packet (NSPTCN)
|
|
37
51
|
* @param {Buffer} connectData Outgoing Connect Data
|
|
@@ -246,13 +260,16 @@ function AcceptPacket(packet, sAtts) {
|
|
|
246
260
|
/* Set negotiated values */
|
|
247
261
|
sAtts.version = packet.buf.readUInt16BE(constants.NSPACVSN);
|
|
248
262
|
sAtts.options = packet.buf.readUInt16BE(constants.NSPACOPT);
|
|
249
|
-
|
|
250
|
-
|
|
263
|
+
|
|
264
|
+
let negotiatedSDU = packet.buf.readUInt16BE(constants.NSPACSDU);
|
|
265
|
+
let negotiatedTDU = packet.buf.readUInt16BE(constants.NSPACTDU);
|
|
266
|
+
|
|
267
|
+
sAtts.largeSDU = false;
|
|
251
268
|
|
|
252
269
|
if (sAtts.version >= 315) {
|
|
253
270
|
/* Large SDU Support */
|
|
254
|
-
|
|
255
|
-
|
|
271
|
+
negotiatedSDU = packet.buf.readUInt32BE(constants.NSPACLSD);
|
|
272
|
+
negotiatedTDU = packet.buf.readUInt32BE(constants.NSPACLTD);
|
|
256
273
|
sAtts.largeSDU = true;
|
|
257
274
|
this.cflag = packet.buf.readUInt8(constants.NSPACCFL); // 00001000
|
|
258
275
|
if ((this.cflag & constants.NSPACCFON) != 0) { // compression ON
|
|
@@ -264,6 +281,9 @@ function AcceptPacket(packet, sAtts) {
|
|
|
264
281
|
sAtts.networkCompressionEnabled = false;
|
|
265
282
|
}
|
|
266
283
|
}
|
|
284
|
+
validateAcceptDataUnits(negotiatedSDU, negotiatedTDU, sAtts.largeSDU);
|
|
285
|
+
sAtts.sdu = negotiatedSDU;
|
|
286
|
+
sAtts.tdu = negotiatedTDU;
|
|
267
287
|
|
|
268
288
|
/* Accept flags */
|
|
269
289
|
this.flag0 = packet.buf.readUInt8(constants.NSPACFL0);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright (c) 2022,
|
|
1
|
+
// Copyright (c) 2022, 2026, Oracle and/or its affiliates.
|
|
2
2
|
|
|
3
3
|
//-----------------------------------------------------------------------------
|
|
4
4
|
//
|
|
@@ -88,7 +88,7 @@ class SessionAtts {
|
|
|
88
88
|
this.networkCompressionThreshold = parseInt(params.networkCompressionThreshold);
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
if (typeof params.walletLocation === 'string') {
|
|
91
|
+
if (typeof params.walletLocation === 'string' && params.walletLocation.trim().toUpperCase() !== 'SYSTEM') {
|
|
92
92
|
this.nt.walletFile = path.join(params.walletLocation, constants.PEM_WALLET_FILE_NAME);
|
|
93
93
|
}
|
|
94
94
|
if (typeof params.walletPassword === 'string') {
|
package/lib/thin/statement.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright (c) 2022,
|
|
1
|
+
// Copyright (c) 2022, 2026, Oracle and/or its affiliates.
|
|
2
2
|
|
|
3
3
|
//-----------------------------------------------------------------------------
|
|
4
4
|
//
|
|
@@ -363,6 +363,9 @@ class Statement {
|
|
|
363
363
|
this.bufferRowCount = 0;
|
|
364
364
|
this.pendingClear = false;
|
|
365
365
|
this.statementType = constants.STMT_TYPE_UNKNOWN;
|
|
366
|
+
|
|
367
|
+
// CQN registration id attached during query registration execute.
|
|
368
|
+
this._registrationId = 0n;
|
|
366
369
|
}
|
|
367
370
|
|
|
368
371
|
//---------------------------------------------------------------------------
|
|
@@ -394,6 +397,7 @@ class Statement {
|
|
|
394
397
|
}
|
|
395
398
|
}
|
|
396
399
|
copiedStatement.returnToCache = false;
|
|
400
|
+
copiedStatement._registrationId = this._registrationId;
|
|
397
401
|
return copiedStatement;
|
|
398
402
|
}
|
|
399
403
|
|
|
@@ -555,6 +559,7 @@ class Statement {
|
|
|
555
559
|
this.numQueryVars = 0;
|
|
556
560
|
this.bufferRowCount = 0;
|
|
557
561
|
this.bufferRowIndex = 0;
|
|
562
|
+
this._registrationId = 0n;
|
|
558
563
|
}
|
|
559
564
|
|
|
560
565
|
//---------------------------------------------------------------------------
|
|
@@ -32,10 +32,34 @@ class StatementCache {
|
|
|
32
32
|
constructor(maxSize) {
|
|
33
33
|
this._cachedStatements = new Map();
|
|
34
34
|
this._maxSize = maxSize;
|
|
35
|
+
this._cursorsToCancel = new Set();
|
|
35
36
|
this._cursorsToClose = new Set();
|
|
36
37
|
this._openCursors = new Set();
|
|
37
38
|
}
|
|
38
39
|
|
|
40
|
+
//---------------------------------------------------------------------------
|
|
41
|
+
// _addCursorToCancel()
|
|
42
|
+
//
|
|
43
|
+
// Add the statement's cursor to the list of cursors that need to be
|
|
44
|
+
// cancelled.
|
|
45
|
+
//---------------------------------------------------------------------------
|
|
46
|
+
_addCursorToCancel(statement) {
|
|
47
|
+
const cursorId = statement.cursorId;
|
|
48
|
+
|
|
49
|
+
if (cursorId <= 0 || !statement.isQuery || !statement.moreRowsToFetch) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (this._cursorsToClose.has(cursorId)) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
this._cursorsToCancel.add(cursorId);
|
|
58
|
+
// Keep the cached statement tracked in _openCursors so its cursor state can
|
|
59
|
+
// be invalidated if the underlying DRCP session changes.
|
|
60
|
+
statement.moreRowsToFetch = false;
|
|
61
|
+
}
|
|
62
|
+
|
|
39
63
|
//---------------------------------------------------------------------------
|
|
40
64
|
// _addCursorToClose()
|
|
41
65
|
//
|
|
@@ -49,6 +73,8 @@ class StatementCache {
|
|
|
49
73
|
if (statement.cursorId != 0) {
|
|
50
74
|
this._cursorsToClose.add(statement.cursorId);
|
|
51
75
|
}
|
|
76
|
+
// Closing the cursor supersedes a pending cancellation.
|
|
77
|
+
this._cursorsToCancel.delete(statement.cursorId);
|
|
52
78
|
this._openCursors.delete(statement);
|
|
53
79
|
}
|
|
54
80
|
|
|
@@ -86,6 +112,7 @@ class StatementCache {
|
|
|
86
112
|
stmt._clearState();
|
|
87
113
|
}
|
|
88
114
|
this._openCursors = newOpenCursors;
|
|
115
|
+
this._cursorsToCancel.clear();
|
|
89
116
|
this._cursorsToClose.clear();
|
|
90
117
|
}
|
|
91
118
|
|
|
@@ -169,6 +196,7 @@ class StatementCache {
|
|
|
169
196
|
});
|
|
170
197
|
}
|
|
171
198
|
if (statement.returnToCache) {
|
|
199
|
+
this._addCursorToCancel(statement);
|
|
172
200
|
statement.inUse = false;
|
|
173
201
|
} else {
|
|
174
202
|
this._addCursorToClose(statement);
|
|
@@ -178,15 +206,15 @@ class StatementCache {
|
|
|
178
206
|
}
|
|
179
207
|
|
|
180
208
|
//---------------------------------------------------------------------------
|
|
181
|
-
//
|
|
182
|
-
// Write the list of cursors to
|
|
209
|
+
// writeCursors()
|
|
210
|
+
// Write the specified list of cursors to the buffer and clear the list.
|
|
183
211
|
//---------------------------------------------------------------------------
|
|
184
|
-
|
|
185
|
-
buf.writeUB4(
|
|
186
|
-
for (const cursorNum of
|
|
212
|
+
writeCursors(buf, cursors) {
|
|
213
|
+
buf.writeUB4(cursors.size);
|
|
214
|
+
for (const cursorNum of cursors) {
|
|
187
215
|
buf.writeUB4(cursorNum);
|
|
188
216
|
}
|
|
189
|
-
|
|
217
|
+
cursors.clear();
|
|
190
218
|
}
|
|
191
219
|
}
|
|
192
220
|
|