UNPKG

enhancer-data-bridge

Version:

A bridge between Enhancer Clould and user business datasource

267 lines (243 loc) 9.38 kB
'use strict'; const BaseServiceClass = require('./service-base'); const mysql = require('mysql'); const async = require('async'); const dmdb = require('dmdb'); var dbTypeMap = { }; var varTypeMap = { }; class DmdbService extends BaseServiceClass { constructor(dbConfig) { super(dbConfig); this.dbConfig = dbConfig; } // @overridden BaseServiceClass#criteriaQuery criteriaQuery(criteria, callback) { var limitReg = /\sLIMIT\s+\d+\s*(\,\s*\d+\s*)?$/i; var that = this; var limitClause = criteria.query.match(limitReg); criteria.query = criteria.query.replace(limitReg, ''); var statement = this.prepareSQLStatement(criteria, '?'); var sql = statement.sql + (limitClause || [''])[0]; var params = statement.params; var ROWS_LENGTH = 'ROWS_LENGTH'; var countRecords = function(cb) { if (!criteria.paged || !criteria.countRecords || !statement.isSelect) { return cb(null, ROWS_LENGTH); } var countSql = that.getCountSql(sql, params); // Create connection and destroy it after use. This is just for preview mode, // and different from connection using method in bodhi app. that.getConnection(function(err, conn) { if (err) { cb(err); return; } conn.execute(countSql.sql, countSql.params, function(err, result) { conn && conn.close(); if (err) { return cb(err); } result = result.rows || []; if (!result.length) { return cb(null, 0); } cb(null, result[0][0]); }); }); }; var fetchData = function(cb) { if ( statement.isSelect && criteria.sortBy ) { sql = sql + " ORDER BY " + criteria.sortBy; } if ( statement.isSelect && criteria.paged === true ) { criteria.rowNum = parseInt(criteria.rowNum) || 1; sql = sql.replace(limitReg, ''); sql = sql + " LIMIT " + ( ( criteria.page - 1 ) * criteria.rowNum ) + ", " + criteria.rowNum; } that.getConnection(function(err, conn) { if (err) { cb(err); return; } conn.execute(sql, params, function(err, result) { conn && conn.close(); if (err) { return cb(err); } var result = that.__handleQueryResult(result); result.paged = criteria.paged; result.page = criteria.page; result.rowNum = criteria.rowNum; cb(null, result); }); }); }; async.parallel([countRecords, fetchData], function(err, results) { if (err) { return callback(err); } var records = results[0]; var finalResult = results[1]; finalResult.records = records === ROWS_LENGTH ? finalResult.rows.length : records; if (criteria.format === 'array') { finalResult.rows = finalResult.rows.map(function(obj) { var arr = []; for (var i in obj) { arr.push(obj[i]); } return arr; }); } callback(null, finalResult); }); } __handleQueryResult(result) { // for sql procure if (result.implicitResults && result.implicitResults.length) { var last = result.implicitResults.length - 1; result.rows = result.implicitResults[last]; result.metaDatas = result.metaData; result.metaData = result.metaData[last]; } var meta = result.metaData; if (result.rows && result.rows.length) { result.rows = result.rows.map(function(r) { var d = {}; r.forEach(function(c, index) { d[meta[index].name] = c; }); return d; }); } result.affectedRows = result.rowsAffected; return result; } execute(sql, params, callback) { // Create connection and destroy it after use. This is just for preview mode, // and different from connection using method in bodhi app. var that = this; that.getConnection(function(err, conn) { if (err) { callback(err); return; } sql = sql.trim(); var methodName = 'execute'; var firstP = params[0]; if (params.length === 1 && firstP instanceof Array && firstP[0] instanceof Array && /^INSERT\sINTO\s/i.test(sql) ) { methodName = 'executeMany'; params = params[0]; // replace params placeholder; var placeholder = []; firstP[0].forEach(function() { placeholder.push('?'); }); sql = sql.replace('?', placeholder.join(',')); } conn[methodName](sql, params, function(err, result) { conn && conn.close(); if (err) { return callback(err); } var result = that.__handleQueryResult(result); callback(null, result); }); }); } beginTransaction(en_cb) { var that = this; var dbConfig = this.dbConfig; dmdb.createPool({ connectString: `dm://${dbConfig.user}:${dbConfig.password}\@${dbConfig.host}:${dbConfig.port}?injectArray=true&autoCommit=false`, poolMin: 1, poolMax: 1, autoCommit: false }).then(function(pool) { pool.getConnection(function(err, conn) { if (err) { console.log(err); en_cb(err); return; } var newConn = { close: function(cb) { conn.close(cb); }, release: function(cb) { conn.release(cb); }, rollback: function(cb) { conn.rollback(cb); }, commit: function(cb) { conn.commit(cb); }, execute: function(sql, params, __callback) { // __callback(null, {rows:[], affectedRows:1}); sql = sql.trim(); var method = 'execute'; var firstP = params[0]; if (params.length === 1 && firstP instanceof Array && firstP[0] instanceof Array && /^INSERT\sINTO\s/i.test(sql) ) { method = 'executeMany'; params = params[0]; // replace params placeholder; var placeholder = []; firstP[0].forEach(function() { placeholder.push('?'); }); sql = sql.replace('?', placeholder.join(',')); } conn[method](sql, params, function(err, result) { if (err) { return __callback(err); } var result = that.__handleQueryResult(result); __callback(null, result); }); } }; en_cb(null, newConn); }); }).catch(function(err) { en_cb(err); }); } getConnection(cb) { var dbConfig = this.dbConfig; dmdb.createPool({ connectString: `dm://${dbConfig.user}:${dbConfig.password}\@${dbConfig.host}:${dbConfig.port}?injectArray=true`, poolMin: 1, poolMax: 1 }).then(function(pool) { pool.getConnection(function(err, conn) { // if (conn) { // var closeConn = conn.close; // conn.close = function() { // closeConn.apply(this, arguments); // setTimeout(function() { // pool.close(); // }, 3000); // } // } cb(err, conn); }); }).catch(function(err) { cb(err); }); } } module.exports = DmdbService;