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 { Datatype } from './dbStructure';
import { Handler } from './defaultHandler';
import { Query } from './query';
import { attributeSettings, onAction, primaryData } from './types';
import { Query, selectQuery } from './query';
import { attributeSettings, onAction, primaryData, serializeReturn } from './types';
export class DB {
tables:Table[] = [];
handler: Handler;
//pool:mariadb.Pool;
constructor(/*{ host, user, password, database, connectionLimit = 5 }*/) {
//this.pool = mariadb.createPool({ host, user, password, database, connectionLimit, multipleStatements: true });
this.handler = new Handler();
}
async query(query: Query) {
console.log(query);
//return this.pool.query(query);
}
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) {
return new Table(name);
let tabel = new Table(name,this);
this.tables.push(tabel);
return tabel;
}
}
export class Attribute {
name: string;
table: Table;
ops: attributeSettings;
type: Datatype;
constructor(name: string, type: Datatype, ops: attributeSettings) {
constructor(name: string, table:Table, type: Datatype, ops: attributeSettings) {
this.name = name;
this.ops = ops;
this.type = type;
this.table = table;
}
serializeDatatype(){
return this.type.serialize();
serializeDatatype(handler : Handler){
return this.type.serialize(handler);
}
serialize() {
return this.toString();
serializeSettings(handler : Handler){
return handler.builders.attributeSettings(handler,this);
}
toString() {
return this.name;
serialize(handler : Handler) {
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 {
dbLangTableName: string;
dbLangTableAttributes: { [key: string]: Attribute; } = {};
dbLangDatabaseInstance: DB;
[key: string]: Attribute | any
constructor(name: string) {
constructor(name: string, table:DB) {
this.dbLangTableName = name;
this.dbLangDatabaseInstance = table;
}
serialize() {
return this.toString();
serialize(handler : Handler) {
return this.toString(handler);
}
toString() {
return this.dbLangTableName;
toString(handler : Handler = this.dbLangDatabaseInstance.getHandler()) {
return handler.builders.escapeID(this.dbLangTableName);
}
addAttribute(name: string, type: Datatype, ops: attributeSettings, noErrorOnNameConflict = false) {
let attr = new Attribute(name,type,ops);
addAttribute(name: string, type: Datatype, ops: attributeSettings = {}, noErrorOnNameConflict = false) {
let attr = new Attribute(name,this,type,ops);
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!");
} else {
this[name] = attr;

View file

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

View file

@ -1,26 +1,30 @@
import { Attribute } from "./db"
import { Attribute, DB, Table } 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 => {
syncDB(db : DB){
}
querys = {
select: (handler:Handler,q: selectQuery): serializeReturn => {
let args: primaryData[] = [];
let w = joinArg(", ", this)(q.attr);
let w = joinArg(", ")(handler,q.attr);
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) {
let whereS = q.whereD.serialize(this);
let whereS = q.whereD.serialize(handler);
args.push(...whereS[1]);
sql += " where " + whereS[0];
}
if (q.groupByD.length > 0) {
let groupByS = joinArg(",", this)(q.groupByD);
let groupByS = joinArg(",")(handler,q.groupByD);
args.push(...groupByS[1]);
sql += " group by " + groupByS[0];
if (q.havingD) {
let havingS = q.havingD.serialize(this);
let havingS = q.havingD.serialize(handler);
args.push(...havingS[1]);
sql += " having " + havingS[0];
}
@ -30,35 +34,94 @@ export class Handler {
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];
}
}
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 + ")", []],
builders = {
attributeSettings: (handler:Handler,a: Attribute): serializeReturn => {
let dtype = a.type.serialize(handler);
let sql = ""+dtype[0];
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 = {
and: joinArg("and", this),
or: joinArg("or", this),
eq: joinArg("=", this),
plus: joinArg("+", this),
minus: joinArg("-", this),
not: (a: allModifierInput[]): serializeReturn => {
if (a.ops.unique != null) {
if (!a.ops.autoIncrement && !a.ops.primaryKey){
sql += " unique";
}
}
if (a.ops.notNull != null) {
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];
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) {
let [sqli, argsi] = e.serialize(this);
let [sqli, argsi] = e.serialize(handler);
return ["not (" + sqli + ")", argsi]
}
return ["not (?)", [e]];
}
}
static datatypes = {
datatypes = {
char: dataTypeSingleNum("char"),
varchar: dataTypeSingleNum("varchar"),
binary: dataTypeSingleNum("binary"),
@ -74,6 +137,7 @@ export class Handler {
longtext: dataTypeNoArg("longtext"),
enum: (a: primaryData[]): serializeReturn => {
console.log(a);
return ["enum(" + a.map(() => "?").join(", ") + ")", a];
},
set: (a: primaryData[]): serializeReturn => {
@ -91,8 +155,8 @@ export class Handler {
double: dataTypeDblNum("double"),
decimal: dataTypeDblNum("decimal"),
data: dataTypeNoArg("data"),
datatime: dataTypeNoArg("datatime"),
date: dataTypeNoArg("data"),
datetime: dataTypeNoArg("datatime"),
timestamp: dataTypeNoArg("timestamp"),
time: dataTypeNoArg("time"),
year: dataTypeNoArg("year"),
@ -117,13 +181,13 @@ function dataTypeDblNum(type:string){
}
function joinArg(type: string, s: any) {
return (a: (allModifierInput)[]): serializeReturn => {
function joinArg(type: string) {
return (handler:Handler,a: (allModifierInput)[]): serializeReturn => {
let args: primaryData[] = [];
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) {
let [sqli, argsi] = d.serialize(s);
let [sqli, argsi] = d.serialize(handler);
args.push(...(argsi.flat(Infinity)));
return "(" + sqli + ")";
}

View file

@ -6,7 +6,11 @@ import { allModifierInput, primaryData, selectElements, selectFromElements } fro
//modifiers
export const and = (...args: (BooleanModifier)[]) => new BooleanModifier("and", 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 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 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 LONGTEXT = new Datatype("longtext",[]);
export const ENUM = (values:string[]) => new Datatype("enum",values);
export const SET = (values:string[]) => new Datatype("set",values);
export const ENUM = (...values:string[]) => new Datatype("enum",values);
export const SET = (...values:string[]) => new Datatype("set",values);
export const BOOL = new Datatype("bool",[]);
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 DECIMAL = (size:number,d:number) => new Datatype("decimal",[size,d]);
export const DATA = new Datatype("data",[]);
export const DATATIME = new Datatype("datatime",[]);
export const DATE = new Datatype("date",[]);
export const DATETIME = new Datatype("datetime",[]);
export const TIMESTAMP = new Datatype("timestamp",[]);
export const TIME = new Datatype("time",[]);
export const YEAR = new Datatype("year",[]);

View file

@ -41,12 +41,12 @@ export class selectQuery {
return this;
}
serialize(handler = Handler): serializeReturn {
return handler.querys.select(this);
serialize(handler : Handler): serializeReturn {
return handler.querys.select(handler,this);
}
query(db: DB) {
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 = {
unique?: boolean,
A_I?: boolean,
autoIncrement?: boolean,
default?: primaryData,
notNull?: boolean
primaryKey?: boolean,