oracledb 6.7.2 → 6.9.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/LICENSE.txt +1 -1
  2. package/NOTICE.txt +1 -1
  3. package/README.md +39 -3
  4. package/build/Release/oracledb-6.9.0-darwin-arm64.node +0 -0
  5. package/build/Release/oracledb-6.9.0-darwin-arm64.node-buildinfo.txt +1 -0
  6. package/build/Release/oracledb-6.9.0-darwin-x64.node +0 -0
  7. package/build/Release/oracledb-6.9.0-darwin-x64.node-buildinfo.txt +1 -0
  8. package/build/Release/oracledb-6.9.0-js-buildinfo.txt +1 -0
  9. package/build/Release/oracledb-6.9.0-linux-arm64.node +0 -0
  10. package/build/Release/oracledb-6.9.0-linux-arm64.node-buildinfo.txt +1 -0
  11. package/build/Release/oracledb-6.9.0-linux-x64.node +0 -0
  12. package/build/Release/oracledb-6.9.0-linux-x64.node-buildinfo.txt +1 -0
  13. package/build/Release/oracledb-6.9.0-win32-x64.node +0 -0
  14. package/build/Release/oracledb-6.9.0-win32-x64.node-buildinfo.txt +1 -0
  15. package/lib/aqMessage.js +10 -1
  16. package/lib/configProviders/file.js +72 -0
  17. package/lib/connection.js +153 -4
  18. package/lib/dbObject.js +51 -10
  19. package/lib/errors.js +144 -36
  20. package/lib/impl/connection.js +24 -1
  21. package/lib/impl/datahandlers/buffer.js +92 -1
  22. package/lib/impl/datahandlers/constants.js +2 -0
  23. package/lib/impl/datahandlers/oson.js +15 -1
  24. package/lib/impl/datahandlers/vector.js +72 -27
  25. package/lib/impl/pool.js +10 -1
  26. package/lib/impl/resultset.js +5 -4
  27. package/lib/lob.js +9 -1
  28. package/lib/oracledb.js +209 -20
  29. package/lib/pool.js +12 -1
  30. package/lib/poolStatistics.js +3 -1
  31. package/lib/settings.js +5 -1
  32. package/lib/thin/connection.js +130 -12
  33. package/lib/thin/dbObject.js +46 -13
  34. package/lib/thin/lob.js +2 -3
  35. package/lib/thin/pool.js +112 -31
  36. package/lib/thin/protocol/capabilities.js +8 -4
  37. package/lib/thin/protocol/constants.js +31 -1
  38. package/lib/thin/protocol/messages/auth.js +42 -6
  39. package/lib/thin/protocol/messages/base.js +98 -9
  40. package/lib/thin/protocol/messages/dataType.js +2 -1
  41. package/lib/thin/protocol/messages/execute.js +46 -4
  42. package/lib/thin/protocol/messages/fastAuth.js +6 -1
  43. package/lib/thin/protocol/messages/lobOp.js +5 -22
  44. package/lib/thin/protocol/messages/logOff.js +0 -1
  45. package/lib/thin/protocol/messages/sessionRelease.js +0 -1
  46. package/lib/thin/protocol/messages/transactionSwitch.js +12 -4
  47. package/lib/thin/protocol/messages/withData.js +10 -1
  48. package/lib/thin/protocol/packet.js +1 -1
  49. package/lib/thin/protocol/protocol.js +2 -1
  50. package/lib/thin/sqlnet/ANO.js +438 -0
  51. package/lib/thin/sqlnet/connStrategy.js +2 -1
  52. package/lib/thin/sqlnet/constants.js +5 -1
  53. package/lib/thin/sqlnet/ezConnectResolver.js +4 -2
  54. package/lib/thin/sqlnet/navNodes.js +22 -3
  55. package/lib/thin/sqlnet/networkSession.js +94 -16
  56. package/lib/thin/sqlnet/ntTcp.js +50 -3
  57. package/lib/thin/sqlnet/packet.js +32 -4
  58. package/lib/thin/sqlnet/sessionAtts.js +24 -2
  59. package/lib/thin/util.js +3 -8
  60. package/lib/transformer.js +13 -2
  61. package/lib/types.js +220 -8
  62. package/lib/util.js +77 -3
  63. package/lib/version.js +2 -2
  64. package/package/install.js +3 -3
  65. package/package/prunebinaries.js +6 -12
  66. package/package.json +2 -2
  67. package/{lib/configProviders/azure.js → plugins/configProviders/azure/index.js} +70 -63
  68. package/plugins/configProviders/azurevault/index.js +84 -0
  69. package/{lib → plugins}/configProviders/base.js +13 -3
  70. package/{lib/configProviders/ociobject.js → plugins/configProviders/ociobject/index.js} +43 -78
  71. package/plugins/configProviders/ocivault/index.js +100 -0
  72. package/plugins/token/extensionAzure/index.js +101 -0
  73. package/plugins/token/extensionOci/index.js +210 -0
  74. package/build/Release/oracledb-6.7.2-darwin-arm64.node +0 -0
  75. package/build/Release/oracledb-6.7.2-darwin-arm64.node-buildinfo.txt +0 -1
  76. package/build/Release/oracledb-6.7.2-darwin-x64.node +0 -0
  77. package/build/Release/oracledb-6.7.2-darwin-x64.node-buildinfo.txt +0 -1
  78. package/build/Release/oracledb-6.7.2-js-buildinfo.txt +0 -1
  79. package/build/Release/oracledb-6.7.2-linux-arm64.node +0 -0
  80. package/build/Release/oracledb-6.7.2-linux-arm64.node-buildinfo.txt +0 -1
  81. package/build/Release/oracledb-6.7.2-linux-x64.node +0 -0
  82. package/build/Release/oracledb-6.7.2-linux-x64.node-buildinfo.txt +0 -1
  83. package/build/Release/oracledb-6.7.2-win32-x64.node +0 -0
  84. package/build/Release/oracledb-6.7.2-win32-x64.node-buildinfo.txt +0 -1
