First Working Version #1
7 changed files with 300 additions and 108 deletions
|
@ -12,7 +12,6 @@ pipeline:
|
||||||
- mkdir dblang
|
- mkdir dblang
|
||||||
- mkdir upload
|
- mkdir upload
|
||||||
- npm run prepublish
|
- npm run prepublish
|
||||||
- ls dist
|
|
||||||
- cp dist/* dblang
|
- cp dist/* dblang
|
||||||
- zip -r upload/DBlang.zip dblang/*
|
- zip -r upload/DBlang.zip dblang/*
|
||||||
- tar -czvf upload/DBlang.tar.gz dblang/*
|
- tar -czvf upload/DBlang.tar.gz dblang/*
|
||||||
|
|
38
src/db.ts
38
src/db.ts
|
@ -1,17 +1,19 @@
|
||||||
import mariadb from 'mariadb';
|
import mariadb from 'mariadb';
|
||||||
import { Datatype } from './dbStructure';
|
import { checkConstraint, Constraint, Datatype, uniqueConstraint } from './dbStructure';
|
||||||
import { Handler } from './defaultHandler';
|
import { Handler } from './defaultHandler';
|
||||||
import { Query, selectQuery } from './query';
|
import { Query, selectQuery } from './query';
|
||||||
import { attributeSettings, onAction, primaryData, serializeReturn } from './types';
|
import { attributeSettings, extendedAttributeSettings, onAction, primaryData, serializeReturn } from './types';
|
||||||
|
|
||||||
|
|
||||||
export class DB {
|
export class DB {
|
||||||
tables:Table[] = [];
|
tables:Table[] = [];
|
||||||
handler: Handler;
|
handler: Handler;
|
||||||
|
name: string;
|
||||||
//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();
|
this.handler = new Handler();
|
||||||
|
this.name = "notimplemented"
|
||||||
}
|
}
|
||||||
async query(query: Query) {
|
async query(query: Query) {
|
||||||
console.log(query);
|
console.log(query);
|
||||||
|
@ -24,7 +26,7 @@ export class DB {
|
||||||
sync(){
|
sync(){
|
||||||
let handler = this.getHandler();
|
let handler = this.getHandler();
|
||||||
this.tables.forEach(t=>{
|
this.tables.forEach(t=>{
|
||||||
console.log(handler.querys.create(handler,t));
|
console.log(new Query(handler.builders.query(handler.querys.create(handler,t))));
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,6 +47,19 @@ export class Attribute {
|
||||||
this.ops = ops;
|
this.ops = ops;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.table = table;
|
this.table = table;
|
||||||
|
|
||||||
|
if(ops.check != null){
|
||||||
|
table.addConstraint(new checkConstraint(
|
||||||
|
table.dbLangDatabaseInstance.name+"_"+table.dbLangTableName+"_"+name+"_check_constraint",
|
||||||
|
ops.check
|
||||||
|
))
|
||||||
|
}
|
||||||
|
if(ops.unique != null){
|
||||||
|
table.addConstraint(new uniqueConstraint(
|
||||||
|
table.dbLangDatabaseInstance.name+"_"+table.dbLangTableName+" "+name+"_unique_constraint",
|
||||||
|
[this]
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
serializeDatatype(handler : Handler){
|
serializeDatatype(handler : Handler){
|
||||||
return this.type.serialize(handler);
|
return this.type.serialize(handler);
|
||||||
|
@ -68,10 +83,11 @@ export class Table {
|
||||||
dbLangTableName: string;
|
dbLangTableName: string;
|
||||||
dbLangTableAttributes: { [key: string]: Attribute; } = {};
|
dbLangTableAttributes: { [key: string]: Attribute; } = {};
|
||||||
dbLangDatabaseInstance: DB;
|
dbLangDatabaseInstance: DB;
|
||||||
|
dbLangConstrains: Constraint[] = [];
|
||||||
[key: string]: Attribute | any
|
[key: string]: Attribute | any
|
||||||
constructor(name: string, table:DB) {
|
constructor(name: string, db:DB) {
|
||||||
this.dbLangTableName = name;
|
this.dbLangTableName = name;
|
||||||
this.dbLangDatabaseInstance = table;
|
this.dbLangDatabaseInstance = db;
|
||||||
}
|
}
|
||||||
serialize(handler : Handler) {
|
serialize(handler : Handler) {
|
||||||
return this.toString(handler);
|
return this.toString(handler);
|
||||||
|
@ -80,15 +96,25 @@ export class Table {
|
||||||
return handler.builders.escapeID(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) {
|
||||||
|
if(this.dbLangTableAttributes[name] != null) throw new Error("You are tring to create an Attribute twise!");
|
||||||
let attr = new Attribute(name,this,type,ops);
|
let attr = new Attribute(name,this,type,ops);
|
||||||
this.dbLangTableAttributes[name] = attr;
|
this.dbLangTableAttributes[name] = attr;
|
||||||
if (["serialize", "toString", "addAttribute", "dbLangTableName", "dbLangTableAttributes", "dbLangDatabaseInstance"].includes(name)) {
|
if (["serialize", "toString", "addAttribute", "dbLangTableName", "dbLangTableAttributes", "dbLangDatabaseInstance","addConstraint","addAttributes"].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;
|
||||||
}
|
}
|
||||||
return attr;
|
return attr;
|
||||||
}
|
}
|
||||||
|
addAttributes(list:{[key: string]:extendedAttributeSettings}):{[key: string]:Attribute} {
|
||||||
|
return Object.fromEntries(Object.entries(list).map(([k,a])=>{
|
||||||
|
return [k,this.addAttribute(k,a.type,a)];
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
addConstraint(c:Constraint){
|
||||||
|
c.check(this);
|
||||||
|
this.dbLangConstrains.push(c);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export * from './funcs';
|
export * from './funcs';
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { Attribute } from "./db";
|
import { Attribute, Table } from "./db";
|
||||||
import { Handler } from "./defaultHandler";
|
import { Handler } from "./defaultHandler";
|
||||||
|
import { QueryBuilder } from "./query";
|
||||||
import { allModifierInput, primaryData, serializeReturn } from "./types";
|
import { allModifierInput, primaryData, serializeReturn } from "./types";
|
||||||
|
|
||||||
export class Datatype{
|
export class Datatype{
|
||||||
|
@ -9,7 +10,7 @@ export class Datatype{
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.args = args;
|
this.args = args;
|
||||||
}
|
}
|
||||||
serialize(handler : Handler): serializeReturn{
|
serialize(handler : Handler): QueryBuilder{
|
||||||
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,7 +22,7 @@ export abstract class Modifier {
|
||||||
this.t = type;
|
this.t = type;
|
||||||
this.a = args;
|
this.a = args;
|
||||||
}
|
}
|
||||||
serialize(handler : Handler): serializeReturn {
|
serialize(handler : Handler): QueryBuilder {
|
||||||
return handler.modifiers[this.t as keyof typeof handler.modifiers](handler,this.a);
|
return handler.modifiers[this.t as keyof typeof handler.modifiers](handler,this.a);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,13 +38,60 @@ export class Aggregation {
|
||||||
this.t = type;
|
this.t = type;
|
||||||
this.a = args;
|
this.a = args;
|
||||||
}
|
}
|
||||||
serialize(handler : Handler): serializeReturn {
|
serialize(handler : Handler): QueryBuilder {
|
||||||
return handler.aggregations[this.t as keyof typeof handler.aggregations](handler,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): QueryBuilder {
|
||||||
return ["", []];
|
return new QueryBuilder();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Constraint{
|
||||||
|
name:string;
|
||||||
|
serialize( handler: Handler) : QueryBuilder;
|
||||||
|
uses(attr:Attribute): boolean;
|
||||||
|
check(attr:Table): boolean | string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class checkConstraint implements Constraint{
|
||||||
|
checkQuery:BooleanModifier;
|
||||||
|
name: string;
|
||||||
|
constructor(name:string, check: BooleanModifier){
|
||||||
|
this.name = name;
|
||||||
|
this.checkQuery = check;
|
||||||
|
}
|
||||||
|
check(attr: Table): boolean {
|
||||||
|
throw new Error("Method not implemented.");
|
||||||
|
}
|
||||||
|
uses(attr: Attribute): boolean {
|
||||||
|
throw new Error("Method not implemented.");
|
||||||
|
}
|
||||||
|
serialize(handler: Handler): QueryBuilder {
|
||||||
|
throw new Error("Method not implemented.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class uniqueConstraint implements Constraint{
|
||||||
|
name: string;
|
||||||
|
attr: Attribute[];
|
||||||
|
constructor(name:string, attr:Attribute[]){
|
||||||
|
this.name = name;
|
||||||
|
this.attr = attr;
|
||||||
|
}
|
||||||
|
check(table: Table): boolean|string {
|
||||||
|
for(let i = 0; i < this.attr.length; i++){
|
||||||
|
if(this.attr[i].ops.primaryKey) return "Can not combine unique Constraint and primary key";
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
uses(attr: Attribute): boolean {
|
||||||
|
throw new Error("Method not implemented.");
|
||||||
|
}
|
||||||
|
serialize(handler: Handler): QueryBuilder {
|
||||||
|
throw new Error("Method not implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,92 +1,123 @@
|
||||||
import { Attribute, DB, Table } from "./db"
|
import { Attribute, DB, Table } from "./db"
|
||||||
import { Aggregation, Modifier } from "./dbStructure"
|
import { Aggregation, Modifier } from "./dbStructure"
|
||||||
import { selectQuery } from "./query"
|
import { QueryBuilder, selectQuery } from "./query"
|
||||||
import { allModifierInput, primaryData, serializeReturn } from "./types"
|
import { allModifierInput, primaryData, serializeReturn } from "./types"
|
||||||
|
|
||||||
export class Handler {
|
export class Handler {
|
||||||
syncDB(db : DB){
|
/*syncDB(db : DB){
|
||||||
|
|
||||||
}
|
}*/
|
||||||
|
|
||||||
querys = {
|
querys = {
|
||||||
select: (handler:Handler,q: selectQuery): serializeReturn => {
|
select: (handler: Handler, q: selectQuery): QueryBuilder => {
|
||||||
let args: primaryData[] = [];
|
const builder = new QueryBuilder();
|
||||||
let w = joinArg(", ")(handler,q.attr);
|
builder.addCode("select ");
|
||||||
args.push(...w[1]);
|
builder.append(joinArg(", ")(handler, q.attr));
|
||||||
let sql = `select ${w[0]} from ${q.from == null ? 'DUAL' : q.from.serialize(handler)}`;
|
builder.addCode(` from ${q.from == null ? 'DUAL' : q.from.serialize(handler)}`);
|
||||||
if (q.whereD) {
|
if (q.whereD) {
|
||||||
let whereS = q.whereD.serialize(handler);
|
builder.addCode(" where ");
|
||||||
args.push(...whereS[1]);
|
builder.append(q.whereD.serialize(handler));
|
||||||
sql += " where " + whereS[0];
|
|
||||||
}
|
}
|
||||||
if (q.groupByD.length > 0) {
|
if (q.groupByD.length > 0) {
|
||||||
let groupByS = joinArg(",")(handler,q.groupByD);
|
builder.addCode(" group by ");
|
||||||
args.push(...groupByS[1]);
|
builder.append(joinArg(",")(handler, q.groupByD));
|
||||||
sql += " group by " + groupByS[0];
|
|
||||||
if (q.havingD) {
|
if (q.havingD) {
|
||||||
let havingS = q.havingD.serialize(handler);
|
builder.addCode(" having ");
|
||||||
args.push(...havingS[1]);
|
builder.append(q.havingD.serialize(handler));
|
||||||
sql += " having " + havingS[0];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (q.limitD != null) {
|
|
||||||
sql += " limit ?";
|
|
||||||
args.push(q.limitD);
|
|
||||||
}
|
|
||||||
|
|
||||||
return [sql, args];
|
if (q.havingD) {
|
||||||
|
builder.addCode(" limit ");
|
||||||
|
builder.addInjection(q.limitD);
|
||||||
|
}
|
||||||
|
return builder;
|
||||||
},
|
},
|
||||||
create:(handler:Handler,table: Table): serializeReturn=>{
|
create: (handler: Handler, table: Table): QueryBuilder => {
|
||||||
let args:primaryData[] = [];
|
const builder = new QueryBuilder();
|
||||||
let sql = `create table if not exists ${table.toString(handler)}(
|
builder.addCode(`create table if not exists ${table.toString(handler)}(`);
|
||||||
${Object.entries(table.dbLangTableAttributes).map(([_,a])=>{
|
let keys = Object.keys(table.dbLangTableAttributes);
|
||||||
let atype = a.serializeSettings(handler);
|
for (let i = 0; i < keys.length; i++) {
|
||||||
args.push(...(atype[1]));
|
const a = table.dbLangTableAttributes[keys[i]];
|
||||||
return a.serialize(handler)+" "+atype[0];
|
builder.addCode(a.serialize(handler) + " ");
|
||||||
}).join(",\n")}
|
builder.append(a.serializeSettings(handler));
|
||||||
)`;
|
if (i + 1 < keys.length) builder.addCode(", ");
|
||||||
return [sql,args];
|
}
|
||||||
}
|
builder.addCode(")");
|
||||||
|
return builder;
|
||||||
|
},
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constraints = {
|
||||||
|
// check constraints
|
||||||
|
listPrimaryKeys: (handler: Handler, table: Table): QueryBuilder => new QueryBuilder(),
|
||||||
|
listForeignKeys: (handler: Handler, table: Table): QueryBuilder => new QueryBuilder(),
|
||||||
|
listUniqueKeys: (handler: Handler, table: Table): QueryBuilder => new QueryBuilder(),
|
||||||
|
listChecks: (handler: Handler, table: Table): QueryBuilder => new QueryBuilder(),
|
||||||
|
// add constraints
|
||||||
|
appPrimaryKeys: (handler: Handler, table: Table): QueryBuilder => new QueryBuilder(),
|
||||||
|
appForeignKeys: (handler: Handler, table: Table): QueryBuilder => new QueryBuilder(),
|
||||||
|
addUniqueKeys: (handler: Handler, table: Table): QueryBuilder => new QueryBuilder(),
|
||||||
|
addChecks: (handler: Handler, table: Table): QueryBuilder => new QueryBuilder(),
|
||||||
|
//should drop all keys to be able to recreate them
|
||||||
|
dropPrimaryKeys: (handler: Handler, table: Table): QueryBuilder => new QueryBuilder(),
|
||||||
|
dropForeignKeys: (handler: Handler, table: Table): QueryBuilder => new QueryBuilder(),
|
||||||
|
dropUniqueKeys: (handler: Handler, table: Table): QueryBuilder => new QueryBuilder(),
|
||||||
|
dropChecks: (handler: Handler, table: Table): QueryBuilder => new QueryBuilder(),
|
||||||
|
}
|
||||||
|
|
||||||
builders = {
|
builders = {
|
||||||
attributeSettings: (handler:Handler,a: Attribute): serializeReturn => {
|
query: (qb: QueryBuilder): serializeReturn => {
|
||||||
let dtype = a.type.serialize(handler);
|
let args: primaryData[] = [];
|
||||||
let sql = ""+dtype[0];
|
let sql = "";
|
||||||
let args:primaryData[] = [...dtype[1]];
|
for (let i = 0; i < qb.list.length; i++) {
|
||||||
|
const [inject, data] = qb.list[i];
|
||||||
|
if (inject) {
|
||||||
|
sql += "?";
|
||||||
|
args.push(data);
|
||||||
|
} else {
|
||||||
|
sql += data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [sql, args];
|
||||||
|
},
|
||||||
|
|
||||||
|
attributeSettings: (handler: Handler, a: Attribute): QueryBuilder => {
|
||||||
|
const builder = new QueryBuilder();
|
||||||
|
builder.append(a.type.serialize(handler));
|
||||||
if (a.ops.autoIncrement) {
|
if (a.ops.autoIncrement) {
|
||||||
sql += " auto_increment";
|
builder.addCode(" auto_increment");
|
||||||
}
|
}
|
||||||
if (a.ops.primaryKey) {
|
/*if (a.ops.primaryKey) {
|
||||||
sql += " primary key";
|
sql += " primary key";
|
||||||
}
|
}*/
|
||||||
if (a.ops.default != null) {
|
if (a.ops.default != null) {
|
||||||
if (a.ops.autoIncrement || a.ops.primaryKey || a.ops.notNull)
|
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)}`);
|
throw new Error(`Can not set default when autoIncrement, primaryKey or notNull ist set on Attribute: ${a.toStringFunc(handler)}`);
|
||||||
sql += " default ?";
|
builder.addCode(" default ");
|
||||||
args.push(a.ops.default);
|
builder.addInjection(a.ops.default);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a.ops.unique != null) {
|
/*if (a.ops.unique != null) {
|
||||||
if (!a.ops.autoIncrement && !a.ops.primaryKey){
|
if (!a.ops.autoIncrement && !a.ops.primaryKey){
|
||||||
sql += " unique";
|
sql += " unique";
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
if (a.ops.notNull != null) {
|
if (a.ops.notNull != null) {
|
||||||
if (!a.ops.autoIncrement && !a.ops.primaryKey && a.ops.default == null){
|
if (!a.ops.autoIncrement && !a.ops.primaryKey && a.ops.default == null) {
|
||||||
sql += " not null";
|
builder.addCode(" not null");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a.ops.foreginKey != null) {
|
/*if (a.ops.foreginKey != null) {
|
||||||
sql += ` foreign key references (${a.ops.foreginKey.link.toStringFunc(handler)})`
|
sql += ` foreign key references (${a.ops.foreginKey.link.toStringFunc(handler)})`
|
||||||
}
|
}*/
|
||||||
|
|
||||||
return [sql, args];
|
return builder;
|
||||||
},
|
},
|
||||||
escapeID: (key:string) :string =>{
|
escapeID: (key: string): string => {
|
||||||
if(!key || key === "" || key.includes('\u0000')) throw new Error("Can not escape empty key or with null unicode!");
|
if (!key || key === "" || key.includes('\u0000')) throw new Error("Can not escape empty key or with null unicode!");
|
||||||
if (key.match(/^`.+`$/g)) return key;
|
if (key.match(/^`.+`$/g)) return key;
|
||||||
return `\`${key.replace(/`/g, '``')}\``;
|
return `\`${key.replace(/`/g, '``')}\``;
|
||||||
}
|
}
|
||||||
|
@ -94,11 +125,11 @@ ${Object.entries(table.dbLangTableAttributes).map(([_,a])=>{
|
||||||
|
|
||||||
|
|
||||||
aggregations = {
|
aggregations = {
|
||||||
count: (handler:Handler,a: Attribute): serializeReturn => ["count(" + a.toString(handler) + ")", []],
|
count: (handler: Handler, a: Attribute): QueryBuilder => new QueryBuilder([{ data: "count(" + a.toString(handler) + ")" }]),
|
||||||
sum: (handler:Handler,a: Attribute): serializeReturn => ["sum(" + a.toString(handler) + ")", []],
|
sum: (handler: Handler, a: Attribute): QueryBuilder => new QueryBuilder([{ data: "sum(" + a.toString(handler) + ")" }]),
|
||||||
avg: (handler:Handler,a: Attribute): serializeReturn => ["avg(" + a.toString(handler) + ")", []],
|
avg: (handler: Handler, a: Attribute): QueryBuilder => new QueryBuilder([{ data: "avg(" + a.toString(handler) + ")" }]),
|
||||||
min: (handler:Handler,a: Attribute): serializeReturn => ["min(" + a.toString(handler) + ")", []],
|
min: (handler: Handler, a: Attribute): QueryBuilder => new QueryBuilder([{ data: "min(" + a.toString(handler) + ")" }]),
|
||||||
max: (handler:Handler,a: Attribute): serializeReturn => ["max(" + a.toString(handler) + ")", []],
|
max: (handler: Handler, a: Attribute): QueryBuilder => new QueryBuilder([{ data: "max(" + a.toString(handler) + ")" }]),
|
||||||
}
|
}
|
||||||
|
|
||||||
modifiers = {
|
modifiers = {
|
||||||
|
@ -111,14 +142,21 @@ ${Object.entries(table.dbLangTableAttributes).map(([_,a])=>{
|
||||||
ge: joinArg(">"),
|
ge: joinArg(">"),
|
||||||
plus: joinArg("+"),
|
plus: joinArg("+"),
|
||||||
minus: joinArg("-"),
|
minus: joinArg("-"),
|
||||||
not: (handler:Handler,a: allModifierInput[]): serializeReturn => {
|
not: (handler: Handler, a: allModifierInput[]): QueryBuilder => {
|
||||||
let e = a[0];
|
let e = a[0];
|
||||||
if (e instanceof Attribute) return ["not (" + e.toString(handler) + ")", []];
|
if (e instanceof Attribute) return new QueryBuilder([{ data: "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(handler);
|
const builder = new QueryBuilder();
|
||||||
return ["not (" + sqli + ")", argsi]
|
builder.addCode("not (");
|
||||||
|
builder.append(e.serialize(handler));
|
||||||
|
builder.addCode(")");
|
||||||
|
return builder;
|
||||||
}
|
}
|
||||||
return ["not (?)", [e]];
|
return new QueryBuilder([
|
||||||
|
{ data: "not(" },
|
||||||
|
{ inject: true, data: e },
|
||||||
|
{ data: ")" }
|
||||||
|
])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
datatypes = {
|
datatypes = {
|
||||||
|
@ -136,12 +174,19 @@ ${Object.entries(table.dbLangTableAttributes).map(([_,a])=>{
|
||||||
mediumtext: dataTypeNoArg("mediumtext"),
|
mediumtext: dataTypeNoArg("mediumtext"),
|
||||||
longtext: dataTypeNoArg("longtext"),
|
longtext: dataTypeNoArg("longtext"),
|
||||||
|
|
||||||
enum: (a: primaryData[]): serializeReturn => {
|
enum: (a: primaryData[]): QueryBuilder => {
|
||||||
console.log(a);
|
const builder = new QueryBuilder();
|
||||||
return ["enum(" + a.map(() => "?").join(", ") + ")", a];
|
builder.addCode("enum(");
|
||||||
|
builder.addInjectionCommaSeperated(a);
|
||||||
|
builder.addCode(")");
|
||||||
|
return builder;
|
||||||
},
|
},
|
||||||
set: (a: primaryData[]): serializeReturn => {
|
set: (a: primaryData[]): QueryBuilder => {
|
||||||
return ["set(" + a.map(() => "?").join(", ") + ")", a];
|
const builder = new QueryBuilder();
|
||||||
|
builder.addCode("set(");
|
||||||
|
builder.addInjectionCommaSeperated(a);
|
||||||
|
builder.addCode(")");
|
||||||
|
return builder;
|
||||||
},
|
},
|
||||||
bool: dataTypeNoArg("bool"),
|
bool: dataTypeNoArg("bool"),
|
||||||
bit: dataTypeNoArg("bit"),
|
bit: dataTypeNoArg("bit"),
|
||||||
|
@ -165,36 +210,50 @@ ${Object.entries(table.dbLangTableAttributes).map(([_,a])=>{
|
||||||
};
|
};
|
||||||
|
|
||||||
function dataTypeNoArg(type: string) {
|
function dataTypeNoArg(type: string) {
|
||||||
return (a: primaryData[]): serializeReturn => {
|
return (a: primaryData[]): QueryBuilder => {
|
||||||
return [type, []];
|
return new QueryBuilder([{
|
||||||
|
inject: false,
|
||||||
|
data: type
|
||||||
|
}]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function dataTypeSingleNum(type: string) {
|
function dataTypeSingleNum(type: string) {
|
||||||
return (a: primaryData[]): serializeReturn => {
|
return (a: primaryData[]): QueryBuilder => {
|
||||||
return [type + "(?)", [a[0]]];
|
return new QueryBuilder([
|
||||||
|
{ data: type + "(" },
|
||||||
|
{ inject: true, data: a[0] },
|
||||||
|
{ data: ")" }
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function dataTypeDblNum(type: string) {
|
function dataTypeDblNum(type: string) {
|
||||||
return (a: primaryData[]): serializeReturn => {
|
return (a: primaryData[]): QueryBuilder => {
|
||||||
return [type + "(?,?)", [a[0], a[1]]];
|
return new QueryBuilder([
|
||||||
|
{ data: type + "(" },
|
||||||
|
{ inject: true, data: a[0] },
|
||||||
|
{ data: ", " },
|
||||||
|
{ inject: true, data: a[1] },
|
||||||
|
{ data: ")" }
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function joinArg(type: string) {
|
function joinArg(type: string) {
|
||||||
return (handler:Handler,a: (allModifierInput)[]): serializeReturn => {
|
return (handler: Handler, a: (allModifierInput)[]): QueryBuilder => {
|
||||||
let args: primaryData[] = [];
|
const builder = new QueryBuilder();
|
||||||
let sql = a.map(d => {
|
for (let i = 0; i < a.length; i++) {
|
||||||
if (d instanceof Attribute) return d.toString(handler);
|
const d = a[i];
|
||||||
if (d instanceof Modifier || d instanceof selectQuery || d instanceof Aggregation) {
|
if (d instanceof Attribute) builder.addCode(d.toString(handler));
|
||||||
let [sqli, argsi] = d.serialize(handler);
|
else if (d instanceof Modifier || d instanceof selectQuery || d instanceof Aggregation) {
|
||||||
args.push(...(argsi.flat(Infinity)));
|
builder.addCode("(");
|
||||||
return "(" + sqli + ")";
|
builder.append(d.serialize(handler));
|
||||||
|
builder.addCode(")");
|
||||||
|
} else {
|
||||||
|
builder.addInjection(d);
|
||||||
}
|
}
|
||||||
args.push(d);
|
if (i + 1 < a.length) builder.addCode(" " + type + " ");
|
||||||
return "?";
|
}
|
||||||
}).join(" " + type + " ");
|
return builder;
|
||||||
return [sql, args]
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
19
src/funcs.ts
19
src/funcs.ts
|
@ -1,5 +1,5 @@
|
||||||
import { Attribute } from "./db";
|
import { Attribute } from "./db";
|
||||||
import { Aggregation, BooleanModifier, Datatype, NumberModifier } from "./dbStructure";
|
import { Aggregation, BooleanModifier, checkConstraint, Datatype, NumberModifier } from "./dbStructure";
|
||||||
import { selectQuery } from "./query";
|
import { selectQuery } from "./query";
|
||||||
import { allModifierInput, primaryData, selectElements, selectFromElements } from "./types";
|
import { allModifierInput, primaryData, selectElements, selectFromElements } from "./types";
|
||||||
|
|
||||||
|
@ -61,4 +61,19 @@ export const DATE = new Datatype("date",[]);
|
||||||
export const DATETIME = new Datatype("datetime",[]);
|
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",[]);
|
||||||
|
|
||||||
|
// Constraints
|
||||||
|
//TODO:
|
||||||
|
//primary key
|
||||||
|
export const foreginKey = (attrs:Attribute[],target:Attribute[])=>{};
|
||||||
|
export const uniqueKey = (attr:Attribute[])=>{};
|
||||||
|
export const check = (name:string,mod:BooleanModifier)=>new checkConstraint(name,mod);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* primary key: kein richtiger Constraint -> renew = drop
|
||||||
|
* foreign key: ?
|
||||||
|
* unique: richtiger Constraint -> achtung manchmal nicht entfernabr
|
||||||
|
* check: richtiger Constraint
|
||||||
|
*/
|
40
src/query.ts
40
src/query.ts
|
@ -7,12 +7,41 @@ import { primaryData, selectElements, selectFromElements, serializeReturn } from
|
||||||
export class Query {
|
export class Query {
|
||||||
sql: string;
|
sql: string;
|
||||||
values: primaryData[];
|
values: primaryData[];
|
||||||
constructor(sql: string, values: primaryData[]) {
|
constructor([sql, values]:serializeReturn) {
|
||||||
this.sql = sql;
|
this.sql = sql;
|
||||||
this.values = values;
|
this.values = values;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class QueryBuilder {
|
||||||
|
//injekt and data
|
||||||
|
list: ([boolean, primaryData])[] = [];
|
||||||
|
constructor(l?: ({ inject?: boolean, data: primaryData })[]) {
|
||||||
|
if (Array.isArray(l))
|
||||||
|
for (let i = 0; i < l.length; i++) {
|
||||||
|
const e = l[i];
|
||||||
|
this.list.push([e.inject ? true : false, e.data]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addCode(text: string) {
|
||||||
|
this.list.push([false, text]);
|
||||||
|
}
|
||||||
|
addInjection(data: primaryData) {
|
||||||
|
this.list.push([true, data]);
|
||||||
|
}
|
||||||
|
addInjectionCommaSeperated(data: primaryData[], comma = ", ") {
|
||||||
|
for (let i = 0; i < data.length; i++) {
|
||||||
|
const e = data[i];
|
||||||
|
this.list.push([true, e]);
|
||||||
|
if(i+1<data.length)this.list.push([false, comma]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
append(qb: QueryBuilder) {
|
||||||
|
this.list.push(...qb.list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export class selectQuery {
|
export class selectQuery {
|
||||||
attr: selectElements[] = [];
|
attr: selectElements[] = [];
|
||||||
from: selectFromElements;
|
from: selectFromElements;
|
||||||
|
@ -41,12 +70,13 @@ export class selectQuery {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
serialize(handler : Handler): serializeReturn {
|
serialize(handler: Handler): QueryBuilder {
|
||||||
return handler.querys.select(handler,this);
|
return handler.querys.select(handler, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
query(db: DB) {
|
query(db: DB) {
|
||||||
const s = this.serialize(db.getHandler());
|
const handler = db.getHandler();
|
||||||
return db.query(new Query(s[0], s[1]));
|
const s = handler.builders.query(this.serialize(handler));
|
||||||
|
return db.query(new Query(s));
|
||||||
}
|
}
|
||||||
}
|
}
|
21
src/types.ts
21
src/types.ts
|
@ -1,5 +1,5 @@
|
||||||
import { Attribute, Table } from "./db";
|
import { Attribute, Table } from "./db";
|
||||||
import { Aggregation, Joins, Modifier } from "./dbStructure";
|
import { Aggregation, BooleanModifier, Datatype, Joins, Modifier } from "./dbStructure";
|
||||||
import { selectQuery } from "./query";
|
import { selectQuery } from "./query";
|
||||||
|
|
||||||
export type primaryData = string | number | boolean | null;
|
export type primaryData = string | number | boolean | null;
|
||||||
|
@ -20,12 +20,27 @@ export type attributeSettings = {
|
||||||
link: Attribute,
|
link: Attribute,
|
||||||
onDelete?: onAction,
|
onDelete?: onAction,
|
||||||
onUpdate?: onAction
|
onUpdate?: onAction
|
||||||
}
|
},
|
||||||
|
check?:BooleanModifier
|
||||||
};
|
};
|
||||||
|
export type extendedAttributeSettings = {
|
||||||
|
type: Datatype,
|
||||||
|
unique?: boolean,
|
||||||
|
autoIncrement?: boolean,
|
||||||
|
default?: primaryData,
|
||||||
|
notNull?: boolean
|
||||||
|
primaryKey?: boolean,
|
||||||
|
foreginKey?: {
|
||||||
|
link: Attribute,
|
||||||
|
onDelete?: onAction,
|
||||||
|
onUpdate?: onAction
|
||||||
|
},
|
||||||
|
check?:BooleanModifier
|
||||||
|
}
|
||||||
|
|
||||||
export enum onAction {
|
export enum onAction {
|
||||||
cascade,
|
cascade,
|
||||||
noAction,
|
noAction,
|
||||||
setNull,
|
setNull,
|
||||||
setDefault
|
setDefault
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue