First Working Version #1

Merged
jusax23 merged 14 commits from dev into main 2023-02-14 23:33:55 +01:00
6 changed files with 168 additions and 77 deletions
Showing only changes of commit 6eae7f0fad - Show all commits

View file

@ -1,44 +1,65 @@
import mariadb from 'mariadb'; import mariadb from 'mariadb';
import { Datatype } from './dbStructure'; import { Datatype } from './dbStructure';
import { Handler } from './defaultHandler'; import { Handler } from './defaultHandler';
import { Query } from './query'; import { Query, selectQuery } from './query';
import { attributeSettings, onAction, primaryData } from './types'; import { attributeSettings, onAction, primaryData, serializeReturn } from './types';
export class DB { export class DB {
tables:Table[] = [];
handler: Handler;
//pool:mariadb.Pool; //pool:mariadb.Pool;
constructor(/*{ host, user, password, database, connectionLimit = 5 }*/) { constructor(/*{ host, user, password, database, connectionLimit = 5 }*/) {
//this.pool = mariadb.createPool({ host, user, password, database, connectionLimit, multipleStatements: true }); //this.pool = mariadb.createPool({ host, user, password, database, connectionLimit, multipleStatements: true });
this.handler = new Handler();
} }
async query(query: Query) { async query(query: Query) {
console.log(query);
//return this.pool.query(query); //return this.pool.query(query);
} }
getHandler() { getHandler() {
return Handler; return this.handler;
}
sync(){
let handler = this.getHandler();
this.tables.forEach(t=>{
console.log(handler.querys.create(handler,t));
})
} }
newTable(name: string) { newTable(name: string) {
return new Table(name); let tabel = new Table(name,this);
this.tables.push(tabel);
return tabel;
} }
} }
export class Attribute { export class Attribute {
name: string; name: string;
table: Table;
ops: attributeSettings; ops: attributeSettings;
type: Datatype; type: Datatype;
constructor(name: string, type: Datatype, ops: attributeSettings) { constructor(name: string, table:Table, type: Datatype, ops: attributeSettings) {
this.name = name; this.name = name;
this.ops = ops; this.ops = ops;
this.type = type; this.type = type;
this.table = table;
} }
serializeDatatype(){ serializeDatatype(handler : Handler){
return this.type.serialize(); return this.type.serialize(handler);
} }
serialize() { serializeSettings(handler : Handler){
return this.toString(); return handler.builders.attributeSettings(handler,this);
} }
toString() { serialize(handler : Handler) {
return this.name; return handler.builders.escapeID(this.name);
}
toString(handler : Handler = this.table.dbLangDatabaseInstance.getHandler()) {
return this.table.serialize(handler)+"."+this.serialize(handler);
}
toStringFunc(handler : Handler){
return this.table.serialize(handler)+"("+this.serialize(handler)+")";
} }
} }
@ -46,20 +67,22 @@ export class Attribute {
export class Table { export class Table {
dbLangTableName: string; dbLangTableName: string;
dbLangTableAttributes: { [key: string]: Attribute; } = {}; dbLangTableAttributes: { [key: string]: Attribute; } = {};
dbLangDatabaseInstance: DB;
[key: string]: Attribute | any [key: string]: Attribute | any
constructor(name: string) { constructor(name: string, table:DB) {
this.dbLangTableName = name; this.dbLangTableName = name;
this.dbLangDatabaseInstance = table;
} }
serialize() { serialize(handler : Handler) {
return this.toString(); return this.toString(handler);
} }
toString() { toString(handler : Handler = this.dbLangDatabaseInstance.getHandler()) {
return this.dbLangTableName; return handler.builders.escapeID(this.dbLangTableName);
} }
addAttribute(name: string, type: Datatype, ops: attributeSettings, noErrorOnNameConflict = false) { addAttribute(name: string, type: Datatype, ops: attributeSettings = {}, noErrorOnNameConflict = false) {
let attr = new Attribute(name,type,ops); let attr = new Attribute(name,this,type,ops);
this.dbLangTableAttributes[name] = attr; this.dbLangTableAttributes[name] = attr;
if (["serialize", "toString", "addAttribute", "dbLangTableName", "dbLangTableAttributes"].includes(name)) { if (["serialize", "toString", "addAttribute", "dbLangTableName", "dbLangTableAttributes", "dbLangDatabaseInstance"].includes(name)) {
if (!noErrorOnNameConflict) throw new Error("You cannot name Attribute like Methode of this Table!"); if (!noErrorOnNameConflict) throw new Error("You cannot name Attribute like Methode of this Table!");
} else { } else {
this[name] = attr; this[name] = attr;

View file

@ -9,7 +9,7 @@ export class Datatype{
this.type = type; this.type = type;
this.args = args; this.args = args;
} }
serialize(handler = Handler): serializeReturn{ serialize(handler : Handler): serializeReturn{
return handler.datatypes[this.type as keyof typeof handler.datatypes](this.args); return handler.datatypes[this.type as keyof typeof handler.datatypes](this.args);
} }
} }
@ -21,8 +21,8 @@ export abstract class Modifier {
this.t = type; this.t = type;
this.a = args; this.a = args;
} }
serialize(handler = Handler): serializeReturn { serialize(handler : Handler): serializeReturn {
return handler.modifiers[this.t as keyof typeof handler.modifiers](this.a); return handler.modifiers[this.t as keyof typeof handler.modifiers](handler,this.a);
} }
} }
@ -37,13 +37,13 @@ export class Aggregation {
this.t = type; this.t = type;
this.a = args; this.a = args;
} }
serialize(handler = Handler): serializeReturn { serialize(handler : Handler): serializeReturn {
return handler.aggregations[this.t as keyof typeof handler.aggregations](this.a); return handler.aggregations[this.t as keyof typeof handler.aggregations](handler,this.a);
} }
} }
export class Joins { export class Joins {
serialize(handler = Handler): serializeReturn { serialize(handler : Handler): serializeReturn {
return ["", []]; return ["", []];
} }
} }