package/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2015, 2024 Oracle and/or its affiliates.
1
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates.
2
2
 
3
3
  This software is dual-licensed to you under the Universal Permissive License
4
4
  (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License
package/NOTICE.txt CHANGED
@@ -1 +1 @@
1
- Copyright (c) 2015, 2024, Oracle and/or its affiliates.
1
+ Copyright (c) 2015, 2025, Oracle and/or its affiliates.
package/README.md CHANGED
@@ -1,10 +1,10 @@
1
- # node-oracledb version 6.7.2
1
+ # node-oracledb version 6.9.0 <img src="https://img.shields.io/npm/v/oracledb.svg" alt="oracledb"/> <img src="https://img.shields.io/npm/dm/oracledb.svg" alt="oracledb"/>
2
2
 
3
3
  The node-oracledb add-on for Node.js powers high performance Oracle Database
4
4
  applications. Applications can be written in TypeScript, or directly in
5
5
  JavaScript.
6
6
 
7
- Use node-oracledb 6.7.2 to connect Node.js 14.6, or later, to Oracle
7
+ Use node-oracledb 6.9.0 to connect Node.js 14.17, or later, to Oracle
8
8
  Database. Older versions of node-oracledb may work with older versions of
9
9
  Node.js.
10
10
 
@@ -16,8 +16,42 @@ It is stable, well documented, and has a comprehensive test suite.
16
16
 
17
17
  ## Installation
18
18
 
19
+ Run `npm install oracledb`
20
+
19
21
  See [Getting Started with Node-oracledb][1] and [Quick Start Node-oracledb Installation][2].
20
22
 
23
+ ## Dependencies and Interoperability
24
+
25
+ - Node.js versions 14.17 and later.
26
+
27
+ Pre-built packages are available on [npm][14] and other mirror repositories.
28
+
29
+ Source code is also available.
30
+
31
+ Previous versions of node-oracledb supported older Node.js versions.
32
+
33
+ - Oracle Client libraries are *optional* starting from node-oracledb 6.0.
34
+ Older versions of node-oracledb require Oracle Client libraries.
35
+
36
+ **Thin mode**: By default node-oracledb (from version 6.0 onwards) runs in a
37
+ 'Thin' mode which connects directly to Oracle Database.
38
+
39
+ **Thick mode**: Some advanced Oracle Database functionality is currently only
40
+ available when optional Oracle Client libraries are loaded by
41
+ node-oracledb. Libraries are available in the free [Oracle Instant
42
+ Client][15] packages. Node-oracledb can use Oracle Client
43
+ libraries 11.2 through 23ai.
44
+
45
+ - Oracle Database
46
+
47
+ **Thin mode**: Oracle Database 12.1 (or later) is required.
48
+
49
+ **Thick mode**: Oracle Database 9.2 (or later) is required, depending on the
50
+ Oracle Client library version. Oracle Database's standard client-server
51
+ version interoperability allows connection to both older and newer
52
+ databases. For example when node-oracledb uses Oracle Client 19c libraries,
53
+ then it can connect to Oracle Database 11.2 or later.
54
+
21
55
  ## Documentation
22
56
 
23
57
  See [Documentation for the Oracle Database Node.js Add-on][9] and the [release
@@ -34,7 +68,7 @@ to join Slack][6]).
34
68
 
