multi-db-orm
Version:
CRUD , Backup , Restore and Migration library for multiple databases
251 lines (219 loc) • 8.03 kB
JavaScript
const path = require("path");
const { MultiDbORM } = require("./multidb");
var fs = require('fs')
const os = require('os');
class OracleDB extends MultiDbORM {
connection_pool_name
schema
pool_creation
dataMap = {
"id": "VARCHAR(50) NOT NULL PRIMARY KEY",
"string": "VARCHAR2(4000)",
"number": "NUMBER",
"boolean": "VARCHAR(5)",
"array": "CLOB",
"object": "CLOB",
}
static async initOracleLibraries() {
}
constructor({
username,
password,
net_service_name,
wallet_dir,
connection_pool_name,
wallet_password,
lib_dir }) {
super()
const oracledb = require('oracledb')
const oracleInstantClient = require("oracle-instantclient");
if (!wallet_password)
wallet_password = password
process.env.LD_LIBRARY_PATH = lib_dir || oracleInstantClient.path
process.env.TS_ADMIN = wallet_dir
oracledb.initOracleClient({
configDir: wallet_dir,
libDir: lib_dir || oracleInstantClient.path
})
oracledb.autoCommit = true;
oracledb.outFormat = oracledb.OUT_FORMAT_OBJECT
oracledb.fetchAsString = [oracledb.CLOB];
this.connection_pool_name = connection_pool_name || username
this.db = oracledb
this.schema = username
let sqlnetora = path.join(wallet_dir, 'sqlnet.ora')
let configString = fs.readFileSync(sqlnetora).toString()
const regex = /DIRECTORY="([^"]*)"/;
let walletDirPath = wallet_dir
if (os.platform() == 'win32')
walletDirPath = wallet_dir.split("\\").join("\\\\")
configString = configString.replace(regex, `DIRECTORY="${walletDirPath}"`);
fs.writeFileSync(sqlnetora, configString)
this.pool_creation = oracledb.createPool({
user: username,
password: password,
configDir: wallet_dir,
walletLocation: wallet_dir,
walletPassword: wallet_password,
connectString: net_service_name,
poolAlias: this.connection_pool_name
}).then(async (pool) => {
console.log(`OracleDB Initialized`);
}).catch(e => {
console.log("Error initializing oracle DB: " + e.message)
throw e
})
this.dbType = 'oracle'
this.reqMade = 0
}
async connect() {
await this.pool_creation
}
async run(query) {
let connection
var that = this
this.reqMade++
return new Promise(async function (resolve, reject) {
try {
connection = await that.db.getConnection(that.connection_pool_name);
let resp = await connection.execute(query)
resolve(resp);
if (that.loglevel > 3)
console.log("Query ", query, ' -> ', resp)
} catch (err) {
reject(err)
} finally {
if (connection) {
try {
await connection.close();
} catch (err) {
throw (err);
}
}
}
})
}
async get(modelname, filter, options) {
this.metrics.get(modelname, filter, options)
var where = ''
for (var key in filter) {
where = where + `"${key}" = '${filter[key]}' AND `
}
where = where + " 1 = 1 ";
var sort = "";
if (options) {
if (options.apply) {
if (options.apply.ineq) {
where = where + ` AND "${options.apply.field}" ${options.apply.ineq.op} '${options.apply.ineq.value}'`;
}
if (options.apply.sort) {
sort = `ORDER BY "${options.apply.field}" ${options.apply.sort}`
}
}
else if (options.sort) {
sort = `ORDER BY`
for (let i = 0; i < options.sort.length; i++) {
sort = sort + ` "${options.sort[i].field}" ${options.sort[i].order}`;
if (i < options.sort.length - 1) {
sort = sort + ' , ';
}
}
}
}
var query = `SELECT * FROM ${modelname} WHERE ${where} ${sort} `
var row = await this.run(query)
return row.rows
}
async getOne(modelname, filter) {
this.metrics.getOne(modelname, filter)
var where = ''
for (var key in filter) {
where = where + `"${key}" = '${filter[key]}' AND `
}
where = where + " 1 = 1 ";
var query = `SELECT * FROM ${modelname} WHERE ${where} AND rownum < 2`
var row = await this.run(query)
return row.rows[0];
}
async create(modelname, sampleObject) {
this.sync.create(modelname, sampleObject)
this.metrics.create(modelname, sampleObject)
var cols = ''
for (var key in sampleObject) {
var type = this.dataMap[typeof (sampleObject[key])] || 'VARCHAR(4000)'
if (Array.isArray(sampleObject[key])) {
type = this.dataMap['array']
}
if (key == 'id') {
type = this.dataMap['id']
}
cols = cols + `"${key}" ${type}, `
}
cols = cols.substring(0, cols.length - 2)
var query = `CREATE TABLE ${modelname} (${cols})`
try {
return await this.run(query)
} catch (err) {
if (!err.message.indexOf("name is already used")) {
console.log(err)
}
return undefined;
}
}
async insert(modelname, object) {
this.sync.insert(modelname, object)
this.metrics.insert(modelname, object)
var cols = ''
var vals = ''
for (var key in object) {
cols = cols + `"${key}",`
let value = object[key]
if (typeof value == 'object')
value = JSON.stringify(value)
vals = vals + `'${value}',`
}
cols = cols.substring(0, cols.length - 1)
vals = vals.substring(0, vals.length - 1)
var query = `INSERT INTO ${modelname} (${cols}) VALUES(${vals})`
try {
return await this.run(query)
} catch (err) {
if (err.message && err.message.indexOf('SQLITE_ERROR: no such table: ') > -1) {
await this.create(modelname, object);
return await this.run(query)
}
else
throw err;
}
}
async update(modelname, filter, object) {
this.sync.update(modelname, filter, object)
this.metrics.update(modelname, filter, object)
var where = ''
var vals = ''
for (var key in filter) {
where = where + `"${key}" = '${filter[key]}' AND `
}
for (var key in object) {
vals = vals + ` "${key}" = '${object[key]}',`
}
where = where + " 1 = 1";
vals = vals.substring(0, vals.length - 1)
var query = `UPDATE ${modelname} SET ${vals} WHERE ${where}`
return await this.run(query)
}
async delete(modelname, filter) {
this.sync.delete(modelname, filter)
this.metrics.delete(modelname, filter)
var where = ''
for (var key in filter) {
where = where + `"${key}" = '${filter[key]}' AND `
}
where = where + " 1 = 1";
var query = `DELETE FROM ${modelname} WHERE ${where}`
return await this.run(query)
}
}
module.exports = {
OracleDB
}