oracledb 6.8.0 → 6.10.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 (85) hide show
  1. package/README.md +39 -3
  2. package/build/Release/oracledb-6.10.0-darwin-arm64.node +0 -0
  3. package/build/Release/oracledb-6.10.0-darwin-arm64.node-buildinfo.txt +1 -0
  4. package/build/Release/oracledb-6.10.0-darwin-x64.node +0 -0
  5. package/build/Release/oracledb-6.10.0-darwin-x64.node-buildinfo.txt +1 -0
  6. package/build/Release/oracledb-6.10.0-js-buildinfo.txt +1 -0
  7. package/build/Release/oracledb-6.10.0-linux-arm64.node +0 -0
  8. package/build/Release/oracledb-6.10.0-linux-arm64.node-buildinfo.txt +1 -0
  9. package/build/Release/oracledb-6.10.0-linux-x64.node +0 -0
  10. package/build/Release/oracledb-6.10.0-linux-x64.node-buildinfo.txt +1 -0
  11. package/build/Release/oracledb-6.10.0-win32-x64.node +0 -0
  12. package/build/Release/oracledb-6.10.0-win32-x64.node-buildinfo.txt +1 -0
  13. package/lib/aqDeqOptions.js +18 -1
  14. package/lib/aqMessage.js +10 -1
  15. package/lib/aqQueue.js +10 -6
  16. package/lib/configProviders/file.js +72 -0
  17. package/lib/connection.js +93 -4
  18. package/lib/dbObject.js +34 -4
  19. package/lib/errors.js +70 -35
  20. package/lib/impl/aqDeqOptions.js +10 -1
  21. package/lib/impl/connection.js +9 -0
  22. package/lib/impl/datahandlers/buffer.js +49 -0
  23. package/lib/impl/datahandlers/oson.js +7 -2
  24. package/lib/impl/pool.js +10 -1
  25. package/lib/impl/resultset.js +5 -4
  26. package/lib/impl/sodaDocument.js +5 -14
  27. package/lib/lob.js +9 -1
  28. package/lib/oracledb.js +152 -30
  29. package/lib/pool.js +199 -147
  30. package/lib/poolStatistics.js +4 -2
  31. package/lib/sodaCollection.js +12 -8
  32. package/lib/sodaDatabase.js +35 -8
  33. package/lib/sodaDocument.js +24 -6
  34. package/lib/sodaOperation.js +7 -6
  35. package/lib/thin/aq.js +475 -0
  36. package/lib/thin/connection.js +171 -14
  37. package/lib/thin/dbObject.js +8 -6
  38. package/lib/thin/lob.js +2 -3
  39. package/lib/thin/pool.js +105 -28
  40. package/lib/thin/protocol/capabilities.js +10 -4
  41. package/lib/thin/protocol/constants.js +90 -1
  42. package/lib/thin/protocol/encryptDecrypt.js +2 -2
  43. package/lib/thin/protocol/messages/aqArray.js +238 -0
  44. package/lib/thin/protocol/messages/aqBase.js +305 -0
  45. package/lib/thin/protocol/messages/aqDeq.js +164 -0
  46. package/lib/thin/protocol/messages/aqEnq.js +135 -0
  47. package/lib/thin/protocol/messages/auth.js +25 -27
  48. package/lib/thin/protocol/messages/base.js +98 -9
  49. package/lib/thin/protocol/messages/dataType.js +2 -1
  50. package/lib/thin/protocol/messages/execute.js +46 -4
  51. package/lib/thin/protocol/messages/lobOp.js +5 -22
  52. package/lib/thin/protocol/messages/logOff.js +0 -1
  53. package/lib/thin/protocol/messages/sessionRelease.js +0 -1
  54. package/lib/thin/protocol/messages/transactionSwitch.js +12 -4
  55. package/lib/thin/protocol/messages/withData.js +3 -3
  56. package/lib/thin/protocol/packet.js +6 -5
  57. package/lib/thin/protocol/protocol.js +2 -1
  58. package/lib/thin/sqlnet/connStrategy.js +2 -1
  59. package/lib/thin/sqlnet/navNodes.js +1 -1
  60. package/lib/thin/sqlnet/networkSession.js +10 -4
  61. package/lib/thin/sqlnet/packet.js +2 -1
  62. package/lib/thin/sqlnet/sessionAtts.js +2 -3
  63. package/lib/types.js +6 -11
  64. package/lib/util.js +72 -11
  65. package/lib/version.js +1 -1
  66. package/package/install.js +3 -3
  67. package/package/prunebinaries.js +6 -12
  68. package/package.json +2 -2
  69. package/{lib/configProviders/azure.js → plugins/configProviders/azure/index.js} +73 -63
  70. package/plugins/configProviders/azurevault/index.js +84 -0
  71. package/{lib → plugins}/configProviders/base.js +13 -3
  72. package/{lib/configProviders/ociobject.js → plugins/configProviders/ociobject/index.js} +43 -78
  73. package/plugins/configProviders/ocivault/index.js +100 -0
  74. package/plugins/token/extensionOci/index.js +71 -35
  75. package/build/Release/oracledb-6.8.0-darwin-arm64.node +0 -0
  76. package/build/Release/oracledb-6.8.0-darwin-arm64.node-buildinfo.txt +0 -1
  77. package/build/Release/oracledb-6.8.0-darwin-x64.node +0 -0
  78. package/build/Release/oracledb-6.8.0-darwin-x64.node-buildinfo.txt +0 -1
  79. package/build/Release/oracledb-6.8.0-js-buildinfo.txt +0 -1
  80. package/build/Release/oracledb-6.8.0-linux-arm64.node +0 -0
  81. package/build/Release/oracledb-6.8.0-linux-arm64.node-buildinfo.txt +0 -1
  82. package/build/Release/oracledb-6.8.0-linux-x64.node +0 -0
  83. package/build/Release/oracledb-6.8.0-linux-x64.node-buildinfo.txt +0 -1
  84. package/build/Release/oracledb-6.8.0-win32-x64.node +0 -0
  85. package/build/Release/oracledb-6.8.0-win32-x64.node-buildinfo.txt +0 -1
