123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267 |
- /**
- * @Author HonorLee (dev@honorlee.me)
- * @Version 1.0 (2018-05-04)
- * @License MIT
- */
- import Mysql = require('mysql');
- interface DBClient{
- getConnection:(callback:(err:Error,connection:any)=>void|null)=>void;
- }
- //数据对象
- export class MysqlDB{
- private _pool:DBClient;
- constructor(option:DBOption){
- this._pool = new MysqlPool().create(option);
- }
- public query(queryStr:string,callback:(err:Error,ret:any,fields:any)=>void){
- this._pool.getConnection((err,con)=>{
- if(err) return callback(err,null,null);
- con.query(queryStr,(err:Error, ret:any, fields:any)=>{
- if(err){
- LOGGER.error(`MysqlDB: "${queryStr}" error`);
- if(err.stack) LOGGER.error(err.stack);
- }
- con.release();
- if(callback) callback(err,ret,fields);
- });
- });
- }
- public querySync(queryStr:string){
- return new Promise((resolve)=>{
- this._pool.getConnection((err,con)=>{
- if(err){
- if(err.stack) LOGGER.error(err.stack);
- return resolve({err:err,data:[]});
- }
- con.query(queryStr,(err:Error, ret:any, fields:any)=>{
- con.release();
- if(err){
- LOGGER.error(`MysqlDB: "${queryStr}" error`);
- if(err.stack) LOGGER.error(err.stack);
- return resolve({err:err,data:[]});
- }
- resolve({err:null,data:ret});
- });
- });
- })
- }
- async count(tablename:string,whereObj?:any){
- let whereRule="";
- if(whereObj){
- whereRule = ` where ${MysqlUtil.objToKVString(whereObj,' and ')}`;
- }
- const sqlStr = `select count(1) as total from ${tablename} ${whereRule}`;
- const ret = await this.querySync(sqlStr) as MysqlResult;
- if(ret.err || ret.data.length==0) return 0;
- return ret.data[0].total;
- }
- async update(tablename:string,updateObj:any,whereObj:any){
- if(!tablename || !updateObj) return;
- let whereRule="";
- const updateRule = MysqlUtil.objToKVString(updateObj);
- if(whereObj){
- whereRule = ` where ${MysqlUtil.objToKVString(whereObj,' and ')}`;
- }
- const sqlStr = `update ${tablename} set ${updateRule} ${whereRule}`;
- return await this.querySync(sqlStr);
- }
- async select(tablename:string,queryField?:Array<string>|null,whereObj?:any){
- if(!tablename){
- const err = new Error("Missing table name")
- if(err.stack) LOGGER.error(err.stack);
- return {err:err,data:null};
- }
- let queryStr = "*",whereStr = "";
- if(queryField){
- queryField = queryField.map(v=>`\`${v}\``);
- queryStr = queryField.join(",");
- }
- if(whereObj) whereStr = ` where ${MysqlUtil.objToKVString(whereObj,' and ')}`;
- const sql = `select ${queryStr} from ${tablename} ${whereStr}`;
- return await this.querySync(sql);
- }
- async insert(tablename:string,insertData:any){
- if(!tablename){
- const err = new Error("Missing table name")
- if(err.stack) LOGGER.error(err.stack);
- return {err:err,data:null};
- }
- if(!insertData){
- const err = new Error("Missing insertData")
- if(err.stack) LOGGER.error(err.stack);
- return {err:err,data:null};
- }
- let sql = `insert into ${tablename} `;
- if(insertData.constructor == Object){
- sql += `set ${MysqlUtil.objToKVString(insertData)}`;
- }else if(insertData.constructor == Array && insertData.length>0 && insertData[0].constructor == Object){
- const fields = Object.keys(insertData[0]);
- const values = [];
- for(const data of insertData){
- const rawData = JSON.parse(JSON.stringify(data));
- const valueArr = [];
- for(const key of fields){
- if(rawData[key] != null || rawData[key] != undefined){
- if(rawData[key].constructor == String){
- rawData[key] = `"${rawData[key]}"`;
- }else if(rawData[key].constructor == Number){
- rawData[key] = Number(rawData[key]);
- }
- }else{
- rawData[key] = null;
- }
- valueArr.push(rawData[key]);
- }
- values.push(`(${valueArr.join(',')})`);
- }
- for(const i in fields){
- fields[i] = `\`${fields[i]}\``;
- }
- sql += `(${fields.join(',')}) values ${values.join(',')}`;
- }else{
- const err = new Error("InsertData type not support")
- if(err.stack) LOGGER.error(err.stack);
- return {err:err,data:null};
- }
- return await this.querySync(sql);
- }
- }
- export class MysqlUtil{
- /**
- * K-V数据转为Sql语句结构
- **/
- public static objToKVString(obj:any,joinStr?:string,keyPrefix?:string){
- const strArr:Array<string> = [];
- const dupObj = JSON.parse(JSON.stringify(obj));
- const keys = Object.keys(dupObj);
- let _extraSql = '',_extraLink = '';
- keyPrefix = keyPrefix?`${keyPrefix}.`:'';
- if(keys.length>0){
- keys.forEach(key =>{
- let v = dupObj[key];
- if(key=='_extra'){
- if(Array.isArray(v)){
- _extraSql = v.join(joinStr);
- }else if(v.constructor == Object){
- if(v.sql){
- _extraSql = v.sql;
- if(v.link!=null){
- _extraLink = v.link||'and';
- }
- }
- }else{
- _extraSql = v;
- }
- }else{
- if(typeof(v)=='string'){
- if(v[0]=='='){
- v = v.substring(1,-1);
- }else{
- if(!(v.substr(0,1)=="'" && v.substr(-1,1)=="'") && !(v.substr(0,1)=='"' && v.substr(-1,1)=='"')){
- v = `"${v}"`;
- }else{
- v = v;
- }
- }
- }
- keyPrefix = keyPrefix?`${keyPrefix}`:'';
- const sqlkey = `${keyPrefix}\`${key}\``;
- strArr.push(`${sqlkey}=${v}`);
-
- }
- })
- const sql = `${strArr.join(joinStr||',')} ${_extraLink} ${_extraSql}`;
- return sql;
- }else{
- return '';
- }
- }
- /**
- * 自动处理数据模型与数据,返回处理后符合模型的数据对象,包含数据安全性处理
- * @param module 数据模型
- * @param data 待处理数据
- * @param filter 自动过滤非模型字段数据(可选,默认不过滤)
- * @prarm reverse 反向处理,由写入处理变为取出处理,并自动根据模型字段类型进行可视化处理(可选,默认写入状态)
- **/
- public static analyzeFields(module:any,data:any,filter?:boolean,reverse?:boolean){
- const outData:AnyKeyString = {};
- Object.keys(data).forEach(key=>{
- if(module[key]!=undefined && data[key]!=null){
- let value = data[key];
- switch(module[key].type){
- case String:
- value = String(value);
- if(!reverse) value = Mysql.escape(value)
- break;
- case Number:
- value = Number(value)||0;
- break;
- case 'Date_Timestamp':
- case 'DateTime_Timestamp':
- case 'Time_Timestamp':
- value = Number(value)||0;
- if(value>0 && reverse){
- if(module[key].type=='Date_Timestamp') value = Moment.unix(value).format('YYYY-MM-DD');
- if(module[key].type=='DateTime_Timestamp') value = Moment.unix(value).format('YYYY-MM-DD HH:mm:ss');
- if(module[key].type=='Time_Timestamp') value = Moment.unix(value).format('HH:mm:ss');
- }
- break;
- }
- if(module[key].reverseKey && reverse) key = module[key].reverseKey;
- outData[key] = value;
- }else{
- if(!filter){
- if(data[key]==null){
- outData[key] = String(data[key]);
- }else{
- outData[key] = data[key];
- }
- }
- }
- })
- return outData;
- }
- public static escape(value:any){
- return Mysql.escape(value);
- }
- public static createPageLimit(page?:number,page_size?:number,orderField?:string){
- page = page||0;
- page_size = page_size||10;
- let sql = ``;
- if(orderField) sql += `ORDER BY \`${orderField}\` `;
- sql += `LIMIT ${page*page_size},${page_size}`;
- return sql;
- }
- public static createOrderBy(order_filed?:string,order_desc?:boolean){
- let orderStr = '';
- if(order_filed){
- orderStr = `order by \`${order_filed}\``;
- if(order_desc) orderStr += ' desc';
- }
- return orderStr;
- }
- }
- //连接池
- class MysqlPool{
- private _option:DBOption|null = null;
- private _pool:any;
- public Client:DBClient|null = null;
- create(option:DBOption):DBClient{
- this._option = option;
- this._pool = Mysql.createPool(option);
- this.Client = {
- getConnection:(callback)=>{
- if(!this._pool) throw new Error("Mysql pool not created!");
- if(!callback || typeof(callback)!='function') throw new Error("Mysql pool get connection lost callback!");
- this._pool.getConnection((err:any,connection:any)=>{
- callback(err,connection);
- });
- }
- }
- return this.Client;
- }
- }
|