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
package/lib/oracledb.js CHANGED
@@ -66,6 +66,7 @@ const SodaCollection = require('./sodaCollection.js');
66
66
  const SodaDocCursor = require('./sodaDocCursor.js');
67
67
  const SodaDocument = require('./sodaDocument.js');
68
68
  const SodaOperation = require('./sodaOperation.js');
69
+ const securityContextProviderModule = require('./securityContextProvider.js');
69
70
  const EndUserSecurityContext = require('./endUserSecurityContext.js');
70
71
 
71
72
  const poolCache = {};
@@ -417,6 +418,12 @@ async function _verifyOptions(options, inCreatePool) {
417
418
  outOptions.appContext = options.appContext;
418
419
  }
419
420
 
421
+ // txnPriority must be a supported value
422
+ if (options.txnPriority !== undefined) {
423
+ errors.assertTxnPriority(options.txnPriority);
424
+ outOptions.txnPriority = options.txnPriority;
425
+ }
426
+
420
427
  // check pool specific options
421
428
  if (inCreatePool) {
422
429
 
@@ -631,6 +638,11 @@ async function createPool(options) {
631
638
  errors.throwWrapErr(error, errors.ERR_CALLOUT_FN);
632
639
  }
633
640
  }
641
+ // Connect-string parsing can rebuild the options object and omit internal
642
+ // fields. Preserve the hook-provided unified-security state before that.
643
+ const securityContextProviderForPool = options._securityContextProvider;
644
+ // This is driver-only state and must not be passed to the implementation.
645
+ delete options._securityContextProvider;
634
646
  options = await _updateUserOptionsFromConnectString(options, true);
635
647
  const sessionCallback = options.sessionCallback;
636
648
  if (typeof sessionCallback === 'function')
@@ -715,6 +727,7 @@ async function createPool(options) {
715
727
  }
716
728
 
717
729
  pool._setup(options, poolAlias);
730
+ pool._securityContextProvider = securityContextProviderForPool;
718
731
  pool._sessionCallback = sessionCallback;