35
69
  ## <a name="testing"></a> Tests
36
70
 
37
- To run the test suite see [test/README][11].
71
+ To run the test suite, see [test/README][11].
38
72
 
39
73
  ## Contributing
40
74
 
@@ -83,3 +117,5 @@ limitations under the License.
83
117
  [11]: https://github.com/oracle/node-oracledb/blob/main/test/README.md
84
118
  [12]: https://github.com/oracle/node-oracledb/blob/main/CONTRIBUTING.md
85
119
  [13]: https://github.com/oracle/node-oracledb/blob/main/SECURITY.md
120
+ [14]: https://www.npmjs.com/package/oracledb
121
+ [15]: https://www.oracle.com/database/technologies/instant-client.html
@@ -0,0 +1 @@
1
+ oracledb-6.9.0-darwin-arm64.node v23.10.0 2eb94e8660458ba0f6a59a00ebaa1d65e380cbd9 9cbfa993c59da0cfba2baa65e1c51fc0216bf586 Tue, 15 Jul 2025 11:23:44 GMT
@@ -0,0 +1 @@
1
+ oracledb-6.9.0-darwin-x64.node v22.16.0 2eb94e8660458ba0f6a59a00ebaa1d65e380cbd9 9cbfa993c59da0cfba2baa65e1c51fc0216bf586 Tue, 15 Jul 2025 11:07:19 GMT
@@ -0,0 +1 @@
1
+ 2eb94e8660458ba0f6a59a00ebaa1d65e380cbd9
@@ -0,0 +1 @@
1
+ oracledb-6.9.0-linux-arm64.node v20.19.2 2eb94e8660458ba0f6a59a00ebaa1d65e380cbd9 9cbfa993c59da0cfba2baa65e1c51fc0216bf586 Tue, 15 Jul 2025 11:06:47 GMT
@@ -0,0 +1 @@
1
+ oracledb-6.9.0-linux-x64.node v22.13.1 2eb94e8660458ba0f6a59a00ebaa1d65e380cbd9 9cbfa993c59da0cfba2baa65e1c51fc0216bf586 Tue, 15 Jul 2025 11:48:53 GMT
@@ -0,0 +1 @@
1
+ oracledb-6.9.0-win32-x64.node v20.17.0 2eb94e8660458ba0f6a59a00ebaa1d65e380cbd9 9cbfa993c59da0cfba2baa65e1c51fc0216bf586 Tue, 15 Jul 2025 11:04:06 GMT
package/lib/aqMessage.js CHANGED
@@ -1,4 +1,4 @@
1
- // Copyright (c) 2019, 2022, Oracle and/or its affiliates.
1
+ // Copyright (c) 2019, 2025, Oracle and/or its affiliates.
2
2
 
3
3
  //-----------------------------------------------------------------------------
4
4
  //
@@ -48,6 +48,15 @@ class AqMessage {
48
48
  return this._impl.getDelay();
49
49
  }
50
50
 
