oracledb 6.7.2 → 6.8.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 (60) hide show
  1. package/LICENSE.txt +1 -1
  2. package/NOTICE.txt +1 -1
  3. package/README.md +2 -2
  4. package/build/Release/oracledb-6.8.0-darwin-arm64.node +0 -0
  5. package/build/Release/oracledb-6.8.0-darwin-arm64.node-buildinfo.txt +1 -0
  6. package/build/Release/oracledb-6.8.0-darwin-x64.node +0 -0
  7. package/build/Release/oracledb-6.8.0-darwin-x64.node-buildinfo.txt +1 -0
  8. package/build/Release/oracledb-6.8.0-js-buildinfo.txt +1 -0
  9. package/build/Release/oracledb-6.8.0-linux-arm64.node +0 -0
  10. package/build/Release/oracledb-6.8.0-linux-arm64.node-buildinfo.txt +1 -0
  11. package/build/Release/oracledb-6.8.0-linux-x64.node +0 -0
  12. package/build/Release/oracledb-6.8.0-linux-x64.node-buildinfo.txt +1 -0
  13. package/build/Release/oracledb-6.8.0-win32-x64.node +0 -0
  14. package/build/Release/oracledb-6.8.0-win32-x64.node-buildinfo.txt +1 -0
  15. package/lib/connection.js +66 -2
  16. package/lib/dbObject.js +42 -10
  17. package/lib/errors.js +96 -13
  18. package/lib/impl/connection.js +15 -1
  19. package/lib/impl/datahandlers/buffer.js +92 -1
  20. package/lib/impl/datahandlers/constants.js +2 -0
  21. package/lib/impl/datahandlers/oson.js +15 -1
  22. package/lib/impl/datahandlers/vector.js +72 -27
  23. package/lib/oracledb.js +80 -4
  24. package/lib/settings.js +5 -1
  25. package/lib/thin/connection.js +13 -2
  26. package/lib/thin/dbObject.js +38 -7
  27. package/lib/thin/pool.js +7 -3
  28. package/lib/thin/protocol/capabilities.js +1 -1
  29. package/lib/thin/protocol/constants.js +2 -0
  30. package/lib/thin/protocol/messages/auth.js +29 -6
  31. package/lib/thin/protocol/messages/fastAuth.js +6 -1
  32. package/lib/thin/protocol/messages/withData.js +10 -1
  33. package/lib/thin/protocol/packet.js +1 -1
  34. package/lib/thin/sqlnet/ANO.js +438 -0
  35. package/lib/thin/sqlnet/constants.js +5 -1
  36. package/lib/thin/sqlnet/ezConnectResolver.js +4 -2
  37. package/lib/thin/sqlnet/navNodes.js +21 -2
  38. package/lib/thin/sqlnet/networkSession.js +88 -16
  39. package/lib/thin/sqlnet/ntTcp.js +50 -3
  40. package/lib/thin/sqlnet/packet.js +31 -4
  41. package/lib/thin/sqlnet/sessionAtts.js +25 -2
  42. package/lib/thin/util.js +3 -8
  43. package/lib/transformer.js +13 -2
  44. package/lib/types.js +220 -3
  45. package/lib/util.js +1 -1
  46. package/lib/version.js +2 -2
  47. package/package.json +1 -1
  48. package/plugins/token/extensionAzure/index.js +101 -0
  49. package/plugins/token/extensionOci/index.js +174 -0
  50. package/build/Release/oracledb-6.7.2-darwin-arm64.node +0 -0
  51. package/build/Release/oracledb-6.7.2-darwin-arm64.node-buildinfo.txt +0 -1
  52. package/build/Release/oracledb-6.7.2-darwin-x64.node +0 -0
  53. package/build/Release/oracledb-6.7.2-darwin-x64.node-buildinfo.txt +0 -1
  54. package/build/Release/oracledb-6.7.2-js-buildinfo.txt +0 -1
  55. package/build/Release/oracledb-6.7.2-linux-arm64.node +0 -0
  56. package/build/Release/oracledb-6.7.2-linux-arm64.node-buildinfo.txt +0 -1
  57. package/build/Release/oracledb-6.7.2-linux-x64.node +0 -0
  58. package/build/Release/oracledb-6.7.2-linux-x64.node-buildinfo.txt +0 -1
  59. package/build/Release/oracledb-6.7.2-win32-x64.node +0 -0
  60. package/build/Release/oracledb-6.7.2-win32-x64.node-buildinfo.txt +0 -1
@@ -1,4 +1,4 @@
1
- // Copyright (c) 2024, Oracle and/or its affiliates.
1
+ // Copyright (c) 2024, 2025, Oracle and/or its affiliates.
2
2
 
