Skip to content

Commit 161dc0c

Browse files
committed
Add oracledb.initOracleClient() for Oracle Client initialization
1 parent 5109bef commit 161dc0c

File tree

10 files changed

+1332
-1009
lines changed

10 files changed

+1332
-1009
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@
44

55
**This release is under development**
66

7+
- Added a
8+
[`oracledb.initOracleClient()`](https://oracle.github.io/node-oracledb/doc/api.html#odbinitoracleclient)
9+
function to specify the directory that the Oracle Client libraries and
10+
optional configuration files should be located from, and to specify other
11+
configuration values, see [Initializing
12+
Node-oracledb](https://oracle.github.io/node-oracledb/doc/api.html#initnodeoracledb).
13+
714
- Added database instance startup and shutdown functions
815
[`oracledb.startup()`](https://oracle.github.io/node-oracledb/doc/api.html#odbstartup),
916
[`oracledb.shutdown()`](https://oracle.github.io/node-oracledb/doc/api.html#odbshutdown),

INSTALL.md

Lines changed: 454 additions & 391 deletions
Large diffs are not rendered by default.

doc/api.md

Lines changed: 724 additions & 554 deletions
Large diffs are not rendered by default.

examples/example.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ process.env.ORA_SDTZ = 'UTC';
3535
const oracledb = require('oracledb');
3636
const dbConfig = require('./dbconfig.js');
3737

38+
// On Windows and macOS, you can specify the directory containing your Oracle
39+
// Client Libraries. If this is not done, then a standard search heuristic is
40+
// used, see the node-oracledb documentation.
41+
// oracledb.initOracleClient({ libDir: 'C:\instantclient_19_3' }); // Windows
42+
// oracledb.initOracleClient({ libDir: '/Users/myname/instantclient_19_3' }); // macOS
43+
3844
async function run() {
3945
let connection;
4046

lib/oracledb.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,16 @@ class OracleDb {
132132
return pool;
133133
}
134134

135+
initOracleClient(arg1) {
136+
let options = {};
137+
nodbUtil.checkArgCount(arguments, 0, 1);
138+
if (arg1 !== undefined) {
139+
nodbUtil.assert(nodbUtil.isObject(arg1), 'NJS-005', 1);
140+
options = arg1;
141+
}
142+
this._initOracleClient(options);
143+
}
144+
135145
}
136146

137147
// Oracledb functions and classes

package/install.js

Lines changed: 11 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. */
1+
/* Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. */
22

33
/******************************************************************************
44
*
@@ -22,10 +22,6 @@
2222
* This script is included in the npm bundle of node-oracledb. It
2323
* is invoked by package.json during npm install.
2424
*
25-
* The node-oracledb npm package bundles all available pre-built
26-
* binaries, so this script is really just a check to see if an
27-
* appropriate pre-built binary is available.
28-
*
2925
* MAINTENANCE NOTES
3026
* This file should only ever 'require' packages included in core Node.js.
3127
*
@@ -50,7 +46,7 @@ function error(message) { // eslint-disable-line
5046
console.error.apply(console, args);
5147
}
5248

53-
// Print a concluding messages and quits
49+
// Print concluding messages and quit
5450
function done(err) {
5551
let installUrl = 'https://oracle.github.io/node-oracledb/INSTALL.html';
5652

@@ -64,58 +60,28 @@ function done(err) {
6460
process.exit(87);
6561
} else { // Successfully installed
6662
let arch;
67-
let clientUrl;
6863

6964
if (process.arch === 'x64') {
7065
arch = '64-bit';
7166
} else {
7267
arch = '32-bit';
7368
}
7469

75-
log('********************************************************************************');
76-
77-
log('** Node-oracledb ' + nodbUtil.PACKAGE_JSON_VERSION + ' installed for Node.js ' + process.versions.node + ' (' + process.platform + ', ' + process.arch +')');
78-
79-
log('**');
80-
log('** To use node-oracledb:');
81-
8270
if (process.platform === 'linux') {
83-
if (process.arch === 'x64') {
84-
clientUrl = 'https://www.oracle.com/database/technologies/instant-client/linux-x86-64-downloads.html';
85-
} else {
86-
clientUrl = 'https://www.oracle.com/database/technologies/instant-client/linux-x86-32-downloads.html';
87-
}
88-
89-
log('** - Oracle Client libraries (' + arch + ') must be configured with ldconfig or LD_LIBRARY_PATH');
90-
log('** - To get libraries, install an Instant Client Basic or Basic Light package from');
91-
log('** ' + clientUrl);
71+
installUrl += '#linuxinstall';
9272
} else if (process.platform === 'darwin') {
93-
clientUrl = 'https://www.oracle.com/database/technologies/instant-client/macos-intel-x86-downloads.html';
94-
installUrl = 'https://oracle.github.io/node-oracledb/INSTALL.html#instosx';
95-
96-
log('** - Oracle Instant Client Basic or Basic Light package libraries must be in ~/lib or /usr/local/lib');
97-
log('** Download from ' + clientUrl);
73+
installUrl += '#instosx';
9874
} else if (process.platform === 'win32') {
99-
if (process.arch === 'x64') {
100-
clientUrl = 'https://www.oracle.com/database/technologies/instant-client/winx64-64-downloads.html';
101-
} else {
102-
clientUrl = 'https://www.oracle.com/database/technologies/instant-client/microsoft-windows-32-downloads.html';
103-
}
104-
105-
log('** - Oracle Client libraries (' + arch + ') must be in your PATH environment variable');
106-
log('** - To get libraries, install an Instant Client Basic or Basic Light package from');
107-
log('** ' + clientUrl);
108-
log('** - A Microsoft Visual Studio Redistributable suitable for your Oracle Client library version must be available');
109-
log('** See ' + installUrl + ' for details');
110-
} else {
111-
clientUrl = 'https://www.oracle.com/technetwork/database/database-technologies/instant-client/overview/index.html';
112-
log('** - Oracle Client libraries (' + arch + ') must be in your operating system library search path');
113-
log('** - To get libraries, install an Instant Client Basic or Basic Light package from:');
114-
log('** ' + clientUrl);
75+
installUrl += '#windowsinstallation';
11576
}
11677

78+
log('********************************************************************************');
79+
log('** Node-oracledb ' + nodbUtil.PACKAGE_JSON_VERSION + ' installed for Node.js ' + process.versions.node + ' (' + process.platform + ', ' + process.arch +')');
11780
log('**');
118-
log('** Installation instructions: ' + installUrl);
81+
log('** To use node-oracledb:');
82+
log('** - Oracle Client libraries (' + arch + ') must be available.');
83+
log('** - Follow the installation instructions:');
84+
log('** ' + installUrl);
11985
log('********************************************************************************\n');
12086
}
12187
}

src/njsErrors.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ static const char *njsErrorMessages[] = {
8383
"NJS-074: cannot convert from JavaScript value to attribute \"%.*s\" of type \"%.*s\"", // errConvertToObjAttr
8484
"NJS-075: only one of connectString and connectionString can be used", // errDblConnectionString
8585
"NJS-076: connection request rejected. Pool queue length queueMax %d reached", // errQueueMax
86+
"NJS-077: Oracle Client library has already been initialized", // errClientLibAlreadyInitialized
8687
};
8788

8889

src/njsModule.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,9 @@
113113
// fetchInfo
114114
#define NJS_MAX_FETCH_AS_STRING_SIZE 200
115115

116+
// encoding name to use for all strings
117+
#define NJS_ENCODING "UTF-8"
118+
116119

117120
//-----------------------------------------------------------------------------
118121
// enumerations
@@ -195,7 +198,7 @@ typedef enum {
195198
errConvertToObjAttr,
196199
errDblConnectionString,
197200
errQueueMax,
198-
201+
errClientLibAlreadyInitialized,
199202

200203
// New ones should be added here
201204

src/njsOracleDb.c

Lines changed: 114 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
// class methods
2929
static NJS_NAPI_METHOD(njsOracleDb_createPool);
3030
static NJS_NAPI_METHOD(njsOracleDb_getConnection);
31+
static NJS_NAPI_METHOD(njsOracleDb_initOracleClient);
3132

3233
// asynchronous methods
3334
static NJS_ASYNC_METHOD(njsOracleDb_createPoolAsync);
@@ -95,7 +96,7 @@ static NJS_NAPI_FINALIZE(njsOracleDb_finalize);
9596
static bool njsOracleDb_initCommonCreateParams(njsBaton *baton,
9697
dpiCommonCreateParams *params);
9798
static bool njsOracleDb_initDPI(njsOracleDb *oracleDb, napi_env env,
98-
njsBaton *baton);
99+
dpiContextCreateParams *params, njsBaton *baton);
99100

100101
// define constants exposed to JS
101102
static njsConstant njsClassConstants[] = {
@@ -324,6 +325,8 @@ static const napi_property_descriptor njsClassProperties[] = {
324325
napi_default, NULL },
325326
{ "_getConnection", NULL, njsOracleDb_getConnection, NULL, NULL, NULL,
326327
napi_default, NULL },
328+
{ "_initOracleClient", NULL, njsOracleDb_initOracleClient, NULL, NULL,
329+
NULL, napi_default, NULL },
327330
{ NULL, NULL, NULL, NULL, NULL, NULL, napi_default, NULL }
328331
};
329332

@@ -437,7 +440,7 @@ static bool njsOracleDb_createPoolProcessArgs(njsBaton *baton, napi_env env,
437440
bool connStrFound, connStrFound1;
438441

439442
// initialize ODPI-C library, if necessary
440-
if (!njsOracleDb_initDPI(baton->oracleDb, env, baton))
443+
if (!njsOracleDb_initDPI(baton->oracleDb, env, NULL, baton))
441444
return false;
442445

443446
// set defaults on baton
@@ -656,7 +659,7 @@ static bool njsOracleDb_getConnectionProcessArgs(njsBaton *baton,
656659
bool connStrFound, connStrFound1;
657660

658661
// initialize ODPI-C library, if necessary
659-
if (!njsOracleDb_initDPI(baton->oracleDb, env, baton))
662+
if (!njsOracleDb_initDPI(baton->oracleDb, env, NULL, baton))
660663
return false;
661664

662665
// copy items used from the OracleDb class since they may change after
@@ -884,7 +887,7 @@ static napi_value njsOracleDb_getOracleClientVersion(napi_env env,
884887

885888
if (!njsUtils_validateGetter(env, info, (njsBaseInstance**) &oracleDb))
886889
return NULL;
887-
if (!njsOracleDb_initDPI(oracleDb, env, NULL))
890+
if (!njsOracleDb_initDPI(oracleDb, env, NULL, NULL))
888891
return NULL;
889892
if (dpiContext_getClientVersion(oracleDb->context, &versionInfo) < 0) {
890893
njsUtils_throwErrorDPI(env, oracleDb);
@@ -907,7 +910,7 @@ static napi_value njsOracleDb_getOracleClientVersionString(napi_env env,
907910

908911
if (!njsUtils_validateGetter(env, info, (njsBaseInstance**) &oracleDb))
909912
return NULL;
910-
if (!njsOracleDb_initDPI(oracleDb, env, NULL))
913+
if (!njsOracleDb_initDPI(oracleDb, env, NULL, NULL))
911914
return NULL;
912915
if (dpiContext_getClientVersion(oracleDb->context, &versionInfo) < 0) {
913916
njsUtils_throwErrorDPI(env, oracleDb);
@@ -1074,6 +1077,84 @@ static napi_value njsOracleDb_getVersionSuffix(napi_env env,
10741077
}
10751078

10761079

1080+
//-----------------------------------------------------------------------------
1081+
// njsOracleDb_initOracleClientHelper()
1082+
// Helper method that performs the work of njsOracleDb_initOracleClient().
1083+
//-----------------------------------------------------------------------------
1084+
static bool njsOracleDb_initOracleClientHelper(napi_env env,
1085+
napi_callback_info info)
1086+
{
1087+
size_t libDirLength, configDirLength, errorUrlLength, driverNameLength;
1088+
char *libDir, *configDir, *errorUrl, *driverName;
1089+
njsBaseInstance *callingInstance;
1090+
napi_value callingObj, args[1];
1091+
dpiContextCreateParams params;
1092+
njsOracleDb *oracleDb;
1093+
bool ok;
1094+
1095+
// process arguments
1096+
libDir = configDir = errorUrl = driverName = NULL;
1097+
libDirLength = configDirLength = errorUrlLength = driverNameLength = 0;
1098+
if (!njsUtils_validateArgs(env, info, 1, args, &callingObj,
1099+
&callingInstance))
1100+
return false;
1101+
if (!njsUtils_getStringFromArg(env, args, 0, "libDir", &libDir,
1102+
&libDirLength, NULL, NULL))
1103+
return false;
1104+
if (!njsUtils_getStringFromArg(env, args, 0, "configDir", &configDir,
1105+
&configDirLength, NULL, NULL))
1106+
return false;
1107+
if (!njsUtils_getStringFromArg(env, args, 0, "errorUrl", &errorUrl,
1108+
&errorUrlLength, NULL, NULL))
1109+
return false;
1110+
if (!njsUtils_getStringFromArg(env, args, 0, "driverName", &driverName,
1111+
&driverNameLength, NULL, NULL))
1112+
return false;
1113+
1114+
// initialize library
1115+
memset(&params, 0, sizeof(params));
1116+
if (libDirLength > 0)
1117+
params.oracleClientLibDir = libDir;
1118+
if (configDirLength > 0)
1119+
params.oracleClientConfigDir = configDir;
1120+
if (errorUrlLength > 0)
1121+
params.loadErrorUrl = errorUrl;
1122+
if (driverNameLength > 0)
1123+
params.defaultDriverName = driverName;
1124+
oracleDb = (njsOracleDb*) callingInstance;
1125+
ok = njsOracleDb_initDPI(oracleDb, env, &params, NULL);
1126+
1127+
// cleanup
1128+
if (libDir)
1129+
free(libDir);
1130+
if (configDir)
1131+
free(configDir);
1132+
if (errorUrl)
1133+
free(errorUrl);
1134+
if (driverName)
1135+
free(driverName);
1136+
return ok;
1137+
}
1138+
1139+
1140+
//-----------------------------------------------------------------------------
1141+
// njsOracleDb_initOracleClient()
1142+
// Initialize the Oracle Client library now, rather than when the first pool
1143+
// or standalone connection is created, or a request is made to determine the
1144+
// Oracle Client version. If the Oracle Client library has already been
1145+
// initialized, an exception is raised.
1146+
//
1147+
// PARAMETERS
1148+
// - options
1149+
//-----------------------------------------------------------------------------
1150+
static napi_value njsOracleDb_initOracleClient(napi_env env,
1151+
napi_callback_info info)
1152+
{
1153+
njsOracleDb_initOracleClientHelper(env, info);
1154+
return NULL;
1155+
}
1156+
1157+
10771158
//-----------------------------------------------------------------------------
10781159
// njsOracleDb_initCommonCreateParams()
10791160
// Initialize common creation parameters for pools and standalone
@@ -1089,10 +1170,6 @@ static bool njsOracleDb_initCommonCreateParams(njsBaton *baton,
10891170
if (baton->events)
10901171
params->createMode = (dpiCreateMode)
10911172
(params->createMode | DPI_MODE_CREATE_EVENTS);
1092-
params->encoding = "UTF-8";
1093-
params->nencoding = "UTF-8";
1094-
params->driverName = NJS_DRIVER_NAME;
1095-
params->driverNameLength = (uint32_t) strlen(params->driverName);
10961173
return true;
10971174
}
10981175

@@ -1106,27 +1183,47 @@ static bool njsOracleDb_initCommonCreateParams(njsBaton *baton,
11061183
// errors that can take place when the module is imported.
11071184
//-----------------------------------------------------------------------------
11081185
static bool njsOracleDb_initDPI(njsOracleDb *oracleDb, napi_env env,
1109-
njsBaton *baton)
1186+
dpiContextCreateParams *params, njsBaton *baton)
11101187
{
1188+
dpiContextCreateParams localParams;
11111189
napi_value error, message;
11121190
dpiErrorInfo errorInfo;
11131191

1114-
// if already initialized, nothing needs to be done
1115-
if (oracleDb->context)
1116-
return true;
1192+
// if already initialized and parameters were passed, raise an exception;
1193+
// otherwise do nothing as this is implicitly called when creating a
1194+
// standalone connection or session pool and when getting the Oracle Client
1195+
// library version
1196+
if (oracleDb->context) {
1197+
if (!params)
1198+
return true;
1199+
return njsUtils_throwError(env, errClientLibAlreadyInitialized);
1200+
}
1201+
1202+
// set up parameters used for initializing ODPI-C
1203+
if (params) {
1204+
memcpy(&localParams, params, sizeof(dpiContextCreateParams));
1205+
} else {
1206+
memset(&localParams, 0, sizeof(dpiContextCreateParams));
1207+
}
1208+
localParams.defaultEncoding = NJS_ENCODING;
1209+
if (!localParams.defaultDriverName)
1210+
localParams.defaultDriverName = NJS_DRIVER_NAME;
1211+
if (!localParams.loadErrorUrl)
1212+
localParams.loadErrorUrl =
1213+
"https://oracle.github.io/node-oracledb/INSTALL.html";
11171214

11181215
// create global DPI context (with baton available)
11191216
if (baton) {
1120-
if (dpiContext_create(DPI_MAJOR_VERSION, DPI_MINOR_VERSION,
1121-
&oracleDb->context, &baton->errorInfo) < 0) {
1217+
if (dpiContext_createWithParams(DPI_MAJOR_VERSION, DPI_MINOR_VERSION,
1218+
&localParams, &oracleDb->context, &baton->errorInfo) < 0) {
11221219
baton->dpiError = true;
11231220
return false;
11241221
}
11251222

11261223
// create global DPI context (no baton available, throw error immediately)
11271224
} else {
1128-
if (dpiContext_create(DPI_MAJOR_VERSION, DPI_MINOR_VERSION,
1129-
&oracleDb->context, &errorInfo) < 0) {
1225+
if (dpiContext_createWithParams(DPI_MAJOR_VERSION, DPI_MINOR_VERSION,
1226+
&localParams, &oracleDb->context, &errorInfo) < 0) {
11301227
NJS_CHECK_NAPI(env, napi_create_string_utf8(env, errorInfo.message,
11311228
errorInfo.messageLength, &message))
11321229
NJS_CHECK_NAPI(env, napi_create_error(env, NULL, message, &error))

0 commit comments

Comments
 (0)