First Working Version #1
6 changed files with 168 additions and 77 deletions
61
src/db.ts
61
src/db.ts
|
@ -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;
|
||||
|
|
|
@ -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 ["", []];
|
||||
}
|
||||
}
|
|
@ -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 + ")";
|
||||
}
|
||||
|
|
12
src/funcs.ts
12
src/funcs.ts
|
@ -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",[]);
|
|
@ -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]));
|
||||
}
|
||||
}
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue