First Working Version #1
7 changed files with 300 additions and 108 deletions
|
@ -12,7 +12,6 @@ pipeline:
|
|||
- mkdir dblang
|
||||
- mkdir upload
|
||||
- npm run prepublish
|
||||
- ls dist
|
||||
- cp dist/* dblang
|
||||
- zip -r upload/DBlang.zip 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 { Datatype } from './dbStructure';
|
||||
import { checkConstraint, Constraint, Datatype, uniqueConstraint } from './dbStructure';
|
||||
import { Handler } from './defaultHandler';
|
||||
import { Query, selectQuery } from './query';
|
||||
import { attributeSettings, onAction, primaryData, serializeReturn } from './types';
|
||||
import { attributeSettings, extendedAttributeSettings, onAction, primaryData, serializeReturn } from './types';
|
||||
|
||||
|
||||
export class DB {
|
||||
tables:Table[] = [];
|
||||
handler: Handler;
|
||||
name: string;
|
||||
//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();
|
||||
this.name = "notimplemented"
|
||||
}
|
||||
async query(query: Query) {
|
||||
console.log(query);
|
||||
|
@ -24,7 +26,7 @@ export class DB {
|
|||
sync(){
|
||||
let handler = this.getHandler();
|
||||
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.type = type;
|
||||
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){
|
||||
return this.type.serialize(handler);
|
||||
|
@ -68,10 +83,11 @@ export class Table {
|
|||
dbLangTableName: string;
|
||||
dbLangTableAttributes: { [key: string]: Attribute; } = {};
|
||||
dbLangDatabaseInstance: DB;
|
||||
dbLangConstrains: Constraint[] = [];
|
||||
[key: string]: Attribute | any
|
||||
constructor(name: string, table:DB) {
|
||||
constructor(name: string, db:DB) {
|
||||
this.dbLangTableName = name;
|
||||
this.dbLangDatabaseInstance = table;
|
||||
this.dbLangDatabaseInstance = db;
|
||||
}
|
||||
serialize(handler : Handler) {
|
||||
return this.toString(handler);
|
||||
|
@ -80,15 +96,25 @@ export class Table {
|
|||
return handler.builders.escapeID(this.dbLangTableName);
|
||||
}
|
||||
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);
|
||||
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!");
|
||||
} else {
|
||||
this[name] = 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';
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { Attribute } from "./db";
|
||||
import { Attribute, Table } from "./db";
|
||||
import { Handler } from "./defaultHandler";
|
||||
import { QueryBuilder } from "./query";
|
||||
import { allModifierInput, primaryData, serializeReturn } from "./types";
|
||||
|
||||
export class Datatype{
|
||||
|
@ -9,7 +10,7 @@ export class Datatype{
|
|||
this.type = type;
|
||||
this.args = args;
|
||||
}
|
||||
serialize(handler : Handler): serializeReturn{
|
||||
serialize(handler : Handler): QueryBuilder{
|
||||
return handler.datatypes[this.type as keyof typeof handler.datatypes](this.args);
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +22,7 @@ export abstract class Modifier {
|
|||
this.t = type;
|
||||
this.a = args;
|
||||
}
|
||||
serialize(handler : Handler): serializeReturn {
|
||||
serialize(handler : Handler): QueryBuilder {
|
||||
return handler.modifiers[this.t as keyof typeof handler.modifiers](handler,this.a);
|
||||
}
|
||||
}
|
||||
|
@ -37,13 +38,60 @@ export class Aggregation {
|
|||
this.t = type;
|
||||
this.a = args;
|
||||
}
|
||||
serialize(handler : Handler): serializeReturn {
|
||||
serialize(handler : Handler): QueryBuilder {
|
||||
return handler.aggregations[this.t as keyof typeof handler.aggregations](handler,this.a);
|
||||
}
|
||||
}
|
||||
export class Joins {
|
||||
|
||||
serialize(handler : Handler): serializeReturn {
|
||||
return ["", []];
|
||||
serialize(handler : Handler): QueryBuilder {
|
||||
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 { Aggregation, Modifier } from "./dbStructure"
|
||||
import { selectQuery } from "./query"
|
||||
import { QueryBuilder, selectQuery } from "./query"
|
||||
import { allModifierInput, primaryData, serializeReturn } from "./types"
|
||||
|
||||
export class Handler {
|
||||
syncDB(db : DB){
|
||||
/*syncDB(db : DB){
|
||||
|
||||
}
|
||||
}*/
|
||||
|
||||
querys = {
|
||||
select: (handler:Handler,q: selectQuery): serializeReturn => {
|
||||
let args: primaryData[] = [];
|
||||
let w = joinArg(", ")(handler,q.attr);
|
||||
args.push(...w[1]);
|
||||
let sql = `select ${w[0]} from ${q.from == null ? 'DUAL' : q.from.serialize(handler)}`;
|
||||
select: (handler: Handler, q: selectQuery): QueryBuilder => {
|
||||
const builder = new QueryBuilder();
|
||||
builder.addCode("select ");
|
||||
builder.append(joinArg(", ")(handler, q.attr));
|
||||
builder.addCode(` from ${q.from == null ? 'DUAL' : q.from.serialize(handler)}`);
|
||||
if (q.whereD) {
|
||||
let whereS = q.whereD.serialize(handler);
|
||||
args.push(...whereS[1]);
|
||||
sql += " where " + whereS[0];
|
||||
builder.addCode(" where ");
|
||||
builder.append(q.whereD.serialize(handler));
|
||||
}
|
||||
if (q.groupByD.length > 0) {
|
||||
let groupByS = joinArg(",")(handler,q.groupByD);
|
||||
args.push(...groupByS[1]);
|
||||
sql += " group by " + groupByS[0];
|
||||
builder.addCode(" group by ");
|
||||
builder.append(joinArg(",")(handler, q.groupByD));
|
||||
if (q.havingD) {
|
||||
let havingS = q.havingD.serialize(handler);
|
||||
args.push(...havingS[1]);
|
||||
sql += " having " + havingS[0];
|
||||
builder.addCode(" having ");
|
||||
builder.append(q.havingD.serialize(handler));
|
||||
}
|
||||
}
|
||||
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=>{
|
||||
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];
|
||||
}
|
||||
create: (handler: Handler, table: Table): QueryBuilder => {
|
||||
const builder = new QueryBuilder();
|
||||
builder.addCode(`create table if not exists ${table.toString(handler)}(`);
|
||||
let keys = Object.keys(table.dbLangTableAttributes);
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
const a = table.dbLangTableAttributes[keys[i]];
|
||||
builder.addCode(a.serialize(handler) + " ");
|
||||
builder.append(a.serializeSettings(handler));
|
||||
if (i + 1 < keys.length) builder.addCode(", ");
|
||||
}
|
||||
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 = {
|
||||
attributeSettings: (handler:Handler,a: Attribute): serializeReturn => {
|
||||
let dtype = a.type.serialize(handler);
|
||||
let sql = ""+dtype[0];
|
||||
let args:primaryData[] = [...dtype[1]];
|
||||
query: (qb: QueryBuilder): serializeReturn => {
|
||||
let args: primaryData[] = [];
|
||||
let sql = "";
|
||||
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) {
|
||||
sql += " auto_increment";
|
||||
builder.addCode(" auto_increment");
|
||||
}
|
||||
if (a.ops.primaryKey) {
|
||||
/*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);
|
||||
builder.addCode(" default ");
|
||||
builder.addInjection(a.ops.default);
|
||||
}
|
||||
|
||||
if (a.ops.unique != null) {
|
||||
/*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.autoIncrement && !a.ops.primaryKey && a.ops.default == 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)})`
|
||||
}
|
||||
}*/
|
||||
|
||||
return [sql, args];
|
||||
return builder;
|
||||
},
|
||||
escapeID: (key:string) :string =>{
|
||||
if(!key || key === "" || key.includes('\u0000')) throw new Error("Can not escape empty key or with null unicode!");
|
||||
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, '``')}\``;
|
||||
}
|
||||
|
@ -94,11 +125,11 @@ ${Object.entries(table.dbLangTableAttributes).map(([_,a])=>{
|
|||
|
||||
|
||||
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) + ")", []],
|
||||
count: (handler: Handler, a: Attribute): QueryBuilder => new QueryBuilder([{ data: "count(" + a.toString(handler) + ")" }]),
|
||||
sum: (handler: Handler, a: Attribute): QueryBuilder => new QueryBuilder([{ data: "sum(" + a.toString(handler) + ")" }]),
|
||||
avg: (handler: Handler, a: Attribute): QueryBuilder => new QueryBuilder([{ data: "avg(" + a.toString(handler) + ")" }]),
|
||||
min: (handler: Handler, a: Attribute): QueryBuilder => new QueryBuilder([{ data: "min(" + a.toString(handler) + ")" }]),
|
||||
max: (handler: Handler, a: Attribute): QueryBuilder => new QueryBuilder([{ data: "max(" + a.toString(handler) + ")" }]),
|
||||
}
|
||||
|
||||
modifiers = {
|
||||
|
@ -111,14 +142,21 @@ ${Object.entries(table.dbLangTableAttributes).map(([_,a])=>{
|
|||
ge: joinArg(">"),
|
||||
plus: joinArg("+"),
|
||||
minus: joinArg("-"),
|
||||
not: (handler:Handler,a: allModifierInput[]): serializeReturn => {
|
||||
not: (handler: Handler, a: allModifierInput[]): QueryBuilder => {
|
||||
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) {
|
||||
let [sqli, argsi] = e.serialize(handler);
|
||||
return ["not (" + sqli + ")", argsi]
|
||||
const builder = new QueryBuilder();
|
||||
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 = {
|
||||
|
@ -136,12 +174,19 @@ ${Object.entries(table.dbLangTableAttributes).map(([_,a])=>{
|
|||
mediumtext: dataTypeNoArg("mediumtext"),
|
||||
longtext: dataTypeNoArg("longtext"),
|
||||
|
||||
enum: (a: primaryData[]): serializeReturn => {
|
||||
console.log(a);
|
||||
return ["enum(" + a.map(() => "?").join(", ") + ")", a];
|
||||
enum: (a: primaryData[]): QueryBuilder => {
|
||||
const builder = new QueryBuilder();
|
||||
builder.addCode("enum(");
|
||||
builder.addInjectionCommaSeperated(a);
|
||||
builder.addCode(")");
|
||||
return builder;
|
||||
},
|
||||
set: (a: primaryData[]): serializeReturn => {
|
||||
return ["set(" + a.map(() => "?").join(", ") + ")", a];
|
||||
set: (a: primaryData[]): QueryBuilder => {
|
||||
const builder = new QueryBuilder();
|
||||
builder.addCode("set(");
|
||||
builder.addInjectionCommaSeperated(a);
|
||||
builder.addCode(")");
|
||||
return builder;
|
||||
},
|
||||
bool: dataTypeNoArg("bool"),
|
||||
bit: dataTypeNoArg("bit"),
|
||||
|
@ -165,36 +210,50 @@ ${Object.entries(table.dbLangTableAttributes).map(([_,a])=>{
|
|||
};
|
||||
|
||||
function dataTypeNoArg(type: string) {
|
||||
return (a: primaryData[]): serializeReturn => {
|
||||
return [type, []];
|
||||
return (a: primaryData[]): QueryBuilder => {
|
||||
return new QueryBuilder([{
|
||||
inject: false,
|
||||
data: type
|
||||
}]);
|
||||
}
|
||||
}
|
||||
function dataTypeSingleNum(type: string) {
|
||||
return (a: primaryData[]): serializeReturn => {
|
||||
return [type + "(?)", [a[0]]];
|
||||
return (a: primaryData[]): QueryBuilder => {
|
||||
return new QueryBuilder([
|
||||
{ data: type + "(" },
|
||||
{ inject: true, data: a[0] },
|
||||
{ data: ")" }
|
||||
]);
|
||||
}
|
||||
}
|
||||
function dataTypeDblNum(type: string) {
|
||||
return (a: primaryData[]): serializeReturn => {
|
||||
return [type + "(?,?)", [a[0], a[1]]];
|
||||
return (a: primaryData[]): QueryBuilder => {
|
||||
return new QueryBuilder([
|
||||
{ data: type + "(" },
|
||||
{ inject: true, data: a[0] },
|
||||
{ data: ", " },
|
||||
{ inject: true, data: a[1] },
|
||||
{ data: ")" }
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function joinArg(type: string) {
|
||||
return (handler:Handler,a: (allModifierInput)[]): serializeReturn => {
|
||||
let args: primaryData[] = [];
|
||||
let sql = a.map(d => {
|
||||
if (d instanceof Attribute) return d.toString(handler);
|
||||
if (d instanceof Modifier || d instanceof selectQuery || d instanceof Aggregation) {
|
||||
let [sqli, argsi] = d.serialize(handler);
|
||||
args.push(...(argsi.flat(Infinity)));
|
||||
return "(" + sqli + ")";
|
||||
return (handler: Handler, a: (allModifierInput)[]): QueryBuilder => {
|
||||
const builder = new QueryBuilder();
|
||||
for (let i = 0; i < a.length; i++) {
|
||||
const d = a[i];
|
||||
if (d instanceof Attribute) builder.addCode(d.toString(handler));
|
||||
else if (d instanceof Modifier || d instanceof selectQuery || d instanceof Aggregation) {
|
||||
builder.addCode("(");
|
||||
builder.append(d.serialize(handler));
|
||||
builder.addCode(")");
|
||||
} else {
|
||||
builder.addInjection(d);
|
||||
}
|
||||
args.push(d);
|
||||
return "?";
|
||||
}).join(" " + type + " ");
|
||||
return [sql, args]
|
||||
|
||||
if (i + 1 < a.length) builder.addCode(" " + type + " ");
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
}
|
17
src/funcs.ts
17
src/funcs.ts
|
@ -1,5 +1,5 @@
|
|||
import { Attribute } from "./db";
|
||||
import { Aggregation, BooleanModifier, Datatype, NumberModifier } from "./dbStructure";
|
||||
import { Aggregation, BooleanModifier, checkConstraint, Datatype, NumberModifier } from "./dbStructure";
|
||||
import { selectQuery } from "./query";
|
||||
import { allModifierInput, primaryData, selectElements, selectFromElements } from "./types";
|
||||
|
||||
|
@ -62,3 +62,18 @@ export const DATETIME = new Datatype("datetime",[]);
|
|||
export const TIMESTAMP = new Datatype("timestamp",[]);
|
||||
export const TIME = new Datatype("time",[]);
|
||||
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 {
|
||||
sql: string;
|
||||
values: primaryData[];
|
||||
constructor(sql: string, values: primaryData[]) {
|
||||
constructor([sql, values]:serializeReturn) {
|
||||
this.sql = sql;
|
||||
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 {
|
||||
attr: selectElements[] = [];
|
||||
from: selectFromElements;
|
||||
|
@ -41,12 +70,13 @@ export class selectQuery {
|
|||
return this;
|
||||
}
|
||||
|
||||
serialize(handler : Handler): serializeReturn {
|
||||
return handler.querys.select(handler,this);
|
||||
serialize(handler: Handler): QueryBuilder {
|
||||
return handler.querys.select(handler, this);
|
||||
}
|
||||
|
||||
query(db: DB) {
|
||||
const s = this.serialize(db.getHandler());
|
||||
return db.query(new Query(s[0], s[1]));
|
||||
const handler = db.getHandler();
|
||||
const s = handler.builders.query(this.serialize(handler));
|
||||
return db.query(new Query(s));
|
||||
}
|
||||
}
|
19
src/types.ts
19
src/types.ts
|
@ -1,5 +1,5 @@
|
|||
import { Attribute, Table } from "./db";
|
||||
import { Aggregation, Joins, Modifier } from "./dbStructure";
|
||||
import { Aggregation, BooleanModifier, Datatype, Joins, Modifier } from "./dbStructure";
|
||||
import { selectQuery } from "./query";
|
||||
|
||||
export type primaryData = string | number | boolean | null;
|
||||
|
@ -20,8 +20,23 @@ export type attributeSettings = {
|
|||
link: Attribute,
|
||||
onDelete?: 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 {
|
||||
cascade,
|
||||
|
|
Loading…
Reference in a new issue