UNPKG

@rtinternal/oracledb

Version:

[Fork of oracle/node-oracledb ] Oracle Database driver for Node.js maintained by Oracle Corp.

258 lines (218 loc) 10.4 kB
// Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved //----------------------------------------------------------------------------- // // You may not use the identified files except in compliance with the Apache // License, Version 2.0 (the "License.") // // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0. // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // // See the License for the specific language governing permissions and // limitations under the License. // //----------------------------------------------------------------------------- 'use strict'; const util = require('util'); // node-oracledb version number let packageJSON; try { packageJSON = require('../package.json'); } catch (err) { throw new Error('package.json is missing'); } const PACKAGE_JSON_VERSION = packageJSON.version; module.exports.PACKAGE_JSON_VERSION = PACKAGE_JSON_VERSION; // Directory containing the node-oracledb add-on binary const RELEASE_DIR = 'build/Release'; module.exports.RELEASE_DIR = RELEASE_DIR; // The default node-oracledb add-on binary filename for this Node.js const BINARY_FILE = 'oracledb-' + PACKAGE_JSON_VERSION + '-' + process.platform + '-' + process.arch + '.node'; module.exports.BINARY_FILE = BINARY_FILE; // Staging directory used by maintainers building the npm package const STAGING_DIR = 'package/Staging'; module.exports.STAGING_DIR = STAGING_DIR; // errorMessages is for NJS error messages used in the JavaScript layer const errorMessages = { 'NJS-002': 'NJS-002: invalid pool', 'NJS-004': 'NJS-004: invalid value for property %s', 'NJS-005': 'NJS-005: invalid value for parameter %d', 'NJS-009': 'NJS-009: invalid number of parameters', 'NJS-017': 'NJS-017: concurrent operations on ResultSet are not allowed', 'NJS-023': 'NJS-023: concurrent operations on LOB are not allowed', 'NJS-037': 'NJS-037: incompatible type of value provided', 'NJS-040': 'NJS-040: connection request timeout. Request exceeded queueTimeout of %d', 'NJS-041': 'NJS-041: cannot convert ResultSet to QueryStream after invoking methods', 'NJS-042': 'NJS-042: cannot invoke ResultSet methods after converting to QueryStream', 'NJS-043': 'NJS-043: ResultSet already converted to QueryStream', 'NJS-045': 'NJS-045: cannot load a node-oracledb binary for Node.js ' + process.versions.node + ' (' + process.platform + ' ' + process.arch + ') %s', 'NJS-046': 'NJS-046: poolAlias "%s" already exists in the connection pool cache', 'NJS-047': 'NJS-047: poolAlias "%s" not found in the connection pool cache', 'NJS-064': 'NJS-064: connection pool is closing', 'NJS-065': 'NJS-065: connection pool was closed', 'NJS-067': 'NJS-067: a pre-built node-oracledb binary was not found for %s', 'NJS-069': 'NJS-069: node-oracledb %s requires Node.js %s or later', 'NJS-076': 'NJS-076: connection request rejected. Pool queue length queueMax %d reached', 'NJS-081': 'NJS-081: concurrent operations on a connection are disabled', 'NJS-082': 'NJS-082: connection pool is being reconfigured', 'NJS-083': 'NJS-083: pool statistics not enabled' }; // getInstallURL returns a string with installation URL function getInstallURL() { return ('Node-oracledb installation instructions: https://oracle.github.io/node-oracledb/INSTALL.html'); } module.exports.getInstallURL = getInstallURL; // getInstallHelp returns a string with installation usage tips that may be helpful function getInstallHelp() { let arch, url; let mesg = getInstallURL() + '\n'; if (process.platform === 'linux') { if (process.arch === 'x64') { url = 'https://www.oracle.com/database/technologies/instant-client/linux-x86-64-downloads.html\n'; arch = '64-bit'; } else if (process.arch === 'x32') { url = 'https://www.oracle.com/database/technologies/instant-client/linux-x86-32-downloads.html\n'; arch = '32-bit'; } else { url = 'https://www.oracle.com/database/technologies/instant-client.html\n'; arch = process.arch; } mesg += 'You must have ' + arch + ' Oracle Client libraries configured with ldconfig, or in LD_LIBRARY_PATH.\n'; mesg += 'If you do not have Oracle Database on this computer, then install the Instant Client Basic or Basic Light package from \n'; mesg += url; } else if (process.platform === 'darwin') { if (process.arch === 'x64') { url = 'https://www.oracle.com/database/technologies/instant-client/macos-intel-x86-downloads.html\n'; arch = '64-bit'; } else { url = 'https://www.oracle.com/database/technologies/instant-client.html\n'; arch = process.arch; } mesg += 'You must have the ' + arch + ' Oracle Instant Client Basic or Basic Light package libraries in\n'; mesg += '/usr/local/lib or set by calling oracledb.initOracleClient({libDir: "/my/instant_client_directory"}).\n'; mesg += 'Oracle Instant Client can be downloaded from ' + url; } else if (process.platform === 'win32') { if (process.arch === 'x64') { url = 'https://www.oracle.com/database/technologies/instant-client/winx64-64-downloads.html\n'; arch = '64-bit'; } else if (process.arch === 'x32') { url = 'https://www.oracle.com/database/technologies/instant-client/microsoft-windows-32-downloads.html\n'; arch = '32-bit'; } else { url = 'https://www.oracle.com/database/technologies/instant-client.html\n'; arch = process.arch; } mesg += 'You must have ' + arch + ' Oracle Client libraries in your PATH environment variable.\n'; mesg += 'If you do not have Oracle Database on this computer, then install the Instant Client Basic or Basic Light package from\n'; mesg += url; mesg += 'A Microsoft Visual Studio Redistributable suitable for your Oracle client library version must be available.\n'; } else { url = 'https://www.oracle.com/database/technologies/instant-client.html\n'; mesg += 'You must have ' + process.arch + ' Oracle Client libraries in your operating system library search path.\n'; mesg += 'If you do not have Oracle Database on this computer, then install an Instant Client Basic or Basic Light package from: \n'; mesg += url; } return mesg; } module.exports.getInstallHelp = getInstallHelp; // getErrorMessage is used to get and format error messages to make throwing // errors a little more convenient. function getErrorMessage(errorCode) { let args = Array.prototype.slice.call(arguments); args[0] = errorMessages[errorCode]; return util.format.apply(util, args); } module.exports.getErrorMessage = getErrorMessage; // assert is typically used at the beginning of public functions to assert // preconditions for the function to execute. Most commonly it is used to // validate the number of arguments and their types and throw an error if they // don't match what is expected. function assert(condition, errorCode, messageArg1) { if (!condition) { throw new Error(getErrorMessage(errorCode, messageArg1)); } } module.exports.assert = assert; // checkArgCount is used to validate the number of arguments, particularly with // optional parameters (range of number of parameters). If the number of // arguments is not within the given range, an error is thrown. function checkArgCount(args, minArgCount, maxArgCount) { if (args.length < minArgCount || args.length > maxArgCount) throw new Error(getErrorMessage('NJS-009')); } module.exports.checkArgCount = checkArgCount; // The callbackify function is used to wrap async methods to add optional // callback support. If the last parameter passed to a method is a function, // then it is assumed that the callback pattern is being used and the promise // is resolved or rejected and the callback invoked; otherwise, the function is // called unchanged and a promise is returned function callbackify(func) { return function() { // if last argument is not a function, simply invoke the function as usual // and a promise will be returned if (typeof arguments[arguments.length - 1] !== 'function') { return func.apply(this, arguments); } // otherwise, resolve or reject the promise and invoke the callback const args = Array.prototype.slice.call(arguments, 0, arguments.length - 1); const cb = arguments[arguments.length - 1]; func.apply(this, args).then(function(result) { cb(null, result); }, cb); }; } module.exports.callbackify = callbackify; // The serialize function is used to wrap methods to ensure that the connection // is not used concurrently by multiple threads function serialize(func) { return async function() { // determine the connection associated with the object const connection = this._getConnection(); // acquire the "lock"; this simply checks to see if another operation is in // progress, and if so, waits for it to complete await connection._acquireLock(); // call the function and ensure that the lock is "released" once the // function has completed -- either successfully or in failure try { return await func.apply(this, arguments); } finally { connection._releaseLock(); } }; } module.exports.serialize = serialize; function preventConcurrent(func, errorCode) { return async function() { if (this._isActive) throw new Error(getErrorMessage(errorCode)); this._isActive = true; try { return await func.apply(this, arguments); } finally { this._isActive = false; } }; } module.exports.preventConcurrent = preventConcurrent; function isObject(value) { return value !== null && typeof value === 'object'; } module.exports.isObject = isObject; function isObjectOrArray(value) { return (value !== null && typeof value === 'object') || Array.isArray(value); } module.exports.isObjectOrArray = isObjectOrArray; function isSodaDocument(value) { return (value != null && value._sodaDocumentMarker); } function isXid(value) { return (isObject(value) && (value.formatId !== undefined) && (value.globalTransactionId !== undefined) && (value.branchQualifier !== undefined)); } module.exports.isXid = isXid; module.exports.isSodaDocument = isSodaDocument;