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,363 @@
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 errors = require("../errors.js");
30
+ const constants = require("../constants.js");
31
+ const protocolUtils = require("./protocol/utils.js");
32
+ const protocolConstants = require("./protocol/constants.js");
33
+ const messages = require("./protocol/messages");
34
+
35
+ class ThinSubscrImpl {
36
+
37
+ /**
38
+ * Creates a thin subscription implementation instance.
39
+ */
40
+ constructor(connImpl, options) {
41
+ this._connImpl = connImpl;
42
+ this.callback = options.callback;
43
+ this.namespace = options.namespace;
44
+ this.name = options.name;
45
+ this.timeout = options.timeout || 0;
46
+ this.operations = options.operations || 0;
47
+ this.qos = options.qos || 0;
48
+ this.groupingClass = options.groupingClass || 0;
49
+ this.groupingValue = options.groupingValue || 0;
50
+ this.groupingType = options.groupingType || 0;
51
+ this.regId = 0n;
52
+ this.clientId = null;
53
+ this._notifyConnImpl = null;
54
+ this._notifyLoopPromise = null;
55
+ this._unsubscribing = false;
56
+ this._notifyLoopActive = false;
57
+ this._listenerStopped = false;
58
+ this._registered = false;
59
+ this._onRetire = options._onRetire;
60
+ }
61
+
62
+ /**
63
+ * Invokes the user callback safely for a decoded notification.
64
+ */
65
+ _invokeCallback(message) {
66
+ if (typeof this.callback !== 'function') {
67
+ return;
68
+ }
69
+ try {
70
+ this.callback(message);
71
+ } catch {
72
+ // swallow callback exceptions so notification loop remains active
73
+ }
74
+ }
75
+
76
+ /**
77
+ * Retires a subscription after server deregistration or successful explicit
78
+ * unsubscribe, removing the public entry that retains its callback.
79
+ */
80
+ _retire() {
81
+ this._registered = false;
82
+ this._notifyLoopActive = false;
83
+ this._listenerStopped = false;
84
+ if (this._onRetire) {
85
+ this._onRetire(this);
86
+ this._onRetire = null;
87
+ }
88
+ }
89
+
90
+ /**
91
+ * Closes and releases the dedicated EMON notification connection.
92
+ */
93
+ _closeNotifyConnection() {
94
+ const notifyConnImpl = this._notifyConnImpl;
95
+ this._notifyConnImpl = null;
96
+ if (notifyConnImpl?.nscon) {
97
+ notifyConnImpl.nscon.forceDisconnect();
98
+ }
99
+ }
100
+
101
+ /**
102
+ * Internal method that registers the subscription with the database
103
+ * and stores returned IDs.
104
+ */
105
+ async _register() {
106
+ const message = new messages.SubscrMessage(this._connImpl, this);
107
+ await this._connImpl._protocol._processMessage(message);
108
+ this.regId = message.registrationId;
109
+ this.clientId = message.clientId;
110
+ this._registered = true;
111
+ this._listenerStopped = false;
112
+ }
113
+
114
+ /**
115
+ * Marks the EMON listener as unavailable while retaining the server
116
+ * registration for explicit unregister or same-name replacement. This is
117
+ * used for abnormal/recovery cases, not normal notification completion.
118
+ */
119
+ _stopListener() {
120
+ this._notifyLoopActive = false;
121
+ this._listenerStopped = true;
122
+ }
123
+
124
+ /**
125
+ * Internal method that registers a CQN query against an existing
126
+ * subscription registration.
127
+ */
128
+ async _registerQuery(sql, binds) {
129
+ const options = {
130
+ _subscriptionRegId: this.regId,
131
+ keepInStmtCache: false,
132
+ autoCommit: false,
133
+ resultSet: true,
134
+ fetchArraySize: 1,
135
+ prefetchRows: 1
136
+ };
137
+ options.connection = {
138
+ _impl: this._connImpl,
139
+ _getDbObjectClass: (dbObjectClass) => dbObjectClass
140
+ };
141
+ const statement = this._connImpl._prepare(sql, options);
142
+ const internalTempLobs = [];
143
+ let statementReturned = false;
144
+
145
+ try {
146
+ if (!statement.isQuery) {
147
+ errors.throwErr(errors.ERR_NOT_A_QUERY);
148
+ }
149
+ const result = await this._connImpl._execute(statement, 1,
150
+ binds || [], options, false, internalTempLobs);
151
+
152
+ if (result?.resultSet) {
153
+ await result.resultSet.close();
154
+ statementReturned = true;
155
+ }
156
+ } finally {
157
+ if (!statementReturned) {
158
+ this._connImpl._returnStatement(statement);
159
+ }
160
+
161
+ for (const lob of internalTempLobs) {
162
+ this._connImpl._tempLobsToClose.push(lob._locator);
163
+ this._connImpl._tempLobsTotalSize += lob._locator.length;
164
+ }
165
+ }
166
+ }
167
+
168
+ /**
169
+ * Starts the dedicated notification channel by establishing a separate EMON
170
+ * connection, sending a single notify request, and launching the async
171
+ * receive/decode loop until the subscription is unsubscribed, deregistered,
172
+ * or the listener fails.
173
+ */
174
+ async _startNotifyLoop() {
175
+
176
+ // Use a separate EMON connection for notifications.
177
+ const notifyParams = await this._connImpl._getNotificationConnectParams();
178
+ const NotifyConnImpl = this._connImpl.constructor;
179
+ const notifyConnImpl = new NotifyConnImpl();
180
+
181
+ // Marking it as notification connection so that we do not cache
182
+ // connection parameters. Only the user-facing connection retains
183
+ // obfuscated parameters for future notification connections.
184
+ notifyConnImpl._isNotificationConnection = true;
185
+
186
+ // Retain user-facing connection metadata on the internal connection.
187
+ notifyConnImpl._connectString = this._connImpl._connectString;
188
+ notifyConnImpl._user = this._connImpl._user;
189
+ this._notifyConnImpl = notifyConnImpl;
190
+ try {
191
+ await notifyConnImpl.connect(notifyParams);
192
+
193
+ // clientId links this listener to the registered subscription.
194
+ const notifyMessage = new messages.NotifyMessage(notifyConnImpl, this);
195
+ notifyMessage.clientId = this.clientId;
196
+ await notifyConnImpl._protocol._encodeMessage(notifyMessage);
197
+
198
+ // Unsubscribe, deregistration, or listener failure stops this loop and
199
+ // closes the notification connection.
200
+ this._notifyLoopActive = true;
201
+ this._notifyLoopPromise = this._runNotifyLoop(notifyConnImpl,
202
+ notifyMessage);
203
+ this._notifyLoopPromise.catch(() => {
204
+ // prevent unhandled rejection if listener fails asynchronously
205
+ });
206
+ } catch (err) {
207
+ // Setup can fail before _runNotifyLoop() owns cleanup.
208
+ if (this._notifyConnImpl === notifyConnImpl) {
209
+ this._closeNotifyConnection();
210
+ }
211
+ throw err;
212
+ }
213
+ }
214
+
215
+ /**
216
+ * Runs the notification receive/decode loop for the dedicated channel.
217
+ */
218
+ async _runNotifyLoop(notifyConnImpl, notifyMessage) {
219
+ const protocol = notifyConnImpl._protocol;
220
+ const readBuf = protocol.readBuf;
221
+ try {
222
+ notifyMessage.preProcess();
223
+ await readBuf.waitForPackets();
224
+
225
+ // Decode records as packets arrive until unsubscribe or deregistration.
226
+ while (this._notifyLoopActive) {
227
+ try {
228
+ notifyMessage.decode(readBuf);
229
+ } catch (err) {
230
+ if (err instanceof protocolUtils.OutOfPacketsError) {
231
+ await readBuf.waitForPackets();
232
+ readBuf.restorePoint();
233
+ continue;
234
+ }
235
+ if (!this._unsubscribing) {
236
+
237
+ // Listener failure while still subscribed is unexpected.
238
+ // Throw the error.
239
+ throw err;
240
+ }
241
+
242
+ // Listener interruption during explicit unsubscribe is expected.
243
+ return;
244
+ }
245
+ }
246
+ } catch (err) {
247
+ if (!this._unsubscribing) {
248
+ // The server registration can still exist after an EMON failure. Keep
249
+ // it in the public registry so unsubscribe() can deregister it.
250
+ this._stopListener();
251
+ }
252
+ throw err;
253
+ } finally {
254
+ // Close the EMON connection whenever the loop ends without going
255
+ // through unsubscribe(), so its socket cannot keep the Node.js event
256
+ // loop alive.
257
+ if (this._notifyConnImpl === notifyConnImpl) {
258
+ this._notifyLoopActive = false;
259
+ this._closeNotifyConnection();
260
+ }
261
+ }
262
+ }
263
+
264
+ /**
265
+ * Internal method for creating a subscription. Each new subscription uses a
266
+ * dedicated client-initiated EMON connection to receive notifications. CQN
267
+ * registrations with the same name reuse this listener to add queries.
268
+ */
269
+ async subscribe(options) {
270
+ if (this.namespace === constants.SUBSCR_NAMESPACE_AQ && !this.qos) {
271
+ // Default AQ registrations request query notifications.
272
+ this.qos = constants.SUBSCR_QOS_QUERY;
273
+ }
274
+ await this._register();
275
+ try {
276
+ await this._startNotifyLoop();
277
+ if (this.namespace === constants.SUBSCR_NAMESPACE_DBCHANGE) {
278
+ await this._registerQuery(options.sql, options.binds);
279
+ }
280
+ } catch (err) {
281
+ try {
282
+ await this.unsubscribe(this._connImpl);
283
+ } catch {
284
+ // preserve the original subscribe failure
285
+ }
286
+ throw err;
287
+ }
288
+ }
289
+
290
+ /**
291
+ * Registers an additional query for an existing DBCHANGE subscription.
292
+ */
293
+ async registerQuery(options) {
294
+ if (this.namespace === constants.SUBSCR_NAMESPACE_AQ) {
295
+ errors.throwErr(errors.ERR_NOT_IMPLEMENTED,
296
+ "registering a query on AQ subscriptions");
297
+ }
298
+ if (!this._registered || this._listenerStopped) {
299
+ errors.throwErr(errors.ERR_INVALID_SUBSCR);
300
+ }
301
+ await this._registerQuery(options.sql, options.binds);
302
+ }
303
+
304
+ /**
305
+ * Internal method for destroying the subscription.
306
+ */
307
+ async unsubscribe(connImpl) {
308
+ if (!this.regId) {
309
+ errors.throwErr(errors.ERR_INVALID_SUBSCR);
310
+ }
311
+ this._unsubscribing = true;
312
+ let unregisterError;
313
+ let shouldRetire = false;
314
+ try {
315
+ if (this._registered) {
316
+ const message = new messages.SubscrMessage(connImpl, this);
317
+ message.opCode = protocolConstants.TNS_SUBSCR_OP_UNREGISTER;
318
+ message.registrationId = this.regId;
319
+ message.clientId = this.clientId;
320
+ await connImpl._protocol._processMessage(message);
321
+ }
322
+ shouldRetire = true;
323
+ } catch (err) {
324
+ unregisterError = err;
325
+ if (err.code === errors.getErr(errors.ERR_INVALID_SUBSCR).code) {
326
+ // The server already discarded this registration. Remove the public
327
+ // entry as well so its callback is not retained and the name can be
328
+ // subscribed again.
329
+ shouldRetire = true;
330
+ }
331
+ } finally {
332
+ this._notifyLoopActive = false;
333
+ if (shouldRetire) {
334
+ this._retire();
335
+ this.regId = 0n;
336
+ this.clientId = null;
337
+ } else {
338
+ // The EMON socket is closed below, so this registration cannot be
339
+ // reused without first creating a replacement listener. Retain the
340
+ // registration so the caller can retry UNREGISTER.
341
+ this._stopListener();
342
+ }
343
+ // Interrupt the background wait by force-closing the notification socket.
344
+ this._closeNotifyConnection();
345
+ if (this._notifyLoopPromise) {
346
+ try {
347
+ await this._notifyLoopPromise;
348
+ } catch {
349
+ // ignore listener errors during explicit unsubscribe
350
+ }
351
+ this._notifyLoopPromise = null;
352
+ }
353
+ if (!shouldRetire) {
354
+ this._unsubscribing = false;
355
+ }
356
+ }
357
+ if (unregisterError) {
358
+ throw unregisterError;
359
+ }
360
+ }
361
+ }
362
+
363
+ module.exports = ThinSubscrImpl;
@@ -1,4 +1,4 @@
1
- // Copyright (c) 2023, 2025, Oracle and/or its affiliates.
1
+ // Copyright (c) 2023, 2026, Oracle and/or its affiliates.
2
2
 