3
3
  //-----------------------------------------------------------------------------
4
4
  //
@@ -30,6 +30,7 @@ const { BaseBuffer, GrowableBuffer } = require('./buffer.js');
30
30
  const { Buffer } = require('buffer');
31
31
  const constants = require("./constants.js");
32
32
  const errors = require("../../errors.js");
33
+ const types = require("../../types.js");
33
34
 
34
35
  /**
35
36
  * Class used for decoding
@@ -50,68 +51,83 @@ class VectorDecoder extends BaseBuffer {
50
51
  errors.throwErr(errors.ERR_UNEXPECTED_DATA,
51
52
  Buffer.from([magicByte]).toString('hex'));
52
53
  const version = this.readUInt8();
53
- if (version > constants.TNS_VECTOR_VERSION_WITH_BINARY)
54
+ if (version > constants.TNS_VECTOR_VERSION_WITH_SPARSE)
54
55
  errors.throwErr(errors.ERR_VECTOR_VERSION_NOT_SUPPORTED, version);
55
56
  const flags = this.readUInt16BE();
56
57
  const vectorFormat = this.readUInt8();
57
58
  let numElements = this.readUInt32BE();
58
- let elementSize, result;
59
+ let elementSize, value, sparseValue;
60
+
61
+ // For binary vector, NORM will never be present but space for NORM is reserved to keep
62
+ // same header lengh across the different vector formats.
63
+ if (vectorFormat === constants.VECTOR_FORMAT_BINARY || flags & constants.TNS_VECTOR_FLAG_NORM)
64
+ this.skipBytes(8);
65
+
66
+ let sparseFormat;
67
+ if (flags & constants.TNS_VECTOR_FLAG_SPARSE) {
68
+ sparseFormat = true;
69
+ sparseValue = {};
70
+ sparseValue.numDimensions = numElements; // vector dimensions.
71
+ numElements = this.readUInt16BE(); // actual elements.
72
+ sparseValue.indices = new Uint32Array(numElements);
73
+ for (let i = 0; i < numElements; i++) {
74
+ sparseValue.indices[i] = this.readUInt32BE();
75
+ }
76
+ }
77
+
59
78
  if (vectorFormat === constants.VECTOR_FORMAT_FLOAT32) {
60
79
  elementSize = 4;
61
- result = new Float32Array(numElements);
80
+ value = new Float32Array(numElements);
62
81
  } else if (vectorFormat === constants.VECTOR_FORMAT_FLOAT64) {
63
82
  elementSize = 8;
64
- result = new Float64Array(numElements);
83
+ value = new Float64Array(numElements);
65
84
  } else if (vectorFormat === constants.VECTOR_FORMAT_INT8) {
66
85
  elementSize = 1;
67
- result = new Int8Array(numElements);
86
+ value = new Int8Array(numElements);
68
87
  } else if (vectorFormat === constants.VECTOR_FORMAT_BINARY) {
69
88
  elementSize = 1;
70
89
  // The number of dimensions are assumed to be multiple of 8.
71
90
  numElements = numElements / 8;
72
- result = new Uint8Array(numElements);
91
+ value = new Uint8Array(numElements);
73
92
  } else {
74
93
  errors.throwErr(errors.ERR_VECTOR_FORMAT_NOT_SUPPORTED, vectorFormat);
75
94
  }
76
95
 
77
- // For binary vector, NORM will never be present but space for NORM is reserved to keep
78
- // same header lengh across the different vector formats.
79
- if (vectorFormat === constants.VECTOR_FORMAT_BINARY || flags & constants.TNS_VECTOR_FLAG_NORM)
80
- this.skipBytes(8);
96
+ if (sparseFormat) {
97
+ sparseValue.values = value;
98
+ }
81
99
 
82
100
  // parse data
101
+ let res;
83
102
  for (let i = 0; i < numElements; i++) {
84
103
  const buf = this.readBytes(elementSize);
85
104
  if (vectorFormat === constants.VECTOR_FORMAT_FLOAT32) {
86
- result[i] = this.parseBinaryFloat(buf);
105
+ res = this.parseBinaryFloat(buf);
87
106
  } else if (vectorFormat === constants.VECTOR_FORMAT_FLOAT64) {
88
- result[i] = this.parseBinaryDouble(buf);
107
+ res = this.parseBinaryDouble(buf);
89
108
  } else {
90
- result[i] = buf[0];
109
+ res = buf[0];
91
110
  }
111
+ value[i] = res;
92
112
  }
93
113
 
94
- return result;
114
+ return sparseFormat ? types.SparseVector.create(sparseValue) : value;
95
115
  }
96
116
 
97
117
  }
98
118
 
99
119
  class VectorEncoder extends GrowableBuffer {
100
120
 
101
- //---------------------------------------------------------------------------
102
- // encode()
103
- //
104
- // Encodes the value as OSON and returns a buffer containing the OSON bytes.
105
- //---------------------------------------------------------------------------
106
- encode(value) {
107
-
108
- // determine some basic information about the vector
109
- let vectorFormat = constants.VECTOR_FORMAT_FLOAT32;
110
- let writeFn = this.writeBinaryFloat.bind(this);
121
+ // Writes Header from value.
122
+ // It returns function to serialize the value.
123
+ // sparseVal is provided for SparseVector.
124
+ _updateVectorHeader(value, sparseVal) {
125
+ let flags = constants.TNS_VECTOR_FLAG_NORMSRC
126
+ | constants.TNS_VECTOR_FLAG_NORM; // NORM is present and reserve space.
111
127
  let numElements = value.length;
112
128
  let vectorVersion = constants.TNS_VECTOR_VERSION_BASE;
113
- let flags = constants.TNS_VECTOR_FLAG_NORMSRC
114
- | constants.TNS_VECTOR_FLAG_NORM; // NORM is present and reserve space.
129
+ let vectorFormat = constants.VECTOR_FORMAT_FLOAT32;
130
+ let writeFn = this.writeBinaryFloat.bind(this);
115
131
 
116
132
  if (Array.isArray(value) || value instanceof Float64Array) {
117
133
  vectorFormat = constants.VECTOR_FORMAT_FLOAT64;
@@ -127,6 +143,11 @@ class VectorEncoder extends GrowableBuffer {
127
143
  flags = constants.TNS_VECTOR_FLAG_NORMSRC; // only space is reserved.
128
144
  writeFn = this.writeUInt8.bind(this);
129
145
  }
146
+ if (sparseVal && sparseVal instanceof types.SparseVector) {
147
+ vectorVersion = constants.TNS_VECTOR_VERSION_WITH_SPARSE;
148
+ numElements = sparseVal.numDimensions;
149
+ flags |= constants.TNS_VECTOR_FLAG_SPARSE;
150
+ }
130
151
 
131
152
  // write header
132
153
  this.writeUInt8(constants.TNS_VECTOR_MAGIC_BYTE);
@@ -135,6 +156,30 @@ class VectorEncoder extends GrowableBuffer {
135
156
  this.writeUInt8(vectorFormat);
136
157
  this.writeUInt32BE(numElements);
137
158
  this.reserveBytes(8);
159
+ return writeFn;
160
+ }
161
+
162
+ //---------------------------------------------------------------------------
163
+ // encode()
164
+ //
165
+ // Encodes the value as OSON and returns a buffer containing the OSON bytes.
166
+ //---------------------------------------------------------------------------
167
+ encode(value) {
168
+ let writeFn;
169
+
170
+ if (value instanceof types.SparseVector) {
171
+ writeFn = this._updateVectorHeader(value.values, value);
172
+ const numElements = value.indices.length;
173
+ this.writeUInt16BE(numElements);
174
+
175
+ // Write indices
176
+ value.indices.forEach((element) => {
177
+ this.writeUInt32BE(element);
178
+ });
179
+ value = value.values;
180
+ } else {
181
+ writeFn = this._updateVectorHeader(value);
182
+ }
138
183
 
139
184
  // write data
140
185
  value.forEach((element) => {
package/lib/oracledb.js 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
  //-----------------------------------------------------------------------------
4
4
  //
@@ -67,6 +67,7 @@ const SodaOperation = require('./sodaOperation.js');
67
67
  const poolCache = {};
68
68
  const tempUsedPoolAliases = {};
69
69
  const defaultPoolAlias = 'default';
70
+ const registeredHooks = [];
70
71
  let configProviderCache;
71
72
 
72
73
  // save arguments for call to initOracleClient()
@@ -188,6 +189,18 @@ async function _verifyOptions(options, inCreatePool) {
188
189
  "walletLocation");
189
190
  outOptions.walletLocation = options.walletLocation;
190
191
  }
192
+ if (options.networkCompression !== undefined) {
193
+ errors.assertParamPropValue(typeof options.networkCompression === 'boolean', 1,
194
+ "networkCompression");
195
+ outOptions.networkCompression = options.networkCompression;
196
+ outOptions.networkCompressionLevels = [];
197
+ outOptions.networkCompressionLevels.push('high');
198
+ }
199
+
200
+ if (options.networkCompressionThreshold !== undefined) {
201
+ errors.assertParamPropValue(Number.isInteger(options.networkCompressionThreshold), 1, "networkCompressionThreshold");
202
+ outOptions.networkCompressionThreshold = options.networkCompressionThreshold;
203
+ }
191
204
 
192
205
  //wallet content must be a string
193
206
  if (options.walletContent !== undefined) {
@@ -362,6 +375,13 @@ async function _verifyOptions(options, inCreatePool) {
362
375
  outOptions.terminal = options.terminal;
363
376
  }
364
377
 
378
+ // useSNI must be a boolean
379
+ if (options.useSNI !== undefined) {
380
+ errors.assertParamPropValue(typeof options.useSNI === 'boolean', 1,
381
+ "useSNI");
382
+ outOptions.useSNI = options.useSNI;
383
+ }
384
+
365
385
  // check pool specific options
366
386
  if (inCreatePool) {
367
387
 
@@ -513,9 +533,13 @@ async function _verifyOptions(options, inCreatePool) {
513
533
  if (typeof options.accessToken === 'function') {
514
534
  outOptions.accessTokenFn = options.accessToken;
515
535
  outOptions.accessTokenConfig = options.accessTokenConfig;
516
- accessToken = await options.accessToken(false, options.accessTokenConfig);
517
- if (!nodbUtil.isTokenValid(accessToken)) {
518
- accessToken = await options.accessToken(true, options.accessTokenConfig);
536
+ try {
537
+ accessToken = await options.accessToken(false, outOptions.accessTokenConfig);
538
+ if (!nodbUtil.isTokenValid(accessToken)) {
539
+ accessToken = await options.accessToken(true, outOptions.accessTokenConfig);
540
+ }
541
+ } catch (error) {
542
+ errors.throwWrapErr(error, errors.ERR_ACCESS_TOKEN);
519
543
  }
520
544
  } else {
521
545
  accessToken = options.accessToken;
@@ -568,6 +592,18 @@ async function createPool(options) {
568
592
  // check arguments
569
593
  errors.assertArgCount(arguments, 1, 1);
570
594
  errors.assertParamValue(nodbUtil.isObject(options), 1);
595
+
596
+ // this will invoke hookFn() written in application side.
597
+ // for token based auth it will generate access token and save it in options.
598
+ for (const hookFn of registeredHooks) {
599
+ // eslint-disable-next-line no-useless-catch
600
+ try {
601
+ await hookFn(options);
602
+ } catch (error) {
603
+ errors.throwWrapErr(error, errors.ERR_CALLOUT_FN);
604
+ }
605
+ }
606
+
571
607
  options = await _verifyOptions(options, true);
572
608
  const sessionCallback = options.sessionCallback;
573
609
  if (typeof sessionCallback === 'function')
@@ -700,6 +736,17 @@ async function getConnection(a1) {
700
736
  return await pool.getConnection(options);
701
737
  }
702
738
 
739
+ // this will invoke hookFn() written in application side.
740
+ // for token based auth it will generate access token and save it in options.
741
+ for (const hookFn of registeredHooks) {
742
+ // eslint-disable-next-line no-useless-catch
743
+ try {
744
+ await hookFn(options);
745
+ } catch (error) {
746
+ errors.throwWrapErr(error, errors.ERR_CALLOUT_FN);
747
+ }
748
+ }
749
+
703
750
  // create a standalone connection
704
751
  options = await _verifyOptions(options, false);
705
752
  settings.addToOptions(options,
@@ -998,6 +1045,18 @@ async function startup(a1, a2) {
998
1045
  await conn.close();
999
1046
  }
1000
1047
 
1048
+ //-----------------------------------------------------------------------------
1049
+ // registerProcessConfigurationHook()
1050
+ //
1051
+ // Registers extension modules and registered modules will be called and
1052
+ // executed during pool and standalone connection creation.
1053
+ //-----------------------------------------------------------------------------
1054
+ function registerProcessConfigurationHook(fn) {
1055
+ errors.assertArgCount(arguments, 1, 1);
1056
+ errors.assertParamValue(typeof fn === 'function', 1);
1057
+ registeredHooks.push(fn);
1058
+ }
1059
+
1001
1060
  // module exports
1002
1061
  module.exports = {
1003
1062
 
@@ -1018,6 +1077,9 @@ module.exports = {
1018
1077
  SodaDocCursor,
1019
1078
  SodaDocument,
1020
1079
  SodaOperation,
1080
+ SparseVector: types.SparseVector,
1081
+ IntervalYM: types.IntervalYM,
1082
+ IntervalDS: types.IntervalDS,
1021
1083
 
1022
1084
  // top-level functions
1023
1085
  getConnection: nodbUtil.callbackify(nodbUtil.wrapFn(getConnection)),
@@ -1025,6 +1087,7 @@ module.exports = {
1025
1087
  getNetworkServiceNames: nodbUtil.callbackify(nodbUtil.wrapFn(getNetworkServiceNames)),
1026
1088
  getPool,
1027
1089
  initOracleClient,
1090
+ registerProcessConfigurationHook,
1028
1091
  shutdown: nodbUtil.callbackify(nodbUtil.wrapFn(shutdown)),
1029
1092
  startup: nodbUtil.callbackify(nodbUtil.wrapFn(startup)),
1030
1093
 
@@ -1269,6 +1332,10 @@ module.exports = {
1269
1332
  return settings.fetchTypeHandler;
1270
1333
  },
1271
1334
 
1335
+ get dbObjectTypeHandler() {
1336
+ return settings.dbObjectTypeHandler;
1337
+ },
1338
+
1272
1339
  get lobPrefetchSize() {
1273
1340
  return settings.lobPrefetchSize;
1274
1341
  },
@@ -1329,6 +1396,7 @@ module.exports = {
1329
1396
  return settings.configProviderCacheTimeout;
1330
1397
  },
1331
1398
 
1399
+
1332
1400
  get thin() {
1333
1401
  return settings.thin;
1334
1402
  },
@@ -1413,6 +1481,13 @@ module.exports = {
1413
1481
  settings.fetchTypeHandler = value;
1414
1482
  },
1415
1483
 
1484
+ set dbObjectTypeHandler(value) {
1485
+ if (value !== undefined) {
1486
+ errors.assertPropValue(typeof value === 'function', "dbObjectTypeHandler");
1487
+ }
1488
+ settings.dbObjectTypeHandler = value;
1489
+ },
1490
+
1416
1491
  set lobPrefetchSize(value) {
1417
1492
  errors.assertPropValue(Number.isInteger(value) && value >= 0,
1418
1493
  "lobPrefetchSize");
@@ -1509,6 +1584,7 @@ module.exports = {
1509
1584
  errors.assertPropValue(typeof value === 'string', "terminal");
1510
1585
  settings.terminal = value;
1511
1586
  },
1587
+
1512
1588
  set configProviderCacheTimeout(value) {
1513
1589
  errors.assertPropValue(Number.isInteger(value) && value >= 0,
1514
1590
  "configProviderCacheTimeout");
package/lib/settings.js CHANGED
@@ -1,4 +1,4 @@
1
- // Copyright (c) 2022, 2024, Oracle and/or its affiliates.
1
+ // Copyright (c) 2022, 2025, Oracle and/or its affiliates.
2
2
 
3
3
  //-----------------------------------------------------------------------------
4
4
  //
@@ -64,7 +64,11 @@ class Settings {
64
64
  this.thinDriverInitialized = false;
65
65
  this.createFetchTypeMap(this.fetchAsString, this.fetchAsBuffer);
66
66
  this.fetchTypeHandler = undefined;
67
+ this.dbObjectTypeHandler = undefined;
67
68
  this._JsonId = types.JsonId;
69
+ this._SparseVector = types.SparseVector;
70
+ this._IntervalYM = types.IntervalYM;
71
+ this._IntervalDS = types.IntervalDS;
68
72
  }
69
73
 
70
74
  //---------------------------------------------------------------------------
@@ -1,4 +1,4 @@
1
- // Copyright (c) 2022, 2024, Oracle and/or its affiliates.
1
+ // Copyright (c) 2022, 2025, Oracle and/or its affiliates.
2
2
 
3
3
  //-----------------------------------------------------------------------------
4
4
  //
@@ -715,6 +715,9 @@ class ThinConnectionImpl extends ConnectionImpl {
715
715
  await this._protocol.breakMessage();
716
716
  }
717
717
 
718
+ isCompressionEnabled() {
719
+ return this.nscon.compressionEnabled;
720
+ }
718
721
  isHealthy() {
719
722
  try {
720
723
  if (this.nscon.recvInbandNotif() === 0)
@@ -839,7 +842,7 @@ class ThinConnectionImpl extends ConnectionImpl {
839
842
  this.nscon.endOfRequestSupport = endOfRequestSupport;
840
843
  await this._protocol._processMessage(authMessage);
841
844
  }
842
- if (!params.token) { // non-token Authentication
845
+ if (!params.externalAuth) { // non-token Authentication
843
846
  await this._protocol._processMessage(authMessage); // OAUTH
844
847
  }
845
848
  } catch (err) {
@@ -1312,6 +1315,14 @@ class ThinConnectionImpl extends ConnectionImpl {
1312
1315
  return this.maxOpenCursors;
1313
1316
  }
1314
1317
 
1318
+ //---------------------------------------------------------------------------
1319
+ // Returns the maximum length of identifiers supported by the database to
1320
+ // which this connection has been established.
1321
+ //---------------------------------------------------------------------------
1322
+ getMaxIdentifierLength() {
1323
+ return this.maxIdentifierLength;
1324
+ }
1325
+
1315
1326
  //---------------------------------------------------------------------------
1316
1327
  // Returns the Oracle Database service name associated with the connection.
1317
1328
  //---------------------------------------------------------------------------
@@ -1,4 +1,4 @@
1
- // Copyright (c) 2023, 2024, Oracle and/or its affiliates.
1
+ // Copyright (c) 2023, 2025, Oracle and/or its affiliates.
2
2
 
3
3
  //-----------------------------------------------------------------------------
4
4
  //
@@ -368,10 +368,7 @@ class ThinDbObjectImpl extends DbObjectImpl {
368
368
  let isNull, obj, value;
369
369
  switch (type) {
370
370
  case types.DB_TYPE_NUMBER:
371
- value = buf.readOracleNumber();
372
- if (value !== null)
373
- value = parseFloat(value);
374
- return value;
371
+ return buf.readOracleNumber();
375
372
  case types.DB_TYPE_BINARY_INTEGER:
376
373
  return buf.readBinaryInteger();
377
374
  case types.DB_TYPE_VARCHAR:
@@ -429,7 +426,7 @@ class ThinDbObjectImpl extends DbObjectImpl {
429
426
  if (objType.maxNumElements > 0 &&
430
427
  this.unpackedArray.length >= objType.maxNumElements) {
431
428
  errors.throwErr(errors.ERR_INVALID_COLL_INDEX_SET,
432
- this.unpackedArray.length, 0, objType.maxNumElements);
429
+ this.unpackedArray.length, 0, objType.maxNumElements - 1);
433
430
  }
434
431
  this.unpackedArray.push(value);
435
432
  } else {
@@ -446,6 +443,26 @@ class ThinDbObjectImpl extends DbObjectImpl {
446
443
  }
447
444
  }
448
445
 
446
+ //---------------------------------------------------------------------------
447
+ // copy
448
+ //
449
+ // Creates and returns a copy of the ThinDBObjectImpl object. The copy is
450
+ // independent of the original object that was copied.
451
+ //---------------------------------------------------------------------------
452
+ copy() {
453
+ // We send in marshalled data of the original object to the constructor
454
+ // when we create the object copy
455
+ const newObjImpl = new ThinDbObjectImpl(this._objType, this._getPackedData());
456
+
457
+ // Set other properties
458
+ newObjImpl.toid = this.toid;
459
+ newObjImpl.flags = this.flags;
460
+ newObjImpl.imageFlags = this.imageFlags;
461
+ newObjImpl.imageVersion = this.imageVersion;
462
+
463
+ return newObjImpl;
464
+ }
465
+
449
466
  //---------------------------------------------------------------------------
450
467
  // deleteElement()
451
468
  //
@@ -459,7 +476,7 @@ class ThinDbObjectImpl extends DbObjectImpl {
459
476
  }
460
477
  this.unpackedArray.splice(index, 1);
461
478
  } else {
462
- this._unpackedAssocKeys = undefined;
479
+ this.unpackedAssocKeys = undefined;
463
480
  this.unpackedAssocArray.delete(index);
464
481
  }
465
482
  }
@@ -610,6 +627,20 @@ class ThinDbObjectImpl extends DbObjectImpl {
610
627
  return result;
611
628
  }
612
629
 
630
+ //---------------------------------------------------------------------------
631
+ // getLength
632
+ //
633
+ // Gets the size of the database object if it is a collection. Else returns
634
+ // undefined.
635
+ //---------------------------------------------------------------------------
636
+ getLength() {
637
+ this._ensureUnpacked();
638
+ if (this.unpackedArray)
639
+ return this.unpackedArray.length;
640
+ if (this.unpackedAssocArray)
641
+ return this.unpackedAssocArray.size;
642
+ }
643
+
613
644
  //---------------------------------------------------------------------------
614
645
  // hasElement()
615
646
  //
package/lib/thin/pool.js CHANGED
@@ -1,4 +1,4 @@
1
- // Copyright (c) 2022, 2024, Oracle and/or its affiliates.
1
+ // Copyright (c) 2022, 2025, Oracle and/or its affiliates.
2
2
 
3
3
  //-----------------------------------------------------------------------------
4
4
  //
@@ -197,7 +197,11 @@ class ThinPoolImpl extends PoolImpl {
197
197
  protocolUtil.getDeobfuscatedValue(this._token, this._obfuscatedToken);
198
198
  if (util.isTokenExpired(clonedAttrs.token)) {
199
199
  if (typeof this._accessTokenFn === 'function') {
200
- accessToken = await this._accessTokenFn(true, this._accessTokenConfig);
200
+ try {
201
+ accessToken = await this._accessTokenFn(true, this._accessTokenConfig);
202
+ } catch (error) {
203
+ errors.throwWrapErr(error, errors.ERR_ACCESS_TOKEN);
204
+ }
201
205
  if (typeof accessToken === 'string') {
202
206
  clonedAttrs.token = accessToken;
203
207
  if (util.isTokenExpired(clonedAttrs.token)) {
@@ -211,7 +215,7 @@ class ThinPoolImpl extends PoolImpl {
211
215
  }
212
216
  } else if (typeof accessToken === 'object') {
213
217
  clonedAttrs.token = accessToken.token;
214
- clonedAttrs.privateKey = accessToken.privateKey;
218
+ clonedAttrs.privateKey = util.denormalizePrivateKey(accessToken.privateKey);
215
219
  if (util.isTokenExpired(clonedAttrs.token)) {
216
220
  // IAM token is expired
217
221
  errors.throwErr(errors.ERR_TOKEN_HAS_EXPIRED);
@@ -119,7 +119,7 @@ class Capabilities {
119
119
  this.compileCaps[constants.TNS_CCAP_TTC5] =
120
120
  constants.TNS_CCAP_VECTOR_SUPPORT;
121
121
  this.compileCaps[constants.TNS_CCAP_VECTOR_FEATURES] =
122
- constants.TNS_CCAP_VECTOR_FEATURE_BINARY;
122
+ constants.TNS_CCAP_VECTOR_FEATURE_BINARY | constants.TNS_CCAP_VECTOR_FEATURE_SPARSE;
123
123
  }
124
124
 
125
125
  initRuntimeCaps() {
@@ -644,6 +644,7 @@ module.exports = {
644
644
  TNS_CCAP_CTB_IMPLICIT_POOL: 0x08,
645
645
  TNS_CCAP_VECTOR_SUPPORT: 0x08,
646
646
  TNS_CCAP_VECTOR_FEATURE_BINARY: 0x01,
647
+ TNS_CCAP_VECTOR_FEATURE_SPARSE: 0x02,
647
648
 
648
649
  // runtime capability indices
649
650
  TNS_RCAP_COMPAT: 0,
@@ -767,6 +768,7 @@ module.exports = {
767
768
  TNS_VECTOR_MAX_LENGTH: 1048576,
768
769
  VECTOR_FORMAT_FLEX: 0,
769
770
  VECTOR_META_FLAG_FLEXIBLE_DIM: 1,
771
+ VECTOR_META_FLAG_SPARSE: 2,
770
772
 
771
773
  // other constants
772
774
  PACKET_HEADER_SIZE: 8,
@@ -1,4 +1,4 @@
1
- // Copyright (c) 2022, 2023, Oracle and/or its affiliates.
1
+ // Copyright (c) 2022, 2025, Oracle and/or its affiliates.
2
2
 
3
3
  //-----------------------------------------------------------------------------
4
4
  //
@@ -94,8 +94,10 @@ class AuthMessage extends Message {
94
94
  this.userByteLen = 0;
95
95
  }
96
96
  this.token = config.token;
97
- if (this.token)
97
+ if (config.externalAuth) {
98
98
  this.functionCode = constants.TNS_FUNC_AUTH_PHASE_TWO;
99
+ this.externalAuth = true;
100
+ }
99
101
  this.privateKey = config.privateKey;
100
102
  if (this.privateKey) {
101
103
  this.privateKey = util.normalizePrivateKey(this.privateKey);
@@ -107,6 +109,11 @@ class AuthMessage extends Message {
107
109
  this.osUser = config.osUser;
108
110
  this.program = config.program;
109
111
  this.terminal = config.terminal;
112
+ if (config.edition) {
113
+ this.edition = config.edition;
114
+ } else if (process.env.ORA_EDITION) {
115
+ this.edition = process.env.ORA_EDITION;
116
+ }
110
117
  this.setAuthMode(config);
111
118
  }
112
119
 
@@ -141,7 +148,7 @@ class AuthMessage extends Message {
141
148
  if (this.newPassword) {
142
149
  this.authMode |= constants.TNS_AUTH_MODE_CHANGE_PASSWORD;
143
150
  }
144
- if (!this.token) {
151
+ if (!config.externalAuth) {
145
152
  this.authMode |= constants.TNS_AUTH_MODE_WITH_PASSWORD;
146
153
  }
147
154
  }
@@ -199,8 +206,10 @@ class AuthMessage extends Message {
199
206
  numPairs = 2;
200
207
  } else {
201
208
  numPairs = 4;
202
- if (this.token) {
203
- numPairs += 1;
209
+ if (this.externalAuth) {
210
+ numPairs += 5;
211
+ if (this.token)
212
+ numPairs += 1;
204
213
  } else {
205
214
  numPairs += 2;
206
215
  if (this.verifierType === constants.TNS_VERIFIER_TYPE_11G_1 ||
@@ -235,6 +244,9 @@ class AuthMessage extends Message {
235
244
  this.encryptedJDWPData = ED.getEncryptedJSWPData(this.sessionKey, this.conn.jdwpData);
236
245
  numPairs += 1;
237
246
  }
247
+ if (this.edition) {
248
+ numPairs += 1;
249
+ }
238
250
  if (this.schemaUser.length !== 0) {
239
251
  numPairs += 1;
240
252
  }
@@ -246,10 +258,17 @@ class AuthMessage extends Message {
246
258
  buf.writeUInt8(1);
247
259
  if (this.userByteLen > 0)
248
260
  buf.writeBytesWithLength(Buffer.from(this.username));
261
+ if (this.externalAuth) {
262
+ buf.writeKeyValue("AUTH_TERMINAL", this.terminal ?? cInfo.terminal);
263
+ buf.writeKeyValue("AUTH_PROGRAM_NM", this.program ?? cInfo.program);
264
+ buf.writeKeyValue("AUTH_MACHINE", this.machine ?? cInfo.hostName);
265
+ buf.writeKeyValue("AUTH_PID", cInfo.pid);
266
+ buf.writeKeyValue("AUTH_SID", this.osUser ?? cInfo.userName);
267
+ }
249
268
  if (this.token) {
250
269
  buf.writeKeyValue("AUTH_TOKEN", this.token);
251
270
  } else {
252
- if (!this.changePassword) {
271
+ if (!this.changePassword && !this.externalAuth) {
253
272
  buf.writeKeyValue("AUTH_SESSKEY", this.sessionKey, 1);
254
273
  if (!verifier11G) {
255
274
  buf.writeKeyValue("AUTH_PBKDF2_SPEEDY_KEY", this.speedyKey);
@@ -297,6 +316,9 @@ class AuthMessage extends Message {
297
316
  if (this.conn.jdwpData) {
298
317
  buf.writeKeyValue("AUTH_ORA_DEBUG_JDWP", this.encryptedJDWPData);
299
318
  }
319
+ if (this.edition) {
320
+ buf.writeKeyValue("AUTH_ORA_EDITION", this.edition);
321
+ }
300
322
 
301
323
  }
302
324
  }
@@ -331,6 +353,7 @@ class AuthMessage extends Message {
331
353
  this.conn.maxOpenCursors = Number(this.sessionData['AUTH_MAX_OPEN_CURSORS'] || 0);
332
354
  this.conn.serviceName = this.sessionData['AUTH_SC_SERVICE_NAME'];
333
355
  this.conn.instanceName = this.sessionData['AUTH_INSTANCENAME'];
356
+ this.conn.maxIdentifierLength = Number(this.sessionData['AUTH_MAX_IDEN_LENGTH'] || 30);
334
357
  const fullVersionNum = Number(this.sessionData['AUTH_VERSION_NO']);
335
358
  const versionNum = (fullVersionNum >> 24) & 0xFF;
336
359
  this.conn.warning = this.warning;
@@ -1,4 +1,4 @@
1
- // Copyright (c) 2023, 2024, Oracle and/or its affiliates.
1
+ // Copyright (c) 2023, 2025, Oracle and/or its affiliates.
2
2
 
3
3
  //-----------------------------------------------------------------------------
4
4
  //
@@ -70,6 +70,11 @@ class FastAuthMessage extends Message {
70
70
  } else {
71
71
  this.authMessage.processMessage(buf, messageType);
72
72
  this.endOfResponse = this.authMessage.endOfResponse;
73
+ if (this.authMessage.errorOccurred) {
74
+ // Capture the Error returned in TNS_MSG_TYPE_ERROR processing.
75
+ this.errorOccurred = this.authMessage.errorOccurred;
76
+ this.errorInfo = this.authMessage.errorInfo;
77
+ }
73
78
  }
74
79
  }
75
80