import mariadb from 'mariadb'; import { checkConstraint, Constraint, Datatype, foreignConstraint, uniqueConstraint } from './dbStructure'; import { Handler } from './defaultHandler'; import { Query } from './query'; import { attributeSettings, extendedAttributeSettings, onAction, dbType } from './types'; //import { postgresHandler } from "./postgresHandler" export class DB { tables: Table[] = []; handler: Handler; name: string; type: dbType; mariaPool!: mariadb.Pool; //pgPool!: pg.Pool; constructor({ host, user, password, database, connectionLimit = 5, databaseType = dbType.mariadb }: { host: string, user: string, password: string, database: string, connectionLimit: number, databaseType: dbType }) { this.type = databaseType; if (databaseType == dbType.mariadb) { this.mariaPool = mariadb.createPool({ host, user, password, database, connectionLimit, multipleStatements: true }); 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) { //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() { return this.handler; } async sync(force = false) { 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.type == dbType.mariadb && this.mariaPool) await this.mariaPool.end(); //if (this.type == dbType.postgres && this.pgPool) await this.pgPool.end(); } } export class Attribute { name: string; table: Table; ops: attributeSettings; type: Datatype; constructor(name: string, table: Table, type: Datatype, ops: attributeSettings) { this.name = name.toLowerCase(); 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.foreginKey != null) { table.addConstraint(new foreignConstraint( table.dbLangDatabaseInstance.name + "_" + table.dbLangTableName + "_" + name + "_foreign_constraint_to_" + ops.foreginKey.link.name, [this], [ops.foreginKey.link], ops.foreginKey.onDelete, ops.foreginKey.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); } 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) + ")"; } } 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, this, type, ops); this.dbLangTableAttributes[lowName] = attr; if (["serialize", "toString", "addAttribute", "dbLangTableName", "dbLangTableAttributes", "dbLangDatabaseInstance", "addConstraint", "addAttributes"].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) { c.check(this); this.dbLangConstrains.push(c); } } export * from './funcs'; export { onAction }; export { dbType as databaseType }