First Working Version #1
6 changed files with 304 additions and 86 deletions
|
@ -1,4 +1,4 @@
|
|||
# DBlang
|
||||
sql Querys with js ot ts Syntax.
|
||||
sql Querys with js or ts Syntax.
|
||||
|
||||
[![status-badge](https://ci.jusax.de/api/badges/jusax23/dblang/status.svg)](https://ci.jusax.de/jusax23/dblang)
|
78
src/db.ts
78
src/db.ts
|
@ -1,37 +1,38 @@
|
|||
import mariadb from 'mariadb';
|
||||
import { checkConstraint, Constraint, Datatype, uniqueConstraint } from './dbStructure';
|
||||
import { Handler } from './defaultHandler';
|
||||
import { Query, selectQuery } from './query';
|
||||
import { attributeSettings, extendedAttributeSettings, onAction, primaryData, serializeReturn } from './types';
|
||||
import { Query } from './query';
|
||||
import { attributeSettings, extendedAttributeSettings, onAction } from './types';
|
||||
|
||||
|
||||
export class DB {
|
||||
tables:Table[] = [];
|
||||
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 });
|
||||
pool: mariadb.Pool;
|
||||
constructor({ host, user, password, database, connectionLimit = 5 }: { host: string, user: string, password: string, database: string, connectionLimit: number }) {
|
||||
this.pool = mariadb.createPool({ host, user, password, database, connectionLimit, multipleStatements: true });
|
||||
this.handler = new Handler();
|
||||
this.name = "notimplemented"
|
||||
this.name = database;
|
||||
}
|
||||
async query(query: Query) {
|
||||
console.log(query);
|
||||
//return this.pool.query(query);
|
||||
return await this.pool.query(query);
|
||||
}
|
||||
getHandler() {
|
||||
return this.handler;
|
||||
}
|
||||
|
||||
sync(){
|
||||
async sync() {
|
||||
let handler = this.getHandler();
|
||||
this.tables.forEach(t=>{
|
||||
console.log(new Query(handler.builders.query(handler.querys.create(handler,t))));
|
||||
})
|
||||
await handler.syncDB(this, handler);
|
||||
//this.tables.forEach(t=>{
|
||||
// console.log(handler.builders.query(handler.querys.create(handler,t)));
|
||||
//})
|
||||
}
|
||||
|
||||
newTable(name: string) {
|
||||
let tabel = new Table(name,this);
|
||||
let tabel = new Table(name, this);
|
||||
this.tables.push(tabel);
|
||||
return tabel;
|
||||
}
|
||||
|
@ -42,39 +43,40 @@ export class Attribute {
|
|||
table: Table;
|
||||
ops: attributeSettings;
|
||||
type: Datatype;
|
||||
constructor(name: string, table:Table, 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;
|
||||
this.ops = ops;
|
||||
|
||||
if(ops.check != null){
|
||||
if (ops.check != null) {
|
||||
if(typeof ops.check == "function")ops.check = ops.check(this);
|
||||
table.addConstraint(new checkConstraint(
|
||||
table.dbLangDatabaseInstance.name+"_"+table.dbLangTableName+"_"+name+"_check_constraint",
|
||||
table.dbLangDatabaseInstance.name + "_" + table.dbLangTableName + "_" + name + "_check_constraint",
|
||||
ops.check
|
||||
))
|
||||
}
|
||||
if(ops.unique != null){
|
||||
if (ops.unique != null) {
|
||||
table.addConstraint(new uniqueConstraint(
|
||||
table.dbLangDatabaseInstance.name+"_"+table.dbLangTableName+" "+name+"_unique_constraint",
|
||||
table.dbLangDatabaseInstance.name + "_" + table.dbLangTableName + " " + name + "_unique_constraint",
|
||||
[this]
|
||||
))
|
||||
}
|
||||
}
|
||||
serializeDatatype(handler : Handler){
|
||||
serializeDatatype(handler: Handler) {
|
||||
return this.type.serialize(handler);
|
||||
}
|
||||
serializeSettings(handler : Handler){
|
||||
return handler.builders.attributeSettings(handler,this);
|
||||
serializeSettings(handler: Handler) {
|
||||
return handler.builders.attributeSettings(handler, this);
|
||||
}
|
||||
serialize(handler : Handler) {
|
||||
serialize(handler: Handler) {
|
||||
return handler.builders.escapeID(this.name);
|
||||
}
|
||||
toString(handler : Handler = this.table.dbLangDatabaseInstance.getHandler()) {
|
||||
return this.table.serialize(handler)+"."+this.serialize(handler);
|
||||
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)+")";
|
||||
toStringFunc(handler: Handler) {
|
||||
return this.table.serialize(handler) + "(" + this.serialize(handler) + ")";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,34 +86,34 @@ export class Table {
|
|||
dbLangTableAttributes: { [key: string]: Attribute; } = {};
|
||||
dbLangDatabaseInstance: DB;
|
||||
dbLangConstrains: Constraint[] = [];
|
||||
[key: string]: Attribute | any
|
||||
constructor(name: string, db:DB) {
|
||||
[key: string]: Attribute | any;
|
||||
constructor(name: string, db: DB) {
|
||||
this.dbLangTableName = name;
|
||||
this.dbLangDatabaseInstance = db;
|
||||
}
|
||||
serialize(handler : Handler) {
|
||||
serialize(handler: Handler) {
|
||||
return this.toString(handler);
|
||||
}
|
||||
toString(handler : Handler = this.dbLangDatabaseInstance.getHandler()) {
|
||||
toString(handler: Handler = this.dbLangDatabaseInstance.getHandler()) {
|
||||
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);
|
||||
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","addConstraint","addAttributes"].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)];
|
||||
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){
|
||||
addConstraint(c: Constraint) {
|
||||
c.check(this);
|
||||
this.dbLangConstrains.push(c);
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ export class checkConstraint implements Constraint{
|
|||
this.checkQuery = check;
|
||||
}
|
||||
check(attr: Table): boolean {
|
||||
throw new Error("Method not implemented.");
|
||||
return true;
|
||||
}
|
||||
uses(attr: Attribute): boolean {
|
||||
throw new Error("Method not implemented.");
|
||||
|
@ -76,19 +76,19 @@ export class checkConstraint implements Constraint{
|
|||
|
||||
export class uniqueConstraint implements Constraint{
|
||||
name: string;
|
||||
attr: Attribute[];
|
||||
constructor(name:string, attr:Attribute[]){
|
||||
attrs: Attribute[];
|
||||
constructor(name:string, attrs:Attribute[]){
|
||||
this.name = name;
|
||||
this.attr = attr;
|
||||
this.attrs = attrs;
|
||||
}
|
||||
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";
|
||||
for(let i = 0; i < this.attrs.length; i++){
|
||||
if(this.attrs[i].ops.primaryKey) return "Can not combine unique Constraint and primary key";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
uses(attr: Attribute): boolean {
|
||||
throw new Error("Method not implemented.");
|
||||
return this.attrs.includes(attr);
|
||||
}
|
||||
serialize(handler: Handler): QueryBuilder {
|
||||
throw new Error("Method not implemented.");
|
||||
|
|
|
@ -1,12 +1,115 @@
|
|||
import { Attribute, DB, Table } from "./db"
|
||||
import { Aggregation, Modifier } from "./dbStructure"
|
||||
import { QueryBuilder, selectQuery } from "./query"
|
||||
import { Aggregation, checkConstraint, Constraint, Datatype, Modifier, uniqueConstraint } from "./dbStructure"
|
||||
import { Query, QueryBuilder, selectQuery } from "./query"
|
||||
import { allModifierInput, primaryData, serializeReturn } from "./types"
|
||||
|
||||
export class Handler {
|
||||
/*syncDB(db : DB){
|
||||
async syncDB(db: DB, handler: Handler, deleteInDB: boolean = false) {
|
||||
console.log("start sync");
|
||||
|
||||
}*/
|
||||
let gd = new QueryBuilder();
|
||||
gd.addCode(`SELECT * FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE where CONSTRAINT_SCHEMA = `);
|
||||
gd.addInjection(db.name);
|
||||
gd.addCode(` or TABLE_SCHEMA = `);
|
||||
gd.addInjection(db.name);
|
||||
gd.addCode(`;select * from information_schema.table_constraints where CONSTRAINT_SCHEMA = `);
|
||||
gd.addInjection(db.name)
|
||||
gd.addCode(` or TABLE_SCHEMA = `);
|
||||
gd.addInjection(db.name);
|
||||
|
||||
let [key, constraints] = await db.query(handler.builders.query(gd));
|
||||
|
||||
|
||||
let tableData = [];
|
||||
for (let i = 0; i < db.tables.length; i++) {
|
||||
const table = db.tables[i];
|
||||
try {
|
||||
const tableDataBuilder = new QueryBuilder();
|
||||
tableDataBuilder.addCode("DESCRIBE ");
|
||||
tableDataBuilder.addCode(table.serialize(handler));
|
||||
tableData[i] = Object.fromEntries((await db.query(handler.builders.query(tableDataBuilder))).map((d: any) => [d.Field, d]));
|
||||
} catch (_) {
|
||||
tableData[i] = null;
|
||||
}
|
||||
}
|
||||
|
||||
const del = new QueryBuilder();
|
||||
const create = new QueryBuilder();
|
||||
|
||||
for (let i = 0; i < constraints.length; i++) {
|
||||
const c = constraints[i];
|
||||
if (c.CONSTRAINT_TYPE == "CHECK") {
|
||||
del.appendEnding(handler.querys.removeCheck(handler, c.TABLE_NAME, c.CONSTRAINT_NAME));
|
||||
}
|
||||
}
|
||||
// TODO: delete old constraints/tables
|
||||
|
||||
function freeForUpdate(a: Attribute) {
|
||||
for (let i = 0; i < key.length; i++) {
|
||||
const k = key[i];
|
||||
if (
|
||||
k.REFERENCED_TABLE_NAME == a.table.dbLangTableName
|
||||
&& k.REFERENCED_TABLE_NAME == a.name
|
||||
) {
|
||||
del.appendEnding(handler.querys.removeForeignKey(handler, k.TABLE_NAME, k.CONSTRAINT_NAME));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//create tables
|
||||
for (let i = 0; i < db.tables.length; i++) {
|
||||
const table = db.tables[i];
|
||||
const tableD = tableData[i];
|
||||
let changePrimary = false;
|
||||
if (tableD == null) {
|
||||
create.appendEnding(handler.querys.create(handler, table));
|
||||
changePrimary = true;
|
||||
} else {
|
||||
let keys = Object.keys(table.dbLangTableAttributes);
|
||||
for (let j = 0; j < keys.length; j++) {
|
||||
const a = table.dbLangTableAttributes[keys[j]];
|
||||
const attrData = tableD[keys[j]];
|
||||
if (attrData == null) {
|
||||
create.appendEnding(handler.querys.addColumn(handler, a));
|
||||
changePrimary = true;
|
||||
} else if (
|
||||
!handler.builders.compareDatatypes(handler, a.type, attrData.Type) ||
|
||||
a.ops.default != attrData.Default ||
|
||||
(!!a.ops.notNull || !!a.ops.autoIncrement || !!a.ops.primaryKey) != (attrData.Null == "NO") ||
|
||||
(!!a.ops.autoIncrement) != (attrData.Extra == "auto_increment")
|
||||
) {
|
||||
console.log(!handler.builders.compareDatatypes(handler, a.type, attrData.Type), "|",
|
||||
a.ops.default, attrData.Default, "|",
|
||||
(!!a.ops.notNull || !!a.ops.autoIncrement || !!a.ops.primaryKey), (attrData.Null == "NO"), "|",
|
||||
(!!a.ops.autoIncrement), (attrData.Extra == "auto_increment"));
|
||||
freeForUpdate(a);
|
||||
create.appendEnding(handler.querys.changeColumn(handler, a));
|
||||
}
|
||||
if (attrData == null) {
|
||||
changePrimary = true;
|
||||
} else {
|
||||
if ((attrData.Key == "PRI") != (!!a.ops.primaryKey)) {
|
||||
freeForUpdate(a);
|
||||
changePrimary = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (changePrimary) {
|
||||
create.appendEnding(handler.querys.removePrimaryKey(handler, table));
|
||||
create.appendEnding(handler.querys.addPrimaryKey(handler, table));
|
||||
}
|
||||
for (let j = 0; j < table.dbLangConstrains.length; j++) {
|
||||
const c = table.dbLangConstrains[j];
|
||||
if (c instanceof checkConstraint) {
|
||||
create.appendEnding(handler.querys.addCheck(handler, table, c));
|
||||
}
|
||||
}
|
||||
// TODO: unique
|
||||
}
|
||||
if (!create.isEmpty()) del.append(create);
|
||||
if (!del.isEmpty()) await db.query(handler.builders.query(del));
|
||||
}
|
||||
|
||||
querys = {
|
||||
select: (handler: Handler, q: selectQuery): QueryBuilder => {
|
||||
|
@ -26,11 +129,15 @@ export class Handler {
|
|||
builder.append(q.havingD.serialize(handler));
|
||||
}
|
||||
}
|
||||
|
||||
if (q.havingD) {
|
||||
builder.addCode(" limit ");
|
||||
builder.addInjection(q.limitD);
|
||||
}
|
||||
|
||||
/*builder.setHandler((json)=>{
|
||||
return json;
|
||||
});*/
|
||||
|
||||
return builder;
|
||||
},
|
||||
create: (handler: Handler, table: Table): QueryBuilder => {
|
||||
|
@ -46,16 +153,102 @@ export class Handler {
|
|||
builder.addCode(")");
|
||||
return builder;
|
||||
},
|
||||
addColumn: (handler: Handler, attr: Attribute): QueryBuilder => {
|
||||
const builder = new QueryBuilder();
|
||||
builder.addCode(`alter table `);
|
||||
builder.addCode(attr.table.toString(handler));
|
||||
builder.addCode(` add if not exists `);
|
||||
builder.addCode(attr.serialize(handler) + " ");
|
||||
builder.append(attr.serializeSettings(handler));
|
||||
return builder;
|
||||
},
|
||||
changeColumn: (handler: Handler, attr: Attribute): QueryBuilder => {
|
||||
const builder = new QueryBuilder();
|
||||
builder.addCode(`alter table `);
|
||||
builder.addCode(attr.table.toString(handler));
|
||||
builder.addCode(` change `);
|
||||
builder.addCode(attr.serialize(handler) + " ");
|
||||
builder.addCode(attr.serialize(handler) + " ");
|
||||
builder.append(attr.serializeSettings(handler));
|
||||
return builder;
|
||||
},
|
||||
addForeignKey: (handler: Handler, table: Table) => {
|
||||
const builder = new QueryBuilder();
|
||||
|
||||
}
|
||||
return builder;
|
||||
},
|
||||
removeForeignKey: (handler: Handler, tablenName: string, name: string) => {
|
||||
const builder = new QueryBuilder();
|
||||
builder.addCode("ALTER TABLE ");
|
||||
builder.addCode(handler.builders.escapeID(tablenName));
|
||||
builder.addCode(" DROP FOREIGN KEY IF EXISTS ");
|
||||
builder.addCode(handler.builders.escapeID(name));
|
||||
builder.addCode(";ALTER TABLE ");
|
||||
builder.addCode(handler.builders.escapeID(tablenName));
|
||||
builder.addCode(" DROP INDEX IF EXISTS ");
|
||||
builder.addCode(handler.builders.escapeID(name));
|
||||
|
||||
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
|
||||
return builder;
|
||||
},
|
||||
addPrimaryKey: (handler: Handler, table: Table) => {
|
||||
const qb = new QueryBuilder();
|
||||
qb.addCode("ALTER TABLE ");
|
||||
qb.addCode(table.serialize(handler));
|
||||
qb.addCode(" add PRIMARY KEY if not exists (");
|
||||
qb.addCodeCommaSeperated(
|
||||
Object.entries(table.dbLangTableAttributes)
|
||||
.filter(([n, attr]) => !!attr.ops.primaryKey)
|
||||
.map(([n, attr]) => handler.builders.escapeID(n))
|
||||
);
|
||||
qb.addCode(")");
|
||||
return qb;
|
||||
},
|
||||
removePrimaryKey: (handler: Handler, table: Table) => {
|
||||
const qb = new QueryBuilder();
|
||||
qb.addCode("ALTER TABLE ");
|
||||
qb.addCode(table.serialize(handler));
|
||||
qb.addCode(" DROP INDEX IF EXISTS `PRIMARY`");
|
||||
return qb;
|
||||
},
|
||||
removeCheck: (handler: Handler, table: string, name: string) => {
|
||||
const qb = new QueryBuilder();
|
||||
qb.addCode("ALTER TABLE ");
|
||||
qb.addCode(handler.builders.escapeID(table));
|
||||
qb.addCode(" DROP CONSTRAINT IF EXISTS ");
|
||||
qb.addCode(handler.builders.escapeID(name));
|
||||
return qb;
|
||||
},
|
||||
addCheck: (handler: Handler, table: Table, c: checkConstraint) => {
|
||||
const qb = new QueryBuilder();
|
||||
qb.addCode(`ALTER TABLE `);
|
||||
qb.addCode(table.serialize(handler));
|
||||
qb.addCode(` ADD CONSTRAINT `);
|
||||
qb.addCode(handler.builders.escapeID(c.name));
|
||||
qb.addCode(` CHECK (`);
|
||||
qb.append(c.checkQuery.serialize(handler));
|
||||
qb.addCode(")");
|
||||
return qb;
|
||||
},
|
||||
removeUnique: (handler: Handler, table: string, name: string) => {
|
||||
const qb = new QueryBuilder();
|
||||
qb.addCode("ALTER TABLE ");
|
||||
qb.addCode(handler.builders.escapeID(table));
|
||||
qb.addCode(" DROP INDEX IF EXISTS ");
|
||||
qb.addCode(handler.builders.escapeID(name));
|
||||
return qb;
|
||||
},
|
||||
addUnique: (handler: Handler, table: Table, u: uniqueConstraint) => {
|
||||
const qb = new QueryBuilder();
|
||||
qb.addCode("ALTER TABLE ");
|
||||
qb.addCode(table.serialize(handler));
|
||||
qb.addCode(" ADD CONSTRAINT ");
|
||||
qb.addCode(handler.builders.escapeID(u.name));
|
||||
qb.addCode(" UNIQUE (");
|
||||
qb.addCodeCommaSeperated(u.attrs.map(a => a.serialize(handler)));
|
||||
qb.addCode(")");
|
||||
return qb;
|
||||
},
|
||||
/*// 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(),
|
||||
|
@ -65,10 +258,15 @@ export class Handler {
|
|||
dropForeignKeys: (handler: Handler, table: Table): QueryBuilder => new QueryBuilder(),
|
||||
dropUniqueKeys: (handler: Handler, table: Table): QueryBuilder => new QueryBuilder(),
|
||||
dropChecks: (handler: Handler, table: Table): QueryBuilder => new QueryBuilder(),
|
||||
// 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(),*/
|
||||
}
|
||||
|
||||
builders = {
|
||||
query: (qb: QueryBuilder): serializeReturn => {
|
||||
query: (qb: QueryBuilder): Query => {
|
||||
let args: primaryData[] = [];
|
||||
let sql = "";
|
||||
for (let i = 0; i < qb.list.length; i++) {
|
||||
|
@ -80,7 +278,7 @@ export class Handler {
|
|||
sql += data;
|
||||
}
|
||||
}
|
||||
return [sql, args];
|
||||
return new Query([sql, args]);
|
||||
},
|
||||
|
||||
attributeSettings: (handler: Handler, a: Attribute): QueryBuilder => {
|
||||
|
@ -89,38 +287,34 @@ export class Handler {
|
|||
if (a.ops.autoIncrement) {
|
||||
builder.addCode(" 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)}`);
|
||||
builder.addCode(" default ");
|
||||
builder.addInjection(a.ops.default);
|
||||
}
|
||||
|
||||
/*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) {
|
||||
builder.addCode(" not null");
|
||||
}
|
||||
}
|
||||
|
||||
/*if (a.ops.foreginKey != null) {
|
||||
sql += ` foreign key references (${a.ops.foreginKey.link.toStringFunc(handler)})`
|
||||
}*/
|
||||
|
||||
} else builder.addCode(" null");
|
||||
} else builder.addCode(" null");
|
||||
return builder;
|
||||
},
|
||||
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, '``')}\``;
|
||||
}
|
||||
},
|
||||
compareDatatypes: (handler: Handler, attr: Datatype, curr: String) => {
|
||||
let qb = attr.serialize(handler);
|
||||
let sql = "";
|
||||
for (let i = 0; i < qb.list.length; i++) {
|
||||
const [inject, data] = qb.list[i];
|
||||
sql += data;
|
||||
}
|
||||
|
||||
return curr.split(" ").join("").startsWith(sql.split(" ").join(""));
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
|
@ -200,7 +394,7 @@ export class Handler {
|
|||
double: dataTypeDblNum("double"),
|
||||
decimal: dataTypeDblNum("decimal"),
|
||||
|
||||
date: dataTypeNoArg("data"),
|
||||
date: dataTypeNoArg("date"),
|
||||
datetime: dataTypeNoArg("datatime"),
|
||||
timestamp: dataTypeNoArg("timestamp"),
|
||||
time: dataTypeNoArg("time"),
|
||||
|
|
25
src/query.ts
25
src/query.ts
|
@ -16,6 +16,7 @@ export class Query {
|
|||
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++) {
|
||||
|
@ -26,6 +27,13 @@ export class QueryBuilder {
|
|||
addCode(text: string) {
|
||||
this.list.push([false, text]);
|
||||
}
|
||||
addCodeCommaSeperated(data: string[], comma = ", ") {
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
const e = data[i];
|
||||
this.list.push([false, e]);
|
||||
if(i+1<data.length)this.list.push([false, comma]);
|
||||
}
|
||||
}
|
||||
addInjection(data: primaryData) {
|
||||
this.list.push([true, data]);
|
||||
}
|
||||
|
@ -39,6 +47,16 @@ export class QueryBuilder {
|
|||
append(qb: QueryBuilder) {
|
||||
this.list.push(...qb.list);
|
||||
}
|
||||
appendEnding(qb: QueryBuilder){
|
||||
this.append(qb);
|
||||
this.list.push([false,";"]);
|
||||
}
|
||||
isEmpty(){
|
||||
return this.list.length == 0;
|
||||
}
|
||||
/*setHandler(fun:(d:any)=>any){
|
||||
|
||||
}*/
|
||||
}
|
||||
|
||||
|
||||
|
@ -74,9 +92,10 @@ export class selectQuery {
|
|||
return handler.querys.select(handler, this);
|
||||
}
|
||||
|
||||
query(db: DB) {
|
||||
async query(db: DB) {
|
||||
const handler = db.getHandler();
|
||||
const s = handler.builders.query(this.serialize(handler));
|
||||
return db.query(new Query(s));
|
||||
const builder = this.serialize(handler);
|
||||
const s = handler.builders.query(builder);
|
||||
return await db.query(s);
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
import { Attribute, Table } from "./db";
|
||||
import { Aggregation, BooleanModifier, Datatype, Joins, Modifier } from "./dbStructure";
|
||||
import { selectQuery } from "./query";
|
||||
import { QueryBuilder, selectQuery } from "./query";
|
||||
|
||||
export type primaryData = string | number | boolean | null;
|
||||
export type allModifierInput = primaryData | Modifier | selectQuery | Attribute | Aggregation;
|
||||
|
@ -10,6 +10,8 @@ export type selectFromElements = Table | Joins | null;
|
|||
|
||||
export type serializeReturn = [string, primaryData[]];
|
||||
|
||||
export type DatatypeBuild = [QueryBuilder, number];
|
||||
|
||||
export type attributeSettings = {
|
||||
unique?: boolean,
|
||||
autoIncrement?: boolean,
|
||||
|
@ -21,8 +23,9 @@ export type attributeSettings = {
|
|||
onDelete?: onAction,
|
||||
onUpdate?: onAction
|
||||
},
|
||||
check?:BooleanModifier
|
||||
check?: BooleanModifier | ((a: Attribute) => BooleanModifier)
|
||||
};
|
||||
|
||||
export type extendedAttributeSettings = {
|
||||
type: Datatype,
|
||||
unique?: boolean,
|
||||
|
@ -35,7 +38,7 @@ export type extendedAttributeSettings = {
|
|||
onDelete?: onAction,
|
||||
onUpdate?: onAction
|
||||
},
|
||||
check?:BooleanModifier
|
||||
check?: BooleanModifier | ((a: Attribute) => BooleanModifier)
|
||||
}
|
||||
|
||||
export enum onAction {
|
||||
|
|
Loading…
Reference in a new issue