@@ -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
  //
@@ -30,6 +30,34 @@ const { Buffer } = require('buffer');
30
30
  const constants = require("../constants.js");
31
31
  const errors = require("../../../errors.js");
32
32
 
33
+ // List of recoverable errors
34
+ const RECOVERABLE_ERRORS = new Set([
35
+ 28, // session has been terminated
36
+ 31, // session marked for kill
37
+ 376, // file %s cannot be read at this time
38
+ 603, // ORACLE server session terminated
39
+ 1012, // not logged on
40
+ 1033, // ORACLE initialization or shutdown in progress
41
+ 1034, // the Oracle instance is not available for use
42
+ 1089, // immediate shutdown or close in progress
43
+ 1090, // shutdown in progress
44
+ 1092, // ORACLE instance terminated
45
+ 1115, // IO error reading block from file %s (block # %s)
46
+ 2396, // exceeded maximum idle time
47
+ 3113, // end-of-file on communication channel
48
+ 3114, // not connected to ORACLE
49
+ 3135, // connection lost contact
50
+ 12153, // TNS:not connected
51
+ 12514, // Service %s is not registered with the listener
52
+ 12537, // TNS:connection closed
53
+ 12547, // TNS:lost contact
54
+ 12570, // TNS:packet reader failure
55
+ 12571, // TNS:packet writer failure
56
+ 12583, // TNS:no reader
57
+ 12757, // instance does not currently know of requested service
58
+ 16456 // missing or invalid value
59
+ ]);
60
+
33
61
  /**
34
62
  *
35
63
  * Base class for all the RPC messages to support encode/decode functions
@@ -52,6 +80,7 @@ class Message {
52
80
  async postProcess() { }
53
81
 
54
82
  writeFunctionHeader(buf) {
83
+ this.writePiggybacks(buf);
55
84
  buf.writeUInt8(this.messageType);
56
85
  buf.writeUInt8(this.functionCode);
57
86
  buf.writeSeqNum();
@@ -160,6 +189,8 @@ class Message {
160
189
  */
161
190
  this.errorInfo.message = this.errorInfo.message.trim();
162
191
  }
192
+ this.errorInfo.isRecoverable = RECOVERABLE_ERRORS.has(this.errorInfo.num);
193
+
163
194
  this.endOfResponse = !this.connection.nscon.endOfRequestSupport;
164
195
  }
165
196
 
