oracledb 6.6.0 → 6.7.1

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 (67) hide show
  1. package/README.md +2 -2
  2. package/build/Release/Linux_cmds.txt +972 -0
  3. package/build/Release/oracledb-6.7.1-darwin-arm64.node +0 -0
  4. package/build/Release/oracledb-6.7.1-darwin-arm64.node-buildinfo.txt +1 -0
  5. package/build/Release/oracledb-6.7.1-darwin-x64.node +0 -0
  6. package/build/Release/oracledb-6.7.1-darwin-x64.node-buildinfo.txt +1 -0
  7. package/build/Release/oracledb-6.7.1-js-buildinfo.txt +1 -0
  8. package/build/Release/oracledb-6.7.1-linux-arm64.node +0 -0
  9. package/build/Release/oracledb-6.7.1-linux-arm64.node-buildinfo.txt +1 -0
  10. package/build/Release/oracledb-6.7.1-linux-x64.node +0 -0
  11. package/build/Release/oracledb-6.7.1-linux-x64.node-buildinfo.txt +1 -0
  12. package/build/Release/oracledb-6.7.1-win32-x64.node +0 -0
  13. package/build/Release/oracledb-6.7.1-win32-x64.node-buildinfo.txt +1 -0
  14. package/examples/example.js +5 -5
  15. package/lib/configProviders/azure.js +26 -15
  16. package/lib/configProviders/base.js +23 -37
  17. package/lib/configProviders/ociobject.js +53 -45
  18. package/lib/connection.js +75 -3
  19. package/lib/errors.js +26 -14
  20. package/lib/impl/aqQueue.js +2 -1
  21. package/lib/impl/base.js +45 -0
  22. package/lib/impl/connection.js +53 -0
  23. package/lib/impl/lob.js +2 -1
  24. package/lib/impl/pool.js +15 -0
  25. package/lib/impl/resultset.js +2 -1
  26. package/lib/impl/sodaCollection.js +2 -1
  27. package/lib/impl/sodaDatabase.js +2 -1
  28. package/lib/impl/sodaDocCursor.js +2 -1
  29. package/lib/impl/sodaOperation.js +2 -1
  30. package/lib/lob.js +3 -2
  31. package/lib/oracledb.js +221 -36
  32. package/lib/pool.js +14 -5
  33. package/lib/settings.js +1 -0
  34. package/lib/thin/connection.js +150 -91
  35. package/lib/thin/dbObject.js +13 -4
  36. package/lib/thin/pool.js +3 -0
  37. package/lib/thin/protocol/constants.js +1 -1
  38. package/lib/thin/protocol/messages/auth.js +12 -6
  39. package/lib/thin/protocol/messages/base.js +3 -0
  40. package/lib/thin/protocol/messages/sessionRelease.js +1 -0
  41. package/lib/thin/protocol/messages/withData.js +6 -13
  42. package/lib/thin/protocol/protocol.js +23 -0
  43. package/lib/thin/sqlnet/connStrategy.js +12 -3
  44. package/lib/thin/sqlnet/constants.js +2 -0
  45. package/lib/thin/sqlnet/navNodes.js +30 -23
  46. package/lib/thin/sqlnet/networkSession.js +18 -14
  47. package/lib/thin/sqlnet/ntTcp.js +12 -6
  48. package/lib/thin/sqlnet/nvStrToNvPair.js +23 -26
  49. package/lib/thin/sqlnet/paramParser.js +42 -43
  50. package/lib/thin/sqlnet/sessionAtts.js +1 -1
  51. package/lib/thin/util.js +4 -3
  52. package/lib/traceHandler.js +133 -0
  53. package/lib/util.js +177 -33
  54. package/lib/version.js +2 -2
  55. package/package.json +1 -1
  56. package/build/Release/oracledb-6.6.0-darwin-arm64.node +0 -0
  57. package/build/Release/oracledb-6.6.0-darwin-arm64.node-buildinfo.txt +0 -1
  58. package/build/Release/oracledb-6.6.0-darwin-x64.node +0 -0
  59. package/build/Release/oracledb-6.6.0-darwin-x64.node-buildinfo.txt +0 -1
  60. package/build/Release/oracledb-6.6.0-js-buildinfo.txt +0 -1
  61. package/build/Release/oracledb-6.6.0-linux-arm64.node +0 -0
  62. package/build/Release/oracledb-6.6.0-linux-arm64.node-buildinfo.txt +0 -1
  63. package/build/Release/oracledb-6.6.0-linux-x64.node +0 -0
  64. package/build/Release/oracledb-6.6.0-linux-x64.node-buildinfo.txt +0 -1
  65. package/build/Release/oracledb-6.6.0-win32-x64.node +0 -0
  66. package/build/Release/oracledb-6.6.0-win32-x64.node-buildinfo.txt +0 -1
  67. package/examples/README.md +0 -138