51
+ //---------------------------------------------------------------------------
52
+ // enqTime
53
+ //
54
+ // Property to indicate the enqueue time for the message.
55
+ //---------------------------------------------------------------------------
56
+ get enqTime() {
57
+ return this._impl.getEnqTime();
58
+ }
59
+
51
60
  //---------------------------------------------------------------------------
52
61
  // deliveryMode
53
62
  //
@@ -0,0 +1,72 @@
1
+ // Copyright (c) 2025, 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
+ const fs = require('fs').promises;
27
+ const util = require('node:util');
28
+ const oracledb = require('oracledb');
29
+ class locaJson {
30
+
31
+ constructor(provider_arg, urlExtendedPart) {
32
+ const params = new URLSearchParams(urlExtendedPart);
33
+ this.paramMap = new URLSearchParams([...params].map(([key, value]) => [key.toLowerCase(), value])); //parse the extended part and store parameters in Map
34
+ this.paramMap.set('filepath', provider_arg);
35
+ }
36
+ //---------------------------------------------------------------------------
37
+ // init()
38
+ //
39
+ // Require/import modules from ociobject
40
+ //---------------------------------------------------------------------------
41
+ init() {
42
+ // nothing to require
43
+ }
44
+ async returnConfig() {
45
+ const alias = this.paramMap.get('alias');
46
+ // Read input file
47
+ const data = Buffer.from(await fs.readFile(this.paramMap.get("filepath"), { encoding: 'utf8', flag: 'r' }));
48
+ // Converting to JSON
49
+ const listofAliases = JSON.parse(data);
50
+ if (alias) {
51
+ this.obj = listofAliases[alias];
52
+ } else {
53
+ this.obj = listofAliases;
54
+ }
55
+ return this.obj;
56
+ }
57
+ }
58
+ //---------------------------------------------------------------------------
59
+ // hookFn()
60
+ // hookFn will get registered to the driver while loading the plugins
61
+ //---------------------------------------------------------------------------
62
+ async function hookFn(args) {
63
+ const configProvider = new locaJson(args.provider_arg, args.urlExtendedPart);
64
+ try {
65
+ configProvider.init();
66
+ } catch (err) {
67
+ const errmsg = util.format('Centralized Config Provider failed to load required libraries. Please install the required libraries.\n %s', err.message);
68
+ throw new Error(errmsg);
69
+ }
70
+ return [await configProvider.returnConfig(), configProvider.credential];
71
+ }
72
+ oracledb.registerConfigurationProviderHook('file', hookFn);
package/lib/connection.js CHANGED
@@ -1,4 +1,4 @@
1
- // Copyright (c) 2016, 2024, Oracle and/or its affiliates.
1
+ // Copyright (c) 2016, 2025, Oracle and/or its affiliates.
2
2
 
3
3
  //-----------------------------------------------------------------------------
4
4
  //
@@ -50,6 +50,48 @@ const oson = require('./impl/datahandlers/oson.js');
50
50
  // and destroyed with another!
51
51
  const _subscriptions = new Map();
52
52
 
53
+ // default closure for NUMBER type.
54
+ const defaultNumberConverter = (v) => (v === null) ? null : parseFloat(v);
55
+
56
+ //---------------------------------------------------------------------------
57
+ // _determineDbObjTypeConverter()
58
+ //
59
+ // Determines the converter associated with each DB type and its metadata.
60
+ // This function is called once during metadata construction and the
61
+ // converters are invoked when retriving DBObject values.
62
+ //---------------------------------------------------------------------------
63
+ function _determineDbObjTypeConverter(metadata, options) {
64
+ // clear any previous converter functions that may have been
65
+ // retained
66
+ delete metadata.converter;
67
+
68
+ // If a DBfetch type handler is specified, update converter,
69
+ // if available.
70
+ if (options.dbObjectTypeHandler) {
71
+ const result = options.dbObjectTypeHandler(metadata);
72
+ if (result !== undefined) {
73
+ errors.assert(typeof result === 'object',
74
+ errors.ERR_DB_FETCH_TYPE_HANDLER_RETURN_VALUE);
75
+ if (result.converter !== undefined) {
76
+ errors.assert(typeof result.converter === 'function',
77
+ errors.ERR_DB_FETCH_TYPE_HANDLER_CONVERTER);
78
+ }
79
+ if ([types.DB_TYPE_CLOB, types.DB_TYPE_NCLOB, types.DB_TYPE_BLOB,
80
+ types.DB_TYPE_BFILE].includes(metadata.type)) {
81
+ // converters for LOB's are not supported.
82
+ return errors.throwErr(errors.ERR_NOT_IMPLEMENTED,
83
+ 'DbObjConverter for LOBs');
84
+ }
85
+ metadata.converter = result.converter;
86
+ }
87
+ }
88
+ if (metadata.type === types.DB_TYPE_NUMBER && !metadata.converter) {
89
+ // set default converter for NUMBER type as they are returned as strings
90
+ // from DB.
91
+ metadata.converter = defaultNumberConverter;
92
+ }
93
+ }
94
+
53
95
  // define class