719
732
  pool.on('_afterPoolClose', () => {
720
733
  if (pool.poolAlias) {
@@ -781,6 +794,9 @@ async function getConnection(a1) {
781
794
  errors.throwWrapErr(error, errors.ERR_CALLOUT_FN);
782
795
  }
783
796
  }
797
+ const securityContextProviderForConnection = options._securityContextProvider;
798
+ // This is driver-only state and must not be passed to the implementation.
799
+ delete options._securityContextProvider;
784
800
  // create a standalone connection
785
801
  options = await _updateUserOptionsFromConnectString(options, false);
786
802
  settings.addToOptions(options,
@@ -799,6 +815,7 @@ async function getConnection(a1) {
799
815
  }
800
816
  const conn = new Connection();
801
817
  conn._impl = new impl.ConnectionImpl();
818
+ conn._impl._securityContextProvider = securityContextProviderForConnection;
802
819
 
803
820
  conn._impl._connectString = options.connectString;
804
821
  conn._impl._user = options.user;
@@ -1213,6 +1230,16 @@ function registerConfigurationProviderHook(configProvider, fn) {
1213
1230
  registeredConfigProviderHooks[configProvider] = fn;
1214
1231
  }
1215
1232
 
1233
+ //-----------------------------------------------------------------------------
1234
+ // getSecurityContextProvider()
1235
+ //
1236
+ // Exposes the internal security context provider helpers without requiring
1237
+ // callers to reference the module path directly.
1238
+ //-----------------------------------------------------------------------------
1239
+ function getSecurityContextProvider() {
1240
+ return securityContextProviderModule;
1241
+ }
1242
+
1216
1243
  //-----------------------------------------------------------------------------
1217
1244
  // enquoteLiteral()
1218
1245
  //
@@ -1302,6 +1329,7 @@ module.exports = {
1302
1329
  createPool: nodbUtil.callbackify(nodbUtil.wrapFn(createPool)),
1303
1330
  getNetworkServiceNames: nodbUtil.callbackify(nodbUtil.wrapFn(getNetworkServiceNames)),
1304
1331
  getPool,
1332
+ getSecurityContextProvider,
1305
1333
  initOracleClient,
1306
1334
  isQualifiedSqlName,
1307
1335
  isSimpleSqlName,
@@ -1500,6 +1528,12 @@ module.exports = {
1500
1528
  ARRAY: constants.OUT_FORMAT_ARRAY,
1501
1529
  OBJECT: constants.OUT_FORMAT_OBJECT,
1502
1530
 
1531
+ // txnPriority
1532
+ TXN_PRIORITY_HIGH: constants.TXN_PRIORITY_HIGH,
1533
+ TXN_PRIORITY_MEDIUM: constants.TXN_PRIORITY_MEDIUM,
1534
+ TXN_PRIORITY_LOW: constants.TXN_PRIORITY_LOW,
1535
+ TXN_PRIORITY_DEFAULT: constants.TXN_PRIORITY_DEFAULT,
1536
+
1503
1537
  // Trace Interface
1504
1538
  traceHandler,
1505
1539
 
package/lib/pool.js CHANGED
@@ -1,4 +1,4 @@
1
- // Copyright (c) 2016, 2025, Oracle and/or its affiliates.
1
+ // Copyright (c) 2016, 2026, Oracle and/or its affiliates.
2
2
 
3
3
  //-----------------------------------------------------------------------------
4
4
  //
@@ -115,6 +115,7 @@ class Pool extends EventEmitter {
115
115
  this._user = options.user;
116
116
  this._connectString = options.connectString;
117
117
  this._status = constants.POOL_STATUS_OPEN;
118
+ // Current number of connections that are out for processing or being used
118
119
  this._connectionsOut = 0;
119
120
  this._poolAlias = poolAlias;
120
121
  this._bgRequestHandler();
@@ -514,6 +515,9 @@ class Pool extends EventEmitter {
514
515
  this._connectionsOut += 1;
515
516
  this._pendingRequestQueue.delete(request);
516
517
  conn._impl = await this._impl.getConnection(request.options);
518
+ // Each acquired connection uses the provider configured for this pool.
519
+ // Pools can have distinct Azure, OCI, or custom OBO configurations.
520
+ conn._impl._securityContextProvider = this._securityContextProvider;
517
521
  conn._pool = this;
518
522
  await this._tagFixup(conn, request.options.tag);
519
523
  if (request.isWaiting)
@@ -572,12 +576,12 @@ class Pool extends EventEmitter {
572
576
  // _processRequest' to decrease connectionsOut & wake up _bgRequestWaiter
573
577
  //---------------------------------------------------------------------------
574
578
  async _release(impl, options) {
575
- this._connectionsOut -= 1;
576
579
  try {
577
580
  // Directly close the connection using the underlying connection impl
578
581
  if (impl)
579
582
  await impl.close(options);
580
583
  } finally {
584
+ this._connectionsOut -= 1;
581
585
  if (this._connectionsOut == 0)
582
586
  this.emit('_allCheckedIn');
583
587
  setImmediate(() => {
@@ -1,4 +1,4 @@
1
- // Copyright (c) 2015, 2023, Oracle and/or its affiliates.
1
+ // Copyright (c) 2015, 2026, Oracle and/or its affiliates.
2
2
 
3
3
  //-----------------------------------------------------------------------------
4
4
  //
@@ -31,10 +31,11 @@ const { Readable } = require('stream');
31
31
 
32
32
  class QueryStream extends Readable {
33
33
 
34
- constructor(rs) {
34
+ constructor(rs, rowsPerDataEvent = 1) {
35
35
  super({ objectMode: true });
36
36
  this._fetching = false;
37
37
  this._numRows = 0;
38
+ this._rowsPerDataEvent = rowsPerDataEvent;
38
39
 
39
40
  // calling open via process.nextTick to allow event handlers to be
40
41
  // registered prior to the events being emitted
@@ -95,10 +96,17 @@ class QueryStream extends Readable {
95
96
  // created via ResultSet.toQueryStream()
96
97
  try {
97
98
  this._fetching = true;
99
+ const rows = [];
98
100
  this._resultSet._allowGetRowCall = true;
99
- const row = await this._resultSet.getRow();
100
- if (row) {
101
- this.push(row);
101
+ for (let i = 0; i < this._rowsPerDataEvent; i++) {
102
+ const row = await this._resultSet.getRow();
103
+ if (!row)
104
+ break;
105
+ rows.push(row);
106
+ this._resultSet._allowGetRowCall = true;
107
+ }
108
+ if (rows.length > 0) {
109
+ this.push(this._rowsPerDataEvent === 1 ? rows[0] : rows);
102
110
  } else {
103
111
  this.push(null);
104
112
  }
package/lib/resultset.js CHANGED
@@ -341,8 +341,15 @@ class ResultSet {
341
341
  //
342
342
  // Converts a result set to a QueryStream object.
343
343
  //---------------------------------------------------------------------------
344
- toQueryStream() {
345
- errors.assertArgCount(arguments, 0, 0);
344
+ toQueryStream(options) {
345
+ errors.assertArgCount(arguments, 0, 1);
346
+ if (arguments.length == 1) {
347
+ errors.assertParamValue(nodbUtil.isObject(options), 1);
348
+ options = {...options};
349
+ } else {
350
+ options = {};
351
+ }
352
+ errors.assertParamPropUnsignedIntNonZero(options, 1, "rowsPerDataEvent");
346
353
 
347
354
  if (this._processingStarted) {
348
355
  errors.throwErr(errors.ERR_CANNOT_CONVERT_RS_TO_STREAM);
@@ -354,7 +361,7 @@ class ResultSet {
354
361
 
355
362
  this._convertedToStream = true;
356
363
 
357
- return new QueryStream(this);
364
+ return new QueryStream(this, options.rowsPerDataEvent);
358
365
  }
359
366
 
360
367
  [Symbol.asyncIterator]() {
@@ -0,0 +1,206 @@
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
+ 'use strict';
27
+
28
+ const { AsyncLocalStorage } = require('async_hooks');
29
+ const errors = require('./errors.js');
30
+
31
+ const asyncLocalStorage = new AsyncLocalStorage();
32
+ // One driver-wide invocation hook dispatches every supported operation. It
33
+ // does not hold security configuration: applyForOperation() selects the
34
+ // provider from the individual connection, so pools may use different
35
+ // providers concurrently.
36
+ let invocationHook = null;
37
+
38
+ //---------------------------------------------------------------------------
39
+ // getInvocationHook()
40
+ //---------------------------------------------------------------------------
41
+ function getInvocationHook() {
42
+ return invocationHook;
43
+ }
44
+
45
+ //---------------------------------------------------------------------------
46
+ // setInvocationHook()
47
+ //---------------------------------------------------------------------------
48
+ function setInvocationHook(hook) {
49
+ invocationHook = hook;
50
+ }
51
+
52
+ //---------------------------------------------------------------------------
53
+ // _getProvider()
54
+ //
55
+ // Determines the provider associated with the supplied connection.
56
+ //---------------------------------------------------------------------------
57
+ function _getProvider(connection) {
58
+ // A token configuration hook attaches a provider to an individual pool or
59
+ // standalone connection. This permits multiple pools to use different
60
+ // identity providers in the same process without process-global state.
61
+ return connection?._securityContextProvider;
62
+ }
63
+
64
+ //---------------------------------------------------------------------------
65
+ // _clearConnection()
66
+ //
67
+ // Clears cached security context for the provided connection.
68
+ //---------------------------------------------------------------------------
69
+ function _clearConnection(connection) {
70
+ connection.clearEndUserSecurityContext();
71
+ }
72
+
73
+ //---------------------------------------------------------------------------
74
+ // getCurrentContext()
75
+ //
76
+ // Returns the current context stored in AsyncLocalStorage.
77
+ //---------------------------------------------------------------------------
78
+ function getCurrentContext() {
79
+ return asyncLocalStorage.getStore()?.metadata ?? null;
80
+ }
81
+
82
+ //---------------------------------------------------------------------------
83
+ // _getScopedValue() / _setScopedValue()
84
+ //
85
+ // Internal per-runWithContext() scratch storage; it never holds application
86
+ // metadata. The built-in provider uses it to cache an encoded EUSC in
87
+ // operation resolution. Values are keyed by provider because one scope may
88
+ // use connections from differently configured pools. The Map is fresh for
89
+ // every scope and is released with that asynchronous scope.
90
+ //---------------------------------------------------------------------------
91
+ function _getScopedValue(key) {
92
+ return asyncLocalStorage.getStore()?.values.get(key);
93
+ }
94
+
95
+ function _setScopedValue(key, value) {
96
+ const scope = asyncLocalStorage.getStore();
97
+ if (scope) {
98
+ scope.values.set(key, value);
99
+ }
100
+ }
101
+
102
+ //---------------------------------------------------------------------------
103
+ // applyForOperation()
104
+ //
105
+ // Invokes the registered provider before the supplied database operation. A
106
+ // provider returns a ready-to-apply EndUserSecurityContext, or undefined when
107
+ // this operation should use the normal database login.
108
+ //---------------------------------------------------------------------------
109
+ async function applyForOperation(connection) {
110
+ const provider = _getProvider(connection);
111
+ if (!provider) {
112
+ return;
113
+ }
114
+ const perOperation = provider._contextResolution === 'operation';
115
+ if (!perOperation && connection._securityContextInitialized) {
116
+ return;
117
+ }
118
+ let securityContext;
119
+ try {
120
+ securityContext = await provider();
121
+ } catch (err) {
122
+ const error = errors.getErr(errors.ERR_END_USER_SECURITY_CONTEXT_PROVIDER);
123
+ error.cause = err;
124
+ throw error;
125
+ }
126
+
127
+ if (securityContext) {
128
+ connection.setEndUserSecurityContext(securityContext);
129
+ }
130
+ if (!perOperation) {
131
+ // The implementation already owns the installed context. Keep only the
132
+ // fact that this borrowed connection has resolved its provider.
133
+ connection._securityContextInitialized = true;
134
+ } else if (securityContext) {
135
+ return { connection };
136
+ }
137
+ }
138
+
139
+ //---------------------------------------------------------------------------
140
+ // _validateContext()
141
+ //
142
+ // Security metadata is an object assembled by the application. Token syntax is
143
+ // deliberately not validated here; the configured identity provider remains
144
+ // authoritative for token validation and exchange.
145
+ //---------------------------------------------------------------------------
146
+ function _validateContext(context) {
147
+ if (context === null || typeof context !== 'object' || Array.isArray(context)) {
148
+ errors.throwErr(errors.ERR_INVALID_SECURITY_CONTEXT_METADATA);
149
+ }
150
+ const hasEndUserToken = context.endUserToken !== undefined &&
151
+ context.endUserToken !== null;
152
+ const hasEndUserName = context.endUserName !== undefined &&
153
+ context.endUserName !== null;
154
+ const hasKey = context.key !== undefined && context.key !== null;
155
+ // These fields represent mutually exclusive EUSC identity forms. Validate
156
+ // them before entering the callback so a conflicting request cannot perform
157
+ // unrelated work or reach a database operation before being rejected.
158
+ if (hasEndUserToken && (hasEndUserName || hasKey)) {
159
+ errors.throwErr(errors.ERR_CONFLICTING_SECURITY_CONTEXT_IDENTITIES);
160
+ }
161
+ }
162
+
163
+ //---------------------------------------------------------------------------
164
+ // runWithContext()
165
+ //
166
+ // Associates the supplied metadata object with the callback's asynchronous
167
+ // work. Applications must treat the metadata object, including nested values, as
168
+ // immutable until the callback and all its database operations complete. The
169
+ // separate Map is mutable driver-only scratch storage, not a copy of metadata.
170
+ //---------------------------------------------------------------------------
171
+ function runWithContext(context, fn, ...args) {
172
+ _validateContext(context);
173
+ if (typeof fn !== 'function') {
174
+ errors.throwErr(errors.ERR_INVALID_SECURITY_CONTEXT_CALLBACK);
175
+ }
176
+ return asyncLocalStorage.run({ metadata: context, values: new Map() },
177
+ () => fn(...args));
178
+ }
179
+
180
+ //---------------------------------------------------------------------------
181
+ function createInvocationHook() {
182
+ return {
183
+ before: async ({ connection }) => {
184
+ if (!connection) {
185
+ return undefined;
186
+ }
187
+ return await applyForOperation(connection);
188
+ },
189
+ after: (state) => {
190
+ if (state?.connection) {
191
+ _clearConnection(state.connection);
192
+ }
193
+ }
194
+ };
195
+ }
196
+
197
+ module.exports = {
198
+ applyForOperation,
199
+ runWithContext,
200
+ getCurrentContext,
201
+ _getScopedValue,
202
+ _setScopedValue,
203
+ getInvocationHook,
204
+ setInvocationHook,
205
+ createInvocationHook
206
+ };
package/lib/thin/aq.js CHANGED
@@ -1,4 +1,4 @@
1
- // Copyright (c) 2025, Oracle and/or its affiliates.
1
+ // Copyright (c) 2025, 2026, Oracle and/or its affiliates.
2
2
 
3
3
  //-----------------------------------------------------------------------------
4
4
  //
@@ -354,7 +354,6 @@ class ThinMsgPropsImpl {
354
354
  this.recipients = [];
355
355
  this.numAttempts = 0;
356
356
  this.deliveryMode = 0;
357
- this.enqTime = null;
358
357
  this.msgId = null;
359
358
  this.state = 0;
360
359
  this.payload = null;
@@ -472,4 +471,4 @@ class ThinMsgPropsImpl {
472
471
 
473
472
  }
474
473
 
475
- module.exports = { ThinQueueImpl };
474
+ module.exports = { ThinQueueImpl, ThinMsgPropsImpl };