Skip to content

Commit 701e564

Browse files
committed
Added support for fetching the list of network service names from tnsnames.ora using the new getNetworkServiceNames method
1 parent b952e8c commit 701e564

File tree

3 files changed

+191
-0
lines changed

3 files changed

+191
-0
lines changed

doc/src/release_notes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ Common Changes
1616
Thin Mode Changes
1717
+++++++++++++++++
1818

19+
#) Added support for fetching the list of network service names from
20+
tnsnames.ora using a new method, oracledb.getNetworkServiceNames()
21+
1922
#) Fixed bug that did not allow connection to Oracle Database 23ai instances
2023
that have fast authentication disabled.
2124

lib/oracledb.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,22 @@ async function createPool(options) {
606606
return pool;
607607
}
608608

609+
//-----------------------------------------------------------------------------
610+
// getNetworkServiceNames()
611+
//
612+
// Returns a list of the network service names found in the
613+
// tnsnames.ora file which is inside the directory
614+
// configDir or the $TNS_ADMIN dir
615+
// If a tnsnames.ora file does not exist, then an exception is raised
616+
//-----------------------------------------------------------------------------
617+
async function getNetworkServiceNames(configDir) {
618+
const { NLParamParser, tnsnamesFilePath } = require('thin/sqlnet/paramParser.js');
619+
const nlParamParser = new NLParamParser;
620+
const filePath = tnsnamesFilePath(configDir);
621+
const aliasht = await nlParamParser.initializeNlpa(filePath);
622+
const keysArr = [ ...aliasht.keys() ];
623+
return keysArr;
624+
}
609625