54
96
  class Connection extends EventEmitter {
55
97
 
@@ -68,6 +110,8 @@ class Connection extends EventEmitter {
68
110
  options.connection = this;
69
111
  if (options.keepInStmtCache === undefined)
70
112
  options.keepInStmtCache = true;
113
+ if (options.suspendOnSuccess === undefined)
114
+ options.suspendOnSuccess = false;
71
115
  settings.addToOptions(options,
72
116
  "autoCommit",
73
117
  "dbObjectAsPojo",
@@ -96,7 +140,12 @@ class Connection extends EventEmitter {
96
140
  }
97
141
  return (proxy);
98
142
  } else if (initialValue !== undefined) {
99
- Object.assign(this, initialValue);
143
+ for (const attr of objType.attributes) {
144
+ const value = initialValue[attr.name];
145
+ if (value !== undefined) {
146
+ this._setAttrValue(attr, value);
147
+ }
148
+ }
100
149
  }
101
150
  };
102
151
  DbObject.prototype = Object.create(BaseDbObject.prototype);
@@ -106,9 +155,11 @@ class Connection extends EventEmitter {
106
155
  const cls = this._getDbObjectClass(objType.elementTypeClass);
107
156
  objType.elementTypeClass = cls;
108
157
  }
158
+ const options = {dbObjectTypeHandler: settings.dbObjectTypeHandler};
109
159
  if (objType.isCollection) {
110
160
  nodbUtil.addTypeProperties(objType, "elementType");
111
161
  objType.elementTypeInfo.type = objType.elementType;
162
+ _determineDbObjTypeConverter(objType.elementTypeInfo, options);
112
163
  }
113
164
  if (objType.attributes) {
114
165
  const props = {};
@@ -126,6 +177,10 @@ class Connection extends EventEmitter {
126
177
  }
127
178
  };
128
179
  props[attr.name] = prop;
180
+
181
+ // calculate for each attribute metadata as converters might change
182
+ // based on precision, scale, maxSize,..
183
+ _determineDbObjTypeConverter(attr, options);
129
184
  }
130
185
  Object.defineProperties(DbObject.prototype, props);
131
186
  }
@@ -368,7 +423,9 @@ class Connection extends EventEmitter {
368
423
  bindInfo.type !== types.DB_TYPE_TIMESTAMP &&
369
424
  bindInfo.type !== types.DB_TYPE_TIMESTAMP_LTZ &&
370
425
  bindInfo.type !== types.DB_TYPE_TIMESTAMP_TZ &&
371
- bindInfo.type !== types.DB_TYPE_RAW) {
426
+ bindInfo.type !== types.DB_TYPE_RAW &&
427
+ bindInfo.type !== types.DB_TYPE_INTERVAL_YM &&
428
+ bindInfo.type !== types.DB_TYPE_INTERVAL_DS) {
372
429
  errors.throwErr(errors.ERR_INVALID_TYPE_FOR_ARRAY_BIND);
373
430
  }
374
431
 
@@ -541,6 +598,11 @@ class Connection extends EventEmitter {
541
598
  outOptions.keepInStmtCache = options.keepInStmtCache;
542
599
  }
543
600
 
601
+ if (options.suspendOnSuccess !== undefined) {
602
+ errors.assertParamPropBool(options, 2, "suspendOnSucess");
603
+ outOptions.suspendOnSuccess = options.suspendOnSuccess;
604
+ }
605
+
544
606
  // handle options specific to executeMany()
