oracledb 6.5.1 → 6.7.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 (73) hide show
  1. package/README.md +2 -2
  2. package/build/Release/oracledb-6.7.0-darwin-arm64.node +0 -0
  3. package/build/Release/oracledb-6.7.0-darwin-arm64.node-buildinfo.txt +1 -0
  4. package/build/Release/oracledb-6.7.0-darwin-x64.node +0 -0
  5. package/build/Release/oracledb-6.7.0-darwin-x64.node-buildinfo.txt +1 -0
  6. package/build/Release/oracledb-6.7.0-js-buildinfo.txt +1 -0
  7. package/build/Release/oracledb-6.7.0-linux-arm64.node +0 -0
  8. package/build/Release/oracledb-6.7.0-linux-arm64.node-buildinfo.txt +1 -0
  9. package/build/Release/oracledb-6.7.0-linux-x64.node +0 -0
  10. package/build/Release/oracledb-6.7.0-linux-x64.node-buildinfo.txt +1 -0
  11. package/build/Release/oracledb-6.7.0-win32-x64.node +0 -0
  12. package/build/Release/oracledb-6.7.0-win32-x64.node-buildinfo.txt +1 -0
  13. package/examples/README.md +4 -0
  14. package/lib/configProviders/azure.js +178 -0
  15. package/lib/configProviders/base.js +85 -0
  16. package/lib/configProviders/ociobject.js +211 -0
  17. package/lib/connection.js +97 -14
  18. package/lib/constants.js +1 -0
  19. package/lib/errors.js +68 -6
  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/datahandlers/constants.js +3 -1
  24. package/lib/impl/datahandlers/vector.js +24 -9
  25. package/lib/impl/lob.js +29 -1
  26. package/lib/impl/pool.js +15 -0
  27. package/lib/impl/resultset.js +28 -2
  28. package/lib/impl/sodaCollection.js +2 -1
  29. package/lib/impl/sodaDatabase.js +2 -1
  30. package/lib/impl/sodaDocCursor.js +2 -1
  31. package/lib/impl/sodaOperation.js +2 -1
  32. package/lib/lob.js +55 -3
  33. package/lib/oracledb.js +246 -7
  34. package/lib/pool.js +14 -5
  35. package/lib/settings.js +1 -0
  36. package/lib/thin/connection.js +304 -29
  37. package/lib/thin/dbObject.js +4 -0
  38. package/lib/thin/lob.js +193 -1
  39. package/lib/thin/pool.js +18 -0
  40. package/lib/thin/protocol/capabilities.js +2 -0
  41. package/lib/thin/protocol/constants.js +29 -1
  42. package/lib/thin/protocol/messages/auth.js +12 -6
  43. package/lib/thin/protocol/messages/base.js +3 -0
  44. package/lib/thin/protocol/messages/index.js +5 -1
  45. package/lib/thin/protocol/messages/lobOp.js +17 -5
  46. package/lib/thin/protocol/messages/sessionRelease.js +1 -0
  47. package/lib/thin/protocol/messages/transactionChangeState.js +99 -0
  48. package/lib/thin/protocol/messages/transactionSwitch.js +139 -0
  49. package/lib/thin/protocol/messages/withData.js +21 -6
  50. package/lib/thin/protocol/protocol.js +23 -0
  51. package/lib/thin/sqlnet/connStrategy.js +9 -1
  52. package/lib/thin/sqlnet/constants.js +2 -0
  53. package/lib/thin/sqlnet/navNodes.js +14 -2
  54. package/lib/thin/sqlnet/networkSession.js +11 -10
  55. package/lib/thin/sqlnet/ntTcp.js +1 -1
  56. package/lib/thin/sqlnet/paramParser.js +87 -50
  57. package/lib/thin/sqlnet/sessionAtts.js +14 -2
  58. package/lib/thin/util.js +4 -3
  59. package/lib/traceHandler.js +133 -0
  60. package/lib/transformer.js +1 -2
  61. package/lib/types.js +1 -1
  62. package/lib/util.js +213 -35
  63. package/lib/version.js +2 -2
  64. package/package.json +1 -1
  65. package/build/Release/oracledb-6.5.1-darwin-x64.node +0 -0
  66. package/build/Release/oracledb-6.5.1-darwin-x64.node-buildinfo.txt +0 -1
  67. package/build/Release/oracledb-6.5.1-js-buildinfo.txt +0 -1
  68. package/build/Release/oracledb-6.5.1-linux-arm64.node +0 -0
  69. package/build/Release/oracledb-6.5.1-linux-arm64.node-buildinfo.txt +0 -1
  70. package/build/Release/oracledb-6.5.1-linux-x64.node +0 -0
  71. package/build/Release/oracledb-6.5.1-linux-x64.node-buildinfo.txt +0 -1
  72. package/build/Release/oracledb-6.5.1-win32-x64.node +0 -0
  73. package/build/Release/oracledb-6.5.1-win32-x64.node-buildinfo.txt +0 -1
