import * as _ from 'lodash'; /** * author đức 28/1/2017 * lớp hỗ trợ cho các lớp repo */ export class RepoUtil { /* Build WHERE string with options Return: where = {str: strWhere, params: params} + strWhere = "1" nếu không có điều kiện gì + params = [] nếu không có điều kiện gì Sử dụng: where.str where.params */ public static buildWhere(options: any) : { str: string, params: Array } { let strWhere = "TRUE"; let parseOptions = RepoUtil.parseOptions(options); if ( parseOptions.index > 0 ) { strWhere = parseOptions.arrStr.join(" AND "); } return {str: strWhere, params: parseOptions.params}; } public static buildSetForUpdate(options: any) : { str: string, params: Array } { let strSet = ""; let arrSet = []; let params = []; let parseOptions = RepoUtil.parseOptions(options); if ( parseOptions.index > 0 ) { strSet = parseOptions.arrStr.join(", "); return {str: strSet, params: parseOptions.params}; } throw new Error("RepoUtil.buildSetForUpdate: options không được rỗng! "); } private static parseOptions(options: any): { arrStr: Array, params: Array, index: number } { let arrStr = []; let params = []; let index = 0 if ( options ) { var keys = Object.keys(options), key: string, value: any; for ( var i = 0, count = keys.length; i < count; i++ ) { key = keys[i]; value = options[key]; if ( value ) { // console.log(typeof( value )) switch ( typeof( value ) ) { case "number": index++ arrStr.push(key + " = $" + index) break; case "string": index++ arrStr.push(key + " ilike $" + index) break; case "object": index++ arrStr.push(key + " = ANY($" + index + ")") break; default: break; } //value params.push(value); } } } return {arrStr: arrStr, params: params, index: index} } /** * @author đức 28/1/2017 * * tạo truy vấn Where * * @static * @param {any} object chứa các cột và giá trị muốn có trong where * @param {Array} special chứa các cột đặc biệt * @returns {{ query: string, params: Array }} * @throws {Error} nếu object rỗng * * @memberOf RepoUtil */ public static buildWhereQuery(object, excludes: Array = [], special?: Array, count: number = 1): { query: string, params: Array } { if (_.isEmpty(object)) { return { query: '', params: [] }; } let query = ' WHERE '; let subQuery = {}; let params = []; for (let prop in object) { if (excludes.indexOf(prop) === -1) { let template = this.mapTypeToCompareOperator(prop, object[prop]); subQuery[prop] = template; if (template.indexOf('ilike') !== -1) { params.push('%' + object[prop] + '%'); if (prop === 'user_name_search') { params.push('%' + object[prop] + '%'); } } else { params.push(object[prop]); } } } if (special) { special.forEach(element => { if (subQuery[element]) { subQuery[element] = `${element}::text = any($$::text[])`; } }); } /** * co the overide template mặc định * vd: subQuery['tag_int'] = `tag_int in [$$]`; */ query += Object.keys(subQuery).map(key => subQuery[key]).join(' and '); query = this.reFormatQuery(query, count); return { query: query, params: params }; } /** * @author đức 28/1/2017 * * tạo truy vấn SET * * @static * @param {any} object chứa các cột vá giá trị muốn có trong SET * @param {Array} excludes chứa tên các cột ko muốn có trong SET * @returns {{ query: string, params: Array }} * @throws {Error} nếu object rỗng * * @memberOf RepoUtil */ public static buildSetQuery(object, excludes: Array): { query: string, params: Array } { if (Object.keys(object).length === 0 && object.constructor === Object) { throw new Error('object đưa vào không được rỗng '); } let set = { query: 'SET ', params: [] }; let temp = []; let count = 1; for (let prop in object) { if (excludes.indexOf(prop) === -1) { temp.push(`${prop} = $${count}`); set.params.push(object[prop]); count++; } } set.query += temp.join(','); return set; } /** * @author đức 28/1/2017 * * tạo câu truy vấn ORDER BY * * @static * @param {string} standard theo format ten_cot+0(hoặc 1)[,ten_cot+0(hoặc 1)...] * @returns {string} * @throws {Error} nếu standard không đúng format * * @memberOf RepoUtil */ public static convertQueryForOrderBy(standard: string): string { if (standard.length < 0 || !(new RegExp(/^(\w+\+[0||1])(,\w+\+[0||1])*$/g).test(standard))) { throw new Error(`standard không đúng format, nhận được: '${standard}', nhưng phải là 'ten_cot+0(hoặc 1)[,ten_cot+1,...]'`); } let result = standard.split(',') .filter(s => s.length > 0) .map(s1 => s1.split('+')) .map(s2 => s2[0] + ' ' + (s2[1] === '0' ? 'ASC' : 'DESC')) .join(','); return 'ORDER BY ' + result; } /** * @author đức 28/1/2017 * * hỗ trợ hàm WHERE * * @private * @static * @param {any} query câu truy vấn * @returns {string} * * @memberOf RepoUtil */ private static reFormatQuery(query, count = 1): string { while (query.indexOf('$$') !== -1) { query = query.replace('$$', `$${count}`); count++; } return query; } /** * @author đức 28/1/2017 * * hỗ trợ hàm WHERE * * @private * @static * @param {any} col_name tên cột * @param {any} value giá trị * @returns {string} template so sánh * * @memberOf RepoUtil */ private static mapTypeToCompareOperator(col_name, value): string { let templateOperator = `${col_name} = $$`; if (typeof value === 'string') { templateOperator = `${col_name}::text ilike $$`; } if (Array.isArray(value)) { templateOperator = `$$ && ${col_name}`; } return templateOperator; } /** * @author Thành 16-06-2017 * Build hàm insert động! tham số truyền bao nhiêu thì insert bấy nhiêu * @param object * @param loai: mặc định là false * @param excludes loại trừ */ public static buildInsert(object, excludes: Array): { query: string, value: string, params: Array } { if (Object.keys(object).length === 0 && object.constructor === Object) { throw new Error('object đưa vào không được rỗng '); } let set = { query: '', value: '', params: [] }; let temp = []; let value = []; let count = 1; for (let prop in object) { if (excludes.indexOf(prop) === -1) { temp.push(`${prop}`); value.push(`$${count}`); set.params.push(object[prop]); count++; } } set.query += temp.join(','); set.value += value.join(','); return set; } }