import { Attribute } from "./db" import { Aggregation, Modifier } from "./dbStructure" import { selectQuery } from "./query" import { allModifierInput, primaryData, serializeReturn } from "./types" export class Handler { static querys = { select: (q: selectQuery): serializeReturn => { let args: primaryData[] = []; let w = joinArg(", ", this)(q.attr); args.push(...w[1]); let sql = `select ${w[0]} from ${q.from == null ? 'DUAL' : q.from.serialize(this)}`; if (q.whereD) { let whereS = q.whereD.serialize(this); args.push(...whereS[1]); sql += " where " + whereS[0]; } if (q.groupByD.length > 0) { let groupByS = joinArg(",", this)(q.groupByD); args.push(...groupByS[1]); sql += " group by " + groupByS[0]; if (q.havingD) { let havingS = q.havingD.serialize(this); args.push(...havingS[1]); sql += " having " + havingS[0]; } } if (q.limitD != null) { sql += " limit ?"; args.push(q.limitD); } return [sql, args]; } } static aggregations = { count: (a: Attribute): serializeReturn => ["count(" + a + ")", []], sum: (a: Attribute): serializeReturn => ["sum(" + a + ")", []], avg: (a: Attribute): serializeReturn => ["avg(" + a + ")", []], min: (a: Attribute): serializeReturn => ["min(" + a + ")", []], max: (a: Attribute): serializeReturn => ["max(" + a + ")", []], } static modifiers = { and: joinArg("and", this), or: joinArg("or", this), eq: joinArg("=", this), plus: joinArg("+", this), minus: joinArg("-", this), not: (a: allModifierInput[]): serializeReturn => { let e = a[0]; if (e instanceof Attribute) return ["not (" + e + ")", []]; if (e instanceof Modifier || e instanceof selectQuery || e instanceof Aggregation) { let [sqli, argsi] = e.serialize(this); return ["not (" + sqli + ")", argsi] } return ["not (?)", [e]]; } } static datatypes = { char: dataTypeSingleNum("char"), varchar: dataTypeSingleNum("varchar"), binary: dataTypeSingleNum("binary"), varbinary: dataTypeSingleNum("varbinary"), tinyblob: dataTypeNoArg("tinyblob"), blob: dataTypeNoArg("blob"), mediumblob: dataTypeNoArg("mediumblob"), longblob: dataTypeNoArg("longblob"), tinytext: dataTypeNoArg("tinytext"), text: dataTypeNoArg("text"), mediumtext: dataTypeNoArg("mediumtext"), longtext: dataTypeNoArg("longtext"), enum: (a: primaryData[]): serializeReturn =>{ return ["enum("+a.map(()=>"?").join(", ")+")",a]; }, set: (a: primaryData[]): serializeReturn =>{ return ["set("+a.map(()=>"?").join(", ")+")",a]; }, bool: dataTypeNoArg("bool"), bit: dataTypeNoArg("bit"), tinyint: dataTypeNoArg("tinyint"), smallint: dataTypeNoArg("smallint"), mediumint: dataTypeNoArg("mediumint"), int: dataTypeNoArg("int"), bigint: dataTypeNoArg("bigint"), float: dataTypeDblNum("float"), double: dataTypeDblNum("double"), decimal: dataTypeDblNum("decimal"), data: dataTypeNoArg("data"), datatime: dataTypeNoArg("datatime"), timestamp: dataTypeNoArg("timestamp"), time: dataTypeNoArg("time"), year: dataTypeNoArg("year"), } }; function dataTypeNoArg(type:string){ return (a : primaryData[]): serializeReturn =>{ return [type,[]]; } } function dataTypeSingleNum(type:string){ return (a : primaryData[]): serializeReturn =>{ return [type+"(?)",[a[0]]]; } } function dataTypeDblNum(type:string){ return (a : primaryData[]): serializeReturn =>{ return [type+"(?,?)",[a[0],a[1]]]; } } function joinArg(type: string, s: any) { return (a: (allModifierInput)[]): serializeReturn => { let args: primaryData[] = []; let sql = a.map(d => { if (d instanceof Attribute) return d; if (d instanceof Modifier || d instanceof selectQuery || d instanceof Aggregation) { let [sqli, argsi] = d.serialize(s); args.push(...(argsi.flat(Infinity))); return "("+sqli+")"; } args.push(d); return "?"; }).join(" " + type + " "); return [sql, args] } }