610626
//-----------------------------------------------------------------------------
611627
// getConnection()
@@ -881,6 +897,7 @@ module.exports = {
881897
// top-level functions
882898
getConnection: nodbUtil.callbackify(nodbUtil.wrapFn(getConnection)),
883899
createPool: nodbUtil.callbackify(nodbUtil.wrapFn(createPool)),
900+
getNetworkServiceNames: nodbUtil.callbackify(nodbUtil.wrapFn(getNetworkServiceNames)),
884901
getPool,
885902
initOracleClient,
886903
shutdown: nodbUtil.callbackify(nodbUtil.wrapFn(shutdown)),
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
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 https://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+
* NAME
26+
* listNetworkServiceNamesTest.js
27+
*
28+
* DESCRIPTION
29+
* Checks the correctness of the oracledb.listNetworkServiceNames() functionality.
30+
*/
31+
'use strict';
32+
33+
const fs = require('fs');
34+
const os = require('os');
35+
const path = require('path');
36+
const { join } = require("path");
37+
const assert = require('assert');
38+
const oracledb = require('oracledb');
39+
40+
describe('1. getNetworkServiceNames() functionality test', function() {
41+
const t_host = '127.0.0.1';
42+
const t_port = 1521;
43+
const t_protocol = 'tcp';
44+
45+
before(async function() {
46+
// Ensure that token generation is complete before tests start
47+
await new Promise(resolve => setTimeout(resolve, 4000));
48+
if (process.env.NODE_ORACLEDB_DRIVER_MODE === 'thick') {
49+
console.log('thick mode');
50+
// Thick mode requires Oracle Client or Oracle Instant Client libraries.
51+
// On Windows and macOS Intel you can specify the directory containing
52+
// the libraries at runtime or before Node.js starts. On other platforms
53+
// (where Oracle libraries are available), the system library search path
54+
// must always include the Oracle library path before Node.js starts. If
55+
// the search path is not correct, you will get a DPI-1047 error. See
56+
// the node-oracledb installation documentation.
57+
let clientOpts = {};
58+
// On Windows and macOS Intel platforms, set the environment
59+
// variable NODE_ORACLEDB_CLIENT_LIB_DIR to the Oracle Client library path
60+
if (process.platform === 'win32' || (process.platform === 'darwin' && process.arch === 'x64')) {
61+
clientOpts = { libDir: process.env.NODE_ORACLEDB_CLIENT_LIB_DIR };
62+
}
63+
oracledb.initOracleClient(clientOpts); // enable node-oracledb Thick mode
64+
const clientVersion = oracledb.oracleClientVersion;
65+
if (clientVersion < 1915000000 || (clientVersion >= 2100000000 && clientVersion < 2105000000)) {
66+
console.log(' Oracle Client Library Version:', oracledb.oracleClientVersionString);
67+
console.log(' Oracle Client version should be greater than 19.14 (19c) or greater than 21.5 (21c) for IAM tests with Thick mode');
68+
this.skip();
69+
}
70+
}
71+
});
72+
73+
it('1.1 getNetworkServiceNames test with multiple aliases', async function() {
74+
const connect_string = "(DESCRIPTION=(ADDRESS=(PROTOCOL=" + t_protocol + ")(HOST=" + t_host + ")(PORT=" + t_port + "))(CONNECT_DATA=(SERVICE_NAME=XEPDB1)))";
75+
const alias = "tns_alias1= " + connect_string;
76+
const connect_string2 = t_protocol + "://" + t_host + ":1521/XEPDB1";
77+
const ialias = "ialias=" + connect_string2;
78+
const folder = fs.mkdtempSync(path.join(os.tmpdir(), 'tnsAlias-'));
79+
const file_name = join(folder, "tnsnames.ora");
80+
fs.writeFileSync(file_name, alias, (err) => {
81+
// In case of a error throw err.
82+
if (err) throw err;
83+
});
84+
fs.appendFileSync(file_name, '\n' + ialias, (err) => {
85+
if (err) throw err;
86+
});
87+
88+
const servNames = await oracledb.getNetworkServiceNames(folder);
89+
if (folder) {
90+
fs.rmSync(folder, { recursive: true });
91+
}
92+
assert.deepStrictEqual(servNames, [ 'TNS_ALIAS1', 'IALIAS' ]);
93+
}); //1.1
94+
95+
it('1.2 getNetworkServiceNames test case with ifile entry', async function() {
96+
const connect_string = "(DESCRIPTION=(ADDRESS=(PROTOCOL=" + t_protocol + ")(HOST=" + t_host + ")(PORT=" + t_port + "))(CONNECT_DATA=(SERVICE_NAME=XEPDB1)))\n";
97+
const connect_string2 = t_protocol + "://" + t_host + ":1521/XEPDB1";
98+
const ialias = "ialias=" + connect_string2;
99+
const folder = fs.mkdtempSync(path.join(os.tmpdir(), 'tnsAlias-'));
100+
const ifilePath = join(folder, "ifile.ora");
101+
const ifileEntry = "IFILE=" + ifilePath;
102+
const file_name = join(folder, "tnsnames.ora");
103+
const alias = "tns_alias1 = " + connect_string + ifileEntry;
104+
fs.writeFileSync(file_name, alias, (err) => {
105+
// In case of a error throw err.
106+
if (err) throw err;
107+
});
108+
fs.writeFileSync(ifilePath, ialias, (err) => {
109+
if (err) throw err;
110+
});
111+
const servNames = await oracledb.getNetworkServiceNames(folder);
112+
if (folder) {
113+
fs.rmSync(folder, { recursive: true });
114+
115+
}
116+
assert.deepStrictEqual(servNames, ['TNS_ALIAS1', 'IALIAS']);
117+
}); //1.2
118+
it('1.3 getNetworkServiceNames test case with multiple line breaks in between 2 aliases ', async function() {
119+
const connect_string = "(DESCRIPTION=(ADDRESS=(PROTOCOL=" + t_protocol + ")(HOST=" + t_host + ")(PORT=" + t_port + "))(CONNECT_DATA=(SERVICE_NAME=XEPDB1)))";
120+
const alias = "tns_alias1= " + connect_string;
121+
const connect_string2 = t_protocol + "://" + t_host + ":1521/XEPDB1";
122+
const ialias = "ialias=" + connect_string2;
123+
const folder = fs.mkdtempSync(path.join(os.tmpdir(), 'tnsAlias-'));
124+
const file_name = join(folder, "tnsnames.ora");
125+
fs.writeFileSync(file_name, alias, (err) => {
126+
// In case of a error throw err.
127+
if (err) throw err;
128+
});
129+
// append multiple line breaks for testing purposes
130+
fs.appendFileSync(file_name, '\n\n\n\n\n\n\n\n' + ialias, (err) => {
131+
if (err) throw err;
132+
});
133+
/* display the file content
134+
const data = fs.readFileSync(file_name,
135+
{ encoding: 'utf8', flag: 'r' });
136+
console.log(data);
137+
*/
138+
const servNames = await oracledb.getNetworkServiceNames(folder);
139+
if (folder) {
140+
fs.rmSync(folder, { recursive: true });
141+
}
142+
assert.deepStrictEqual(servNames, [ 'TNS_ALIAS1', 'IALIAS' ]);
143+
}); //1.3
144+
it('1.4 getNetworkServiceNames test case with multiple line breaks and # commented lines in between', async function() {
145+
const connect_string = "(DESCRIPTION=(ADDRESS=(PROTOCOL=" + t_protocol + ")(HOST=" + t_host + ")(PORT=" + t_port + "))(CONNECT_DATA=(SERVICE_NAME=XEPDB1)))";
146+
const alias = "tns_alias1= " + connect_string;
147+
const connect_string2 = t_protocol + "://" + t_host + ":1521/XEPDB1";
148+
const ialias = "ialias=" + connect_string2;
149+
const folder = fs.mkdtempSync(path.join(os.tmpdir(), 'tnsAlias-'));
150+
const file_name = join(folder, "tnsnames.ora");
151+
fs.writeFileSync(file_name, alias, (err) => {
152+
// In case of a error throw err.
153+
if (err) throw err;
154+
});
155+
// append multiple line breaks for testing purposes
156+
fs.appendFileSync(file_name, '\n\n#commented line\n' + ialias, (err) => {
157+
if (err) throw err;
158+
});
159+
/* display the file content
160+
const data = fs.readFileSync(file_name,
161+
{ encoding: 'utf8', flag: 'r' });
162+
console.log(data);
163+
*/
164+
const servNames = await oracledb.getNetworkServiceNames(folder);
165+
if (folder) {
166+
fs.rmSync(folder, { recursive: true });
167+
}
168+
assert.deepStrictEqual(servNames, [ 'TNS_ALIAS1', 'IALIAS' ]);
169+
}); //1.4
170+
171+
});

0 commit comments

Comments
 (0)