545
607
  if (inExecuteMany) {
546
608
 
@@ -651,6 +713,29 @@ class Connection extends EventEmitter {
651
713
  this._impl.setAction(value);
652
714
  }
653
715
 
716
+ //---------------------------------------------------------------------------
717
+ // beginSessionlessTransaction()
718
+ //
719
+ // Begin a new sessionless transaction with provided transactionId.
720
+ // If transactionId wasn't provided a random-generated transactionId will be
721
+ // used and returned.
722
+ //---------------------------------------------------------------------------
723
+ async beginSessionlessTransaction(options = {}) {
724
+ errors.assertArgCount(arguments, 0, 1);
725
+ errors.assertParamValue(nodbUtil.isObject(options), 1);
726
+ if (options.transactionId !== undefined)
727
+ errors.assertParamPropValue(
728
+ nodbUtil.isTransactionId(options.transactionId), 1, 'transactionId');
729
+ errors.assertParamPropUnsignedIntNonZero(options, 1, 'timeout');
730
+ errors.assertParamPropBool(options, 1, 'deferRoundTrip');
731
+ const normalizedTransactionId =
732
+ nodbUtil.normalizeTransactionId(options.transactionId);
733
+ const {timeout = 60, deferRoundTrip = false} = options;
734
+ await this._impl.startSessionlessTransaction(normalizedTransactionId,
735
+ timeout, constants.TPC_BEGIN_NEW, deferRoundTrip);
736
+ return normalizedTransactionId;
737
+ }
738
+
654
739
  //---------------------------------------------------------------------------
655
740
  // breakExecution()
656
741
  //
@@ -1205,6 +1290,18 @@ class Connection extends EventEmitter {
1205
1290
  this._impl.setInternalName(value);
1206
1291
  }
1207
1292
 
1293
+ //---------------------------------------------------------------------------
1294
+ // ltxid
1295
+ //
1296
+ // Property for identifying the logical transaction ID to avoid duplicate
1297
+ // transactions. Used with Oracle Transaction Guard.
1298
+ //---------------------------------------------------------------------------
1299
+ get ltxid() {
1300
+ if (this._impl)
1301
+ return this._impl.getLTXID();
1302
+ return undefined;
1303
+ }
1304
+
1208
1305
  //--------------------------------------------------------------------------
1209
1306
  // isHealthy()
1210
1307
  //
@@ -1216,6 +1313,20 @@ class Connection extends EventEmitter {
1216
1313
  this._impl.isHealthy());
1217
1314
  }
1218
1315
 
1316
+ isCompressionEnabled() {
1317
+ return (this._impl && this._impl.isCompressionEnabled());
1318
+ }
1319
+
1320
+ //---------------------------------------------------------------------------
1321
+ // maxIdentifierLength
1322
+ //
1323
+ // Returns the maximum length of identifiers supported by the database to
1324
+ // which this connection has been established.
1325
+ //---------------------------------------------------------------------------
1326
+ get maxIdentifierLength() {
1327
+ return this._impl && this._impl.getMaxIdentifierLength();
1328
+ }
1329
+
1219
1330
  //---------------------------------------------------------------------------
1220
1331
  // maxOpenCursors
1221
1332
  //
@@ -1343,6 +1454,25 @@ class Connection extends EventEmitter {
1343
1454
  return (stream);
1344
1455
  }
1345
1456
 
1457
+ //---------------------------------------------------------------------------
1458
+ // resumeSessionlessTransaction()
1459
+ //
1460
+ // Resume an existing sessionlesss transaction using given transactionId
1461
+ //---------------------------------------------------------------------------
1462
+ async resumeSessionlessTransaction(transactionId, options = {}) {
1463
+ errors.assertArgCount(arguments, 1, 2);
1464
+ errors.assertParamValue(nodbUtil.isTransactionId(transactionId), 1);
1465
+ errors.assertParamValue(nodbUtil.isObject(options), 2);
1466
+ errors.assertParamPropUnsignedInt(options, 2, 'timeout');
1467
+ errors.assertParamPropBool(options, 2, 'deferRoundTrip');
1468
+ const normalizedTransactionId =
1469
+ nodbUtil.normalizeTransactionId(transactionId);
1470
+ const {timeout = 60, deferRoundTrip = false} = options;
1471
+ await this._impl.startSessionlessTransaction(normalizedTransactionId,
1472
+ timeout, constants.TPC_BEGIN_RESUME, deferRoundTrip);
1473
+ return normalizedTransactionId;
1474
+ }
1475
+
1346
1476
  //---------------------------------------------------------------------------
