UNPKG

yorm

Version:
801 lines (790 loc) 26.3 kB
// var pool = require("./dbconfig") var numtypes = ["int", "tinyint", "bigint", "double", "decimal", "smalint", "float"]; var strtypeTable = 1 var strtypeType = 2 var pool = function() { var fullpath = __dirname var path = fullpath.split('/') if (path == undefined || path.length < 1) { console.log('Cannot work out directory structure for reading config file. Failed to load yorm...') throw new Error("Failed loading yorm!!") } else { if (path[path.length - 1] == "yorm" && path[path.length - 2] == "node_modules") { vpool = require("../../config/db") } else { console.log('No user dbconfig find. Try to use local db test with user/pass for testing purpose') vpool = require("../config/db") } if (vpool == undefined) { throw new Error("Cannot load dbconfig. You can create dbconfig.js in your root folder...") } else { return vpool } } }() module.exports.pool = pool module.exports.bufferinit = function(doinit) { return new Promise(function (resolve, reject) { if (!doinit && module.exports.tbldefs) { resolve() return } var result = {}; var pros = []; var batchsize = pool.batchsize ? pool.batchsize : 20; var tblarrs = []; var tblarr; var buflist = [] pool.getConnection(function (errz, connz) { connz.query('select table_name as tn from information_schema.tables where table_schema = "' + pool.database + '"', [], function (erry, rsy) { if (erry) { reject(erry) return } if (rsy.length == 0) { resolve (undefined) return } if (pool.buflist == undefined || pool.buflist.length == 0) { for (var i in rsy) { if (i % batchsize == 0) { if (i > 0) { tblarrs.push(tblarr) } tblarr = [] } tblarr.push(rsy[i].tn) } tblarrs.push(tblarr); } else { for (var i in pool.buflist) { if (i % batchsize == 0) { if (i > 0) { tblarrs.push(tblarr); } tblarr = []; } tblarr.push(pool.buflist[i]); } tblarrs.push(tblarr); } var sselectdef = "select table_name as tn, column_name as cn, column_type as ct, data_type as dt, column_key as ck"; var sfromdef = " from information_schema.columns"; var swheredef; for (var i in tblarrs) { tblarr = tblarrs[i]; swheredef = ' where table_schema = "' + pool.database + '" and table_name in ('; for (var j in tblarr) { swheredef = swheredef + "'" + tblarr[j] + "', "; } swheredef = swheredef.substr(0, swheredef.length - 2) + ") order by tn"; ssqldef = sselectdef + sfromdef + swheredef; pros.push(function (pSql) { return new Promise(function (resolve1, reject1) { pool.getConnection(function (err, conn) { conn.query(pSql, [], function (err1, rs) { if (err1) { reject(err1); } else { var cols = {}; var pricols = []; var swhere = " where "; var sselect = "select "; var sfrom = ""; var currtn; var lasttn = ""; for (var j in rs) { currtn = rs[j].tn; if (currtn != lasttn) { if (j > 0) { swhere = swhere.substr(0, swhere.length - 4); sselect = sselect.substr(0, sselect.length - 2); sfrom = " from " + lasttn; result[lasttn] = {}; result[lasttn]["strtype"] = strtypeTable result[lasttn]["cols"] = cols; result[lasttn]["swhere"] = swhere; result[lasttn]["sselect"] = sselect; result[lasttn]["sfrom"] = sfrom; result[lasttn]["pricols"] = pricols; } cols = {}; pricols = []; swhere = " where "; sselect = "select "; } cols[rs[j].cn] = rs[j]; if (rs[j].ck.toLowerCase() == "pri") { swhere = swhere + " " + rs[j].cn + " = ? and "; pricols.push(rs[j].cn); } sselect = sselect + rs[j].cn + ", "; lasttn = currtn; } swhere = swhere.substr(0, swhere.length - 4); sselect = sselect.substr(0, sselect.length - 2); sfrom = " from " + lasttn; result[lasttn] = {}; result[lasttn]["strtype"] = strtypeTable result[lasttn]["cols"] = cols; result[lasttn]["swhere"] = swhere; result[lasttn]["sselect"] = sselect; result[lasttn]["sfrom"] = sfrom; result[lasttn]["pricols"] = pricols; resolve1(); } }) }) }) }(ssqldef)) } Promise.all(pros).then(function () { module.exports.tbldefs = result module.exports.defType = typeDef module.exports.getone = getone module.exports.getmany = getmany module.exports.getbytype = getbytype module.exports.manybymany = manybymany module.exports.refreshByKey = refreshByKey module.exports.refreshone = refreshone module.exports.saveone = saveone module.exports.savemany = savemany console.log('Buffer init of meta data is successful!') resolve(); }).catch(function (errs) { console.log(errs + " in error"); reject(errs) }) }) }) }) } // module.exports.bufferinit() // .then(function (value) { // module.exports.defType = typeDef // module.exports.getone = getone // module.exports.getmany = getmany // module.exports.getbytype = getbytype // module.exports.manybymany = manybymany // module.exports.refreshByKey = refreshByKey // module.exports.refreshone = refreshone // module.exports.saveone = saveone // module.exports.savemany = savemany // }) // var query = function(ssql) { // return new Promise(function(resolve, reject) { // pool.getConnection(function(err, conn) { // if (err) { // reject(err) // } else { // conn.query(ssql, [], function(err1, rs) { // if (err1) { // reject(err1) // } else { // resolve(rs) // } // }) // } // }) // }) // } // module.exports.query = query var typeDef = function (typename, flds) { var tbldefs = module.exports.tbldefs try { if (tbldefs[typename] != undefined) { throw typename + " is defined already" } else { // var sselect = "select " // var sfrom = " from " var typecols = [] for (var i in flds) { // sselect = sselect + flds[i].cn + ", " if (flds[i].ref) { if (!tbldefs) { throw "Please specify tables definition object"; } var aref = flds[i].ref.split("."); var tbl = aref[0]; var fld = aref[1]; typecols.push(tbldefs[tbl]['cols'][fld]) } else { if (!flds[i].dt) { throw "Please either refering to db definition or define datatype with 'dt' for field " + flds[i].cn; } if (!flds[i].ct) { throw "Please either refering to db definition or define datatype with 'ct' for field " + flds[i].cn; } typecols.push(flds[i]) } } // sselect = sselect.substr(0, sselect.length - 2); tbldefs[typename] = {}; tbldefs[typename]["strtype"] = strtypeType // tbldefs[typename]["sselect"] = sselect; tbldefs[typename]["cols"] = typecols; return tbldefs[typename] } } catch (e) { throw e } } var getone = function (tn, objkey) { return new Promise(function (resolve, reject) { var tbldef = module.exports.tbldefs[tn] pool.getConnection(function (err, conn) { if (err) { reject(err); } else { var ssql = tbldef["sselect"] + tbldef["sfrom"] + tbldef.swhere; var keyarr = [] if (objkey[0] != undefined) { keyarr = objkey } else { for (var i in tbldef['pricols']) { keyarr.push(objkey[tbldef['pricols'][i]]) } } conn.query(ssql, keyarr, function (err1, rs) { if (err1) { reject(err1); } else { if (rs && rs.length > 0) { resolve(rs[0]); } else { reject('nothing found'); } } }) } }) }) } var getmany = function (tn, sfilter) { return new Promise(function (resolve, reject) { var tbldef = module.exports.tbldefs[tn] pool.getConnection(function (err, conn) { if (err) { reject(err); } else { if (tbldef.strtype == strtypeType) { reject('This function only table type supported right now') return } var ssql = tbldef["sselect"] + tbldef["sfrom"] + sfilter; conn.query(ssql, [], function (err1, rs) { if (err1) { reject(err1); } else { resolve(rs); } }) } }) }) } var getbytype = function (typename, ssql) { return new Promise(function (resolve, reject) { var def = module.exports.tbldefs[typename] var result = [] var one pool.getConnection(function (err, conn) { conn.query(ssql, [], function (err, rs, fs) { if (err) { reject(err); } else { console.log('fs: ' + JSON.stringify(fs)) for (var i in rs) { one = {} for (var cn in def.cols) { if (rs[i][cn] != undefined) {//? fs.indexOf(cn) > 0? one[cn] = rs[i][cn] } } result.push(one) } resolve(result) } }) }) }) } //1: Null is smallest. 2: Only default comparator supported and assume Mysql is the same. 3: Customized comparator will be supported in future version. var manybymany = function (tn, objs, trans, pParaFlds, pIfandor) { //only trans fields will be selected from db according to the condition in parafields and and/or condition return new Promise(function (resolve, reject) { try { var tbldef = module.exports.tbldefs[tn] var sselect = "select "; var sfrom = " from " + tn; var swhere; var cols = tbldef["cols"]; var keycols = tbldef["pricols"]; for (var i in trans) { sselect = sselect + trans[i] + ", "; } sselect = sselect.substr(0, sselect.length - 2); var ifandor = pIfandor ? pIfandor : "false"; for (var i in objs) { var swhereone = "("; for (var j in pParaFlds) { var aval = objs[pParaFlds[j]]; if (aval && isNaN(aval)) { swhereone = swhereone + pParaFlds[i] + " = '" + objs[pParaFlds[j]] + "' and "; } else if (aval && !isNaN(aval)) { swhereone = swhereone + pParaFlds[i] + " = " + objs[pParaFlds[j]] + " and "; } else { swhereone = swhereone + pParaFlds[i] + " is null and " } } if (ifandor) { swhere = swhere + swhereone.substr(0, swhereone.length - 4) + ") and "; } else { swhere = swhere + swhereone.substr(0, swhereone.length - 4) + ") or "; } } swhere = swhere + swhereone.substr(0, swhereone.length - 4); var ssql = sselect + sfrom + swhere; pool.getConnection(function (err, conn) { if (err) { reject(err); } else { conn.query(ssql, [], function (err1, rs) { if (err1) { reject(err1); } else { resolve(rs); // result = []; // for (var i in rs) { // result.push(rs[i]); // } // resolve(result); } }) } }) }catch (e) { console.log('failed in manybymany: ' + e) reject(e) } }) } var refreshByKey = function (tn, objs, trans, orders, pbatchsize) { return new Promise(function (resolve, reject) { var tbldef = module.exports.tbldefs[tn] var sselect = "select "; var sfrom = " from " + tn; var swhere; var sorder = " order by " var cols = tbldef["cols"]; var keycols = tbldef["pricols"]; var swheres = []; var lowhighs = []; var batchsize = 100; if (pbatchsize) { batchsize = pbatchsize; } for (var i in cols) { if (trans.indexOf(cols[i].cn) >= 0 || cols[i].ck.toLowerCase() == "pri") { sselect = sselect + cols[i].cn + ", "; } if (cols[i].ck.toLowerCase() == "pri") { if (!orders) { sorder = sorder + cols[i].cn + ", " } } } sselect = sselect.substr(0, sselect.length - 2); if (orders) { for (var key in orders) { sorder = sorder + key + " " + orders[key] + ", "; } } else { orders = {}; for (var i in keycols) { orders[keycols[i]] = "asc"; } } sorder = sorder.substr(0, sorder.length - 2); var lowhigh = {}; lowhigh.low = 0; lowhigh.high = 0; for (var i in objs) { if (isNaN(i)) continue; var swhereone; swhereone = " ("; if (i % batchsize == 0) { if (i > 0) { lowhigh.high = i - 1; lowhighs.push(lowhigh); swhere = swhere.substring(0, swhere.length - 4); swheres.push(swhere); } swhere = " where"; lowhigh = {}; lowhigh.low = i; } for (var j in keycols) { swhereone = swhereone + keycols[j] + " = '" + objs[i][keycols[j]] + "' and "; } swhereone = swhereone.substr(0, swhereone.length - 4) + ")"; swhere = swhere + swhereone + " or "; } swhere = swhere.substring(0, swhere.length - 4); lowhigh.high = objs.length - 1; lowhighs.push(lowhigh); swheres.push(swhere); var promises = []; for (var i in swheres) { promises.push(function (pI) { return new Promise(function (resolve1, reject1) { pool.getConnection(function (err, conn) { if (err) { reject(err); } else { var ssql = sselect + sfrom + swheres[pI] + sorder; conn.query(ssql, [], function (err1, rs) { if (err1) { reject(err1); } else { try { var objslice = objs.slice(lowhighs[pI].low, lowhighs[pI].high); var rsj = 0; var j = 0; outer: while (j < objslice.length) { var eq = true; for (var eqj in keycols) { eq = eq && (objslice[j][keycols[eqj]] == rs[rsj][keycols[eqj]]); } if (eq) { for (var k in trans) { objslice[j][trans[k]] = rs[rsj][trans[k]]; } rsj++; j++; } else { while (true) { if (rsj >= rs.length) { break outer; } var eq1 = true; for (var eqj1 in keycols) { eq1 = eq1 && (objslice[j][keycols[eqj1]] == rs[rsj][keycols[eqj]]); } if (eq1) { for (var k in trans) { objslice[j][trans[k]] = rs[rsj][trans[k]]; } rsj++; j++; break; } else { var objbigger = false; for (var eqj in keycols) { if (!objslice[j][keycols[eqj]] && !rs[rsj][keycols[eqj]]) { continue; } else if (!objslice[j][keycols[eqj]] && rs[rsj][keycols[eqj]]) { objbigger = false; break; } else if (objslice[j][keycols[eqj]] && !rs[rsj][keycols[eqj]]) { objbigger = true; break; } else if (objslice[j][keycols[eqj]] > rs[rsj][keycols[eqj]]) { objbigger = true; break; } else if (objslice[j][keycols[eqj]] < rs[rsj][keycols[eqj]]) { objbigger = false; break; } if (orders[keycols[eqj]] == "desc") { objbigger = !objbigger; } } if (objbigger) { rsj++; } else { j++; break; } } } } } resolve1(); } catch (err2) { reject1(err2); } } }); } }) }) }(i)); } Promise.all(promises).then(function (values) { resolve(objs); }).catch(function (err) { console.log(err); reject(err); }); }) } var refreshone = function (tn, one, ptrans) { return new Promise(function (resolve, reject) { var tbldef = module.exports.tbldefs[tn] var sselect = "select "; var sfrom = " from " + tn; var swhere = " where "; var tblcols = tbldef["cols"]; var trans = []; if (!ptrans) { for (var key in one) { if (tblcols[key]) { trans.push(key); } } } else { for (var key in one) { if (tblcols[key] && ptrans.indexOf(key) >= 0) { trans.push(key); } } } for (var key in one) { if (tblcols[key].ck.toLowerCase() == "pri") { if (!one[key]) { swhere = swhere + key + " is null and "; } else if (numtypes.indexOf(tblcols[key].dt) < 0) { swhere = swhere + key + " = '" + one[key] + "' and "; } else { swhere = swhere + key + " = " + one[key] + " and "; } } } for (var i in trans) { sselect = sselect + trans[i] + ", "; } sselect = sselect.substr(0, sselect.length - 2); swhere = swhere.substr(0, swhere.length - 4); pool.getConnection(function (err, conn) { if (err) { reject(err); } else { var ssql = sselect + sfrom + swhere; conn.query(ssql, [], function (err1, rs) { if (err1) { console.log('ssql error: ' + err1) reject(err1); } else { for (var j in rs) { for (var i in trans) { one[trans[i]] = rs[j][trans[i]]; } resolve(one); return; } } }) } }) }) } var saveone = function (tn, one, pconn) { return new Promise(function (resolve, reject) { var tbldef = module.exports.tbldefs[tn] var ssinsert = "insert into " + tn var sfld = ' (' var sval = ' values (' var sondup = ' on duplicate key update ' var cols0 = tbldef["cols"] var cols = [] var colsname = [] var pricols = tbldef['pricols'] for (var key in one) { if (cols0[key]) { cols.push(cols0[key]) colsname.push(key) } } var keymiss = true for (var i in pricols) { if (colsname.indexOf(pricols[i]) < 0) { keymiss = false reject('Key missing for table/key: ' + tn + '/' + pricols[i]) return } } for (var key in cols0) { if (colsname.indexOf(key) < 0) { continue } sfld = sfld + key + ', ' var dt = cols0[key].dt; if (one[key] !== undefined && one[key] !== null) { if (numtypes.indexOf(dt) < 0) { sval = sval + "'" + one[key] + "', "; } else { if (isNaN(one[key])) { reject(tn + "." + key + " must be numeric. But the encountered is: " + one[key]); return } sval = sval + one[key] + ", "; } } else { sval = sval + "null, " } } sfld = sfld.substr(0, sfld.length - 2) + ') ' sval = sval.substr(0, sval.length - 2) + ') ' for (var key in cols0) { if (pricols.indexOf(key) >= 0) { continue } if (colsname.indexOf(key) < 0) { sondup = sondup + key + ' = ' + key + ', ' } else { sondup = sondup + key + ' = ' + 'values(' + key + '), ' } } sondup = sondup.substr(0, sondup.length - 2) var ssql = ssinsert + sfld + sval + sondup if (pconn) { pconn.query(ssql, [], function (err1, rs) { if (err1) { console.log('error inserting on duplicate in yorm saveone 508: ' + err1) reject(err1) } else { resolve(one) } }) } else { pool.getConnection(function (err, conn) { conn.query(ssql, [], function (err1, rs) { if (err1) { console.log('error inserting on duplicate in yorm saveone 508: ' + err1) reject(err1) } else { resolve(one) } }) }) } }) } var savemany = function (tn, objs, pconn, pbatchsize, dupup) { return new Promise(function (resolve, reject) { if (!tn) { reject('Specify table name for yorm.savemany()!') return } if (!objs || !objs.length) { resolve('Nothing to save for table: ' + tn + " in yorm.savemany()!") return } var tbldef = module.exports.tbldefs[tn] var ssupdate = "insert into " + tn; var sflds = " ("; var svalueses = 'values '; var arrvalueses = []; var sondup = " "; var batchsize; var tblcols = tbldef["cols"]; // console.log('objs[0]: ' + JSON.stringify(objs[0])) if (!pbatchsize) { batchsize = 100; } else { batchsize = pbatchsize } if (dupup) { sondup = " on duplicate key update " } for (var key in objs[0]) { if (tblcols[key]) { sflds = sflds + key + ", "; if (dupup) { sondup = sondup + key + " = values(" + key + "), "; } } } if (dupup) { sondup = sondup.substr(0, sondup.length - 2) } for (var i in objs) { if (isNaN(parseInt(i))) continue; if (i % batchsize == 0) { if (i > 0) { svalueses = svalueses.substr(0, svalueses.length - 1); arrvalueses.push(svalueses); } svalueses = " values " } var one = objs[i]; var svaluesone = "(" for (var key in one) { if (tblcols[key]) { var dt = tblcols[key].dt; if (one[key] !== undefined && one[key] !== null) { if (numtypes.indexOf(dt) < 0) { svaluesone = svaluesone + "'" + one[key] + "', "; } else { if (isNaN(one[key])) { reject(tn + "." + key + " must be numeric. But value encountered: " + one[key]); return } svaluesone = svaluesone + one[key] + ", "; } } else { svaluesone = svaluesone + "null, " } } } svaluesone = svaluesone.substr(0, svaluesone.length - 2) + "),"; // console.log("svaluesone: " + svaluesone); svalueses = svalueses + svaluesone; } sflds = sflds.substr(0, sflds.length - 2) + ")"; svalueses = svalueses.substr(0, svalueses.length - 1); arrvalueses.push(svalueses); var promises = []; for (var i in arrvalueses) { promises.push(function (pI) { return new Promise(function (resolve1, reject1) { var ssql = ssupdate + sflds + arrvalueses[pI] + sondup; // console.log("ssql: " + ssql); if (pconn) { pconn.query(ssql, [], function (err1, rs) { if (err1) { console.log('err printing from yorm.js savemany with pconn:') console.log(err1) console.log(ssql) console.log('-----------------from yomr.js savemany() with pconn') reject1(err1 + ssql); } else { resolve1(); } }) } else { pool.getConnection(function (errconn, conn) { if (errconn) { reject1(errconn) } else { conn.query(ssql, [], function (err1, rs) { if (err1) { reject1(err1.message + ": " + ssql); } else { resolve1(); } }) } }) } }); }(i)); } Promise.all(promises).then(function (values) { resolve() }).catch(function (err2) { reject(err2) }); }) };