View file

@ -1,26 +1,30 @@
import { Attribute } from "./db" import { Attribute, DB, Table } from "./db"
import { Aggregation, Modifier } from "./dbStructure" import { Aggregation, Modifier } from "./dbStructure"
import { selectQuery } from "./query" import { selectQuery } from "./query"
import { allModifierInput, primaryData, serializeReturn } from "./types" import { allModifierInput, primaryData, serializeReturn } from "./types"
export class Handler { export class Handler {
static querys = { syncDB(db : DB){
select: (q: selectQuery): serializeReturn => {
}
querys = {
select: (handler:Handler,q: selectQuery): serializeReturn => {
let args: primaryData[] = []; let args: primaryData[] = [];
let w = joinArg(", ", this)(q.attr); let w = joinArg(", ")(handler,q.attr);
args.push(...w[1]); args.push(...w[1]);
let sql = `select ${w[0]} from ${q.from == null ? 'DUAL' : q.from.serialize(this)}`; let sql = `select ${w[0]} from ${q.from == null ? 'DUAL' : q.from.serialize(handler)}`;
if (q.whereD) { if (q.whereD) {
let whereS = q.whereD.serialize(this); let whereS = q.whereD.serialize(handler);
args.push(...whereS[1]); args.push(...whereS[1]);
sql += " where " + whereS[0]; sql += " where " + whereS[0];
} }
if (q.groupByD.length > 0) { if (q.groupByD.length > 0) {
let groupByS = joinArg(",", this)(q.groupByD); let groupByS = joinArg(",")(handler,q.groupByD);
args.push(...groupByS[1]); args.push(...groupByS[1]);
sql += " group by " + groupByS[0]; sql += " group by " + groupByS[0];
if (q.havingD) { if (q.havingD) {
let havingS = q.havingD.serialize(this); let havingS = q.havingD.serialize(handler);
args.push(...havingS[1]); args.push(...havingS[1]);
sql += " having " + havingS[0]; sql += " having " + havingS[0];
} }
@ -30,35 +34,94 @@ export class Handler {
args.push(q.limitD); args.push(q.limitD);
} }
return [sql, args];
},
create:(handler:Handler,table: Table): serializeReturn=>{
let args:primaryData[] = [];
let sql = `create table if not exists ${table.toString(handler)}(
${Object.entries(table.dbLangTableAttributes).map(([_,a])=>{
let atype = a.serializeSettings(handler);
args.push(...(atype[1]));
return a.serialize(handler)+" "+atype[0];
}).join(",\n")}
)`;
return [sql,args]; return [sql,args];
} }
} }
static aggregations = {
count: (a: Attribute): serializeReturn => ["count(" + a + ")", []], builders = {
sum: (a: Attribute): serializeReturn => ["sum(" + a + ")", []], attributeSettings: (handler:Handler,a: Attribute): serializeReturn => {
avg: (a: Attribute): serializeReturn => ["avg(" + a + ")", []], let dtype = a.type.serialize(handler);
min: (a: Attribute): serializeReturn => ["min(" + a + ")", []], let sql = ""+dtype[0];
max: (a: Attribute): serializeReturn => ["max(" + a + ")", []], let args:primaryData[] = [...dtype[1]];
if (a.ops.autoIncrement) {
sql += " auto_increment";
}
if (a.ops.primaryKey) {
sql += " primary key";
}
if (a.ops.default != null) {
if (a.ops.autoIncrement || a.ops.primaryKey || a.ops.notNull)
throw new Error(`Can not set default when autoIncrement, primaryKey or notNull ist set on Attribute: ${a.toStringFunc(handler)}`);
sql += " default ?";
args.push(a.ops.default);
} }
static modifiers = { if (a.ops.unique != null) {
and: joinArg("and", this), if (!a.ops.autoIncrement && !a.ops.primaryKey){
or: joinArg("or", this), sql += " unique";
eq: joinArg("=", this), }
plus: joinArg("+", this), }
minus: joinArg("-", this), if (a.ops.notNull != null) {
not: (a: allModifierInput[]): serializeReturn => { if (!a.ops.autoIncrement && !a.ops.primaryKey && a.ops.default == null){
sql += " not null";
}
}
if (a.ops.foreginKey != null) {
sql += ` foreign key references (${a.ops.foreginKey.link.toStringFunc(handler)})`
}
return [sql, args];
},
escapeID: (key:string) :string =>{
if(!key || key === "" || key.includes('\u0000')) throw new Error("Can not escape empty key or with null unicode!");
if (key.match(/^`.+`$/g)) return key;
return `\`${key.replace(/`/g, '``')}\``;
}
}
aggregations = {
count: (handler:Handler,a: Attribute): serializeReturn => ["count(" + a.toString(handler) + ")", []],
sum: (handler:Handler,a: Attribute): serializeReturn => ["sum(" + a.toString(handler) + ")", []],
avg: (handler:Handler,a: Attribute): serializeReturn => ["avg(" + a.toString(handler) + ")", []],
min: (handler:Handler,a: Attribute): serializeReturn => ["min(" + a.toString(handler) + ")", []],
max: (handler:Handler,a: Attribute): serializeReturn => ["max(" + a.toString(handler) + ")", []],
}
modifiers = {
and: joinArg("and"),
or: joinArg("or"),
le: joinArg("<"),
leq: joinArg("<="),
eq: joinArg("="),
geq: joinArg(">="),
ge: joinArg(">"),
plus: joinArg("+"),
minus: joinArg("-"),
not: (handler:Handler,a: allModifierInput[]): serializeReturn => {
let e = a[0]; let e = a[0];
if (e instanceof Attribute) return ["not (" + e + ")", []]; if (e instanceof Attribute) return ["not (" + e.toString(handler) + ")", []];
if (e instanceof Modifier || e instanceof selectQuery || e instanceof Aggregation) { if (e instanceof Modifier || e instanceof selectQuery || e instanceof Aggregation) {
let [sqli, argsi] = e.serialize(this); let [sqli, argsi] = e.serialize(handler);
return ["not (" + sqli + ")", argsi] return ["not (" + sqli + ")", argsi]
} }
return ["not (?)", [e]]; return ["not (?)", [e]];
} }
} }
static datatypes = { datatypes = {
char: dataTypeSingleNum("char"), char: dataTypeSingleNum("char"),
varchar: dataTypeSingleNum("varchar"), varchar: dataTypeSingleNum("varchar"),
binary: dataTypeSingleNum("binary"), binary: dataTypeSingleNum("binary"),
@ -74,6 +137,7 @@ export class Handler {
longtext: dataTypeNoArg("longtext"), longtext: dataTypeNoArg("longtext"),
enum: (a: primaryData[]): serializeReturn => { enum: (a: primaryData[]): serializeReturn => {
console.log(a);
return ["enum(" + a.map(() => "?").join(", ") + ")", a]; return ["enum(" + a.map(() => "?").join(", ") + ")", a];
}, },
set: (a: primaryData[]): serializeReturn => { set: (a: primaryData[]): serializeReturn => {
@ -91,8 +155,8 @@ export class Handler {
double: dataTypeDblNum("double"), double: dataTypeDblNum("double"),
decimal: dataTypeDblNum("decimal"), decimal: dataTypeDblNum("decimal"),
data: dataTypeNoArg("data"), date: dataTypeNoArg("data"),
datatime: dataTypeNoArg("datatime"), datetime: dataTypeNoArg("datatime"),
timestamp: dataTypeNoArg("timestamp"), timestamp: dataTypeNoArg("timestamp"),
time: dataTypeNoArg("time"), time: dataTypeNoArg("time"),
year: dataTypeNoArg("year"), year: dataTypeNoArg("year"),
@ -117,13 +181,13 @@ function dataTypeDblNum(type:string){
} }
function joinArg(type: string, s: any) { function joinArg(type: string) {
return (a: (allModifierInput)[]): serializeReturn => { return (handler:Handler,a: (allModifierInput)[]): serializeReturn => {
let args: primaryData[] = []; let args: primaryData[] = [];
let sql = a.map(d => { let sql = a.map(d => {
if (d instanceof Attribute) return d; if (d instanceof Attribute) return d.toString(handler);
if (d instanceof Modifier || d instanceof selectQuery || d instanceof Aggregation) { if (d instanceof Modifier || d instanceof selectQuery || d instanceof Aggregation) {
let [sqli, argsi] = d.serialize(s); let [sqli, argsi] = d.serialize(handler);
args.push(...(argsi.flat(Infinity))); args.push(...(argsi.flat(Infinity)));
return "(" + sqli + ")"; return "(" + sqli + ")";
} }

View file

@ -6,7 +6,11 @@ import { allModifierInput, primaryData, selectElements, selectFromElements } fro
//modifiers //modifiers
export const and = (...args: (BooleanModifier)[]) => new BooleanModifier("and", args); export const and = (...args: (BooleanModifier)[]) => new BooleanModifier("and", args);
export const or = (...args: (BooleanModifier)[]) => new BooleanModifier("or", args); export const or = (...args: (BooleanModifier)[]) => new BooleanModifier("or", args);
export const ge = (...args: (allModifierInput)[]) => new BooleanModifier("ge", args);
export const geq = (...args: (allModifierInput)[]) => new BooleanModifier("geq", args);
export const eq = (...args: (allModifierInput)[]) => new BooleanModifier("eq", args); export const eq = (...args: (allModifierInput)[]) => new BooleanModifier("eq", args);
export const leq = (...args: (allModifierInput)[]) => new BooleanModifier("leq", args);
export const le = (...args: (allModifierInput)[]) => new BooleanModifier("le", args);
export const plus = (...args: (allModifierInput)[]) => new NumberModifier("plus", args); export const plus = (...args: (allModifierInput)[]) => new NumberModifier("plus", args);
export const minus = (...args: (allModifierInput)[]) => new NumberModifier("minus", args); export const minus = (...args: (allModifierInput)[]) => new NumberModifier("minus", args);
@ -38,8 +42,8 @@ export const TEXT = new Datatype("text",[]);
export const MEDIUMTEXT = new Datatype("mediumtext",[]); export const MEDIUMTEXT = new Datatype("mediumtext",[]);
export const LONGTEXT = new Datatype("longtext",[]); export const LONGTEXT = new Datatype("longtext",[]);
export const ENUM = (values:string[]) => new Datatype("enum",values); export const ENUM = (...values:string[]) => new Datatype("enum",values);
export const SET = (values:string[]) => new Datatype("set",values); export const SET = (...values:string[]) => new Datatype("set",values);
export const BOOL = new Datatype("bool",[]); export const BOOL = new Datatype("bool",[]);
export const BIT = new Datatype("bit",[]); export const BIT = new Datatype("bit",[]);
@ -53,8 +57,8 @@ export const FLOAT = (size:number,d:number) => new Datatype("float",[size,d]);
export const DOUBLE = (size:number,d:number) => new Datatype("double",[size,d]); export const DOUBLE = (size:number,d:number) => new Datatype("double",[size,d]);
export const DECIMAL = (size:number,d:number) => new Datatype("decimal",[size,d]); export const DECIMAL = (size:number,d:number) => new Datatype("decimal",[size,d]);
export const DATA = new Datatype("data",[]); export const DATE = new Datatype("date",[]);
export const DATATIME = new Datatype("datatime",[]); export const DATETIME = new Datatype("datetime",[]);
export const TIMESTAMP = new Datatype("timestamp",[]); export const TIMESTAMP = new Datatype("timestamp",[]);
export const TIME = new Datatype("time",[]); export const TIME = new Datatype("time",[]);
export const YEAR = new Datatype("year",[]); export const YEAR = new Datatype("year",[]);

View file

@ -41,12 +41,12 @@ export class selectQuery {
return this; return this;
} }
serialize(handler = Handler): serializeReturn { serialize(handler : Handler): serializeReturn {
return handler.querys.select(this); return handler.querys.select(handler,this);
} }
query(db: DB) { query(db: DB) {
const s = this.serialize(db.getHandler()); const s = this.serialize(db.getHandler());
return new Query(s[0], s[1]); return db.query(new Query(s[0], s[1]));
} }
} }

View file

@ -12,7 +12,7 @@ export type serializeReturn = [string, primaryData[]];
export type attributeSettings = { export type attributeSettings = {
unique?: boolean, unique?: boolean,
A_I?: boolean, autoIncrement?: boolean,
default?: primaryData, default?: primaryData,
notNull?: boolean notNull?: boolean
primaryKey?: boolean, primaryKey?: boolean,