UNPKG

jaune-engine

Version:
244 lines (218 loc) 6.95 kB
/** * @file Source code for SQL Database utility * @author Alvaro Juste */ "use strict"; // 3rd const _bind = require("lodash").bind; const _defaults = require("lodash").defaults; /** * @class High level utility which uses best practices and tools * of the framework. This utility should be used by modules * to send queries to database as it separates database * from the module. * @param {String} configurationKey The key that identifies the connection. * @param {Object} dbManager Data base manager */ const SqlUtil = function(configurationKey, dbManager) { this.configurationKey = configurationKey; this.dbManager = dbManager; }; SqlUtil.prototype.getSql = function() { return (this.sql || (this.sql = this.dbManager.getClientFromConfiguration(this.configurationKey))); }; /** * @function Returns callback to be used in chained call backs. * @param {Function} cb The chained callback to be called after default callback does required work. * @param {Object} executor Query executor * @param {*} [options.result] Result to be passed to callback. If passed, result from query is stored inside data property name. * @param {*} [resultProperty] Name of the property were to set result. * @returns {Function} The callback function */ SqlUtil.prototype.defaultCallback = function(cb, executor, options) { options = options || {}; return function(err, result) { if (err) { executor.doError(cb, err); } else { if (options.result) { if (options.resultProperty) { options.result[options.resultProperty] = result; delete options.resultProperty; } else if ("undefined" === typeof options.result.data){ options.result.data = result; } } executor.doSuccess(cb, options.result || result); } }; }; /** * @function Executes a call to an db object. * @param {*} client The client to execute query. * @param {String} query The query. * @param {Array} parameters Parameters for the query. */ SqlUtil.prototype.call = function* (client, query, parameters) { return yield this.query(client, query, parameters, "call"); }; /** * @function Executes a query. * @param {*} client The client to execute query. * @param {String} query The query. * @param {Array} parameters Parameters for the query. * @param {String} [type] Type of query */ SqlUtil.prototype.query = function* (client, query, parameters, type) { switch(type || "query") { case "query" : return yield client.query({ sql : query, args : parameters }); case "call" : return yield client.call({ sql : query, args : parameters }); default : throw new Error("Unsupported type: " + type); } }; /** * @function Executes a function inside a chain. The function to be executed * will be passed with all tools in order to keep any live * transaction functional. * @param {Function} fn Function to be executed. * @param {*} [chainedClient] Connection to use if any. Otherwise a new will be obtained. */ SqlUtil.prototype.executeChained = function* (fn, chainedClient) { let executor = yield this.chain(chainedClient); let result = null; try { result = yield fn(executor); yield executor.doSuccess(); } catch(err) { throw yield executor.doError(err); } return result; }; /** * @function Execute a chained query * @param {Function} fn Function to be executed. * @param {*} [chainedClient] Connection to use if any. Otherwise a new will be obtained. */ SqlUtil.prototype.executeChainedQuery = function* (query, args, chainedClient) { return yield (this.executeChained(_bind(function *(executor) { return yield this.query(executor.client, query, args); }, this), chainedClient)); }; /** * @function Execute a chained query * @param {Function} fn Function to be executed. * @param {*} [chainedClient] Connection to use if any. Otherwise a new will be obtained. */ SqlUtil.prototype.executeChainedCall = function* (query, args, chainedClient) { return yield (this.executeChained(_bind(function *(executor) { return yield this.call(executor.client, query, args); }, this), chainedClient)); }; /** * @function Prepares chained execution. * @param {*} [chainedClient] Connection to use if any. Otherwise a new will be obtained. * @param {Object} [options] Options. */ SqlUtil.prototype.chain = function* (chainedClient, options) { options = _defaults({ tx : false }); let client = yield this.getSql().chain(chainedClient); if (options.tx === true) { yield client.begin(); } return new Executor(client); }; /** * @function Converts an array of any to SQL parameter value. * @param {Array} array Array to convert. * @param {Function} [selector] Function that converts from input to string id. * @returns {String} Parameter. */ SqlUtil.prototype.toIdArray = function(array, selector) { return "{" + array.select(selector || function(e) { return "object" === typeof e ? e.id : e ; }).join() + "}"; }; /** * @function Default function to convert id of record into int. * @param {Object} e Record */ SqlUtil.prototype.convertIdToNumber = function(e) { e.id = parseInt(e.id, 10); }; /** * @function Executes a query within the given client * @param {Object} client The client * @param {String} query The query * @param {Array} parameters The parameters for the query * @param {String} type The query type */ SqlUtil.prototype.execute = function* (client, query, parameters, type) { switch(type || "query") { case "query" : return yield client.query({ sql : query, args : parameters }); case "call" : return yield client.call({ sql : query, args : parameters }); default : throw new Error("Unsupported type: " + type); } }; /** * @class Executor used to be passed on chained calls. * @param {Object} client The SQL client * */ const Executor = function(client) { this.client = client; }; /** * @function Marks success on this executor. */ Executor.prototype.doSuccess = function* () { try { yield this.client.commit(); } finally { yield this.doFinally(); } }; /** * @function Marks roll back on this executor. */ Executor.prototype.doRollback = function* () { try { yield this.client.rollback(); } finally { yield this.doFinally(); } }; /** * @function Marks error on this executor. */ Executor.prototype.doError = function* (e) { try { yield this.client.rollback(); } catch(err) { throw ErrorManager.asUnhandledError(err); } finally { yield this.doFinally(); } return e; }; /** * @function Do finally. * @param {Function} catchCallback Callback * @param {*} err Error */ Executor.prototype.doFinally = function* (cb) { yield this.client.close(); }; module.exports = { SqlUtil : SqlUtil };