@@ -169,12 +169,27 @@ class ThinConnectionImpl extends ConnectionImpl {
169
169
  //---------------------------------------------------------------------------
170
170
  async _execute(statement, numIters, binds, options, executeManyFlag) {
171
171
 
172
+ // Throw error if executeMany is not called on a DML statement or PL/SQL
173
+ if (executeManyFlag && statement.isQuery) {
174
+ errors.throwErr(errors.ERR_EXECMANY_NOT_ALLOWED_ON_QUERIES);
175
+ }
172
176
  // perform binds
173
- const numBinds = statement.bindInfoList.length;
174
- const numVars = binds.length;
175
- if (numBinds !== numVars && (numVars === 0 || !binds[0].name)) {
176
- errors.throwErr(errors.ERR_WRONG_NUMBER_OF_POSITIONAL_BINDS, numBinds, numVars);
177
+ const numStmtBinds = statement.bindInfoList.length;
178
+ const numUserBinds = binds.length;
179
+ if (numStmtBinds !== numUserBinds) {
180
+ if (!binds[0]?.name) {
181
+ // positional bind mismatch or zero binds
182
+ errors.throwErr(errors.ERR_WRONG_NUMBER_OF_BINDS, numStmtBinds, numUserBinds);
183
+ }
184
+
185
+ // named bind mismatch
186
+ // Find the number of distinct named bind placeholders and see
187
+ // if they match the bind values
188
+ const numDistinctStmtBinds = statement.bindInfoDict.size;
189
+ if (numDistinctStmtBinds !== numUserBinds)
190
+ errors.throwErr(errors.ERR_WRONG_NUMBER_OF_BINDS, numStmtBinds, numUserBinds);
177
191
  }
192
+
178
193
  for (let i = 0; i < binds.length; i++) {
179
194
  await this._bind(statement, binds[i], i + 1);
180
195
  }
@@ -404,6 +419,79 @@ class ThinConnectionImpl extends ConnectionImpl {
404
419
  }
405
420
  }
406
421
 
422
+ //---------------------------------------------------------------------------
423
+ // _populateRowTypeInfo()
424
+ //
425
+ // Get column and datatype information in case of %ROWTYPE handling.
426
+ //---------------------------------------------------------------------------
427
+ async _populateRowTypeInfo(info, options, result) {
428
+ const getColumnsSQL = `
429
+ SELECT
430
+ column_name,
431
+ data_type,
432
+ data_type_owner,
433
+ case
434
+ when data_type in
435
+ ('CHAR', 'NCHAR', 'VARCHAR2', 'NVARCHAR2', 'RAW')
436
+ then data_length
437
+ else 0
438
+ end,
439
+ nvl(data_precision, 0),
440
+ nvl(data_scale, 0)
441
+ from all_tab_cols
442
+ where owner = :owner
443
+ and table_name = :name
444
+ and hidden_column != 'YES'
445
+ order by column_id`;
446
+
447
+ const bindVal = [
448
+ {
449
+ name: "owner",
450
+ type: types.DB_TYPE_VARCHAR,
451
+ maxSize: 128,
452
+ dir: constants.BIND_IN,
453
+ values: [result.outBinds.schema],
454
+ },
455
+ {
456
+ name: "name",
457
+ type: types.DB_TYPE_VARCHAR,
458
+ maxSize: 128,
459
+ dir: constants.BIND_IN,
460
+ values: [info.name.substring(0, info.name.length - 8)]
461
+ }
462
+ ];
463
+ const val = await this.execute(
464
+ getColumnsSQL, 1, bindVal, options, false
465
+ );
466
+ try {
467
+ const attrRows = await val.resultSet._getAllRows();
468
+ info.attributes = [];
469
+ for (const row of attrRows) {
470
+ const metaData = {
471
+ name: row[0],
472
+ dataType: row[1],
473
+ dataTypeOwner: row[2],
474
+ maxSize: row[3],
475
+ dataPrecision: row[4],
476
+ dataScale: row[5],
477
+ };
478
+ if (!metaData.dataTypeOwner) {
479
+ const startPos = row[1].indexOf('(');
480
+ const endPos = row[1].indexOf(')');
481
+ if (endPos > startPos) {
482
+ metaData.dataType = metaData.dataType.substring(0, startPos) +
483
+ metaData.dataType.substring(
484
+ endPos + 1, metaData.dataType.length
485
+ );
486
+ }
487
+ }
488
+ this._addAttr(info.attributes, metaData);
489
+ }
490
+ } finally {
491
+ val.resultSet.close();
492
+ }
493
+ }
494
+
407
495
  //---------------------------------------------------------------------------
408
496
  // _populateDbObjectTypeInfo()
409
497
  //
@@ -449,26 +537,6 @@ class ThinConnectionImpl extends ConnectionImpl {
449
537
  end if;
450
538
  end;`;
451
539
 
452
- // get column and datatype information in case of %ROWTYPE handling.
453
- const getColumnsSQL = `
454
- SELECT
455
- column_name,
456
- data_type,
457
- data_type_owner,
458
- case
459
- when data_type in
460
- ('CHAR', 'NCHAR', 'VARCHAR2', 'NVARCHAR2', 'RAW')
461
- then data_length
462
- else 0
463
- end,
464
- nvl(data_precision, 0),
465
- nvl(data_scale, 0)
466
- from all_tab_cols
467
- where owner = :owner
468
- and table_name = :name
469
- and hidden_column != 'YES'
470
- order by column_id`;
471
-
472
540
  const binds = [
473
541
  {
474
542
  name: "full_name",
@@ -540,78 +608,42 @@ class ThinConnectionImpl extends ConnectionImpl {
540
608
  errors.throwErr(errors.ERR_INVALID_OBJECT_TYPE_NAME, name);
541
609
  }
542
610
 
543
- // check cache; if already present, nothing more to do!
544
- const info = this._getDbObjectType(result.outBinds.schema,
545
- result.outBinds.name, result.outBinds.package_name, result.outBinds.oid);
546
- if (!info.partial)
547
- return info;
548
-
549
- // process TDS and attributes cursor
550
- if (info.name.endsWith('%ROWTYPE')) {
551
- const bindVal = [
552
- {
553
- name: "owner",
554
- type: types.DB_TYPE_VARCHAR,
555
- maxSize: 128,
556
- dir: constants.BIND_IN,
557
- values: [result.outBinds.schema],
558
- },
559
- {
560
- name: "name",
561
- type: types.DB_TYPE_VARCHAR,
562
- maxSize: 128,
563
- dir: constants.BIND_IN,
564
- values: [info.name.substring(0, info.name.length - 8)]
565
- }
566
- ];
567
- const val = await this.execute(
568
- getColumnsSQL, 1, bindVal, options, false
569
- );
570
- const attrRows = await val.resultSet._getAllRows();
571
- info.attributes = [];
572
- for (const row of attrRows) {
573
- const metaData = {
574
- name: row[0],
575
- dataType: row[1],
576
- dataTypeOwner: row[2],
577
- maxSize: row[3],
578
- dataPrecision: row[4],
579
- dataScale: row[5],
580
- };
581
- if (!metaData.dataTypeOwner) {
582
- const startPos = row[1].indexOf('(');
583
- const endPos = row[1].indexOf(')');
584
- if (endPos > startPos) {
585
- metaData.dataType = metaData.dataType.substring(0, startPos) +
586
- metaData.dataType.substring(
587
- endPos + 1, metaData.dataType.length
588
- );
589
- }
590
- }
591
- this._addAttr(info.attributes, metaData);
611
+ try {
612
+ // check cache; if already present, nothing more to do!
613
+ const info = this._getDbObjectType(result.outBinds.schema,
614
+ result.outBinds.name, result.outBinds.package_name, result.outBinds.oid);
615
+ if (!info.partial) {
616
+ return info;
592
617
  }
593
- } else {
594
- info.version = result.outBinds.version;
595
- const attrRows = await result.outBinds.attrs_rc._getAllRows();
596
- if (attrRows.length > 0) {
618
+
619
+ // process TDS and attributes cursor
620
+ if (info.name.endsWith('%ROWTYPE')) {
621
+ await this._populateRowTypeInfo(info, options, result);
622
+ } else {
623
+ info.version = result.outBinds.version;
624
+ const attrRows = await result.outBinds.attrs_rc._getAllRows();
625
+ if (attrRows.length > 0) {
597
626
  // Its an object not a collection.
598
- info.attributes = [];
599
- for (const row of attrRows) {
600
- const metaData = {
601
- name: row[1],
602
- dataType: row[3],
603
- dataTypeOwner: row[4],
604
- packageName: row[5],
605
- oid: row[6]
606
- };
607
- this._addAttr(info.attributes, metaData);
608
- }
627
+ info.attributes = [];
628
+ for (const row of attrRows) {
629
+ const metaData = {
630
+ name: row[1],
631
+ dataType: row[3],
632
+ dataTypeOwner: row[4],
633
+ packageName: row[5],
634
+ oid: row[6]
635
+ };
636
+ this._addAttr(info.attributes, metaData);
637
+ }
609
638
 
639
+ }
640
+ await this._parseTDS(result.outBinds.tds, info);
610
641
  }
611
- await this._parseTDS(result.outBinds.tds, info);
642
+ info.partial = false;
643
+ return info;
644
+ } finally {
645
+ result.outBinds.attrs_rc.close();
612
646
  }
613
- info.partial = false;
614
- return info;
615
647
 
616
648
  }
617
649
 
@@ -797,8 +829,14 @@ class ThinConnectionImpl extends ConnectionImpl {
797
829
  await this._protocol._processMessage(authMessage);
798
830
  }
799
831
  } else {
832
+ // When Fast Auth is explicitly disabled on servers > 23ai,
833
+ // we dont rely on message type TNS_MSG_TYPE_END_OF_REQUEST too
834
+ // for protocolMessage and dataTypeMessage.
835
+ const endOfRequestSupport = this.nscon.endOfRequestSupport;
836
+ this.nscon.endOfRequestSupport = false;
800
837
  await this._protocol._processMessage(protocolMessage);
801
838
  await this._protocol._processMessage(dataTypeMessage);
839
+ this.nscon.endOfRequestSupport = endOfRequestSupport;
802
840
  await this._protocol._processMessage(authMessage);
803
841
  }
804
842
  if (!params.token) { // non-token Authentication
@@ -1239,6 +1277,27 @@ class ThinConnectionImpl extends ConnectionImpl {
1239
1277
  return this.dbDomain;
1240
1278
  }
1241
1279
 
1280
+ //---------------------------------------------------------------------------
1281
+ // Returns the Oracle Database host name associated with the connection.
1282
+ //---------------------------------------------------------------------------
1283
+ getHostName() {
1284
+ return this.nscon.ntAdapter.hostName;
1285
+ }
1286
+
1287
+ //---------------------------------------------------------------------------
1288
+ // Returns the Oracle Database port number associated with the connection.
1289
+ //---------------------------------------------------------------------------
1290
+ getPort() {
1291
+ return this.nscon.ntAdapter.port;
1292
+ }
1293
+
1294
+ //---------------------------------------------------------------------------
1295
+ // Returns the protocol associated with the connection.
1296
+ //---------------------------------------------------------------------------
1297
+ getProtocol() {
1298
+ return (this.nscon.ntAdapter.secure) ? 'TCPS' : 'TCP';
1299
+ }
1300
+
1242
1301
  //---------------------------------------------------------------------------
1243
1302
  // Returns the Oracle Database name associated with the connection.
1244
1303
  //---------------------------------------------------------------------------
@@ -179,7 +179,8 @@ class ThinDbObjectImpl extends DbObjectImpl {
179
179
  //---------------------------------------------------------------------------
180
180
  _ensureAssocKeys() {
181
181
  if (!this.unpackedAssocKeys) {
182
- this.unpackedAssocKeys = [...this.unpackedAssocArray.keys()].sort();
182
+ // Associative arrays indexed by integer are only supported now
183
+ this.unpackedAssocKeys = [...this.unpackedAssocArray.keys()].sort((x, y) => x - y);
183
184
  }
184
185
  }
185
186
 
@@ -546,6 +547,9 @@ class ThinDbObjectImpl extends DbObjectImpl {
546
547
  // getNextIndex()
547
548
  //
548
549
  // Returns the next index in a collection.
550
+ // For associative arrays indexed by integers, if the passed-in index
551
+ // parameter is not present, it will return the next higher index found
552
+ // in the associative array.
549
553
  //---------------------------------------------------------------------------
550
554
  getNextIndex(index) {
551
555
  this._ensureUnpacked();
@@ -566,6 +570,9 @@ class ThinDbObjectImpl extends DbObjectImpl {
566
570
  // getPrevIndex()
567
571
  //
568
572
  // Returns the previous index in a collection.
573
+ // For associative arrays indexed by integers, if the passed-in index
574
+ // parameter is not present, it will return the next lower index found
575
+ // in the associative array.
569
576
  //---------------------------------------------------------------------------
570
577
  getPrevIndex(index) {
571
578
  this._ensureUnpacked();
@@ -575,9 +582,11 @@ class ThinDbObjectImpl extends DbObjectImpl {
575
582
  }
576
583
  } else if (this.unpackedAssocArray) {
577
584
  this._ensureAssocKeys();
578
- for (const key of this.unpackedAssocKeys.reverse()) {
579
- if (key < index)
580
- return key;
585
+ let prev;
586
+ for (const key of this.unpackedAssocKeys) {
587
+ if (key >= index)
588
+ return prev;
589
+ prev = key;
581
590
  }
582
591
  }
583
592
  }
package/lib/thin/pool.js CHANGED
@@ -44,6 +44,9 @@ class ThinPoolImpl extends PoolImpl {
44
44
  if (!params.homogeneous) {
45
45
  errors.throwErr(errors.ERR_NOT_IMPLEMENTED, 'Heterogeneous Pooling');
46
46
  }
47
+ if (!params.connectString) {
48
+ errors.throwErr(errors.ERR_EMPTY_CONNECT_STRING);
49
+ }
47
50
  thinUtil.checkCredentials(params);
48
51
 
49
52
  this._availableObjects = [];
@@ -48,7 +48,7 @@ module.exports = {
48
48
  PURITY_NEW: constants.PURITY_NEW,
49
49
  PURITY_SELF: constants.PURITY_SELF,
50
50
  SYSASM: constants.SYSASM,
51
- SYSBKP: constants.SYSBKP,
51
+ SYSBKP: constants.SYSBACKUP,
52
52
  SYSDBA: constants.SYSDBA,
53
53
  SYSDG: constants.SYSDG,
54
54
  SYSKM: constants.SYSKM,
@@ -102,6 +102,11 @@ class AuthMessage extends Message {
102
102
  }
103
103
  this.serviceName = this.conn.serviceName;
104
104
  this.remoteAddress = this.conn.remoteAddress;
105
+ this.driverName = config.driverName;
106
+ this.machine = config.machine;
107
+ this.osUser = config.osUser;
108
+ this.program = config.program;
109
+ this.terminal = config.terminal;
105
110
  this.setAuthMode(config);
106
111
  }
107
112
 
@@ -181,11 +186,11 @@ class AuthMessage extends Message {
181
186
  if (this.userByteLen > 0) {
182
187
  buf.writeBytesWithLength(Buffer.from(this.username));
183
188
  }
184
- buf.writeKeyValue("AUTH_TERMINAL", cInfo.terminal);
185
- buf.writeKeyValue("AUTH_PROGRAM_NM", cInfo.program);
186
- buf.writeKeyValue("AUTH_MACHINE", cInfo.hostName);
189
+ buf.writeKeyValue("AUTH_TERMINAL", this.terminal ?? cInfo.terminal);
190
+ buf.writeKeyValue("AUTH_PROGRAM_NM", this.program ?? cInfo.program);
191
+ buf.writeKeyValue("AUTH_MACHINE", this.machine ?? cInfo.hostName);
187
192
  buf.writeKeyValue("AUTH_PID", cInfo.pid);
188
- buf.writeKeyValue("AUTH_SID", cInfo.userName);
193
+ buf.writeKeyValue("AUTH_SID", this.osUser ?? cInfo.userName);
189
194
  } else {
190
195
  let numPairs = 0;
191
196
 
@@ -253,7 +258,8 @@ class AuthMessage extends Message {
253
258
  }
254
259
  if (!this.changePassword) {
255
260
  buf.writeKeyValue("SESSION_CLIENT_CHARSET", "873");
256
- buf.writeKeyValue("SESSION_CLIENT_DRIVER_NAME", constants.DRIVER_NAME);
261
+ buf.writeKeyValue("SESSION_CLIENT_DRIVER_NAME",
262
+ this.driverName ?? constants.DRIVER_NAME);
257
263
  buf.writeKeyValue("SESSION_CLIENT_VERSION",
258
264
  constants.CLIENT_VERSION.toString());
259
265
  buf.writeKeyValue("AUTH_ALTER_SESSION", this.getAlterTimezoneStatement(), 1);
@@ -321,7 +327,7 @@ class AuthMessage extends Message {
321
327
  let portUpdateNum;
322
328
 
323
329
  this.conn.dbDomain = this.sessionData['AUTH_SC_DB_DOMAIN'];
324
- this.conn.dbName = this.sessionData['AUTH_SC_DBUNIQUE_NAME'];
330
+ this.conn.dbName = this.sessionData['AUTH_DBNAME'];
325
331
  this.conn.maxOpenCursors = Number(this.sessionData['AUTH_MAX_OPEN_CURSORS'] || 0);
326
332
  this.conn.serviceName = this.sessionData['AUTH_SC_SERVICE_NAME'];
327
333
  this.conn.instanceName = this.sessionData['AUTH_INSTANCENAME'];
@@ -296,6 +296,9 @@ class Message {
296
296
  this._writeCurrentSchemaPiggyback(buf);
297
297
  }
298
298
  if (this.connection.statementCache._cursorsToClose.size > 0 && !this.connection._drcpEstablishSession) {
299
+ // skip closing cursors when '_drcpEstablishSession = true' Since we don't know whether the same session
300
+ // is in use. We can not send the information across until after the session information has been returned
301
+ // (on the first round trip).
299
302
  this.writeCloseCursorsPiggyBack(buf);
300
303
  }
301
304
  if (
@@ -45,6 +45,7 @@ class SessionReleaseMessage extends Message {
45
45
  }
46
46
 
47
47
  encode(buf) {
48
+ this.writePiggybacks(buf);
48
49
  this.writeFunctionHeader(buf);
49
50
  buf.writeUInt8(0); // pointer (tag name)
50
51
  buf.writeUInt8(0); // tag name length
@@ -67,7 +67,6 @@ class MessageWithData extends Message {
67
67
  if (messageType === constants.TNS_MSG_TYPE_DESCRIBE_INFO) {
68
68
  buf.skipBytesChunked();
69
69
  const prevQueryVars = this.statement.queryVars;
70
- this.statement.queryVars = [];
71
70
  this.statement.numQueryVars = 0;
72
71
  this.statement.bufferRowCount = 0;
73
72
  this.statement.bufferRowIndex = 0;
@@ -512,9 +511,7 @@ class MessageWithData extends Message {
512
511
  const bvalue = buf.readUB4();
513
512
  if (bvalue > 0) { // Non Null data in column
514
513
  colValue = new ThinLobImpl();
515
- if (oraTypeNum === constants.TNS_DATA_TYPE_BFILE) {
516
- buf.skipUB4();
517
- } else {
514
+ if (oraTypeNum !== constants.TNS_DATA_TYPE_BFILE) {
518
515
  length = buf.readUB8();
519
516
  chunkSize = buf.readUB4();
520
517
  }
@@ -633,7 +630,6 @@ class MessageWithData extends Message {
633
630
  if (variable.type === types.DB_TYPE_CLOB ||
634
631
  variable.type === types.DB_TYPE_NCLOB ||
635
632
  variable.type === types.DB_TYPE_BLOB ||
636
- variable.type === types.DB_TYPE_BFILE ||
637
633
  variable.type === types.DB_TYPE_JSON ||
638
634
  variable.type === types.DB_TYPE_VECTOR) {
639
635
  if (variable.type !== variable.fetchInfo.fetchType) {
@@ -702,7 +698,7 @@ class MessageWithData extends Message {
702
698
  // conversion requested if maxSize is not multiplied by the
703
699
  // bufferSizeFactor
704
700
  if (variable.type._csfrm === constants.CSFRM_NCHAR) {
705
- maxSize *= variable.type._bufferSizeFactor;
701
+ maxSize = Math.min(maxSize * variable.type._bufferSizeFactor, constants.TNS_MAX_LONG_LENGTH);
706
702
  }
707
703
  if ([constants.TNS_DATA_TYPE_ROWID, constants.TNS_DATA_TYPE_UROWID].includes(oraTypeNum)) {
708
704
  oraTypeNum = constants.TNS_DATA_TYPE_VARCHAR;
@@ -715,8 +711,7 @@ class MessageWithData extends Message {
715
711
  let contFlag = 0;
716
712
  if (variable.type === types.DB_TYPE_BLOB ||
717
713
  variable.type === types.DB_TYPE_CLOB ||
718
- variable.type === types.DB_TYPE_NCLOB ||
719
- variable.type === types.DB_TYPE_BFILE) {
714
+ variable.type === types.DB_TYPE_NCLOB) {
720
715
  contFlag = constants.TNS_LOB_PREFETCH_FLAG;
721
716
  } else if (variable.type === types.DB_TYPE_JSON) {
722
717
  contFlag = constants.TNS_LOB_PREFETCH_FLAG;
@@ -731,11 +726,9 @@ class MessageWithData extends Message {
731
726
  // expects that and complains if any other value is sent!
732
727
  buf.writeUInt8(0);
733
728
  buf.writeUInt8(0);
734
- if (maxSize > buf.caps.maxStringSize) {
735
- buf.writeUB4(constants.TNS_MAX_LONG_LENGTH);
736
- } else {
737
- buf.writeUB4(maxSize);
738
- }
729
+
730
+ // Write the max buffer size
731
+ buf.writeUB4(maxSize);
739
732
 
740
733
  if (variable.isArray) {
741
734
  buf.writeUB4(variable.maxArraySize);
@@ -31,6 +31,7 @@ const Capabilities = require("./capabilities.js");
31
31
  const {WritePacket, ReadPacket} = require("./packet.js");
32
32
  const errors = require("../../errors");
33
33
  const utils = require("./utils.js");
34
+ const traceHandler = require('../../traceHandler.js');
34
35
 
35
36
  /**
36
37
  * Handles protocol details.
@@ -141,6 +142,13 @@ class Protocol {
141
142
  async _processMessage(message) {
142
143
  let callTimer;
143
144
  let callTimeoutExpired = false;
145
+ let traceInstance, traceContext;
146
+ const traceEnabled = traceHandler.isEnabled();
147
+
148
+ if (traceEnabled) {
149
+ traceContext = { additionalConfig: {} };
150
+ traceInstance = traceHandler.getTraceInstance();
151
+ }
144
152
  try {
145
153
  if (this.callTimeout > 0) {
146
154
  callTimer = setTimeout(() => {
@@ -148,6 +156,10 @@ class Protocol {
148
156
  this.breakMessage();
149
157
  }, this.callTimeout);
150
158
  }
159
+ if (traceEnabled) {
160
+ traceContext.operation = `oracledb.${message.constructor.name}`;
161
+ traceInstance.onBeginRoundTrip(traceContext);
162
+ }
151
163
  await this._encodeMessage(message);
152
164
  if (message.messageType !== constants.TNS_MSG_TYPE_ONEWAY_FN) {
153
165
  await this._decodeMessage(message);
@@ -157,9 +169,20 @@ class Protocol {
157
169
  err.code !== errors.ERR_CONNECTION_CLOSED_CODE) {
158
170
  await this._recoverFromError(err, message);
159
171
  }
172
+ if (traceEnabled) {
173
+ traceContext.error = err;
174
+ }
160
175
  throw err;
161
176
  } finally {
162
177
  clearTimeout(callTimer);
178
+ if (traceEnabled) {
179
+ traceContext.callLevelConfig = message.connection._callLevelTraceData;
180
+ traceContext.connectLevelConfig = message.connection._getConnectTraceConfig();
181
+ if (message.callStatus & constants.TNS_EOCS_FLAGS_SESS_RELEASE) {
182
+ traceContext.additionalConfig.implicitRelease = true;
183
+ }
184
+ traceInstance.onEndRoundTrip(traceContext);
185
+ }
163
186
  }
164
187
  if (message.flushOutBinds) {
165
188
  await this.flushOutBindMessage(message);
@@ -1,4 +1,4 @@
1
- // Copyright (c) 2022, 2023, Oracle and/or its affiliates.
1
+ // Copyright (c) 2022, 2024, Oracle and/or its affiliates.
2
2
 
3
3
  //-----------------------------------------------------------------------------
4
4
  //
@@ -29,6 +29,7 @@
29
29
  const { NavAddress, NavAddressList, NavDescription, NavDescriptionList } = require("./navNodes.js");
30
30
  const { createNVPair } = require("./nvStrToNvPair.js");
31
31
  const errors = require("../../errors.js");
32
+ const constants = require("./constants.js");
32
33
 
33
34
  /**
34
35
  * Class that holds all possible attributes under Description
@@ -89,6 +90,7 @@ class ConnStrategy {
89
90
  this.descriptionList.push(this.currentDescription);
90
91
  this.currentDescription = null;
91
92
  }
93
+
92
94
  /**
93
95
  * Execute the Connection Options from the array. When a refuse packet is received from
94
96
  * server this method is called again and the next connect option is tried.
@@ -114,6 +116,8 @@ class ConnStrategy {
114
116
  if (config != null) {
115
117
  if ((delay == 0 || delay == undefined) && config.retryDelay > 0) {
116
118
  delay = config.retryDelay * 1000;
119
+ } else if (!delay) {
120
+ delay = constants.DEFAULT_RETRY_DELAY; // 1 sec default
117
121
  }
118
122
  }
119
123
  for (let i = this.lastRetryCounter; i <= this.retryCount; ++i) {
@@ -145,8 +149,8 @@ class ConnStrategy {
145
149
  }
146
150
  // sleep time expects milliseconds
147
151
 
148
-
149
152
  }
153
+
150
154
  function sleep(time) {
151
155
  return new Promise((resolve) => setTimeout(resolve, time));
152
156
  }
@@ -157,7 +161,7 @@ function sleep(time) {
157
161
  * @param {string} str - input description string
158
162
  * @returns {object} - returns a connection strategy object.
159
163
  */
160
- async function createNode(str) {
164
+ async function createNode(str, userConfig) {
161
165
  let nvpair;
162
166
  if (typeof str === 'string')
163
167
  nvpair = createNVPair(str);
@@ -185,6 +189,11 @@ async function createNode(str) {
185
189
  }
186
190
  navobj.initFromNVPair(nvpair);
187
191
  const cs = new ConnStrategy();
192
+ cs.driverName = userConfig.driverName;
193
+ cs.machine = userConfig.machine;
194
+ cs.terminal = userConfig.terminal;
195
+ cs.osUser = userConfig.osUser;
196
+ cs.program = userConfig.program;
188
197
  await navobj.navigate(cs);
189
198
  return cs;
190
199
  }
@@ -187,6 +187,8 @@ module.exports = {
187
187
  DISABLE_OOB_STR: 'DISABLE_OOB', // disable OOB parameter
188
188
  EXPIRE_TIME: 'EXPIRE_TIME', // expire Time
189
189
  PEM_WALLET_FILE_NAME: 'ewallet.pem',
190
+ DEFAULT_TRANSPORT_CONNECT_TIMEOUT: 20000, //default transport connect timeout
191
+ DEFAULT_RETRY_DELAY: 1000, //default retry delay
190
192
 
191
193
  /* Get/Set options */
192
194
  NT_MOREDATA: 1, // More Data in Transport available