-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSQLParse.min.js
1 lines (1 loc) · 6.05 KB
/
SQLParse.min.js
1
let SQLParse=function(queryString){return queryString&&(this.query=queryString),this.setQuery=function(q){return this.query=q,this},this.hasQuery=function(){return""!=this.Query},this.hasSelect=function(){return 0!=this.Parsed.Select.length},this.hasWhere=function(){return 0!=this.Parsed.Where.length},this.hasOrderBy=function(){return 0!=this.Parsed.OrderBy.length},this.get=function(){return this.Parsed},this.getSelect=function(){return this.Parsed.Select},this.getWhere=function(){return this.Parsed.Where},this.getOrderBy=function(){return this.Parsed.OrderBy},this.renderTree=function(){return JSON.stringify(this.Parsed,null,5)},this.where=function(db){return Where(this,this.isWhere,db)},this.sort=function(db){return Sort(this,this.Parsed.OrderBy,db)},this.select=function(db){return Select(this,this.Parsed.Select,db)},this.results=function(){return this.LastResult},this.table=function(db){return toTable(this,db)},this.update=function(obj,db){return Update(this,obj,db)},this};function preParse(str){const regex=/\s+([=!<>]+)\s+/g;let m,search;for(;null!==(m=regex.exec(str));)m.forEach((match,idx)=>{0==idx&&(search=match),1==idx&&(str=str.replace(search,match))});return str}function keyValueSplit(str){const regex=/(?:([\w\d\s\(\)\'\"]+)([\>\=\<\!]+)(.*))/;if(null!==(matched=regex.exec(str))){let results=[];return matched.forEach((match,groupIndex)=>{groupIndex>=1&&results.push(match)}),results}return str}function parenSplit(element){const regex=/^([\(]+)?(.*[^\)])([\)]+)?$/g;let results=[];return null!==(matches=regex.exec(element))&&matches.forEach((match,groupIndex)=>{groupIndex>=1&&(match&&-1!=match.indexOf("(")?results.push(match):match&&-1!=match.indexOf(")")?results.push(match):match&&results.push(keyValueSplit(match)))}),results}function parse(query){const regex=/([^\s\"',]+|\"([^\"]*)\"|'([^']*)')+/g,keys=/^select$|^where$|^orderby$/i,orders=/^asc$|^desc$/i,parens=/^(\(+)|(\)+)$/g;let Segments={Select:[],Where:[],OrderBy:[]},key=null;for(;null!==(matches=regex.exec(query));){let matched=matches[0];if(keys.exec(matched))"select"==matched.toLowerCase()&&(key="Select"),"where"==matched.toLowerCase()&&(key="Where"),"orderby"==matched.toLowerCase()&&(key="OrderBy");else if(key)if("OrderBy"==key&&orders.exec(matched)){let index=Segments[key].length-1;Segments[key][index]=[Segments[key][index],matched]}else"Where"==key&&parens.exec(matched)?parenSplit(matched).forEach(x=>Segments[key].push(x)):Segments[key].push(keyValueSplit(matched))}return Segments}function buildWhere(where){let fn="",regex=/^[\/].*[\/ig]$/,trans={"=":"==",and:"&&",or:"||"};function translate(ele){return trans[ele]?trans[ele]:ele}return 0!=where.length?(where.forEach(ele=>{"object"!=typeof ele?fn+=`${translate(ele)} `:regex.exec(ele[2])?"!="==ele[1]?fn+=`(isNull(data['${ele[0]}']).match(${ele[2]}) == null) `:fn+=`(isNull(data['${ele[0]}']).match(${ele[2]}) != null) `:fn+=`data['${ele[0]}']${translate(ele[1])}${ele[2]} `}),new Function("data",`\n function isNull(ele) { return ele ? ele : '' }\n return (${fn})\n `)):new Function("data","return true")}function Sort(me,groups,data=!1){function isNumber(n){return!isNaN(parseFloat(n))&&isFinite(n)}function isNull(obj,def){return obj||def}function getSchema(data){let Schema={};return data.forEach(row=>{Object.keys(row).forEach(col=>{Schema.hasOwnProperty(col)||(Schema[col]={string:0,number:0}),isNumber(row[col])?Schema[col].number+=1:Schema[col].string+=1})}),Object.keys(Schema).forEach(key=>{0!=Schema[key].number&&0!=Schema[key].string?(console.log(`!WARNING!: Database column '${key}' has multiple types, assuming string`),Schema[key].type="isString"):Schema[key].type=0!=Schema[key].number?"isNumber":"isString"}),Schema}if(me.hasOrderBy){data||(data=me.LastResult);let schema=getSchema(data);groups=Array.isArray(groups)?groups.map(group=>0==Array.isArray(group)?[group,"desc"]:(1==group.length&&group.push("desc"),group)):[[groups,"desc"]],data.sort((function(a,b){let group=[];return groups.forEach(key=>{let isCol=key[0],isRev="asc"==key[1];if("isNumber"==schema[isCol].type){let col1=a[isCol]?Number(a[isCol]):-9e7,col2=b[isCol]?Number(b[isCol]):-9e7;isRev?group.push(col1-col2):group.push(col2-col1)}else{let col1=a[isCol]?a[isCol].toString().toLowerCase():"",col2=b[isCol]?b[isCol].toString().toLowerCase():"";isRev?group.push(col1.localeCompare(col2)):group.push(col2.localeCompare(col1))}}),eval(group.join(" || "))}))}return me.LastResult=data,me}function Where(me,whereFn,data=!1){return rows=[],me.hasWhere&&(data||(data=me.LastResult),data.forEach(row=>{1==whereFn(row)&&rows.push(row)}),me.LastResult=rows),me}function Select(me,selections,data=!1){let rows=[];return me.hasSelect&&(data||(data=me.LastResult),data.forEach(row=>{let tmp={};Object.keys(row).forEach(col=>{(selections.includes(col)||0==selections.length)&&(tmp[col]=row[col])}),rows.push(tmp)}),me.LastResult=rows),me}function Update(me,changes,data=!1){data||(data=me.LastResult),me.where(data);let whereOnly=me.LastResult;return me.LastResult=[],whereOnly.forEach(row=>{Object.keys(changes).forEach(change=>{row[change]=changes[change]}),me.LastResult.push(row)}),me.sort(),me.select(),me}function toTable(me,data=!1){function getWidths(){let widths={};return data.forEach(row=>{Object.keys(row).forEach(col=>{widths.hasOwnProperty(col)||(widths[col]=String(col).length);let width=String(row[col]).length;widths[col]=width>widths[col]?width:widths[col]})}),widths}function build(widths){let header="|",output="",separator="";return Object.keys(widths).forEach(col=>{header+=" {0} |".replace("{0}",col.padEnd(widths[col]))}),separator="+{0}+".replace("{0}","=".repeat(header.length-2)),data.forEach(row=>{output+="|",Object.keys(widths).forEach(col=>{let value=row.hasOwnProperty(col)?String(row[col]):"";output+=" {0} |".replace("{0}",value.padEnd(widths[col]))}),output+="\n"}),`${separator}\n${header}\n${separator}\n${output}${separator}\n`}return data||(data=me.LastResult),build(getWidths())}Object.defineProperty(SQLParse.prototype,"query",{get(){return this.Query},set(query){this.Query=preParse(query),this.Parsed=parse(this.Query),this.isWhere=buildWhere(this.Parsed.Where)}}),module.exports=SQLParse;