@@ -0,0 +1,139 @@
1
+ // Copyright (c) 2024, Oracle and/or its affiliates.
2
+
3
+ //-----------------------------------------------------------------------------
4
+ //
5
+ // This software is dual-licensed to you under the Universal Permissive License
6
+ // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License
7
+ // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose
8
+ // either license.
9
+ //
10
+ // If you elect to accept the software under the Apache License, Version 2.0,
11
+ // the following applies:
12
+ //
13
+ // Licensed under the Apache License, Version 2.0 (the "License");
14
+ // you may not use this file except in compliance with the License.
15
+ // You may obtain a copy of the License at
16
+ //
17
+ // https://www.apache.org/licenses/LICENSE-2.0
18
+ //
19
+ // Unless required by applicable law or agreed to in writing, software
20
+ // distributed under the License is distributed on an "AS IS" BASIS,
21
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22
+ // See the License for the specific language governing permissions and
23
+ // limitations under the License.
24
+ //
25
+ //-----------------------------------------------------------------------------
26
+
27
+ 'use strict';
28
+
29
+ const Message = require("./base.js");
30
+ const constants = require("../constants.js");
31
+
32
+ /**
33
+ * Used for two-phase commit (TPC) transaction start, attach and detach.
34
+ *
35
+ * @class TransactionSwitchMessage
36
+ * @extends {Message}
37
+ */
38
+ class TransactionSwitchMessage extends Message {
39
+
40
+ constructor(connImpl) {
41
+ super(connImpl);
42
+ this.functionCode = constants.TNS_FUNC_TPC_TXN_SWITCH;
43
+ this.applicationValue = 0;
44
+ this.internalName = connImpl.internalName;
45
+ if (this.internalName) {
46
+ this.internalName = Buffer.from(this.internalName);
47
+ }
48
+ this.externalName = connImpl.externalName;
49
+ if (this.externalName) {
50
+ this.externalName = Buffer.from(this.externalName);
51
+ }
52
+ }
53
+
54
+ processReturnParameter(buf) {
55
+ // process the parameters returned by the datatabase
56
+ this.applicationValue = buf.readUB4();
57
+ this.contextLen = buf.readUB2();
58
+ if (this.contextLen > 0) {
59
+ this.context = Buffer.from(buf.readBytes(this.contextLen));
60
+ }
61
+ }
62
+
63
+ encode(buf) {
64
+ // writes the message to the database
65
+ // acquire data to send to the server
66
+ let xidBytes;
67
+ if (this.xid) {
68
+ xidBytes = Buffer.alloc(128);
69
+ this.xid.globalTransactionId.copy(xidBytes);
70
+ this.xid.branchQualifier.copy(xidBytes,
71
+ this.xid.globalTransactionId.length);
72
+ }
73
+
74
+ // write message
75
+ this.writeFunctionHeader(buf);
76
+ buf.writeUB4(this.operation);
77
+ if (this.context) {
78
+ buf.writeUInt8(1); // pointer (transaction context)
79
+ buf.writeUB4(this.context.length);
80
+ } else {
81
+ buf.writeUInt8(0); // pointer (transaction context)
82
+ buf.writeUB4(0); // transaction context length
83
+ }
84
+
85
+ if (this.xid) {
86
+ buf.writeUB4(this.xid.formatId);
87
+ buf.writeUB4(this.xid.globalTransactionId.length);
88
+ buf.writeUB4(this.xid.branchQualifier.length);
89
+ buf.writeUInt8(1); // pointer (XID)
90
+ buf.writeUB4(xidBytes.length);
91
+ } else {
92
+ buf.writeUB4(0); // format id
93
+ buf.writeUB4(0); // global transaction id length
94
+ buf.writeUB4(0); // branch qualifier length
95
+ buf.writeUInt8(0); // pointer (XID)
96
+ buf.writeUB4(0); // XID length
97
+ }
98
+
99
+ buf.writeUB4(this.flags);
100
+ buf.writeUB4(this.timeout);
101
+ buf.writeUInt8(1); // pointer (application value)
102
+ buf.writeUInt8(1); // pointer (return context)
103
+ buf.writeUInt8(1); // pointer (return context length)
104
+
105
+ if (this.internalName) {
106
+ buf.writeUInt8(1); // pointer (internal name)
107
+ buf.writeUB4(this.internalName.length);
108
+ } else {
109
+ buf.writeUInt8(0); // pointer (internal name)
110
+ buf.writeUB4(0); // length of internal name
111
+ }
112
+
113
+ if (this.externalName) {
114
+ buf.writeUInt8(1); // pointer (external name)
115
+ buf.writeUB4(this.externalName.length);
116
+ } else {
117
+ buf.writeUInt8(0); // pointer (external name)
118
+ buf.writeUB4(0); // length of external name
119
+ }
120
+
121
+ if (this.context) {
122
+ buf.writeBytes(this.context);
123
+ }
124
+ if (this.xid) {
125
+ buf.writeBytes(xidBytes);
126
+ }
127
+ buf.writeUB4(this.applicationValue);
128
+
129
+ if (this.internalName) {
130
+ buf.writeBytes(this.internalName);
131
+ }
132
+
133
+ if (this.externalName) {
134
+ buf.writeBytes(this.externalName);
135
+ }
136
+ }
137
+ }
138
+
139
+ module.exports = TransactionSwitchMessage;
@@ -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;
@@ -140,7 +139,11 @@ class MessageWithData extends Message {
140
139
  if ((cVar.fetchInfo.dbType._oraTypeNum === constants.TNS_DATA_TYPE_CLOB
141
140
  && pVar.fetchInfo.fetchType._oraTypeNum === constants.TNS_DATA_TYPE_LONG)
142
141
  || (cVar.fetchInfo.dbType._oraTypeNum === constants.TNS_DATA_TYPE_BLOB
143
- && pVar.fetchInfo.fetchType._oraTypeNum === constants.TNS_DATA_TYPE_LONG_RAW)) {
142
+ && pVar.fetchInfo.fetchType._oraTypeNum === constants.TNS_DATA_TYPE_LONG_RAW)
143
+ || (cVar.fetchInfo.dbType._oraTypeNum === constants.TNS_DATA_TYPE_JSON
144
+ && pVar.fetchInfo.fetchType._oraTypeNum === constants.TNS_DATA_TYPE_VARCHAR)
145
+ || (cVar.fetchInfo.dbType._oraTypeNum === constants.TNS_DATA_TYPE_VECTOR
146
+ && pVar.fetchInfo.fetchType._oraTypeNum === constants.TNS_DATA_TYPE_LONG)) {
144
147
  cVar.type = pVar.fetchInfo.fetchType;
145
148
  cVar.maxSize = pVar.maxSize;
146
149
  }
