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
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
// Copyright (c) 2026, Oracle and/or its affiliates.
|
|
2
|
+
|
|
3
|
+
//-----------------------------------------------------------------------------
|
|
4
|
+
//
|
|
5
|
+
// This software is dual-licensed to you under the Universal Permissive License
|
|
6
|
+
// (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License
|
|
7
|
+
// 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose
|
|
8
|
+
// either license.
|
|
9
|
+
//
|
|
10
|
+
// If you elect to accept the software under the Apache License, Version 2.0,
|
|
11
|
+
// the following applies:
|
|
12
|
+
//
|
|
13
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
14
|
+
// you may not use this file except in compliance with the License.
|
|
15
|
+
// You may obtain a copy of the License at
|
|
16
|
+
//
|
|
17
|
+
// https://www.apache.org/licenses/LICENSE-2.0
|
|
18
|
+
//
|
|
19
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
20
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
21
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
22
|
+
// See the License for the specific language governing permissions and
|
|
23
|
+
// limitations under the License.
|
|
24
|
+
//
|
|
25
|
+
//-----------------------------------------------------------------------------
|
|
26
|
+
|
|
27
|
+
'use strict';
|
|
28
|
+
|
|
29
|
+
const constants = require("../constants.js");
|
|
30
|
+
const errors = require("../../../errors.js");
|
|
31
|
+
const pubConstants = require("../../../constants.js");
|
|
32
|
+
const AqBaseMessage = require("./aqBase.js");
|
|
33
|
+
const { BaseBuffer } = require("../../../impl/datahandlers/buffer.js");
|
|
34
|
+
const { ThinMsgPropsImpl } = require("../../aq.js");
|
|
35
|
+
|
|
36
|
+
class NotifyMessage extends AqBaseMessage {
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Creates a notify protocol message used on the dedicated listener channel.
|
|
40
|
+
*/
|
|
41
|
+
constructor(connection, subscr) {
|
|
42
|
+
super(connection);
|
|
43
|
+
this.functionCode = constants.TNS_FUNC_NOTIFY;
|
|
44
|
+
this.subscr = subscr;
|
|
45
|
+
this.clientId = null;
|
|
46
|
+
this.namespace = subscr.namespace;
|
|
47
|
+
this._processingOac = false;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Decodes the notification message and its OAC records.
|
|
52
|
+
*/
|
|
53
|
+
decode(buf) {
|
|
54
|
+
if (this._processingOac) {
|
|
55
|
+
this._processOacRecords(buf);
|
|
56
|
+
} else {
|
|
57
|
+
super.decode(buf);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Processes all available OAC notification records.
|
|
63
|
+
*/
|
|
64
|
+
_processOacRecords(buf) {
|
|
65
|
+
while (!this.endOfResponse) {
|
|
66
|
+
this._processOac(buf);
|
|
67
|
+
}
|
|
68
|
+
// Normal OAC completion does not stop a live notification listener. The
|
|
69
|
+
// EMON channel is a persistent stream and continues waiting for more
|
|
70
|
+
// packets until unsubscribe, deregistration, STOP_NOTIF, or failure.
|
|
71
|
+
this._processingOac = false;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Processes a single TTC message for notifications.
|
|
76
|
+
*/
|
|
77
|
+
processMessage(buf, messageType) {
|
|
78
|
+
|
|
79
|
+
// Notification supports OAC messages only.
|
|
80
|
+
if (messageType === constants.TNS_MSG_TYPE_OAC) {
|
|
81
|
+
this._processingOac = true;
|
|
82
|
+
this._processOacRecords(buf);
|
|
83
|
+
} else {
|
|
84
|
+
errors.throwErr(errors.ERR_UNEXPECTED_MESSAGE_TYPE, messageType, buf.pos,
|
|
85
|
+
buf.packetNum);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Processes one notification record returned by the server.
|
|
91
|
+
*/
|
|
92
|
+
_processOac(buf) {
|
|
93
|
+
buf.savePoint();
|
|
94
|
+
const notification = {
|
|
95
|
+
regId: BigInt(this.subscr.regId || 0),
|
|
96
|
+
registered: true
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
// first part is the notification header
|
|
100
|
+
const messageType = buf.readUB4();
|
|
101
|
+
if (messageType === constants.TNS_SUBSCR_STOP_NOTIF) {
|
|
102
|
+
// STOP_NOTIF is terminal for this subscription. Report it as a
|
|
103
|
+
// deregistration event and retire the public subscription entry.
|
|
104
|
+
notification.type = pubConstants.SUBSCR_EVENT_TYPE_DEREG;
|
|
105
|
+
notification.registered = false;
|
|
106
|
+
this.subscr._retire();
|
|
107
|
+
this.endOfResponse = true;
|
|
108
|
+
this.subscr._invokeCallback(notification);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
buf.skipUB4(); // error code
|
|
112
|
+
buf.skipUB4(); // registration id
|
|
113
|
+
const queueName = buf.readStrAndLength();
|
|
114
|
+
if (queueName) {
|
|
115
|
+
notification.queueName = queueName;
|
|
116
|
+
}
|
|
117
|
+
const consumerName = buf.readStrAndLength();
|
|
118
|
+
if (consumerName) {
|
|
119
|
+
notification.consumerName = consumerName;
|
|
120
|
+
}
|
|
121
|
+
const msgId = buf.readBytesAndLength();
|
|
122
|
+
if (msgId) {
|
|
123
|
+
notification.msgId = Buffer.from(msgId);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// second part is the message properties
|
|
127
|
+
this._processAqMsgProps(buf, notification);
|
|
128
|
+
buf.readBytesAndLength(); // JMS message properties
|
|
129
|
+
|
|
130
|
+
// third part is the payload (not for AQ without currently unsupported flag)
|
|
131
|
+
let payload = null;
|
|
132
|
+
if (this.namespace !== pubConstants.SUBSCR_NAMESPACE_AQ) {
|
|
133
|
+
buf.skipUB4(); // payload type
|
|
134
|
+
buf.skipUB4(); // payload flags
|
|
135
|
+
buf.skipUB4(); // chunk number
|
|
136
|
+
payload = buf.readBytesAndLength();
|
|
137
|
+
buf.readBytesAndLength(); // DB object/JSON payload
|
|
138
|
+
}
|
|
139
|
+
this._processNotificationPayload(payload, notification);
|
|
140
|
+
|
|
141
|
+
// invoke the callback with the notification that was created
|
|
142
|
+
this.subscr._invokeCallback(notification);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Processes AQ message properties, including extension key/value pairs.
|
|
147
|
+
*/
|
|
148
|
+
_processAqMsgProps(buf, notification) {
|
|
149
|
+
const numProps = buf.readUB4();
|
|
150
|
+
if (numProps > 0) {
|
|
151
|
+
const propsImpl = new ThinMsgPropsImpl();
|
|
152
|
+
buf.skipUB1(); // invalid length
|
|
153
|
+
this._processMsgProps(buf, propsImpl);
|
|
154
|
+
if (propsImpl.originalMsgId) {
|
|
155
|
+
notification.originalMsgId = Buffer.from(propsImpl.originalMsgId);
|
|
156
|
+
}
|
|
157
|
+
if (propsImpl.senderAgentName) {
|
|
158
|
+
notification.senderAgentName = propsImpl.senderAgentName.toString();
|
|
159
|
+
}
|
|
160
|
+
if (propsImpl.senderAgentAddress) {
|
|
161
|
+
notification.senderAgentAddress =
|
|
162
|
+
propsImpl.senderAgentAddress.toString();
|
|
163
|
+
}
|
|
164
|
+
notification.senderAgentProtocol = propsImpl.senderAgentProtocol;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Processes the notification payload and populates callback data.
|
|
170
|
+
*/
|
|
171
|
+
_processNotificationPayload(payload, notification) {
|
|
172
|
+
|
|
173
|
+
// payload is ignored for AQ notification
|
|
174
|
+
if (this.namespace === pubConstants.SUBSCR_NAMESPACE_AQ) {
|
|
175
|
+
notification.type = pubConstants.SUBSCR_EVENT_TYPE_AQ;
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Empty payload for DB/query change means the registration is discarded.
|
|
180
|
+
// Retire the public subscription immediately so Thin does not retain a
|
|
181
|
+
// callback for a registration that can no longer deliver notifications.
|
|
182
|
+
// readBytesAndLength() returns undefined for a zero-length payload.
|
|
183
|
+
if (payload == null) {
|
|
184
|
+
notification.type = pubConstants.SUBSCR_EVENT_TYPE_DEREG;
|
|
185
|
+
notification.registered = false;
|
|
186
|
+
this.subscr._retire();
|
|
187
|
+
this.endOfResponse = true;
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// process payload for DB/query change notification
|
|
192
|
+
if (this.subscr.qos & pubConstants.SUBSCR_QOS_DEREG_NFY) {
|
|
193
|
+
notification.registered = false;
|
|
194
|
+
this.subscr._retire();
|
|
195
|
+
this.endOfResponse = true;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const payloadBuf = new BaseBuffer(payload);
|
|
199
|
+
payloadBuf.readUInt16BE(); // version
|
|
200
|
+
payloadBuf.readUInt32BE(); // registration id
|
|
201
|
+
notification.type = payloadBuf.readUInt32BE();
|
|
202
|
+
const dbNameLen = payloadBuf.readUInt16BE();
|
|
203
|
+
if (dbNameLen > 0) {
|
|
204
|
+
notification.dbName = payloadBuf.readBytes(dbNameLen).toString();
|
|
205
|
+
}
|
|
206
|
+
notification.txId = Buffer.from(payloadBuf.readBytes(8));
|
|
207
|
+
payloadBuf.skipBytes(6); // SCN
|
|
208
|
+
if (notification.type === pubConstants.SUBSCR_EVENT_TYPE_OBJ_CHANGE) {
|
|
209
|
+
notification.tables = [];
|
|
210
|
+
this._processTables(payloadBuf, notification.tables);
|
|
211
|
+
} else if (notification.type ===
|
|
212
|
+
pubConstants.SUBSCR_EVENT_TYPE_QUERY_CHANGE) {
|
|
213
|
+
notification.queries = [];
|
|
214
|
+
this._processQueries(payloadBuf, notification.queries);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Processes query-level notification entries.
|
|
220
|
+
*/
|
|
221
|
+
_processQueries(buf, queries) {
|
|
222
|
+
const numQueries = buf.readUInt16BE();
|
|
223
|
+
for (let i = 0; i < numQueries; i++) {
|
|
224
|
+
const id = buf.readBytes(8).readBigUInt64BE(0); // query id
|
|
225
|
+
const operation = buf.readUInt32BE();
|
|
226
|
+
const query = {
|
|
227
|
+
id,
|
|
228
|
+
operation,
|
|
229
|
+
tables: []
|
|
230
|
+
};
|
|
231
|
+
this._processTables(buf, query.tables);
|
|
232
|
+
queries.push(query);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Processes row-level notification entries.
|
|
238
|
+
*/
|
|
239
|
+
_processRows(buf, rows) {
|
|
240
|
+
const numRows = buf.readUInt16BE();
|
|
241
|
+
for (let i = 0; i < numRows; i++) {
|
|
242
|
+
const operation = buf.readUInt32BE();
|
|
243
|
+
const rowIdLen = buf.readUInt16BE();
|
|
244
|
+
const rowId = buf.readBytes(rowIdLen).toString();
|
|
245
|
+
rows.push({ operation, rowid: rowId });
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Processes table-level notification entries.
|
|
251
|
+
*/
|
|
252
|
+
_processTables(buf, tables) {
|
|
253
|
+
const numTables = buf.readUInt16BE();
|
|
254
|
+
for (let i = 0; i < numTables; i++) {
|
|
255
|
+
const operation = buf.readUInt32BE();
|
|
256
|
+
const tableNameLen = buf.readUInt16BE();
|
|
257
|
+
const name = buf.readBytes(tableNameLen).toString();
|
|
258
|
+
buf.readUInt32BE(); // object num
|
|
259
|
+
const table = { operation, name, rows: [] };
|
|
260
|
+
if ((operation & pubConstants.CQN_OPCODE_ALL_ROWS) === 0) {
|
|
261
|
+
this._processRows(buf, table.rows);
|
|
262
|
+
}
|
|
263
|
+
tables.push(table);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Writes the initial notify request payload to the wire buffer.
|
|
269
|
+
*/
|
|
270
|
+
encode(buf) {
|
|
271
|
+
buf._dataFlags = constants.TNS_DATA_FLAGS_END_OF_REQUEST;
|
|
272
|
+
this.writeFunctionHeader(buf);
|
|
273
|
+
buf.writeUB4(this.clientId.length);
|
|
274
|
+
buf.writeBytesWithLength(this.clientId);
|
|
275
|
+
buf.writeUInt8(constants.TNS_INIT_KPNDRREQ);
|
|
276
|
+
buf.writeUB4(0);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
module.exports = NotifyMessage;
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
// Copyright (c) 2026, Oracle and/or its affiliates.
|
|
2
|
+
|
|
3
|
+
//-----------------------------------------------------------------------------
|
|
4
|
+
//
|
|
5
|
+
// This software is dual-licensed to you under the Universal Permissive License
|
|
6
|
+
// (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License
|
|
7
|
+
// 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose
|
|
8
|
+
// either license.
|
|
9
|
+
//
|
|
10
|
+
// If you elect to accept the software under the Apache License, Version 2.0,
|
|
11
|
+
// the following applies:
|
|
12
|
+
//
|
|
13
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
14
|
+
// you may not use this file except in compliance with the License.
|
|
15
|
+
// You may obtain a copy of the License at
|
|
16
|
+
//
|
|
17
|
+
// https://www.apache.org/licenses/LICENSE-2.0
|
|
18
|
+
//
|
|
19
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
20
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
21
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
22
|
+
// See the License for the specific language governing permissions and
|
|
23
|
+
// limitations under the License.
|
|
24
|
+
//
|
|
25
|
+
//-----------------------------------------------------------------------------
|
|
26
|
+
|
|
27
|
+
'use strict';
|
|
28
|
+
|
|
29
|
+
const constants = require("../constants.js");
|
|
30
|
+
const Message = require("./base.js");
|
|
31
|
+
const pubConstants = require("../../../constants.js");
|
|
32
|
+
|
|
33
|
+
class SubscrMessage extends Message {
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Creates a subscribe protocol message.
|
|
37
|
+
*/
|
|
38
|
+
constructor(connection, subscr) {
|
|
39
|
+
super(connection);
|
|
40
|
+
this.functionCode = constants.TNS_FUNC_SUBSCRIBE;
|
|
41
|
+
this.subscr = subscr;
|
|
42
|
+
this.registrationId = 0n;
|
|
43
|
+
this.clientId = null;
|
|
44
|
+
this.opCode = constants.TNS_SUBSCR_OP_REGISTER;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Processes the return parameters for the subscribe request.
|
|
49
|
+
*/
|
|
50
|
+
processReturnParameter(buf) {
|
|
51
|
+
let numValues = buf.readUB4(); // out parameters (kpnrl)
|
|
52
|
+
for (let i = 0; i < numValues; i++) {
|
|
53
|
+
buf.skipUB4();
|
|
54
|
+
}
|
|
55
|
+
for (let i = 0; i < numValues; i++) {
|
|
56
|
+
buf.skipUB4(); // registration id (short)
|
|
57
|
+
}
|
|
58
|
+
numValues = buf.readUB4(); // out parameters (kpngrl)
|
|
59
|
+
for (let i = 0; i < numValues; i++) {
|
|
60
|
+
this.registrationId = buf.readUB8BigInt();
|
|
61
|
+
if (buf.caps.ttcFieldVersion >= constants.TNS_CCAP_FIELD_VERSION_12_1) {
|
|
62
|
+
buf.readBytesAndLength(); // subscriber name (ignored)
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (buf.caps.ttcFieldVersion >= constants.TNS_CCAP_FIELD_VERSION_12_1) {
|
|
66
|
+
numValues = buf.readUB4(); // num database instances
|
|
67
|
+
for (let i = 0; i < numValues; i++) {
|
|
68
|
+
buf.readBytesAndLength();
|
|
69
|
+
}
|
|
70
|
+
numValues = buf.readUB4(); // num listener addresses
|
|
71
|
+
for (let i = 0; i < numValues; i++) {
|
|
72
|
+
buf.readBytesAndLength();
|
|
73
|
+
}
|
|
74
|
+
const clientId = buf.readBytesAndLength();
|
|
75
|
+
this.clientId = clientId ? Buffer.from(clientId) : null;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Writes the subscribe register/unregister payload to the wire buffer.
|
|
81
|
+
*/
|
|
82
|
+
encode(buf) {
|
|
83
|
+
let groupingType;
|
|
84
|
+
let usernameBytes;
|
|
85
|
+
let qos = constants.TNS_SUBSCR_QOS_SECURE;
|
|
86
|
+
let flags = this.subscr.operations;
|
|
87
|
+
|
|
88
|
+
// determine the QOS flags to send
|
|
89
|
+
if (this.subscr.qos & pubConstants.SUBSCR_QOS_RELIABLE) {
|
|
90
|
+
qos |= constants.TNS_SUBSCR_QOS_RELIABLE;
|
|
91
|
+
}
|
|
92
|
+
if (this.subscr.qos & pubConstants.SUBSCR_QOS_DEREG_NFY) {
|
|
93
|
+
qos |= constants.TNS_SUBSCR_QOS_PURGE_ON_NTFN;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// determine the operations flags to send
|
|
97
|
+
if (this.subscr.qos & pubConstants.SUBSCR_QOS_QUERY) {
|
|
98
|
+
flags |= constants.TNS_SUBSCR_FLAGS_QUERY;
|
|
99
|
+
}
|
|
100
|
+
if (this.subscr.qos & pubConstants.SUBSCR_QOS_ROWIDS) {
|
|
101
|
+
flags |= constants.TNS_SUBSCR_FLAGS_INCLUDE_ROWIDS;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// determine the grouping type to send; default cannot be sent unless
|
|
105
|
+
// grouping class is also set
|
|
106
|
+
if (this.subscr.groupingClass === 0) {
|
|
107
|
+
groupingType = 0;
|
|
108
|
+
} else {
|
|
109
|
+
groupingType = this.subscr.groupingType;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// write the message
|
|
113
|
+
this.writeFunctionHeader(buf);
|
|
114
|
+
buf.writeUInt8(this.opCode);
|
|
115
|
+
buf.writeUB4(constants.TNS_SUBSCR_MODE_CLIENT_INITIATED);
|
|
116
|
+
if (this.connection._user) {
|
|
117
|
+
usernameBytes = Buffer.from(this.connection._user);
|
|
118
|
+
buf.writeUInt8(1); // pointer (username)
|
|
119
|
+
buf.writeUB4(usernameBytes.length);
|
|
120
|
+
} else {
|
|
121
|
+
buf.writeUInt8(0); // pointer (username)
|
|
122
|
+
buf.writeUB4(0); // username length
|
|
123
|
+
}
|
|
124
|
+
if (this.clientId) {
|
|
125
|
+
buf.writeUInt8(1); // pointer (location)
|
|
126
|
+
buf.writeUB4(this.clientId.length);
|
|
127
|
+
} else {
|
|
128
|
+
buf.writeUInt8(0); // pointer (location)
|
|
129
|
+
buf.writeUB4(0); // location array length
|
|
130
|
+
}
|
|
131
|
+
buf.writeUInt8(1); // pointer (registration)
|
|
132
|
+
buf.writeUB4(1); // num registrations
|
|
133
|
+
buf.writeUB2(1); // raw presentation
|
|
134
|
+
buf.writeUB2(6); // version for client notif
|
|
135
|
+
buf.writeUInt8(0); // pointer (namespace out attrs)
|
|
136
|
+
buf.writeUInt8(1); // pointer (num elems array)
|
|
137
|
+
buf.writeUInt8(0); // pointer (generic out attrs)
|
|
138
|
+
buf.writeUInt8(1); // pointer (num elems array)
|
|
139
|
+
if (buf.caps.ttcFieldVersion >= constants.TNS_CCAP_FIELD_VERSION_12_1) {
|
|
140
|
+
buf.writeUInt8(1); // pointer (kpninst)
|
|
141
|
+
buf.writeUInt8(1); // pointer (kpninstl)
|
|
142
|
+
buf.writeUInt8(1); // pointer (kpngcret)
|
|
143
|
+
buf.writeUInt8(1); // pointer (kpngcretl)
|
|
144
|
+
buf.writeUInt8(1); // pointer (client id)
|
|
145
|
+
buf.writeUB4(constants.TNS_SUBSCR_CLIENT_ID_LEN);
|
|
146
|
+
buf.writeUInt8(1); // pointer (client id length)
|
|
147
|
+
}
|
|
148
|
+
if (usernameBytes) {
|
|
149
|
+
buf.writeBytesWithLength(usernameBytes);
|
|
150
|
+
}
|
|
151
|
+
if (this.clientId) {
|
|
152
|
+
buf.writeBytesWithLength(this.clientId);
|
|
153
|
+
}
|
|
154
|
+
buf.writeUB4(this.subscr.namespace);
|
|
155
|
+
if (this.subscr.name) {
|
|
156
|
+
const nameBytes = Buffer.from(this.subscr.name);
|
|
157
|
+
buf.writeUB4(nameBytes.length);
|
|
158
|
+
buf.writeBytesWithLength(nameBytes);
|
|
159
|
+
} else {
|
|
160
|
+
buf.writeUB4(0);
|
|
161
|
+
}
|
|
162
|
+
buf.writeUB4(0); // context length
|
|
163
|
+
buf.writeUB4(0); // payload type
|
|
164
|
+
buf.writeUB4(qos);
|
|
165
|
+
buf.writeUB4(0); // payload callback len (JMS)
|
|
166
|
+
buf.writeUB4(this.subscr.timeout);
|
|
167
|
+
buf.writeUB4(0); // kpdnsd
|
|
168
|
+
buf.writeUB4(flags);
|
|
169
|
+
buf.writeUB4(0); // change lag
|
|
170
|
+
buf.writeUB4(0); // change registration id
|
|
171
|
+
buf.writeUInt8(this.subscr.groupingClass);
|
|
172
|
+
buf.writeUB4(this.subscr.groupingValue);
|
|
173
|
+
buf.writeUInt8(groupingType);
|
|
174
|
+
buf.writeUB4(0); // grouping class start time
|
|
175
|
+
buf.writeSB4(0); // grouping repeat count
|
|
176
|
+
buf.writeUB8BigInt(this.registrationId);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
module.exports = SubscrMessage;
|
|
@@ -318,7 +318,8 @@ class MessageWithData extends Message {
|
|
|
318
318
|
) {
|
|
319
319
|
const useLocalTime = (oraTypeNum === constants.TNS_DATA_TYPE_DATE ||
|
|
320
320
|
oraTypeNum === constants.TNS_DATA_TYPE_TIMESTAMP);
|
|
321
|
-
|
|
321
|
+
const useDbTz = oraTypeNum === constants.TNS_DATA_TYPE_TIMESTAMP_LTZ;
|
|
322
|
+
colValue = buf.readOracleDate(useLocalTime, useDbTz);
|
|
322
323
|
} else if (oraTypeNum === constants.TNS_DATA_TYPE_ROWID) {
|
|
323
324
|
if (!this.inFetch) {
|
|
324
325
|
colValue = buf.readStr(constants.CSFRM_IMPLICIT);
|
|
@@ -425,8 +426,11 @@ class MessageWithData extends Message {
|
|
|
425
426
|
return colValue;
|
|
426
427
|
}
|
|
427
428
|
|
|
429
|
+
/**
|
|
430
|
+
* Processes execute return parameters, including keyword/value pairs and
|
|
431
|
+
* registration data, and optional array DML row counts.
|
|
432
|
+
*/
|
|
428
433
|
processReturnParameter(buf) {
|
|
429
|
-
let keywordNum = 0;
|
|
430
434
|
let keyTextValue;
|
|
431
435
|
let numParams = buf.readUB2(); // al8o4l (ignored)
|
|
432
436
|
|
|
@@ -447,16 +451,18 @@ class MessageWithData extends Message {
|
|
|
447
451
|
if (numBytes > 0) {
|
|
448
452
|
buf.skipBytesChunked();
|
|
449
453
|
}
|
|
450
|
-
keywordNum = buf.readUB2();
|
|
454
|
+
const keywordNum = buf.readUB2(); // keyword num
|
|
451
455
|
if (keywordNum === constants.TNS_KEYWORD_NUM_CURRENT_SCHEMA) {
|
|
452
456
|
this.connection.currentSchema = keyTextValue;
|
|
453
457
|
} else if (keywordNum === constants.TNS_KEYWORD_NUM_EDITION) {
|
|
454
458
|
this.connection._edition = keyTextValue;
|
|
459
|
+
} else if (keywordNum === constants.TNS_KEYWORD_NUM_TXN_PRIORITY) {
|
|
460
|
+
this.connection._txnPriority = keyTextValue;
|
|
455
461
|
}
|
|
456
462
|
}
|
|
457
463
|
numBytes = buf.readUB2(); // registration
|
|
458
464
|
if (numBytes > 0) {
|
|
459
|
-
buf.
|
|
465
|
+
buf.skipBytes(numBytes);
|
|
460
466
|
}
|
|
461
467
|
if (this.arrayDmlRowCounts) {
|
|
462
468
|
const numRows = buf.readUB4();
|
|
@@ -500,13 +506,20 @@ class MessageWithData extends Message {
|
|
|
500
506
|
// LOBs always require define and they change the type that is actually
|
|
501
507
|
// returned by the server
|
|
502
508
|
for (const variable of resultSet.statement.queryVars) {
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
509
|
+
// Use the original database type here. The variable type may already
|
|
510
|
+
// have been changed to the requested define type, such as LONG_RAW for
|
|
511
|
+
// a BLOB fetched as a Buffer, but the original BLOB still requires the
|
|
512
|
+
// special define handling below.
|
|
513
|
+
const dbType = variable.fetchInfo.dbType;
|
|
514
|
+
if (dbType === types.DB_TYPE_CLOB ||
|
|
515
|
+
dbType === types.DB_TYPE_NCLOB ||
|
|
516
|
+
dbType === types.DB_TYPE_BLOB ||
|
|
517
|
+
dbType === types.DB_TYPE_JSON ||
|
|
518
|
+
dbType === types.DB_TYPE_VECTOR) {
|
|
508
519
|
if (variable.type !== variable.fetchInfo.fetchType) {
|
|
509
520
|
variable.type = variable.fetchInfo.fetchType;
|
|
521
|
+
}
|
|
522
|
+
if (dbType !== variable.fetchInfo.fetchType) {
|
|
510
523
|
variable.maxSize = constants.TNS_MAX_LONG_LENGTH;
|
|
511
524
|
}
|
|
512
525
|
if (!resultSet.statement.noPrefetch) {
|
|
@@ -755,7 +768,7 @@ class MessageWithData extends Message {
|
|
|
755
768
|
buf.writeDbObject(value);
|
|
756
769
|
} else {
|
|
757
770
|
const message = `Binding data of type ${variable.type}`;
|
|
758
|
-
errors.
|
|
771
|
+
errors.throwNotImplemented(message);
|
|
759
772
|
}
|
|
760
773
|
}
|
|
761
774
|
|
|
@@ -144,9 +144,8 @@ class ReadPacket extends BaseBuffer {
|
|
|
144
144
|
*/
|
|
145
145
|
|
|
146
146
|
constructor(nsi, caps) {
|
|
147
|
-
super();
|
|
147
|
+
super(undefined, caps);
|
|
148
148
|
this.nsi = nsi;
|
|
149
|
-
this.caps = caps;
|
|
150
149
|
this.chunkedBytesBuf = new ChunkedBytesBuffer();
|
|
151
150
|
}
|
|
152
151
|
|
|
@@ -530,12 +529,11 @@ class ReadPacket extends BaseBuffer {
|
|
|
530
529
|
class WritePacket extends BaseBuffer {
|
|
531
530
|
|
|
532
531
|
constructor(nsi, caps, protocol) {
|
|
533
|
-
super(nsi.sAtts.sdu);
|
|
532
|
+
super(nsi.sAtts.sdu, caps);
|
|
534
533
|
this.size = this.maxSize;
|
|
535
534
|
this.isLargeSDU = nsi.sAtts.version >= constants.TNS_VERSION_MIN_LARGE_SDU;
|
|
536
535
|
this.protocol = protocol;
|
|
537
536
|
this.packetType = constants.TNS_PACKET_TYPE_DATA;
|
|
538
|
-
this.caps = caps;
|
|
539
537
|
this.nsi = nsi;
|
|
540
538
|
this._dataFlags = 0;
|
|
541
539
|
this.tokenNum = 0;
|
|
@@ -253,10 +253,13 @@ class Protocol {
|
|
|
253
253
|
if (traceEnabled) {
|
|
254
254
|
traceContext.operation = `oracledb.${message.constructor.name}`;
|
|
255
255
|
traceInstance.onBeginRoundTrip(traceContext);
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
256
|
+
|
|
257
|
+
const { traceParent, traceState } = traceContext.userContext ?? {};
|
|
258
|
+
if (traceParent) {
|
|
259
|
+
const state = traceState ? `tracestate: ${traceState}\r\n` : '';
|
|
260
|
+
message.connection.appContext('CLIENTCONTEXT', [{
|
|
261
|
+
ora$opentelem$tracectx: `traceparent: ${traceParent}\r\n${state}`
|
|
262
|
+
}]);
|
|
260
263
|
}
|
|
261
264
|
}
|
|
262
265
|
await this._encodeMessage(message);
|
package/lib/thin/resultSet.js
CHANGED
|
@@ -39,7 +39,12 @@ class ThinResultSetImpl extends ResultSetImpl {
|
|
|
39
39
|
// OAL8 RPC if needed; otherwise, the simpler OFETCH RPC is used.
|
|
40
40
|
//---------------------------------------------------------------------------
|
|
41
41
|
async _fetchMoreRows(options) {
|
|
42
|
-
|
|
42
|
+
// prepare the prefetch value for execute
|
|
43
|
+
options.prefetchRows = this.options.prefetchRows;
|
|
44
|
+
|
|
45
|
+
// execute/fetch
|
|
46
|
+
const cls = (this.statement.requiresFullExecute) ?
|
|
47
|
+
ExecuteMessage : FetchMessage;
|
|
43
48
|
const message = new cls(this.connection, this.statement, options, this);
|
|
44
49
|
await this.connection._protocol._processMessage(message);
|
|
45
50
|
this.statement.requiresFullExecute = false;
|
|
@@ -58,18 +63,18 @@ class ThinResultSetImpl extends ResultSetImpl {
|
|
|
58
63
|
}
|
|
59
64
|
|
|
60
65
|
//---------------------------------------------------------------------------
|
|
61
|
-
// Returns
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
//---------------------------------------------------------------------------
|
|
68
|
-
// Returns rows fetched to the common layer in array format
|
|
66
|
+
// Returns rows fetched to the common layer in array format. The caller
|
|
67
|
+
// guarantees that numRowsFetched does not exceed the rows remaining in the
|
|
68
|
+
// statement buffer. This method consumes those rows by advancing
|
|
69
|
+
// bufferRowIndex.
|
|
69
70
|
//---------------------------------------------------------------------------
|
|
70
71
|
_processRows(numRowsFetched) {
|
|
71
72
|
const rows = [];
|
|
73
|
+
|
|
74
|
+
// Index of the first unconsumed row in the statement buffer
|
|
72
75
|
const bufferRowIndex = this.statement.bufferRowIndex;
|
|
76
|
+
|
|
77
|
+
// Get the rows
|
|
73
78
|
for (let row = bufferRowIndex; row < bufferRowIndex + numRowsFetched; row++) {
|
|
74
79
|
const rowObj = [];
|
|
75
80
|
for (let col = 0; col < this.statement.numQueryVars; col++) {
|
|
@@ -77,7 +82,12 @@ class ThinResultSetImpl extends ResultSetImpl {
|
|
|
77
82
|
}
|
|
78
83
|
rows.push(rowObj);
|
|
79
84
|
}
|
|
85
|
+
|
|
86
|
+
// Consume the rows returned above; numRowsFetched is never greater than
|
|
87
|
+
// (bufferRowCount - bufferRowIndex) when this method is called
|
|
80
88
|
this.statement.bufferRowIndex += numRowsFetched;
|
|
89
|
+
|
|
90
|
+
// An empty buffer is reset so that the next fetch starts at index zero
|
|
81
91
|
if (this.statement.bufferRowIndex === this.statement.bufferRowCount) {
|
|
82
92
|
this.statement.bufferRowCount = 0;
|
|
83
93
|
this.statement.bufferRowIndex = 0;
|
|
@@ -85,6 +95,13 @@ class ThinResultSetImpl extends ResultSetImpl {
|
|
|
85
95
|
return rows;
|
|
86
96
|
}
|
|
87
97
|
|
|
98
|
+
//---------------------------------------------------------------------------
|
|
99
|
+
// Returns the statement to cache so that it can be used later
|
|
100
|
+
//---------------------------------------------------------------------------
|
|
101
|
+
close() {
|
|
102
|
+
this.connection._returnStatement(this.statement);
|
|
103
|
+
}
|
|
104
|
+
|
|
88
105
|
//---------------------------------------------------------------------------
|
|
89
106
|
// getRows()
|
|
90
107
|
//
|
|
@@ -92,20 +109,23 @@ class ThinResultSetImpl extends ResultSetImpl {
|
|
|
92
109
|
// the common layer for processing.
|
|
93
110
|
//---------------------------------------------------------------------------
|
|
94
111
|
async getRows(numRows, options) {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
112
|
+
const numRowsRequested = numRows || this.options.fetchArraySize;
|
|
113
|
+
|
|
114
|
+
// Number of rows currently available, starting at bufferRowIndex
|
|
115
|
+
const rowsInBuffer = this.statement.bufferRowCount -
|
|
116
|
+
this.statement.bufferRowIndex;
|
|
117
|
+
if (rowsInBuffer >= numRowsRequested)
|
|
118
|
+
return this._processRows(numRowsRequested);
|
|
99
119
|
|
|
100
120
|
// We fetch for the required number of rows
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
if (this.statement.moreRowsToFetch && options.fetchArraySize > 0)
|
|
121
|
+
if (this.statement.moreRowsToFetch) {
|
|
122
|
+
options.fetchArraySize = numRowsRequested - rowsInBuffer;
|
|
104
123
|
await this._fetchMoreRows(options);
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// All rows currently remaining in the buffer are returned in this path
|
|
127
|
+
const numRowsFetched = this.statement.bufferRowCount -
|
|
128
|
+
this.statement.bufferRowIndex;
|
|
109
129
|
|
|
110
130
|
// process the rows fetched
|
|
111
131
|
return this._processRows(numRowsFetched);
|