1347
1477
  // rollback()
1348
1478
  //
@@ -1457,6 +1587,17 @@ class Connection extends EventEmitter {
1457
1587
  return outValue;
1458
1588
  }
1459
1589
 
1590
+ //---------------------------------------------------------------------------
1591
+ // suspendSessionlessTransaction()
1592
+ //
1593
+ // Suspend any active sessionless transaction immediately
1594
+ //---------------------------------------------------------------------------
1595
+ async suspendSessionlessTransaction() {
1596
+ errors.assertArgCount(arguments, 0, 0);
1597
+ errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
1598
+ await this._impl.suspendSessionlessTransaction();
1599
+ }
1600
+
1460
1601
  //---------------------------------------------------------------------------
1461
1602
  // tag
1462
1603
  //
@@ -1647,7 +1788,12 @@ class Connection extends EventEmitter {
1647
1788
  errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
1648
1789
  errors.assert(_subscriptions.has(name), errors.ERR_INVALID_SUBSCR);
1649
1790
  await this._impl.unsubscribe(_subscriptions.get(name));
1650
- _subscriptions.delete(name);
1791
+
1792
+ // Delay decreasing the reference count
1793
+ // as NJS layer starts cleanup (uv_close) of async handle asynchronously.
1794
+ setTimeout(() => {
1795
+ _subscriptions.delete(name);
1796
+ }, 0);
1651
1797
  }
1652
1798
 
1653
1799
  }
@@ -1660,6 +1806,7 @@ Connection.prototype.break =
1660
1806
  Connection.prototype.tpcRecover =
1661
1807
  nodbUtil.callbackify(nodbUtil.wrapFn(Connection.prototype.tpcRecover));
