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.
- package/README.md +2 -2
- package/build/Release/oracledb-6.7.0-darwin-arm64.node +0 -0
- package/build/Release/oracledb-6.7.0-darwin-arm64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.7.0-darwin-x64.node +0 -0
- package/build/Release/oracledb-6.7.0-darwin-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.7.0-js-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.7.0-linux-arm64.node +0 -0
- package/build/Release/oracledb-6.7.0-linux-arm64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.7.0-linux-x64.node +0 -0
- package/build/Release/oracledb-6.7.0-linux-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.7.0-win32-x64.node +0 -0
- package/build/Release/oracledb-6.7.0-win32-x64.node-buildinfo.txt +1 -0
- package/examples/README.md +4 -0
- package/lib/configProviders/azure.js +178 -0
- package/lib/configProviders/base.js +85 -0
- package/lib/configProviders/ociobject.js +211 -0
- package/lib/connection.js +97 -14
- package/lib/constants.js +1 -0
- package/lib/errors.js +68 -6
- package/lib/impl/aqQueue.js +2 -1
- package/lib/impl/base.js +45 -0
- package/lib/impl/connection.js +53 -0
- package/lib/impl/datahandlers/constants.js +3 -1
- package/lib/impl/datahandlers/vector.js +24 -9
- package/lib/impl/lob.js +29 -1
- package/lib/impl/pool.js +15 -0
- package/lib/impl/resultset.js +28 -2
- package/lib/impl/sodaCollection.js +2 -1
- package/lib/impl/sodaDatabase.js +2 -1
- package/lib/impl/sodaDocCursor.js +2 -1
- package/lib/impl/sodaOperation.js +2 -1
- package/lib/lob.js +55 -3
- package/lib/oracledb.js +246 -7
- package/lib/pool.js +14 -5
- package/lib/settings.js +1 -0
- package/lib/thin/connection.js +304 -29
- package/lib/thin/dbObject.js +4 -0
- package/lib/thin/lob.js +193 -1
- package/lib/thin/pool.js +18 -0
- package/lib/thin/protocol/capabilities.js +2 -0
- package/lib/thin/protocol/constants.js +29 -1
- package/lib/thin/protocol/messages/auth.js +12 -6
- package/lib/thin/protocol/messages/base.js +3 -0
- package/lib/thin/protocol/messages/index.js +5 -1
- package/lib/thin/protocol/messages/lobOp.js +17 -5
- package/lib/thin/protocol/messages/sessionRelease.js +1 -0
- package/lib/thin/protocol/messages/transactionChangeState.js +99 -0
- package/lib/thin/protocol/messages/transactionSwitch.js +139 -0
- package/lib/thin/protocol/messages/withData.js +21 -6
- package/lib/thin/protocol/protocol.js +23 -0
- package/lib/thin/sqlnet/connStrategy.js +9 -1
- package/lib/thin/sqlnet/constants.js +2 -0
- package/lib/thin/sqlnet/navNodes.js +14 -2
- package/lib/thin/sqlnet/networkSession.js +11 -10
- package/lib/thin/sqlnet/ntTcp.js +1 -1
- package/lib/thin/sqlnet/paramParser.js +87 -50
- package/lib/thin/sqlnet/sessionAtts.js +14 -2
- package/lib/thin/util.js +4 -3
- package/lib/traceHandler.js +133 -0
- package/lib/transformer.js +1 -2
- package/lib/types.js +1 -1
- package/lib/util.js +213 -35
- package/lib/version.js +2 -2
- package/package.json +1 -1
- package/build/Release/oracledb-6.5.1-darwin-x64.node +0 -0
- package/build/Release/oracledb-6.5.1-darwin-x64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.5.1-js-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.5.1-linux-arm64.node +0 -0
- package/build/Release/oracledb-6.5.1-linux-arm64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.5.1-linux-x64.node +0 -0
- package/build/Release/oracledb-6.5.1-linux-x64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.5.1-win32-x64.node +0 -0
- 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 (
|
|
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
|
-
|
|
506
|
-
|
|
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 (
|
|
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
|
-
|
|
781
|
-
|
|
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,
|
|
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.
|
|
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
|
|
531
|
+
addressNode = await resolveAddress(connStr, userConfig);
|
|
531
532
|
}
|
|
532
533
|
let address;
|
|
533
534
|
try {
|
package/lib/thin/sqlnet/ntTcp.js
CHANGED
|
@@ -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
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
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
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
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
|
-
|
|
97
|
-
|
|
98
|
-
|
|
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
|
-
|
|
109
|
-
|
|
125
|
+
} else { // new NV Element starting here
|
|
126
|
+
if (nvElem.length == 0) {
|
|
110
127
|
|
|
111
|
-
|
|
112
|
-
|
|
128
|
+
line = this.checkNLPforComments(line);
|
|
129
|
+
nvElem = nvElem + line;
|
|
113
130
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
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
|
-
|
|
119
|
-
|
|
120
|
-
}
|
|
135
|
+
line = this.checkNLPforComments(line);
|
|
136
|
+
nvElem = nvElem + line;
|
|
121
137
|
}
|
|
122
138
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
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
|
-
|
|
173
|
-
|
|
174
|
-
this.
|
|
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 =
|
|
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();
|