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
@@ -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
  //
@@ -405,6 +405,7 @@ module.exports = {
405
405
  TNS_DATA_TYPE_UD21: 639,
406
406
  TNS_DATA_TYPE_TNP: 640,
407
407
  TNS_DATA_TYPE_OAC: 646,
408
+ TNS_DATA_TYPE_SESSSIGN: 647,
408
409
  TNS_DATA_TYPE_OER: 652,
409
410
  TNS_DATA_TYPE_UDS: 663,
410
411
 
@@ -439,6 +440,7 @@ module.exports = {
439
440
  // parameter keyword numbers,
440
441
  TNS_KEYWORD_NUM_CURRENT_SCHEMA: 168,
441
442
  TNS_KEYWORD_NUM_EDITION: 172,
443
+ TNS_KEYWORD_NUM_TRANSACTION_ID: 201,
442
444
 
443
445
  // bind flags
444
446
  TNS_BIND_USE_INDICATORS: 0x0001,
@@ -476,6 +478,7 @@ module.exports = {
476
478
  TNS_SERVER_PIGGYBACK_LTXID: 7,
477
479
  TNS_SERVER_PIGGYBACK_AC_REPLAY_CONTEXT: 8,
478
480
  TNS_SERVER_PIGGYBACK_EXT_SYNC: 9,
481
+ TNS_SERVER_PIGGYBACK_SESS_SIGNATURE: 10,
479
482
 
480
483
  // session return constants
481
484
  TNS_SESSGET_SESSION_CHANGED: 4,
@@ -582,7 +585,9 @@ module.exports = {
582
585
  TNS_CCAP_UB2_DTY: 27,
583
586
  TNS_CCAP_OCI2: 31,
584
587
  TNS_CCAP_CLIENT_FN: 34,
588
+ TNS_CCAP_OCI3: 35,
585
589
  TNS_CCAP_TTC3: 37,
590
+ TNS_CCAP_SESS_SIGNATURE_VERSION: 39,
586
591
  TNS_CCAP_TTC4: 40,
587
592
  TNS_CCAP_LOB2: 42,
588
593
  TNS_CCAP_TTC5: 44,
@@ -625,6 +630,7 @@ module.exports = {
625
630
  TNS_CCAP_RPC_VERSION_MAX: 7,
626
631
  TNS_CCAP_RPC_SIG_VALUE: 3,
627
632
  TNS_CCAP_DBF_VERSION_MAX: 1,
633
+ TNS_CCAP_LTXID: 0x08,
628
634
  TNS_CCAP_IMPLICIT_RESULTS: 0x10,
629
635
  TNS_CCAP_BIG_CHUNK_CLR: 0x20,
630
636
  TNS_CCAP_KEEP_OUT_ORDER: 0x80,
@@ -644,6 +650,9 @@ module.exports = {
644
650
  TNS_CCAP_CTB_IMPLICIT_POOL: 0x08,
645
651
  TNS_CCAP_VECTOR_SUPPORT: 0x08,
646
652
  TNS_CCAP_VECTOR_FEATURE_BINARY: 0x01,
653
+ TNS_CCAP_VECTOR_FEATURE_SPARSE: 0x02,
654
+ TNS_CCAP_TTC5_SESSIONLESS_TXNS: 0x20,
655
+ TNS_CCAP_OCI3_OCSSYNC: 0x20,
647
656
 
648
657
  // runtime capability indices
649
658
  TNS_RCAP_COMPAT: 0,
@@ -673,6 +682,7 @@ module.exports = {
673
682
  // transaction switching op codes
674
683
  TNS_TPC_TXN_START: 0x01,
675
684
  TNS_TPC_TXN_DETACH: 0x02,
685
+ TNS_TPC_TXN_POST_DETACH: 0x04,
676
686
 
677
687
  // transaction change state op codes
678
688
  TNS_TPC_TXN_COMMIT: 0x01,
@@ -688,6 +698,25 @@ module.exports = {
688
698
  TNS_TPC_TXN_STATE_READ_ONLY: 4,
689
699
  TNS_TPC_TXN_STATE_FORGOTTEN: 5,
690
700
 
701
+ // sessionless transaction flag
702
+ TNS_TPC_TRANS_SESSIONLESS: 0x00000010,
703
+
704
+ // sessionless transaction format
705
+ TNS_TPC_TRANS_SESSIONLESS_FORMAT: 0x4e5c3e,
706
+
707
+ // sessionless sync version
708
+ TNS_TPC_TRANS_TRANSACTION_ID_SYNC_VERSION_1: 0x01,
709
+
710
+ // sessionless server states
711
+ TNS_TPC_TRANS_TRANSACTION_ID_SYNC_SET: 0x40,
712
+ TNS_TPC_TRANS_TRANSACTION_ID_SYNC_UNSET: 0x80,
713
+
714
+ // sessionless state reason
715
+ TNS_TPC_TRANS_TRANSACTION_ID_SYNC_SERVER: 0x01,
716
+ TNS_TPC_TRANS_TRANSACTION_ID_SYNC_CLIENT: 0x02,
717
+ TNS_TPC_TRANS_TRANSACTION_ID_SYNC_TXEND_XA: 0x03,
718
+
719
+
691
720
  // other constants
692
721
  TNS_ESCAPE_CHAR: 253,
693
722
  TNS_LONG_LENGTH_INDICATOR: dataHandlerConstants.TNS_LONG_LENGTH_INDICATOR,
@@ -767,6 +796,7 @@ module.exports = {
767
796
  TNS_VECTOR_MAX_LENGTH: 1048576,
768
797
  VECTOR_FORMAT_FLEX: 0,
769
798
  VECTOR_META_FLAG_FLEXIBLE_DIM: 1,
799
+ VECTOR_META_FLAG_SPARSE: 2,
770
800
 
771
801
  // other constants
772
802
  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,12 @@ 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
+ }
117
+ this.appContext = config.appContext;
110
118
  this.setAuthMode(config);
111
119
  }
112
120
 
@@ -141,7 +149,7 @@ class AuthMessage extends Message {
141
149
  if (this.newPassword) {
142
150
  this.authMode |= constants.TNS_AUTH_MODE_CHANGE_PASSWORD;
143
151
  }
144
- if (!this.token) {
152
+ if (!config.externalAuth) {
145
153
  this.authMode |= constants.TNS_AUTH_MODE_WITH_PASSWORD;
146
154
  }
147
155
  }
@@ -199,8 +207,10 @@ class AuthMessage extends Message {
199
207
  numPairs = 2;
200
208
  } else {
201
209
  numPairs = 4;
202
- if (this.token) {
203
- numPairs += 1;
210
+ if (this.externalAuth) {
211
+ numPairs += 5;
212
+ if (this.token)
213
+ numPairs += 1;
204
214
  } else {
205
215
  numPairs += 2;
206
216
  if (this.verifierType === constants.TNS_VERIFIER_TYPE_11G_1 ||
@@ -235,6 +245,12 @@ class AuthMessage extends Message {
235
245
  this.encryptedJDWPData = ED.getEncryptedJSWPData(this.sessionKey, this.conn.jdwpData);
236
246
  numPairs += 1;
237
247
  }
248
+ if (this.edition) {
249
+ numPairs += 1;
250
+ }
251
+ if (this.appContext) {
252
+ numPairs += this.appContext.length * 3;
253
+ }
238
254
  if (this.schemaUser.length !== 0) {
239
255
  numPairs += 1;
240
256
  }
@@ -246,10 +262,17 @@ class AuthMessage extends Message {
246
262
  buf.writeUInt8(1);
247
263
  if (this.userByteLen > 0)
248
264
  buf.writeBytesWithLength(Buffer.from(this.username));
265
+ if (this.externalAuth) {
266
+ buf.writeKeyValue("AUTH_TERMINAL", this.terminal ?? cInfo.terminal);
267
+ buf.writeKeyValue("AUTH_PROGRAM_NM", this.program ?? cInfo.program);
268
+ buf.writeKeyValue("AUTH_MACHINE", this.machine ?? cInfo.hostName);
269
+ buf.writeKeyValue("AUTH_PID", cInfo.pid);
270
+ buf.writeKeyValue("AUTH_SID", this.osUser ?? cInfo.userName);
271
+ }
249
272
  if (this.token) {
250
273
  buf.writeKeyValue("AUTH_TOKEN", this.token);
251
274
  } else {
252
- if (!this.changePassword) {
275
+ if (!this.changePassword && !this.externalAuth) {
253
276
  buf.writeKeyValue("AUTH_SESSKEY", this.sessionKey, 1);
254
277
  if (!verifier11G) {
255
278
  buf.writeKeyValue("AUTH_PBKDF2_SPEEDY_KEY", this.speedyKey);
@@ -297,6 +320,18 @@ class AuthMessage extends Message {
297
320
  if (this.conn.jdwpData) {
298
321
  buf.writeKeyValue("AUTH_ORA_DEBUG_JDWP", this.encryptedJDWPData);
299
322
  }
323
+ if (this.edition) {
324
+ buf.writeKeyValue("AUTH_ORA_EDITION", this.edition);
325
+ }
326
+ if (this.appContext) {
327
+ // NOTE: these keys require a trailing null character as the server
328
+ // expects it!
329
+ for (const entry of this.appContext) {
330
+ buf.writeKeyValue("AUTH_APPCTX_NSPACE\0", entry[0]);
331
+ buf.writeKeyValue("AUTH_APPCTX_ATTR\0", entry[1]);
332
+ buf.writeKeyValue("AUTH_APPCTX_VALUE\0", entry[2]);
333
+ }
334
+ }
300
335
 
301
336
  }
302
337
  }
@@ -331,6 +366,7 @@ class AuthMessage extends Message {
331
366
  this.conn.maxOpenCursors = Number(this.sessionData['AUTH_MAX_OPEN_CURSORS'] || 0);
332
367
  this.conn.serviceName = this.sessionData['AUTH_SC_SERVICE_NAME'];
333
368
  this.conn.instanceName = this.sessionData['AUTH_INSTANCENAME'];
369
+ this.conn.maxIdentifierLength = Number(this.sessionData['AUTH_MAX_IDEN_LENGTH'] || 30);
334
370
  const fullVersionNum = Number(this.sessionData['AUTH_VERSION_NO']);
335
371
  const versionNum = (fullVersionNum >> 24) & 0xFF;
336
372
  this.conn.warning = this.warning;
@@ -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) 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
 
@@ -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)
@@ -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
  //
@@ -280,6 +280,7 @@ class MessageWithData extends Message {
280
280
  if (!(vectorFlags & constants.VECTOR_META_FLAG_FLEXIBLE_DIM)) {
281
281
  fetchInfo.vectorDimensions = dimensions;
282
282
  }
283
+ fetchInfo.isSparseVector = Boolean(vectorFlags & constants.VECTOR_META_FLAG_SPARSE);
283
284
  if (vectorFormat !== constants.VECTOR_FORMAT_FLEX) {
284
285
  fetchInfo.vectorFormat = vectorFormat;
285
286
  }
@@ -501,6 +502,10 @@ class MessageWithData extends Message {
501
502
  }
502
503
  } else if (oraTypeNum === constants.TNS_DATA_TYPE_BOOLEAN) {
503
504
  colValue = buf.readBool();
505
+ } else if (oraTypeNum === constants.TNS_DATA_TYPE_INTERVAL_YM) {
506
+ colValue = buf.readOracleIntervalYM();
507
+ } else if (oraTypeNum === constants.TNS_DATA_TYPE_INTERVAL_DS) {
508
+ colValue = buf.readOracleIntervalDS();
504
509
  } else if (
505
510
  oraTypeNum === constants.TNS_DATA_TYPE_CLOB ||
506
511
  oraTypeNum === constants.TNS_DATA_TYPE_BLOB ||
@@ -861,6 +866,10 @@ class MessageWithData extends Message {
861
866
  } else {
862
867
  buf.writeUInt16BE(0x0100);
863
868
  }
869
+ } else if (oraTypeNum === constants.TNS_DATA_TYPE_INTERVAL_YM) {
870
+ buf.writeOracleIntervalYM(value);
871
+ } else if (oraTypeNum === constants.TNS_DATA_TYPE_INTERVAL_DS) {
872
+ buf.writeOracleIntervalDS(value);
864
873
  } else if (
865
874
  oraTypeNum === constants.TNS_DATA_TYPE_CLOB ||
866
875
  oraTypeNum === constants.TNS_DATA_TYPE_BLOB ||
@@ -530,7 +530,7 @@ class WritePacket extends BaseBuffer {
530
530
  if (!this.nsi.ntAdapter) {
531
531
  errors.throwErr(errors.ERR_INVALID_CONNECTION);
532
532
  }
533
- this.nsi.ntAdapter.send(buf);
533
+ this.nsi.sendPacket(buf);
534
534
  }
535
535
 
536
536
  /**