1662
1808
  nodbUtil.wrapFns(Connection.prototype,
1809
+ "beginSessionlessTransaction",
1663
1810
  "changePassword",
1664
1811
  "close",
1665
1812
  "commit",
@@ -1670,10 +1817,12 @@ nodbUtil.wrapFns(Connection.prototype,
1670
1817
  "getQueue",
1671
1818
  "getStatementInfo",
1672
1819
  "ping",
1820
+ "resumeSessionlessTransaction",
1673
1821
  "rollback",
1674
1822
  "shutdown",
1675
1823
  "startup",
1676
1824
  "subscribe",
1825
+ "suspendSessionlessTransaction",
1677
1826
  "tpcBegin",
1678
1827
  "tpcCommit",
1679
1828
  "tpcEnd",
package/lib/dbObject.js CHANGED
@@ -1,4 +1,4 @@
1
- // Copyright (c) 2019, 2024, Oracle and/or its affiliates.
1
+ // Copyright (c) 2019, 2025, Oracle and/or its affiliates.
2
2
 
3
3
  //----------------------------------------------------------------------------
4
4
  //
@@ -86,7 +86,7 @@ class BaseDbObject {
86
86
  //---------------------------------------------------------------------------
87
87
  _getAttrValue(attr) {
88
88
  const value = this._impl.getAttrValue(attr);
89
- return this._transformValueOut(value, attr.typeClass);
89
+ return this._transformValueOut(value, attr.typeClass, attr);
90
90
  }
91
91
 
92
92
  //---------------------------------------------------------------------------
@@ -138,16 +138,21 @@ class BaseDbObject {
138
138
  //
139
139
  // Transforms a value going out to the caller from the implementation.
140
140
  //---------------------------------------------------------------------------
141
- _transformValueOut(value, cls) {
141
+ _transformValueOut(value, cls, metaData) {
142
142
  let outValue = value;
143
143
  if (value instanceof impl.LobImpl) {
144
144
  outValue = new Lob();
145
145
  outValue._setup(value, true);
146
- } else if (value instanceof impl.DbObjectImpl) {
147
- outValue = Object.create(cls.prototype);
148
- outValue._impl = value;
149
- if (outValue.isCollection) {
150
- outValue = new Proxy(outValue, BaseDbObject._collectionProxyHandler);
146
+ } else {
147
+ if (value instanceof impl.DbObjectImpl) {
148
+ outValue = Object.create(cls.prototype);
149
+ outValue._impl = value;
150
+ if (outValue.isCollection) {
151
+ outValue = new Proxy(outValue, BaseDbObject._collectionProxyHandler);
152
+ }
153
+ }
154
+ if (metaData.converter) {
155
+ outValue = metaData.converter(outValue);
151
156
  }
152
157
  }
153
158
  return outValue;
@@ -195,6 +200,15 @@ class BaseDbObject {
195
200
  if (implAttr.typeClass) {
196
201
  attr.typeClass = implAttr.typeClass;
197
202
  }
203
+ if (implAttr.precision != null) {
204
+ attr.precision = implAttr.precision;
205
+ }
206
+ if (implAttr.scale != null) {
207
+ attr.scale = implAttr.scale;
208
+ }
209
+ if (implAttr.maxSize != null) {
210
+ attr.maxSize = implAttr.maxSize;
211
+ }
198
212
  attrs[implAttr.name] = attr;
199
213
  }
200
214
  this._attributes = attrs;
@@ -202,6 +216,21 @@ class BaseDbObject {
202
216
  return this._attributes;
203
217
  }
204
218
 
219
+ //---------------------------------------------------------------------------
220
+ // copy
221
+ //
222
+ // Creates and returns a copy of the object. The copy is independent of
223
+ // the original object that was copied.
224
+ //---------------------------------------------------------------------------
225
+ copy() {
226
+ errors.assertArgCount(arguments, 0, 0);
227
+ const newObj = Object.create(this);
228
+ newObj._impl = this._impl.copy();
229
+ if (this.isCollection)
230
+ return new Proxy(newObj, BaseDbObject._collectionProxyHandler);
231
+ return newObj;
232
+ }
233
+
205
234
  //---------------------------------------------------------------------------
206
235
  // deleteElement()
207
236
  //
@@ -253,6 +282,17 @@ class BaseDbObject {
253
282
  return this._objType.fqn;
254
283
  }
255
284
 
285
+ //---------------------------------------------------------------------------
286
+ // length
287
+ //
288
+ // Length of the database object type, if it is a collection. Else it
289
+ // returns undefined.
290
+ //---------------------------------------------------------------------------
291
+ get length() {
292
+ if (this.isCollection)
293
+ return this._impl.getLength();
294
+ return undefined;
295
+ }
256
296
  //---------------------------------------------------------------------------
257
297
  // getElement()
258
298
  //
@@ -262,7 +302,7 @@ class BaseDbObject {
262
302
  errors.assertArgCount(arguments, 1, 1);
263
303
  errors.assertParamValue(Number.isInteger(index), 1);
264
304
  const value = this._impl.getElement(index);
265
- return this._transformValueOut(value, this.elementTypeClass);
305
+ return this._transformValueOut(value, this.elementTypeClass, this._objType.elementTypeInfo);
266
306
  }
267
307
 
268
308
  //---------------------------------------------------------------------------
@@ -326,7 +366,7 @@ class BaseDbObject {
326
366
  errors.assertArgCount(arguments, 0, 0);
327
367
  const values = this._impl.getValues();
328
368
  for (let i = 0; i < values.length; i++) {
329
- values[i] = this._transformValueOut(values[i], this.elementTypeClass);
369
+ values[i] = this._transformValueOut(values[i], this.elementTypeClass, this._objType.elementTypeInfo);
330
370
  }
331
371
  return values;
332
372
  }
@@ -483,6 +523,7 @@ wrapFns(BaseDbObject.prototype,
483
523
  "_getAttrValue",
484
524
  "_setAttrValue",
485
525
  "append",
526
+ "copy",
486
527
  "deleteElement",
487
528
  "getElement",
488
529
  "getKeys",