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.
Files changed (84) hide show
  1. package/README.md +16 -6
  2. package/build/Release/oracledb-26.0.0-darwin-arm64.node +0 -0
  3. package/build/Release/oracledb-26.0.0-darwin-arm64.node-buildinfo.txt +1 -0
  4. package/build/Release/oracledb-26.0.0-js-buildinfo.txt +1 -0
  5. package/build/Release/oracledb-26.0.0-linux-arm64.node +0 -0
  6. package/build/Release/oracledb-26.0.0-linux-arm64.node-buildinfo.txt +1 -0
  7. package/build/Release/oracledb-26.0.0-linux-x64.node +0 -0
  8. package/build/Release/oracledb-26.0.0-linux-x64.node-buildinfo.txt +1 -0
  9. package/build/Release/oracledb-26.0.0-win32-x64.node +0 -0
  10. package/build/Release/oracledb-26.0.0-win32-x64.node-buildinfo.txt +1 -0
  11. package/lib/aqDeqOptions.js +4 -4
  12. package/lib/aqEnqOptions.js +2 -2
  13. package/lib/aqQueue.js +11 -6
  14. package/lib/connection.js +73 -18
  15. package/lib/constants.js +4 -0
  16. package/lib/endUserSecurityContext.js +30 -25
  17. package/lib/errors.js +92 -5
  18. package/lib/impl/connection.js +36 -0
  19. package/lib/impl/datahandlers/buffer.js +91 -18
  20. package/lib/impl/datahandlers/oson.js +3 -2
  21. package/lib/impl/parserHelpers.js +6 -2
  22. package/lib/impl/resultset.js +32 -11
  23. package/lib/oracledb.js +34 -0
  24. package/lib/pool.js +6 -2
  25. package/lib/queryStream.js +13 -5
  26. package/lib/resultset.js +10 -3
  27. package/lib/securityContextProvider.js +206 -0
  28. package/lib/thin/aq.js +2 -3
  29. package/lib/thin/connection.js +380 -24
  30. package/lib/thin/dbObject.js +20 -11
  31. package/lib/thin/pool.js +4 -3
  32. package/lib/thin/protocol/capabilities.js +37 -4
  33. package/lib/thin/protocol/constants.js +49 -1
  34. package/lib/thin/protocol/messages/aqArray.js +2 -2
  35. package/lib/thin/protocol/messages/aqBase.js +2 -2
  36. package/lib/thin/protocol/messages/auth.js +17 -6
  37. package/lib/thin/protocol/messages/base.js +75 -17
  38. package/lib/thin/protocol/messages/dataType.js +46 -0
  39. package/lib/thin/protocol/messages/directPathLoadStream.js +3 -2
  40. package/lib/thin/protocol/messages/execute.js +10 -4
  41. package/lib/thin/protocol/messages/index.js +4 -0
  42. package/lib/thin/protocol/messages/notification.js +281 -0
  43. package/lib/thin/protocol/messages/subscribe.js +181 -0
  44. package/lib/thin/protocol/messages/withData.js +23 -10
  45. package/lib/thin/protocol/packet.js +2 -4
  46. package/lib/thin/protocol/protocol.js +7 -4
  47. package/lib/thin/resultSet.js +40 -20
  48. package/lib/thin/sqlnet/ezConnectResolver.js +9 -2
  49. package/lib/thin/sqlnet/navNodes.js +7 -5
  50. package/lib/thin/sqlnet/networkSession.js +17 -11
  51. package/lib/thin/sqlnet/ntTcp.js +24 -8
  52. package/lib/thin/sqlnet/packet.js +24 -4
  53. package/lib/thin/sqlnet/sessionAtts.js +2 -2
  54. package/lib/thin/statement.js +6 -1
  55. package/lib/thin/statementCache.js +34 -6
  56. package/lib/thin/subscr.js +363 -0
  57. package/lib/transformer.js +60 -17
  58. package/lib/util.js +46 -8
  59. package/lib/version.js +1 -1
  60. package/package.json +1 -1
  61. package/plugins/configProviders/gcpstorage/index.js +121 -0
  62. package/plugins/configProviders/ociobject/index.js +1 -1
  63. package/plugins/token/cache.js +154 -0
  64. package/plugins/token/endUserSecurityProvider/index.js +377 -0
  65. package/plugins/token/extensionAzure/index.js +160 -28
  66. package/plugins/token/extensionOci/index.js +221 -16
  67. package/plugins/vectorsdk/OracleVecDB.js +346 -0
  68. package/plugins/vectorsdk/index.js +49 -0
  69. package/plugins/vectorsdk/utils.js +370 -0
  70. package/plugins/vectorsdk/vectorEmbedding.js +223 -0
  71. package/plugins/vectorsdk/vectorIndex.js +177 -0
  72. package/plugins/vectorsdk/vectorRecords.js +406 -0
  73. package/plugins/vectorsdk/vectorSchema.js +408 -0
  74. package/plugins/vectorsdk/vectorSearch.js +538 -0
  75. package/build/Release/oracledb-7.0.0-darwin-arm64.node +0 -0
  76. package/build/Release/oracledb-7.0.0-darwin-arm64.node-buildinfo.txt +0 -1
  77. package/build/Release/oracledb-7.0.0-js-buildinfo.txt +0 -1
  78. package/build/Release/oracledb-7.0.0-linux-arm64.node +0 -0
  79. package/build/Release/oracledb-7.0.0-linux-arm64.node-buildinfo.txt +0 -1
  80. package/build/Release/oracledb-7.0.0-linux-x64.node +0 -0
  81. package/build/Release/oracledb-7.0.0-linux-x64.node-buildinfo.txt +0 -1
  82. package/build/Release/oracledb-7.0.0-win32-x64.node +0 -0
  83. package/build/Release/oracledb-7.0.0-win32-x64.node-buildinfo.txt +0 -1
  84. 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