3
3
  //-----------------------------------------------------------------------------
4
4
  //
@@ -36,6 +36,12 @@ const util = require('util');
36
36
  const types = require('./types.js');
37
37
  const nodbUtil = require('./util.js');
38
38
 
39
+ const unsupportedJsonFieldNames = new Set([
40
+ '__proto__',
41
+ 'constructor',
42
+ 'prototype'
43
+ ]);
44
+
39
45
  //-----------------------------------------------------------------------------
40
46
  // checkType()
41
47
  //
@@ -78,12 +84,31 @@ function checkType(info, options) {
78
84
  //-----------------------------------------------------------------------------
79
85
  // transformJsonValue()
80
86
  //
81
- // Returns a normalized JSON value. Scalar values are returned unchanged.
82
- // Arrays are returned as a new array with transformed JSON values. Objects are
83
- // returned as new objects with keys "fields" and "values", both of which
84
- // are arrays (with the value transformed to JSON values).
87
+ // Returns a normalized JSON value. Supported scalar values are returned
88
+ // unchanged. Arrays are returned as a new array with transformed JSON values.
89
+ // Objects are returned as new objects with keys "fields" and "values", both of
90
+ // which are arrays (with the value transformed to JSON values).
91
+ // Only enumerable own object properties are included.
92
+ // If rejectUnsupportedTypes is set, unsupported JSON values, circular
93
+ // references, and field names are rejected.
85
94
  //-----------------------------------------------------------------------------
86
- function transformJsonValue(value) {
95
+ function transformJsonValue(value, options = {}, activeValues) {
96
+
97
+ // bigInt cannot be represented in JSON and is always rejected
98
+ if (typeof value === 'bigint') {
99
+ errors.throwErr(errors.ERR_UNSUPPORTED_JSON_VALUE_TYPE, typeof value);
100
+ }
101
+
102
+ // reject unsupported values when requested
103
+ if (options.rejectUnsupportedTypes &&
104
+ (typeof value === 'symbol' || typeof value === 'function')) {
105
+ errors.throwErr(errors.ERR_UNSUPPORTED_JSON_VALUE_TYPE, typeof value);
106
+ }
107
+
108
+ if (options.rejectUnsupportedTypes &&
109
+ typeof value === 'number' && !Number.isFinite(value)) {
110
+ errors.throwErr(errors.ERR_NON_FINITE_JSON_NUMBER);
111
+ }
87
112
 
88
113
  // handle simple scalars
89
114
  if (value === undefined || value === null ||
@@ -93,15 +118,6 @@ function transformJsonValue(value) {
93
118
  value instanceof types.IntervalYM || value instanceof types.IntervalDS)
94
119
  return value;
95
120
 
96
- // arrays are transformed to a new array with processed values
97
- if (Array.isArray(value)) {
98
- const outValue = new Array(value.length);
99
- for (let i = 0; i < value.length; i++) {
100
- outValue[i] = transformJsonValue(value[i]);
101
- }
102
- return outValue;
103
- }
104
-
105
121
  // database objects are treated as empty objects
106
122
  if (value instanceof BaseDbObject)
107
123
  return {fields: [], values: []};
@@ -112,14 +128,41 @@ function transformJsonValue(value) {
112
128
  return value;
113
129
  }
114
130
 
131
+ if (options.rejectUnsupportedTypes) {
132
+ if (!activeValues)
133
+ activeValues = new Set();
134
+ if (activeValues.has(value))
135
+ errors.throwErr(errors.ERR_INVALID_PARAMETER_VALUE, 1);
136
+ activeValues.add(value);
137
+ }
138
+
139
+ // arrays are transformed to a new array with processed values
140
+ if (Array.isArray(value)) {
141
+ const outValue = new Array(value.length);
142
+ for (let i = 0; i < value.length; i++) {
143
+ outValue[i] = transformJsonValue(value[i], options, activeValues);
144
+ }
145
+ if (activeValues)
146
+ activeValues.delete(value);
147
+ return outValue;
148
+ }
149
+
115
150
  // all other objects are transformed to an object with two arrays (fields
116
151
  // and values)
117
152
  const outValue = {};
118
- outValue.fields = Object.getOwnPropertyNames(value);
153
+ outValue.fields = Object.keys(value);
119
154
  outValue.values = new Array(outValue.fields.length);
120
155
  for (let i = 0; i < outValue.fields.length; i++) {
121
- outValue.values[i] = transformJsonValue(value[outValue.fields[i]]);
156
+ if (options.rejectUnsupportedTypes &&
157
+ unsupportedJsonFieldNames.has(outValue.fields[i])) {
158
+ errors.throwErr(errors.ERR_UNSUPPORTED_JSON_FIELD_NAME,
159
+ outValue.fields[i]);
160
+ }
161
+ outValue.values[i] = transformJsonValue(value[outValue.fields[i]], options,
162
+ activeValues);
122
163
  }
164
+ if (activeValues)
165
+ activeValues.delete(value);
123
166
  return outValue;
124
167
 
125
168
  }
package/lib/util.js CHANGED
@@ -33,6 +33,7 @@ const util = require('util');
33
33
  const types = require('./types.js');
34
34
  const constants = require('./constants.js');
35
35
  const traceHandler = require('./traceHandler.js');
36
+ const securityContextProvider = require('./securityContextProvider.js');
36
37
  const crypto = require("crypto");
37
38
 
38
39
  const pemHeaders = [
@@ -271,6 +272,8 @@ function wrapFn(func, serialize, preventConcurrentErrorCode) {
271
272
  let connImpl;
272
273
  const traceEnabled = traceHandler.isEnabled();
273
274
  const traceContext = {fn: func, args: arguments};
275
+ const hook = securityContextProvider.getInvocationHook();
276
+ let hookState;
274
277
 
275
278
  // if concurrent operations are to be prevented, check for that now
276
279
  if (preventConcurrentErrorCode) {
@@ -295,12 +298,29 @@ function wrapFn(func, serialize, preventConcurrentErrorCode) {
295
298
  if (traceEnabled) {
296
299
  traceEnterFn.call(this, traceContext);
297
300
  }
301
+ if (hook?.before) {
302
+ // more attributes like args, sql can be passed to
303
+ // provider later.
304
+ const invocation = {
305
+ target: this,
306
+ connection: connImpl
307
+ };
308
+ hookState = await hook.before(invocation);
309
+ }
298
310
  result = await traceContext.fn.apply(this, arguments);
299
- return result;
300
311
  } catch (err) {
301
312
  tErr = errors.transformErr(err, wrapper);
302
- throw tErr;
303
313
  } finally {
314
+ if (hook?.after && hookState) {
315
+ try {
316
+ await hook.after(hookState);
317
+ } catch (err) {
318
+ // Preserve the operation's error if both fail.
319
+ if (!tErr) {
320
+ tErr = errors.transformErr(err, wrapper);
321
+ }
322
+ }
323
+ }
304
324
  if (connImpl)
305
325
  connImpl._releaseLock();
306
326
  if (preventConcurrentErrorCode) {
@@ -311,6 +331,10 @@ function wrapFn(func, serialize, preventConcurrentErrorCode) {
311
331
  }
312
332
  }
313
333
 
334
+ if (tErr) {
335
+ throw tErr;
336
+ }
337
+ return result;
314
338
  };
315
339
  if (func.name) {
316
340
  Object.defineProperty(wrapper, 'name', { value: func.name });
@@ -563,19 +587,33 @@ function isVectorValue(value) {
563
587
  === Uint8Array.prototype) || value instanceof types.SparseVector);
564
588
  }
565
589
 
566
- //-----------------------------------------------------------------------------
590
+ //---------------------------------------------------------------------------
567
591
  // makeDate()
568
592
  //
569
- // Returns a date from the given components.
570
- //
571
- // -----------------------------------------------------------------------------
593
+ // Creates a Date from the supplied date/time components. When useLocal is
594
+ // true, the components are interpreted in the Node.js process local timezone.
595
+ // Otherwise, they are interpreted using the supplied UTC offset.
596
+ //---------------------------------------------------------------------------
572
597
  function makeDate(useLocal, year, month, day, hour, minute,
573
598
  second, fseconds, offset) {
574
599
  if (useLocal) {
575
600
  return new Date(year, month - 1, day, hour, minute, second, fseconds);
576
601
  }
577
- return new Date(Date.UTC(year, month - 1, day, hour, minute, second,
578
- fseconds) - offset * 60000);
602
+ return new Date(makeUTCDate(year, month, day, hour, minute, second,
603
+ fseconds).getTime() - offset * 60000);
604
+ }
605
+
606
+ //-----------------------------------------------------------------------------
607
+ // makeUTCDate()
608
+ //
609
+ // Creates a UTC date without Date.UTC()'s special handling of years 0 through
610
+ // 99, which is important when calculating historical timezone offsets.
611
+ // -----------------------------------------------------------------------------
612
+ function makeUTCDate(year, month, day, hour, minute, second, fseconds = 0) {
613
+ const date = new Date(0);
614
+ date.setUTCFullYear(year, month - 1, day);
615
+ date.setUTCHours(hour, minute, second, fseconds);
616
+ return date;
579
617
  }
580
618
 
581
619
  //---------------------------------------------------------------------------
package/lib/version.js CHANGED
@@ -29,7 +29,7 @@
29
29
  // Leave the suffix an empty string for production releases.
30
30
 
31
31
  module.exports = {
32
- VERSION_MAJOR: 7,
32
+ VERSION_MAJOR: 26,
33
33
  VERSION_MINOR: 0,
34
34
  VERSION_PATCH: 0,
35
35
  VERSION_SUFFIX: ''
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oracledb",
3
- "version": "7.0.0",
3
+ "version": "26.0.0",
4
4
  "description": "A Node.js module for Oracle Database access from JavaScript and TypeScript",
5
5
  "license": "(Apache-2.0 OR UPL-1.0)",
6
6
  "homepage": "http://oracle.github.io/node-oracledb/",