dblang/src/db.ts
jusax23 dc7f68054d
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/pr/woodpecker Pipeline was successful
unique delete bug fix
2023-03-19 13:38:01 +01:00

185 lines
No EOL
7.2 KiB
TypeScript

import mariadb from 'mariadb';
import { checkConstraint, Constraint, Datatype, foreignConstraint, uniqueConstraint } from './dbStructure.js';
import { Handler } from './defaultHandler.js';
import { Query } from './query.js';
import { attributeSettings, extendedAttributeSettings, onAction, dbType } from './types.js';
import { TableAlias } from "./alias.js"
import { insertResponse, readResponse, writeResponse, singleResponse } from "./responses.js"
//import { postgresHandler } from "./postgresHandler"
declare module "mariadb" {
interface Pool{
on(ev: 'error', callback: () => void): Pool;
}
}
export class DB {
tables: Table[] = [];
handler!: Handler;
name!: string;
type!: dbType;
mariaPool!: mariadb.Pool;
private connected = false;
//pgPool!: pg.Pool;
connect({ host, user, password, database, port = 3306, connectionLimit = 5, databaseType = dbType.mariadb }: { host: string, user: string, password: string, database: string, port?: number, connectionLimit?: number, databaseType?: dbType }) {
this.connected = true;
this.type = databaseType;
if (databaseType == dbType.mariadb) {
this.mariaPool = mariadb.createPool({ host, user, password, port, database, connectionLimit, multipleStatements: true });
// catch errors
this.mariaPool.on("error",()=>{});
this.handler = new Handler(this);
}
/*else if (databaseType == dbType.postgres) {
this.pgPool = new pg.Pool({ host, user, password, max: connectionLimit, database, idleTimeoutMillis: 30000, connectionTimeoutMillis: 2000 });
this.handler = new postgresHandler(this);
}*/
else throw new Error("Unsuported Database type!");
this.name = database;
}
async query(query: Query, printQuery = false) {
if (!this.connected) throw new Error("Not connected yet!");
if (printQuery) console.log(query);
if (this.type == dbType.mariadb) return await this.mariaPool.query(query);
/*else if (this.type == dbType.postgres) {
let res = await this.pgPool.query(query.sql, query.values);
console.log([...res.rows]);
return res.rows;
}*/
else throw new Error("Invalid Database Type!");
}
getHandler() {
if (!this.connected) throw new Error("Not connected yet!");
return this.handler;
}
async sync(force = false) {
if (!this.connected) throw new Error("Not connected yet!");
let handler = this.getHandler();
await handler.syncDB(this, handler, force);
}
newTable(name: string) {
let tabel = new Table(name, this);
this.tables.push(tabel);
return tabel;
}
getTable(name: string) {
for (let i = 0; i < this.tables.length; i++) if (this.tables[i].dbLangTableName == name) return this.tables[i];
return null;
}
async close() {
if (!this.connected) throw new Error("Not connected yet!");
if (this.type == dbType.mariadb && this.mariaPool) await this.mariaPool.end();
//if (this.type == dbType.postgres && this.pgPool) await this.pgPool.end();
this.connected = false;
}
}
export class Attribute {
name: string;
nameO: string;
table: Table;
ops: attributeSettings;
type: Datatype;
constructor(name: string, nameO: string, table: Table, type: Datatype, ops: attributeSettings) {
this.name = name.toLowerCase();
this.nameO = nameO;
this.type = type;
this.table = table;
this.ops = ops;
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",
ops.check
))
}
if (ops.unique != null) {
table.addConstraint(new uniqueConstraint(
table.dbLangDatabaseInstance.name + "_" + table.dbLangTableName + "_" + name + "_unique_constraint",
[this]
))
}
if (ops.foreignKey != null) {
table.addConstraint(new foreignConstraint(
table.dbLangDatabaseInstance.name + "_" + table.dbLangTableName + "_" + name + "_foreign_constraint_to_" + ops.foreignKey.link.name,
[this],
[ops.foreignKey.link],
ops.foreignKey.onDelete,
ops.foreignKey.onUpdate
));
}
}
serializeDatatype(handler: Handler) {
return this.type.serialize(handler);
}
serializeSettings(handler: Handler) {
return handler.builders.attributeSettings(handler, this);
}
serialize(handler: Handler) {
return handler.builders.escapeID(this.name);
}
getString(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) + ")";
}
toString() {
return this.table.dbLangTableName + "_" + this.name;
}
}
export class Table {
dbLangTableName: string;
dbLangTableAttributes: { [key: string]: Attribute; } = {};
dbLangDatabaseInstance: DB;
dbLangConstrains: Constraint[] = [];
[key: string]: Attribute | any;
constructor(name: string, db: DB) {
this.dbLangTableName = name;
this.dbLangDatabaseInstance = db;
}
serialize(handler: Handler) {
return this.toString(handler);
}
toString(handler: Handler = this.dbLangDatabaseInstance.getHandler()) {
return handler.builders.escapeID(this.dbLangTableName);
}
addAttribute(name: string, type: Datatype, ops: attributeSettings = {}, noErrorOnNameConflict = false) {
let lowName = name.toLowerCase();
if (this.dbLangTableAttributes[lowName] != null) throw new Error("You are tring to create an Attribute twise!");
let attr = new Attribute(lowName, name, this, type, ops);
this.dbLangTableAttributes[lowName] = attr;
if (["serialize", "toString", "addAttribute", "dbLangTableName", "dbLangTableAttributes", "dbLangDatabaseInstance", "addConstraint", "addAttributes", "createAlias"].includes(lowName)) {
if (!noErrorOnNameConflict) throw new Error("You cannot name Attribute like Methode of this Table!");
} else {
this[lowName] = attr;
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) {
let check = c.check(this);
if(typeof check == "string") throw new Error(check);
this.dbLangConstrains.push(c);
}
createAlias(name: string) {
return new TableAlias(name, this);
}
}
export * from './funcs.js';
export { onAction };
export { dbType as databaseType }
export { readResponse, writeResponse, insertResponse, singleResponse }