@@ -498,12 +501,20 @@ class MessageWithData extends Message {
498
501
  }
499
502
  } else if (oraTypeNum === constants.TNS_DATA_TYPE_BOOLEAN) {
500
503
  colValue = buf.readBool();
501
- } else if (oraTypeNum === constants.TNS_DATA_TYPE_CLOB || oraTypeNum === constants.TNS_DATA_TYPE_BLOB) {
504
+ } else if (
505
+ oraTypeNum === constants.TNS_DATA_TYPE_CLOB ||
506
+ oraTypeNum === constants.TNS_DATA_TYPE_BLOB ||
507
+ oraTypeNum === constants.TNS_DATA_TYPE_BFILE
508
+ ) {
509
+ let length = 0;
510
+ let chunkSize = 0;
502
511
  const bvalue = buf.readUB4();
503
512
  if (bvalue > 0) { // Non Null data in column
504
513
  colValue = new ThinLobImpl();
505
- const length = buf.readUB8();
506
- const chunkSize = buf.readUB4();
514
+ if (oraTypeNum !== constants.TNS_DATA_TYPE_BFILE) {
515
+ length = buf.readUB8();
516
+ chunkSize = buf.readUB4();
517
+ }
507
518
  const locator = Buffer.from(buf.readBytesWithLength());
508
519
  colValue.init(this.connection, locator, dbType, length, chunkSize);
509
520
  }
@@ -852,7 +863,11 @@ class MessageWithData extends Message {
852
863
  } else {
853
864
  buf.writeUInt16BE(0x0100);
854
865
  }
855
- } else if (oraTypeNum === constants.TNS_DATA_TYPE_CLOB || oraTypeNum === constants.TNS_DATA_TYPE_BLOB) {
866
+ } else if (
867
+ oraTypeNum === constants.TNS_DATA_TYPE_CLOB ||
868
+ oraTypeNum === constants.TNS_DATA_TYPE_BLOB ||
869
+ oraTypeNum === constants.TNS_DATA_TYPE_BFILE
870
+ ) {
856
871
  buf.writeUB4(value._locator.length);
857
872
  buf.writeBytesWithLength(value._locator);
858
873
  } else if ([constants.TNS_DATA_TYPE_ROWID, constants.TNS_DATA_TYPE_UROWID].includes(oraTypeNum)) {
@@ -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);
@@ -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
@@ -114,6 +115,8 @@ class ConnStrategy {
114
115
  if (config != null) {
115
116
  if ((delay == 0 || delay == undefined) && config.retryDelay > 0) {
116
117
  delay = config.retryDelay * 1000;
118
+ } else if (!delay) {
119
+ delay = constants.DEFAULT_RETRY_DELAY; // 1 sec default
117
120
  }
118
121
  }
119
122
  for (let i = this.lastRetryCounter; i <= this.retryCount; ++i) {
@@ -157,7 +160,7 @@ function sleep(time) {
157
160
  * @param {string} str - input description string
158
161
  * @returns {object} - returns a connection strategy object.
159
162
  */
160
- async function createNode(str) {
163
+ async function createNode(str, userConfig) {
161
164
  let nvpair;
162
165
  if (typeof str === 'string')
163
166
  nvpair = createNVPair(str);
@@ -185,6 +188,11 @@ async function createNode(str) {
185
188
  }
186
189
  navobj.initFromNVPair(nvpair);
187
190
  const cs = new ConnStrategy();
191
+ cs.driverName = userConfig.driverName;
192
+ cs.machine = userConfig.machine;
193
+ cs.terminal = userConfig.terminal;
194
+ cs.osUser = userConfig.osUser;
195
+ cs.program = userConfig.program;
188
196
  await navobj.navigate(cs);
189
197
  return cs;
190
198
  }
@@ -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
@@ -777,8 +777,20 @@ class NavDescription extends Description {
777
777
  if (this.connectData == null) {
778
778
  this.connectData = "(SERVICE_NAME=)";
779
779
  }
780
- const pgmName = "\"'" + cInfo.program + "'\"";
781
- const cid = `(CID=(PROGRAM=${pgmName})(HOST=${cInfo.hostName})(USER=${cInfo.userName}))`;
780
+
781
+ let pgmName = cInfo.program;
782
+ if (cs.program) {
783
+ pgmName = cs.program;
784
+ }
785
+ let hostName = cInfo.hostName;
786
+ if (cs.machine) {
787
+ hostName = cs.machine;
788
+ }
789
+ let userName = cInfo.userName;
790
+ if (cs.osUser) {
791
+ userName = cs.osUser;
792
+ }
793
+ const cid = `(CID=(PROGRAM=${pgmName})(HOST=${hostName})(USER=${userName}))`;
782
794
  cOpts[i].CNdata.push(NavSchemaObject.CD);
783
795
  cOpts[i].CNdata.push(this.connectData);
784
796
  cOpts[i].CNdata.push(cid);
@@ -46,7 +46,7 @@ const downHostInstance = require("./connStrategy.js").SOLE_INST_DHCACHE;
46
46
 
47
47
  async function getConnectionInfo(userConfig) {
48
48
  const connStr = await resolveConnectStr(userConfig.connectString, userConfig.configDir);
49
- const addressNode = await createNode(connStr);
49
+ const addressNode = await createNode(connStr, userConfig);
50
50
  let nvpair;
51
51
  if (typeof connStr === 'string')
52
52
  nvpair = createNVPair(connStr);
@@ -97,9 +97,9 @@ async function resolveConnectStr(connectString, configDir) {
97
97
 
98
98
  }
99
99
 
100
- async function resolveAddress(connStr, configDir) {
101
- const connstr = await resolveConnectStr(connStr, configDir);
102
- return createNode(connstr);
100
+ async function resolveAddress(connStr, userConfig) {
101
+ const connstr = await resolveConnectStr(connStr, userConfig.configDir);
102
+ return createNode(connstr, userConfig);
103
103
  }
104
104
 
105
105
  /**
@@ -199,7 +199,7 @@ class NetworkSession {
199
199
  * Establish network session .Make transport level connection, send NSPTCN(connect packet) and read the response.
200
200
  * @returns NetError.(connection successfully established(NetError.CONNECTED) or reason for failure)
201
201
  */
202
- async connect2(address) {
202
+ async connect2(address, userConfig) {
203
203
  /* Sanitise SDU */
204
204
  if (this.sAtts.sdu) {
205
205
  if (this.sAtts.sdu > constants.NSPABSSDULN) {
@@ -269,7 +269,7 @@ class NetworkSession {
269
269
  redirConnData = this.cData;
270
270
  }
271
271
 
272
- const redirAddressNode = await resolveAddress(adrStr);
272
+ const redirAddressNode = await resolveAddress(adrStr, userConfig);
273
273
  const host = address.hostname;
274
274
  address = await redirAddressNode.execute();
275
275
  if (address.desc)
@@ -301,7 +301,7 @@ class NetworkSession {
301
301
  this.markerPkt = new Packet.MarkerPacket(this.sAtts.largeSDU);
302
302
  this.controlPkt = new Packet.ControlPacket();
303
303
  this.ntAdapter.largeSDU = this.sAtts.largeSDU;
304
- this.sAtts.nt.wallet = null;
304
+ this.sAtts.clearWallet();
305
305
  this.sAtts.nt.walletPassword = null;
306
306
  return (true);
307
307
  }
@@ -314,10 +314,10 @@ class NetworkSession {
314
314
  do {
315
315
  try {
316
316
  if (this.sAtts.connectTimeout) {
317
- const asyncPromise = this.connect2(address);
317
+ const asyncPromise = this.connect2(address, userConfig);
318
318
  connected = await timeout(asyncPromise, this.sAtts.connectTimeout, "connectTimeout", address, this.sAtts.connectionId);
319
319
  } else {
320
- connected = await this.connect2(address);
320
+ connected = await this.connect2(address, userConfig);
321
321
  }
322
322
  } catch (err) {
323
323
  if (err.message.startsWith('NJS-510') && !this.ntAdapter.connected) {
@@ -328,6 +328,7 @@ class NetworkSession {
328
328
  this.ntAdapter.disconnect(constants.NSFIMM);
329
329
  this.ntAdapter = null;
330
330
  }
331
+ this.sAtts.clearWallet();
331
332
  connected = false;
332
333
  savedErr = err;
333
334
  try {
@@ -527,7 +528,7 @@ class NetworkSession {
527
528
  addressNode = userConfig._connInfo[5];
528
529
  addressNode.reset();
529
530
  } else {
530
- addressNode = await resolveAddress(connStr, userConfig.configDir);
531
+ addressNode = await resolveAddress(connStr, userConfig);
531
532
  }
532
533
  let address;
533
534
  try {
@@ -234,7 +234,7 @@ class NTTCP {
234
234
  ca: this.atts.wallet,
235
235
  });
236
236
  } catch (err) {
237
- errors.throwErr(errors.ERR_TLS_INIT_FAILURE);
237
+ errors.throwErr(errors.ERR_TLS_INIT_FAILURE, err.message);
238
238
  }
239
239
  await this.tlsConnect(secureContext, this.stream);
240
240
  }
@@ -32,6 +32,7 @@ const process = require('process');
32
32
  const readline = require('readline');
33
33
  const errors = require("../../errors.js");
34
34
 
35
+ const MAX_IFILE_DEPTH = 4;
35
36
  /**
36
37
  * Returns File path of the tnsnames.ora if it exists.
37
38
  */
@@ -59,9 +60,12 @@ function tnsnamesFilePath(configDir) {
59
60
  }
60
61
  }
61
62
 
62
- let prevmtime = 0;
63
-
64
63
  class NLParamParser {
64
+
65
+ constructor() {
66
+ this.waiters = [];
67
+ this.readInProgress = false;
68
+ }
65
69
  /**
66
70
  * Reads the given file line by line and stores the
67
71
  * network service names mapped to connect descriptors in the hashtable.
@@ -69,13 +73,29 @@ class NLParamParser {
69
73
  * @returns {Promise}
70
74
  */
71
75
  async initializeNlpa(file_path) {
72
- const stat = fs.statSync(file_path);
73
-
74
- if (!(stat.mtime - prevmtime)) {
75
- /* File has been read */
76
+ if (this.readInProgress) {
77
+ await new Promise((resolve) => {
78
+ this.waiters.push(resolve);
79
+ });
80
+ }
81
+ if (!this.checkModfTime()) {
82
+ /* No File has been modified */
76
83
  return this.ht;
77
84
  }
85
+ this.ht = new Map();
86
+ this.modTime = new Map(); //stores modified time of each IFile
87
+ this.readInProgress = true;
88
+ await this.start(file_path, 0); //start with 0 depth (tnsnames.ora)
89
+ return this.ht;
90
+ }
91
+
92
+ async start(file_path, depth) {
78
93
 
94
+ if (depth > MAX_IFILE_DEPTH)
95
+ return; //ignore after max depth
96
+ const stat = fs.statSync(file_path);
97
+ // store file path and its modified time.
98
+ this.modTime.set(file_path, stat.mtime);
79
99
  // Creating a readable stream from file
80
100
  // readline module reads line by line
81
101
  // but from a readable stream only.
@@ -84,52 +104,49 @@ class NLParamParser {
84
104
  output: process.stdout,
85
105
  terminal: false
86
106
  });
87
- this.ht = new Map();
88
-
89
- const start = async () =>{
90
- let nvElem = "";
91
- for await (let line of file) {
92
- if (line.length == 0) { // ignore empty lines
93
- continue;
94
- } else if (line[0] == '#') { // comment line
107
+ let nvElem = "";
108
+ for await (let line of file) {
109
+ if (line.length == 0) { // ignore empty lines
110
+ continue;
111
+ } else if (line[0] == '#') { // comment line
112
+ continue;
113
+ } else if ((line[0] == ' ') || // continued input on new line
114
+ (line[0] == '\t') ||
115
+ (line[0] == ')') ||
116
+ (line[0] == '(')) {
117
+ line = line.replace(/\s+/g, '');
118
+ line = this.checkNLPforComments(line);
119
+ if (line.length == 0)
95
120
  continue;
96
- } else if ((line[0] == ' ') || // continued input on new line
97
- (line[0] == '\t') ||
98
- (line[0] == ')') ||
99
- (line[0] == '(')) {
100
- line = line.replace(/\s+/g, '');
101
- line = this.checkNLPforComments(line);
102
- if (line.length == 0)
103
- continue;
104
- else {
105
- nvElem = nvElem + line;
106
- }
121
+ else {
122
+ nvElem = nvElem + line;
123
+ }
107
124
 
108
- } else { // new NV Element starting here
109
- if (nvElem.length == 0) {
125
+ } else { // new NV Element starting here
126
+ if (nvElem.length == 0) {
110
127
 
111
- line = this.checkNLPforComments(line);
112
- nvElem = nvElem + line;
128
+ line = this.checkNLPforComments(line);
129
+ nvElem = nvElem + line;
113
130
 
114
- } else if (nvElem.length != 0) {
115
- this.addNLPListElement(nvElem); // Add Parameter to Hashtable
116
- nvElem = ""; // Clear first, before storing current line
131
+ } else if (nvElem.length != 0) {
132
+ await this.addNLPListElement(nvElem, depth); // Add Parameter to Hashtable
133
+ nvElem = ""; // Clear first, before storing current line
117
134
 
118
- line = this.checkNLPforComments(line);
119
- nvElem = nvElem + line;
120
- }
135
+ line = this.checkNLPforComments(line);
136
+ nvElem = nvElem + line;
121
137
  }
122
138
  }
123
- if (nvElem.length != 0) { // at eof, still one more parameter to read
124
- this.addNLPListElement(nvElem);
125
- nvElem = ""; // clear nvElem buffer after added
126
- }
127
- prevmtime = stat.mtime;
128
- return this.ht;
129
- };
130
- return await start();
139
+ }
140
+ if (nvElem.length != 0) { // at eof, still one more parameter to read
141
+ await this.addNLPListElement(nvElem, depth);
142
+ nvElem = ""; // clear nvElem buffer after added
143
+ }
144
+ this.readInProgress = false;
145
+ let waiter;
146
+ while ((waiter = this.waiters.pop())) {
147
+ waiter();
148
+ }
131
149
  }
132
-
133
150
  /**
134
151
  * Given a string, this method looks if the '#' character is present.
135
152
  * If true, the line is truncated from that point onwards until the end
@@ -155,11 +172,28 @@ class NLParamParser {
155
172
  }
156
173
  return str1.join('');
157
174
  }
175
+ // check if any of the IFiles has been changed
176
+ checkModfTime() {
177
+ if (this.modTime) {
178
+ for (const [key, value] of this.modTime) {
179
+ if (fs.existsSync(key)) {
180
+ const stat = fs.statSync(key);
181
+ if ((stat.mtime - value > 0)) {
182
+ return true;
183
+ }
184
+ } else
185
+ return true;
186
+ }
187
+ } else {
188
+ return true;
189
+ }
190
+ return false;
191
+ }
158
192
  /**
159
193
  * adds name value pairs from the input buffer into the hash table.
160
194
  * @param {string} ibuf
161
195
  */
162
- addNLPListElement(ibuf) {
196
+ async addNLPListElement(ibuf, depth) {
163
197
  const res = ibuf.split(/\r?\n/).filter(element => element);
164
198
  for (let i = 0; i < res.length; i++) {
165
199
  if (res[i].charAt(0) != '(') {
@@ -169,14 +203,17 @@ class NLParamParser {
169
203
  const name = nvp.name;
170
204
  const uname = name.toUpperCase();
171
205
  nvp.name = uname;
172
- const unames = uname.split(","); //multiple aliases (alias1, alias2, alias3)
173
- for (let i = 0; i < unames.length; i++) {
174
- this.ht.set(unames[i], nvp);
206
+ // support for ifile
207
+ if (uname == 'IFILE') {
208
+ await this.start(nvp.atom, depth + 1);
209
+ } else {
210
+ const unames = uname.split(","); //multiple aliases (alias1, alias2, alias3)
211
+ for (let i = 0; i < unames.length; i++) {
212
+ this.ht.set(unames[i], nvp);
213
+ }
175
214
  }
176
215
  }
177
216
  }
178
-
179
-
180
217
  toString() {
181
218
  let out = "";
182
219
  this.ht.forEach((value) => {
@@ -77,6 +77,9 @@ class SessionAtts {
77
77
  if (typeof params.walletPassword === 'string') {
78
78
  this.nt.walletPassword = params.walletPassword;
79
79
  }
80
+ if (typeof params.walletContent === 'string') {
81
+ this.nt.wallet = params.walletContent;
82
+ }
80
83
  if (params.expireTime > 0) {
81
84
  this.nt.expireTime = params.expireTime * 1000 * 60;
82
85
  }
@@ -135,6 +138,15 @@ class SessionAtts {
135
138
  });
136
139
  }
137
140
 
141
+ /**
142
+ * Clear wallet
143
+ */
144
+ clearWallet() {
145
+ if (this.nt.wallet && Buffer.isBuffer(this.nt.wallet))
146
+ this.nt.wallet.fill(0);
147
+ this.nt.wallet = null;
148
+ }
149
+
138
150
  /**
139
151
  * Prepare attributes for connection, Generate Connection ID and read Wallet file
140
152
  *
@@ -151,12 +163,12 @@ class SessionAtts {
151
163
  }
152
164
  this.nt.connectionId = this.connectionId;
153
165
 
154
- if (protocol && (protocol.toUpperCase() == "TCPS" && this.nt.walletFile)) {
166
+ if (protocol && (protocol.toUpperCase() == "TCPS" && !this.nt.wallet && this.nt.walletFile)) {
155
167
  this.nt.wallet = await this.readWalletFile();
156
168
  }
157
169
 
158
170
  if (!this.connectTimeout && !this.transportConnectTimeout)
159
- this.transportConnectTimeout = 60 * 1000; /* Default to 60 secs */
171
+ this.transportConnectTimeout = constants.DEFAULT_TRANSPORT_CONNECT_TIMEOUT; /* Default to 20 secs */
160
172
  }
161
173
 
162
174
  }
package/lib/thin/util.js CHANGED
@@ -29,6 +29,7 @@
29
29
  const constants = require('../constants');
30
30
  const errors = require('../errors.js');
31
31
  const os = require('os');
32
+ const nodbUtil = require('../util.js');
32
33
 
33
34
  //---------------------------------------------------------------------------
34
35
  // populateClientInfo()
@@ -36,15 +37,15 @@ const os = require('os');
36
37
  // Populates client process information
37
38
  //---------------------------------------------------------------------------
38
39
  function populateClientInfo() {
39
- this.program = process.argv0;
40
+ this.program = nodbUtil.sanitize(process.argv0);
40
41
  this.terminal = "unknown";
41
42
  this.pid = process.pid.toString();
42
43
  try {
43
- this.userName = os.userInfo().username;
44
+ this.userName = nodbUtil.sanitize(os.userInfo().username);
44
45
  } catch {
45
46
  this.userName = "unknown";
46
47
  }
47
- this.hostName = os.hostname();
48
+ this.hostName = nodbUtil.sanitize(os.hostname());
48
49
  }
49
50
  // Initialize client data on startup.
50
51
  const CLIENT_INFO = new populateClientInfo();