- colValue = buf.readOracleDate(useLocalTime);
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(); // keyword num
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.skip(numBytes);
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
- if (variable.type === types.DB_TYPE_CLOB ||
504
- variable.type === types.DB_TYPE_NCLOB ||
505
- variable.type === types.DB_TYPE_BLOB ||
506
- variable.type === types.DB_TYPE_JSON ||
507
- variable.type === types.DB_TYPE_VECTOR) {
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.throwErr(errors.ERR_NOT_IMPLEMENTED, message);
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
- if (traceContext.userContext?.traceParent) {
257
- // The traceParent is set from instrumentation module.
258
- message.connection.appContext('CLIENTCONTEXT',
259
- [{ ora$opentelem$tracectx: traceContext.userContext.traceParent }]);
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);
@@ -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
- const cls = (this.statement.requiresFullExecute) ? ExecuteMessage : FetchMessage;
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 the statement to cache so that it can be used later
62
- //---------------------------------------------------------------------------
63
- close() {
64
- this.connection._returnStatement(this.statement);
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
- options.fetchArraySize = numRows || this.options.fetchArraySize;
96
- options.prefetchRows = this.options.prefetchRows;
97
- if (this.statement.bufferRowCount - this.statement.bufferRowIndex >= options.fetchArraySize)
98
- return this._processRows(options.fetchArraySize);
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
- options.fetchArraySize = options.fetchArraySize - (this.statement.bufferRowCount - this.statement.bufferRowIndex);
102
- const prevBufferRowCount = this.statement.bufferRowCount;
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
- options.fetchArraySize = numRows || this.options.fetchArraySize;
106
- const numRowsFetched = this.statement.bufferRowCount - this.statement.bufferRowIndex;
107
- if (prevBufferRowCount === this.statement.bufferRowCount)
108
- this.statement.bufferRowCount = 0;
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);