@@ -220,7 +251,7 @@ class Message {
220
251
  if (opcode === constants.TNS_SERVER_PIGGYBACK_LTXID) {
221
252
  const num_bytes = buf.readUB4();
222
253
  if (num_bytes > 0) {
223
- buf.skipBytesChunked();
254
+ this.connection._ltxid = Buffer.from(buf.readBytesWithLength());
224
255
  }
225
256
  } else if ((opcode === constants.TNS_SERVER_PIGGYBACK_QUERY_CACHE_INVALIDATION)
226
257
  || (opcode === constants.TNS_SERVER_PIGGYBACK_TRACE_EVENT)) {
@@ -235,15 +266,22 @@ class Message {
235
266
  const num_elements = buf.readUB4();
236
267
  buf.skipBytes(1); // skip length
237
268
  for (let i = 0; i < num_elements; i++) {
238
- let temp16 = buf.readUB2();
239
- if (temp16 > 0) { // skip key
240
- buf.skipBytesChunked();
269
+ let numBytes = buf.readUB2();
270
+ let keyTextValue, value;
271
+ if (numBytes > 0) { // read key
272
+ keyTextValue = buf.readStr(constants.CSFRM_IMPLICIT);
241
273
  }
242
- temp16 = buf.readUB2();
243
- if (temp16 > 0) { // skip value
244
- buf.skipBytesChunked();
274
+ numBytes = buf.readUB2();
275
+ if (numBytes > 0) // read value
276
+ value = buf.readBytesWithLength();
277
+ const keywordNum = buf.readUB2(); // read keyword number
278
+ if (keywordNum == constants.TNS_KEYWORD_NUM_TRANSACTION_ID) {
279
+ this._updateSessionlessTxnState(value);
280
+ } else if (keywordNum === constants.TNS_KEYWORD_NUM_CURRENT_SCHEMA) {
281
+ this.connection.currentSchema = keyTextValue;
282
+ } else if (keywordNum === constants.TNS_KEYWORD_NUM_EDITION) {
283
+ this.connection._edition = keyTextValue;
245
284
  }
246
- buf.skipUB2(); // skip flags
247
285
  }
248
286
  buf.skipUB4(); // skip overall flags
249
287
  } else if (opcode === constants.TNS_SERVER_PIGGYBACK_EXT_SYNC) {
@@ -286,12 +324,22 @@ class Message {
286
324
  this.connection._drcpEstablishSession = false;
287
325
  buf.skipUB4(); // session id
288
326
  buf.skipUB2(); // serial number
327
+ } else if (opcode === constants.TNS_SERVER_PIGGYBACK_SESS_SIGNATURE) {
328
+ buf.skipUB2(); // number of dtys
329
+ buf.skipUB1(); // length of dty
330
+ buf.skipUB8(); // signature flags
331
+ buf.skipUB8(); // client signature
332
+ buf.skipUB8(); // server signature
289
333
  } else {
290
334
  errors.throwErr(errors.ERR_UNKOWN_SERVER_SIDE_PIGGYBACK, opcode);
291
335
  }
292
336
  }
293
337
 
294
338
  writePiggybacks(buf) {
339
+ // Don't write piggybacks if not authenticated yet
340
+ if (this.connection._protocol.connInProgress)
341
+ return;
342
+
295
343
  if (this.connection._currentSchemaModified) {
296
344
  this._writeCurrentSchemaPiggyback(buf);
297
345
  }
@@ -313,6 +361,11 @@ class Message {
313
361
  if (this.connection._tempLobsTotalSize > 0) {
314
362
  this.writeCloseTempLobsPiggyback(buf);
315
363
  }
364
+ if (this.connection._sessionlessData?.pending) {
365
+ this.connection._sessionlessData.pending = false;
366
+ this.connection._sessionlessData.piggyback.encode(buf);
367
+ this.connection._sessionlessData.piggyback = null;
368
+ }
316
369
  }
317
370
 
318
371
  writePiggybackHeader(buf, functionCode) {
@@ -474,6 +527,42 @@ class Message {
474
527
  this.deferredErr = errors.getErr(...arguments);
475
528
  }
476
529
  }
530
+
531
+ _updateSessionlessTxnState(buf) {
532
+ const length = buf.length;
533
+ const sessionlessState = buf.readUInt8(length - 2);
534
+ const syncVersion = buf.readUInt8(length - 1);
535
+ let startedOnServer;
536
+
537
+ if (syncVersion == constants.TNS_TPC_TRANS_TRANSACTION_ID_SYNC_VERSION_1) {
538
+ // transactionId got unset for this session (txn ended or suspended)
539
+ if (sessionlessState &
540
+ constants.TNS_TPC_TRANS_TRANSACTION_ID_SYNC_UNSET) {
541
+ this.connection._sessionlessData = null;
542
+ this.connection._protocol.txnInProgress = false;
543
+ // transactionId got set for this session
544
+ } else if (sessionlessState &
545
+ constants.TNS_TPC_TRANS_TRANSACTION_ID_SYNC_SET) {
546
+
547
+ // transaction initialized by PL/SQL procedure
548
+ if (sessionlessState &
549
+ constants.TNS_TPC_TRANS_TRANSACTION_ID_SYNC_SERVER)
550
+ startedOnServer = true;
551
+ // transaction initialized by calling client API(RPC call)
552
+ else if (sessionlessState &
553
+ constants.TNS_TPC_TRANS_TRANSACTION_ID_SYNC_CLIENT)
554
+ startedOnServer = false;
555
+
556
+ this.connection._sessionlessData = {
557
+ startedOnServer: startedOnServer,
558
+ };
559
+ this.connection._protocol.txnInProgress = true;
560
+ }
561
+ } else
562
+ errors.throwErr(errors.ERR_INTERNAL, 'Unexpected TransactionId sync ' +
563
+ 'version in session sync piggyback.');
564
+ }
565
+
477
566
  }
478
567
 
479
568
  module.exports = Message;
@@ -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
  //
@@ -394,6 +394,7 @@ const dataTypes = [
394
394
  [constants.TNS_DATA_TYPE_TNP, constants.TNS_DATA_TYPE_TNP, constants.TNS_TYPE_REP_UNIVERSAL],
395
395
  [constants.TNS_DATA_TYPE_OER, constants.TNS_DATA_TYPE_OER, constants.TNS_TYPE_REP_UNIVERSAL],
396
396
  [constants.TNS_DATA_TYPE_OAC, constants.TNS_DATA_TYPE_OAC, constants.TNS_TYPE_REP_UNIVERSAL],
397
+ [constants.TNS_DATA_TYPE_SESSSIGN, constants.TNS_DATA_TYPE_SESSSIGN, constants.TNS_TYPE_REP_UNIVERSAL],
397
398
  [constants.TNS_DATA_TYPE_VECTOR, constants.TNS_DATA_TYPE_VECTOR, constants.TNS_TYPE_REP_UNIVERSAL]
398
399
  ];
399
400
 
@@ -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
  //
@@ -29,6 +29,7 @@
29
29
  const MessageWithData = require("./withData.js");
30
30
  const constants = require("../constants.js");
31
31
  const errors = require("../../../errors.js");
32
+ const TransactionSwitchMessage = require("./transactionSwitch.js");
32
33
 
33
34
  /**
34
35
  *
@@ -110,12 +111,18 @@ class ExecuteMessage extends MessageWithData {
110
111
  options |= constants.TNS_EXEC_OPTION_BATCH_ERRORS;
111
112
  }
112
113
  if (this.arrayDmlRowCounts) {
113
- dmlOptions = constants.TNS_EXEC_OPTION_DML_ROWCOUNTS;
114
+ dmlOptions |= constants.TNS_EXEC_OPTION_DML_ROWCOUNTS;
114
115
  }
115
116
  if (this.options.autoCommit) {
116
117
  options |= constants.TNS_EXEC_OPTION_COMMIT;
117
118
  }
118
- this.writePiggybacks(buf);
119
+
120
+ // In case SuspendOnSuccess is set for execute and a sessionless transaction
121
+ // is active we add a piggyback for post-call suspend
122
+ if (this.options.suspendOnSuccess) {
123
+ this._handleSuspendSessionless();
124
+ }
125
+
119
126
  this.writeFunctionHeader(buf);
120
127
  buf.writeUB4(options); // execute options
121
128
  buf.writeUB4(stmt.cursorId); // cursor id
@@ -258,7 +265,13 @@ class ExecuteMessage extends MessageWithData {
258
265
  }
259
266
  numIters = this.numExecs;
260
267
  }
261
- this.writePiggybacks(buf);
268
+
269
+ // In case SuspendOnSuccess is set for execute and a sessionless transaction
270
+ // is active we add a piggyback for post-call suspend
271
+ if (this.options.suspendOnSuccess) {
272
+ this._handleSuspendSessionless();
273
+ }
274
+
262
275
  this.writeFunctionHeader(buf);
263
276
  buf.writeUB4(stmt.cursorId);
264
277
  buf.writeUB4(numIters);
@@ -267,6 +280,35 @@ class ExecuteMessage extends MessageWithData {
267
280
  return params;
268
281
  }
269
282
 
283
+ //-------------------------------------------------------------------------
284
+ // _handleSuspendSessionless()
285
+ //
286
+ // Suspend the active sessionless transaction after DML execution if
287
+ // suspendOnSuccess option was given to execute()
288
+ //-------------------------------------------------------------------------
289
+ _handleSuspendSessionless() {
290
+ const sessionlessData = this.connection._sessionlessData;
291
+ // If sessionless transaction was started by server-call we cannot suspend
292
+ // using client API(RPC) calls
293
+ this.connection._validateSessionlessState();
294
+
295
+ if (!sessionlessData)
296
+ errors.throwErr(errors.ERR_SESSIONLESS_INACTIVE);
297
+ // If a piggybacks already exists it is most likely a start/resume for a
298
+ // sessionless transaction, add a post-call detach opcode to it
299
+ if (sessionlessData.piggyback) {
300
+ sessionlessData.piggyback.operation |=
301
+ constants.TNS_TPC_TXN_POST_DETACH;
302
+ } else {
303
+ const message = new TransactionSwitchMessage(this.connection);
304
+ message.operation = constants.TNS_TPC_TXN_POST_DETACH;
305
+ message.flags = constants.TNS_TPC_TRANS_SESSIONLESS;
306
+ message.messageType = constants.TNS_MSG_TYPE_PIGGYBACK;
307
+ sessionlessData.piggyback = message;
308
+ sessionlessData.pending = true;
309
+ }
310
+ }
311
+
270
312
  //-------------------------------------------------------------------------
271
313
  // encode()
272
314
  //
@@ -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
  //
@@ -45,10 +45,6 @@ class LobOpMessage extends Message {
45
45
  */
46
46
  this.sourceLobImpl = options.sourceLobImpl || null;
47
47
  this.operation = options.operation;
48
- /*
49
- * Destination LOB locator. For copy, append operations,...
50
- */
51
- this.destLobImpl = options.destLobImpl || null;
52
48
  /*
53
49
  * Offset from where sourceLob operation to start
54
50
  */
@@ -64,6 +60,7 @@ class LobOpMessage extends Message {
64
60
  this.functionCode = constants.TNS_FUNC_LOB_OP;
65
61
  this.sendAmount = options.sendAmount;
66
62
  this.amount = options.amount || 0; // LOB length
63
+ this.destLength = options.destLength || 0;
67
64
  }
68
65
 
69
66
  encode(buf) {
@@ -75,13 +72,8 @@ class LobOpMessage extends Message {
75
72
  buf.writeUInt8(1);
76
73
  buf.writeUB4(this.sourceLobImpl._locator.length);
77
74
  }
78
- if (this.destLobImpl === null) {
79
- buf.writeUInt8(0);
80
- buf.writeUB4(0);
81
- } else {
82
- buf.writeUInt8(1);
83
- buf.writeUB4(this.destLobImpl._locator.length);
84
- }
75
+ buf.writeUInt8(0);
76
+ buf.writeUB4(this.destLength);
85
77
  buf.writeUB4(0);
86
78
  buf.writeUB4(0);
87
79
  if (this.operation === constants.TNS_LOB_OP_CREATE_TEMP) {
@@ -117,9 +109,6 @@ class LobOpMessage extends Message {
117
109
  if (this.sourceLobImpl) {
118
110
  buf.writeBytes(this.sourceLobImpl._locator);
119
111
  }
120
- if (this.destLobImpl) {
121
- buf.writeBytes(this.destLobImpl._locator);
122
- }
123
112
  if (this.operation === constants.TNS_LOB_OP_CREATE_TEMP) {
124
113
  if (this.sourceLobImpl.dbType._csfrm === constants.CSFRM_NCHAR) {
125
114
  buf.caps.checkNCharsetId();
@@ -185,15 +174,9 @@ class LobOpMessage extends Message {
185
174
  locator = lobArray.slice(0, numBytes);
186
175
  locator.copy(this.sourceLobImpl._locator);
187
176
  }
188
- if (this.destLobImpl !== null) {
189
- numBytes = this.destLobImpl._locator.length;
190
- lobArray = buf.readBytes(numBytes);
191
- locator = lobArray.slice(0, numBytes);
192
- locator.copy(this.destLobImpl._locator);
193
- }
194
177
  if (this.operation === constants.TNS_LOB_OP_CREATE_TEMP) {
195
178
  buf.skipUB2(); // skip character set
196
- buf.skipBytes(3); // skip trailing flags, amount
179
+ buf.skipUB1(); // skip trailing flags
197
180
  } else if (this.sendAmount) {
198
181
  this.amount = buf.readSB8();
199
182
  }
@@ -44,7 +44,6 @@ class LogOffMessage extends Message {
44
44
  }
45
45
 
46
46
  encode(buf) {
47
- this.writePiggybacks(buf);
48
47
  this.writeFunctionHeader(buf);
49
48
  }
50
49
 
@@ -45,7 +45,6 @@ class SessionReleaseMessage extends Message {
45
45
  }
46
46
 
47
47
  encode(buf) {
48
- this.writePiggybacks(buf);
49
48
  this.writeFunctionHeader(buf);
50
49
  buf.writeUInt8(0); // pointer (tag name)
51
50
  buf.writeUInt8(0); // tag name length
@@ -28,6 +28,7 @@
28
28
 
29
29
  const Message = require("./base.js");
30
30
  const constants = require("../constants.js");
31
+ const errors = require("../../../errors.js");
31
32
 
32
33
  /**
33
34
  * Used for two-phase commit (TPC) transaction start, attach and detach.
@@ -61,18 +62,25 @@ class TransactionSwitchMessage extends Message {
61
62
  }
62
63
 
63
64
  encode(buf) {
65
+ // We unset the pending flag in writePiggybacks just before encode is
66
+ // called to ensure message is written
67
+ if (this.connection._sessionlessData?.pending)
68
+ errors.throwErr(errors.ERR_SESSIONLESS_ALREADY_ACTIVE);
69
+
64
70
  // writes the message to the database
65
71
  // acquire data to send to the server
66
72
  let xidBytes;
67
73
  if (this.xid) {
68
74
  xidBytes = Buffer.alloc(128);
69
75
  this.xid.globalTransactionId.copy(xidBytes);
70
- this.xid.branchQualifier.copy(xidBytes,
71
- this.xid.globalTransactionId.length);
76
+ if (this.xid.branchQualifier)
77
+ this.xid.branchQualifier.copy(xidBytes,
78
+ this.xid.globalTransactionId.length);
72
79
  }
73
80
 
74
- // write message
75
81
  this.writeFunctionHeader(buf);
82
+
83
+
76
84
  buf.writeUB4(this.operation);
77
85
  if (this.context) {
78
86
  buf.writeUInt8(1); // pointer (transaction context)
@@ -97,7 +105,7 @@ class TransactionSwitchMessage extends Message {
97
105
  }
98
106
 
99
107
  buf.writeUB4(this.flags);
100
- buf.writeUB4(this.timeout);
108
+ buf.writeUB4(this.timeout ? this.timeout : 0);
101
109
  buf.writeUInt8(1); // pointer (application value)
102
110
  buf.writeUInt8(1); // pointer (return context)
103
111
  buf.writeUInt8(1); // pointer (return context length)
@@ -156,7 +156,6 @@ class MessageWithData extends Message {
156
156
  if (statement.numQueryVars > 0) {
157
157
  buf.skipUB1();
158
158
  }
159
- resultSet.metadata = [];
160
159
  const metadata = [];
161
160
  const queryVars = [];
162
161
  for (let i = 0; i < statement.numQueryVars; i++) {
@@ -185,7 +184,7 @@ class MessageWithData extends Message {
185
184
  * at end of the DescribeInfo function so that an OutOfPacketsError
186
185
  * won't cause partial information state to be stored.
187
186
  */
188
- resultSet.metadata = metadata;
187
+ resultSet.metaData = metadata;
189
188
  statement.queryVars = queryVars;
190
189
  this.resultSetsToSetup.push(resultSet);
191
190
  }
@@ -236,6 +235,7 @@ class MessageWithData extends Message {
236
235
  // build metadata
237
236
  const fetchInfo = {
238
237
  name: name,
238
+ dbColumnName: name,
239
239
  dbType: types.getTypeByOraTypeNum(dataType, csfrm),
240
240
  nullable: nullable
241
241
  };
@@ -628,7 +628,7 @@ class MessageWithData extends Message {
628
628
  }
629
629
  await this.connection._populatePartialDbObjectTypes();
630
630
  for (const resultSet of this.resultSetsToSetup) {
631
- resultSet._setup(this.options, resultSet.metadata);
631
+ resultSet._setup(this.options, resultSet.metaData);
632
632
  // LOBs always require define and they change the type that is actually
633
633
  // returned by the server
634
634
  for (const variable of resultSet.statement.queryVars) {
@@ -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
  //
@@ -576,10 +576,10 @@ class WritePacket extends BaseBuffer {
576
576
  * Encodes a JavaScript object into OSON and then writes it (QLocator
577
577
  * followed by data) to the buffer.
578
578
  */
579
- writeOson(value, osonMaxFieldSize) {
579
+ writeOson(value, osonMaxFieldSize, writeLength = true) {
580
580
  const encoder = new oson.OsonEncoder();
581
581
  const buf = encoder.encode(value, osonMaxFieldSize);
582
- this.writeQLocator(buf.length);
582
+ this.writeQLocator(buf.length, writeLength);
583
583
  this.writeBytesWithLength(buf);
584
584
  }
585
585
 
@@ -604,9 +604,10 @@ class WritePacket extends BaseBuffer {
604
604
  //
605
605
  // Writes a QLocator. QLocators are always 40 bytes in length.
606
606
  //---------------------------------------------------------------------------
607
- writeQLocator(numBytes) {
607
+ writeQLocator(numBytes, writeLength = true) {
608
608
  this.writeUB4(40); // QLocator length
609
- this.writeUInt8(40); // repeated length
609
+ if (writeLength)
610
+ this.writeUInt8(40); // repeated length
610
611
  this.writeUInt16BE(38); // internal length
611
612
  this.writeUInt16BE(constants.TNS_LOB_QLOCATOR_VERSION);
612
613
  this.writeUInt8(constants.TNS_LOB_LOC_FLAGS_VALUE_BASED |
@@ -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
  //
@@ -204,6 +204,7 @@ class Protocol {
204
204
  let err = new Error(message.errorInfo.message);
205
205
  err.offset = message.errorInfo.pos;
206
206
  err.errorNum = message.errorInfo.num;
207
+ err.isRecoverable = message.errorInfo.isRecoverable;
207
208
  err = errors.transformErr(err);
208
209
  if (err.code === errors.ERR_CONNECTION_CLOSED_CODE) {
209
210
  this.nsi.disconnect();
@@ -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
  //
@@ -194,6 +194,7 @@ async function createNode(str, userConfig) {
194
194
  cs.terminal = userConfig.terminal;
195
195
  cs.osUser = userConfig.osUser;
196
196
  cs.program = userConfig.program;
197
+ cs.httpsProxy = userConfig.httpsProxy;
197
198
  await navobj.navigate(cs);
198
199
  return cs;
199
200
  }
@@ -500,7 +500,7 @@ class NavAddress extends Address {
500
500
  cs.newConnectionDescription();
501
501
  needToCloseDescription = true;
502
502
  }
503
- if (!net.isIP(this.host)) {
503
+ if (!net.isIP(this.host) && !(cs.httpsProxy || this.httpsProxy)) {
504
504
  try {
505
505
  addresses = await dnsPromises.lookup(this.host, options);
506
506
  for (const addr of addresses) {
@@ -298,7 +298,6 @@ class NetworkSession {
298
298
 
299
299
  /* Accepted */
300
300
 
301
- this.connected = true;
302
301
  this.cData = null;
303
302
  this.sndDatapkt = new Packet.DataPacket(this.sAtts.largeSDU);
304
303
  this.markerPkt = new Packet.MarkerPacket(this.sAtts.largeSDU);
@@ -319,6 +318,7 @@ class NetworkSession {
319
318
  this.sndDatapkt.createPacket(constants.NSPDADAT); //Currently only used for disconnect
320
319
  this.sndDatapkt.offset = this.sndDatapkt.dataPtr;
321
320
  this.sndDatapkt.len = this.sndDatapkt.bufLen;
321
+ this.connected = true;
322
322
  return (true);
323
323
  }
324
324
 
@@ -374,9 +374,9 @@ class NetworkSession {
374
374
  const buffertoDeCompress = packet.buf.subarray(constants.NSPDADAT, size);
375
375
  let deCompressedDataBuffer;
376
376
  try {
377
- if (this.sAtts.firstCompressedPacket) {
377
+ if (this.sAtts.firstRecvCompressedPacket) {
378
378
  deCompressedDataBuffer = zlib.inflateSync(buffertoDeCompress, {finishFlush: zlib.constants.Z_SYNC_FLUSH});
379
- this.sAtts.firstCompressedPacket = 0;
379
+ this.sAtts.firstRecvCompressedPacket = 0;
380
380
  } else {
381
381
  deCompressedDataBuffer = zlib.inflateRawSync(buffertoDeCompress, {finishFlush: zlib.constants.Z_SYNC_FLUSH});
382
382
  }
@@ -457,7 +457,13 @@ class NetworkSession {
457
457
  const bufferHeader = buf.subarray(0, constants.NSPDADAT);
458
458
  let compressedDataBuffer;
459
459
  try {
460
- compressedDataBuffer = zlib.deflateSync(buffertoCompress, {finishFlush: zlib.constants.Z_SYNC_FLUSH});
460
+ if (this.sAtts.firstSendCompressedPacket) {
461
+ compressedDataBuffer = zlib.deflateSync(buffertoCompress, {finishFlush: zlib.
462
+ constants.Z_SYNC_FLUSH});
463
+ this.sAtts.firstSendCompressedPacket = 0;
464
+ } else {
465
+ compressedDataBuffer = zlib.deflateRawSync(buffertoCompress, {finishFlush: zlib.constants.Z_SYNC_FLUSH});
466
+ }
461
467
  } catch (err) {
462
468
  errors.throwErr(errors.ERR_DATA_COMPRESSION, err.message);
463
469
  }
@@ -258,7 +258,8 @@ function AcceptPacket(packet, sAtts) {
258
258
  if ((this.cflag & constants.NSPACCFON) != 0) { // compression ON
259
259
  sAtts.negotiatedNetworkCompressionScheme = (this.cflag & 0x3c) >> 2; // 0x3c
260
260
  sAtts.networkCompressionEnabled = true;
261
- sAtts.firstCompressedPacket = true;
261
+ sAtts.firstRecvCompressedPacket = true;
262
+ sAtts.firstSendCompressedPacket = true;
262
263
  } else {
263
264
  sAtts.networkCompressionEnabled = false;
264
265
  }
@@ -62,6 +62,7 @@ class SessionAtts {
62
62
  this.nt.sslServerDNMatch = true;
63
63
  this.nt.sslAllowWeakDNMatch = false;
64
64
  this.nt.useSNI = false;
65
+ this.networkCompressionThreshold = 1024;
65
66
  }
66
67
 
67
68
  /**
@@ -85,9 +86,7 @@ class SessionAtts {
85
86
  }
86
87
  if (params.networkCompressionThreshold >= 200) {
87
88
  this.networkCompressionThreshold = parseInt(params.networkCompressionThreshold);
88
- } else
89
- this.networkCompressionThreshold = 1024;
90
-
89
+ }
91
90
 
92
91
  if (typeof params.walletLocation === 'string') {
93
92
  this.nt.walletFile = path.join(params.walletLocation, constants.PEM_WALLET_FILE_NAME);
package/lib/types.js CHANGED
@@ -46,7 +46,7 @@ class DbType {
46
46
  this._oraTypeNum = options.oraTypeNum || 0;
47
47
  this._csfrm = options.csfrm || 0;
48
48
  dbTypeByNum.set(num, this);
49
- const key = (options.csfrm || 0) * 256 + options.oraTypeNum;
49
+ const key = this._csfrm * 256 + this._oraTypeNum;
50
50
  dbTypeByOraTypeNum.set(key, this);
51
51
  dbTypeByColumnTypeName.set(columnTypeName, this);
52
52
  }
@@ -322,14 +322,9 @@ const DB_TYPE_FETCH_TYPE_MAP = new Map([
322
322
  ]);
323
323
 
324
324
  // additional aliases for types by column type name
325
- dbTypeByColumnTypeName.set("DOUBLE PRECISION", DB_TYPE_NUMBER);
326
- dbTypeByColumnTypeName.set("FLOAT", DB_TYPE_NUMBER);
327
- dbTypeByColumnTypeName.set("INTEGER", DB_TYPE_NUMBER);
328
325
  dbTypeByColumnTypeName.set("PL/SQL BOOLEAN", DB_TYPE_BOOLEAN);
329
326
  dbTypeByColumnTypeName.set("PL/SQL BINARY INTEGER", DB_TYPE_BINARY_INTEGER);
330
327
  dbTypeByColumnTypeName.set("PL/SQL PLS INTEGER", DB_TYPE_BINARY_INTEGER);
331
- dbTypeByColumnTypeName.set("REAL", DB_TYPE_NUMBER);
332
- dbTypeByColumnTypeName.set("SMALLINT", DB_TYPE_NUMBER);
333
328
  dbTypeByColumnTypeName.set("TIMESTAMP WITH LOCAL TZ", DB_TYPE_TIMESTAMP_LTZ);
334
329
  dbTypeByColumnTypeName.set("TIMESTAMP WITH TZ", DB_TYPE_TIMESTAMP_TZ);
335
330
 
@@ -530,8 +525,8 @@ class IntervalYM {
530
525
  errors.assertParamPropInt(obj, 1, "years");
531
526
  errors.assertParamPropInt(obj, 1, "months");
532
527
  }
533
- this.years = obj?.years || 0;
534
528
  this.months = obj?.months || 0;
529
+ this.years = obj?.years || 0;
535
530
  }
536
531
  }
537
532
 
@@ -545,11 +540,11 @@ class IntervalDS {
545
540
  errors.assertParamPropInt(obj, 1, "seconds");
546
541
  errors.assertParamPropInt(obj, 1, "fseconds");
547
542
  }
548
- this.days = obj?.days || 0;
549
- this.hours = obj?.hours || 0;
550
- this.minutes = obj?.minutes || 0;
551
- this.seconds = obj?.seconds || 0;
552
543
  this.fseconds = obj?.fseconds || 0;
544
+ this.seconds = obj?.seconds || 0;
545
+ this.minutes = obj?.minutes || 0;
546
+ this.hours = obj?.hours || 0;
547
+ this.days = obj?.days || 0;
553
548
  }
554
549
  }
555
550