Aliases #3

Merged
jusax23 merged 10 commits from dev into main 2023-02-18 15:47:44 +01:00
5 changed files with 92 additions and 34 deletions
Showing only changes of commit 039ae26773 - Show all commits

View file

@ -1,9 +1,51 @@
import { Attribute, Table } from "./db" import { Attribute, DB, Table } from "./db"
import { Handler } from "./defaultHandler";
export class TableAlias extends Table{
export class AttributeAlias {
name: string;
nameO: string;
table: TableAlias;
attr: Attribute;
constructor(attr: Attribute, table: TableAlias) {
this.name = attr.name;
this.nameO = attr.nameO;
this.attr = attr;
this.table = table;
}
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 AttributeAlias extends Attribute{ export class TableAlias {
dbLangTableName: string;
dbLangTableAttributes: { [key: string]: AttributeAlias; } = {};
dbLangDatabaseInstance: DB;
dbLangTableInstance: Table;
[key: string]: AttributeAlias | any;
constructor(name: string, table: Table) {
this.dbLangTableName = name;
this.dbLangTableInstance = table;
this.dbLangDatabaseInstance = table.dbLangDatabaseInstance;
let keys = Object.keys(table.dbLangTableAttributes);
for (let i = 0; i < keys.length; i++) {
const a = table.dbLangTableAttributes[keys[i]];
let attrAlias = new AttributeAlias(a, this);
this[a.name] = attrAlias;
this[a.nameO] = attrAlias;
this.dbLangTableAttributes[a.name] = attrAlias;
}
}
serialize(handler: Handler) {
return this.toString(handler);
}
toString(handler: Handler = this.dbLangDatabaseInstance.getHandler()) {
return handler.builders.escapeID(this.dbLangTableName);
}
} }

View file

@ -3,6 +3,7 @@ import { checkConstraint, Constraint, Datatype, foreignConstraint, uniqueConstra
import { Handler } from './defaultHandler'; import { Handler } from './defaultHandler';
import { Query } from './query'; import { Query } from './query';
import { attributeSettings, extendedAttributeSettings, onAction, dbType } from './types'; import { attributeSettings, extendedAttributeSettings, onAction, dbType } from './types';
import { TableAlias } from "./alias"
//import { postgresHandler } from "./postgresHandler" //import { postgresHandler } from "./postgresHandler"
@ -16,7 +17,7 @@ export class DB {
constructor({ host, user, password, database, connectionLimit = 5, databaseType = dbType.mariadb }: { host: string, user: string, password: string, database: string, connectionLimit: number, databaseType: dbType }) { 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; this.type = databaseType;
if (databaseType == dbType.mariadb) { if (databaseType == dbType.mariadb) {
this.mariaPool = mariadb.createPool({ host, user, password, database, connectionLimit, multipleStatements: true }); this.mariaPool = mariadb.createPool({ host, user, password, database, connectionLimit, multipleStatements: false });
this.handler = new Handler(this); this.handler = new Handler(this);
} }
/*else if (databaseType == dbType.postgres) { /*else if (databaseType == dbType.postgres) {
@ -28,7 +29,7 @@ export class DB {
this.name = database; this.name = database;
} }
async query(query: Query) { async query(query: Query) {
//console.log(query); console.log(query);
if (this.type == dbType.mariadb) return await this.mariaPool.query(query); if (this.type == dbType.mariadb) return await this.mariaPool.query(query);
/*else if (this.type == dbType.postgres) { /*else if (this.type == dbType.postgres) {
let res = await this.pgPool.query(query.sql, query.values); let res = await this.pgPool.query(query.sql, query.values);
@ -64,11 +65,13 @@ export class DB {
export class Attribute { export class Attribute {
name: string; name: string;
nameO: string;
table: Table; table: Table;
ops: attributeSettings; ops: attributeSettings;
type: Datatype; type: Datatype;
constructor(name: string, table: Table, type: Datatype, ops: attributeSettings) { constructor(name: string, nameO: string, table: Table, type: Datatype, ops: attributeSettings) {
this.name = name.toLowerCase(); this.name = name.toLowerCase();
this.nameO = nameO;
this.type = type; this.type = type;
this.table = table; this.table = table;
this.ops = ops; this.ops = ops;
@ -133,9 +136,9 @@ export class Table {
addAttribute(name: string, type: Datatype, ops: attributeSettings = {}, noErrorOnNameConflict = false) { addAttribute(name: string, type: Datatype, ops: attributeSettings = {}, noErrorOnNameConflict = false) {
let lowName = name.toLowerCase(); let lowName = name.toLowerCase();
if (this.dbLangTableAttributes[lowName] != null) throw new Error("You are tring to create an Attribute twise!"); if (this.dbLangTableAttributes[lowName] != null) throw new Error("You are tring to create an Attribute twise!");
let attr = new Attribute(lowName, this, type, ops); let attr = new Attribute(lowName, name, this, type, ops);
this.dbLangTableAttributes[lowName] = attr; this.dbLangTableAttributes[lowName] = attr;
if (["serialize", "toString", "addAttribute", "dbLangTableName", "dbLangTableAttributes", "dbLangDatabaseInstance", "addConstraint", "addAttributes"].includes(lowName)) { 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!"); if (!noErrorOnNameConflict) throw new Error("You cannot name Attribute like Methode of this Table!");
} else { } else {
this[lowName] = attr; this[lowName] = attr;
@ -152,6 +155,9 @@ export class Table {
c.check(this); c.check(this);
this.dbLangConstrains.push(c); this.dbLangConstrains.push(c);
} }
createAlias(name: string) {
return new TableAlias(name, this);
}
} }
export * from './funcs'; export * from './funcs';

View file

@ -1,3 +1,4 @@
import { AttributeAlias, TableAlias } from "./alias";
import { Attribute, DB, Table } from "./db" import { Attribute, DB, Table } from "./db"
import { Aggregation, checkConstraint, joinCross, Datatype, foreignConstraint, Modifier, joinNatural, onJoin, uniqueConstraint, usingJoin } from "./dbStructure" import { Aggregation, checkConstraint, joinCross, Datatype, foreignConstraint, Modifier, joinNatural, onJoin, uniqueConstraint, usingJoin } from "./dbStructure"
import { insertQuery, Query, QueryBuilder, removeQuery, selectQuery, updateQuery } from "./query" import { insertQuery, Query, QueryBuilder, removeQuery, selectQuery, updateQuery } from "./query"
@ -5,13 +6,13 @@ import { allModifierInput, joinType, onAction, primaryData } from "./types"
export class Handler { export class Handler {
db: DB; db: DB;
constructor(db: DB){ constructor(db: DB) {
this.db = db; this.db = db;
} }
async syncDB(db: DB, handler: Handler, deleteInDB: boolean = false) { async syncDB(db: DB, handler: Handler, deleteInDB: boolean = false) {
//Constraint Data //Constraint Data
let constraints = await db.query(handler.builders.query(handler.querys.listConstraints(handler, db))); let constraints = await db.query(handler.builders.query(handler.querys.listConstraints(handler, db)));
let key = await db.query(handler.builders.query(handler.querys.listConstraintDetails(handler, db))); let key = [...await db.query(handler.builders.query(handler.querys.listConstraintDetails(handler, db)))];
//Table List //Table List
let allTables = (await db.query(handler.builders.query(handler.querys.listTables(handler, db)))).map((d: any) => d.TABLE_NAME ?? d.table_name); let allTables = (await db.query(handler.builders.query(handler.querys.listTables(handler, db)))).map((d: any) => d.TABLE_NAME ?? d.table_name);
@ -23,10 +24,10 @@ export class Handler {
const tableDataBuilder = new QueryBuilder(); const tableDataBuilder = new QueryBuilder();
tableDataBuilder.addCode("DESCRIBE "); tableDataBuilder.addCode("DESCRIBE ");
tableDataBuilder.addCode(table.serialize(handler)); tableDataBuilder.addCode(table.serialize(handler));
tableData[table.dbLangTableName.toLowerCase()] = tableData[table.dbLangTableName] =
Object.fromEntries((await db.query(handler.builders.query(tableDataBuilder))).map((d: any) => [d.Field.toLowerCase(), d])); Object.fromEntries((await db.query(handler.builders.query(tableDataBuilder))).map((d: any) => [d.Field.toLowerCase(), d]));
} catch (_) { } catch (_) {
tableData[table.dbLangTableName.toLowerCase()] = null; tableData[table.dbLangTableName] = null;
} }
} }
@ -126,12 +127,12 @@ export class Handler {
del.appendEnding(handler.querys.removeCheck(handler, (c.TABLE_NAME ?? c.table_name), (c.CONSTRAINT_NAME ?? c.constraint_name))); del.appendEnding(handler.querys.removeCheck(handler, (c.TABLE_NAME ?? c.table_name), (c.CONSTRAINT_NAME ?? c.constraint_name)));
} else if ((c.CONSTRAINT_TYPE ?? c.constraint_type) == "UNIQUE") { } else if ((c.CONSTRAINT_TYPE ?? c.constraint_type) == "UNIQUE") {
if ( if (
(typeof tableData[(c.TABLE_NAME ?? c.table_name).toLowerCase()] == "undefined" && deleteInDB) (typeof tableData[c.TABLE_NAME ?? c.table_name] == "undefined" && deleteInDB)
|| !checkUniqueIsVaild((c.CONSTRAINT_NAME ?? c.constraint_name), (c.TABLE_NAME ?? c.table_name)) || !checkUniqueIsVaild((c.CONSTRAINT_NAME ?? c.constraint_name), (c.TABLE_NAME ?? c.table_name))
) del.appendEnding(handler.querys.removeUnique(handler, (c.TABLE_NAME ?? c.table_name), (c.CONSTRAINT_NAME ?? c.constraint_name))); ) del.appendEnding(handler.querys.removeUnique(handler, (c.TABLE_NAME ?? c.table_name), (c.CONSTRAINT_NAME ?? c.constraint_name)));
} else if ((c.CONSTRAINT_TYPE ?? c.constraint_type) == "FOREIGN KEY") { } else if ((c.CONSTRAINT_TYPE ?? c.constraint_type) == "FOREIGN KEY") {
if ( if (
(typeof tableData[(c.TABLE_NAME ?? c.table_name).toLowerCase()] == "undefined" && deleteInDB) (typeof tableData[c.TABLE_NAME ?? c.table_name] == "undefined" && deleteInDB)
|| !checkForeignIsVaild((c.CONSTRAINT_NAME ?? c.constraint_name), (c.TABLE_NAME ?? c.table_name)) || !checkForeignIsVaild((c.CONSTRAINT_NAME ?? c.constraint_name), (c.TABLE_NAME ?? c.table_name))
) del.appendEnding(handler.querys.removeForeignKey(handler, (c.TABLE_NAME ?? c.table_name), (c.CONSTRAINT_NAME ?? c.constraint_name))); ) del.appendEnding(handler.querys.removeForeignKey(handler, (c.TABLE_NAME ?? c.table_name), (c.CONSTRAINT_NAME ?? c.constraint_name)));
} }
@ -149,6 +150,7 @@ export class Handler {
&& (k.REFERENCED_COLUMN_NAME ?? k.referenced_column_name).toLowerCase() == attr.toLowerCase() && (k.REFERENCED_COLUMN_NAME ?? k.referenced_column_name).toLowerCase() == attr.toLowerCase()
) { ) {
del.appendEnding(handler.querys.removeForeignKey(handler, (k.TABLE_NAME ?? k.table_name), (k.CONSTRAINT_NAME ?? k.constraint_name))); del.appendEnding(handler.querys.removeForeignKey(handler, (k.TABLE_NAME ?? k.table_name), (k.CONSTRAINT_NAME ?? k.constraint_name)));
key.splice(i--, 1);
} }
} }
} }
@ -156,7 +158,7 @@ export class Handler {
//create tables //create tables
for (let i = 0; i < db.tables.length; i++) { for (let i = 0; i < db.tables.length; i++) {
const table = db.tables[i]; const table = db.tables[i];
const tableD = tableData[table.dbLangTableName.toLowerCase()]; const tableD = tableData[table.dbLangTableName];
//delete unused Columns //delete unused Columns
if (deleteInDB && tableD != null) { if (deleteInDB && tableD != null) {
let keys = Object.keys(tableD); let keys = Object.keys(tableD);
@ -191,7 +193,8 @@ export class Handler {
(!!a.ops.notNull || !!a.ops.autoIncrement || !!a.ops.primaryKey), (attrData.Null == "NO"), "|", (!!a.ops.notNull || !!a.ops.autoIncrement || !!a.ops.primaryKey), (attrData.Null == "NO"), "|",
(!!a.ops.autoIncrement), (attrData.Extra == "auto_increment"));*/ (!!a.ops.autoIncrement), (attrData.Extra == "auto_increment"));*/
freeForUpdate(a.name, a.table.dbLangTableName); freeForUpdate(a.name, a.table.dbLangTableName);
create.appendEnding(handler.querys.changeColumn(handler, a)); if (a.ops.autoIncrement)
create.appendEnding(handler.querys.changeColumn(handler, a));
} }
if (attrData == null) { if (attrData == null) {
changePrimary = true; changePrimary = true;
@ -207,6 +210,9 @@ export class Handler {
create.appendEnding(handler.querys.removePrimaryKey(handler, table.dbLangTableName)); create.appendEnding(handler.querys.removePrimaryKey(handler, table.dbLangTableName));
create.appendEnding(handler.querys.addPrimaryKey(handler, table)); create.appendEnding(handler.querys.addPrimaryKey(handler, table));
} }
}
for (let i = 0; i < db.tables.length; i++) {
const table = db.tables[i];
for (let j = 0; j < table.dbLangConstrains.length; j++) { for (let j = 0; j < table.dbLangConstrains.length; j++) {
const c = table.dbLangConstrains[j]; const c = table.dbLangConstrains[j];
if (c instanceof checkConstraint) { if (c instanceof checkConstraint) {
@ -235,7 +241,7 @@ export class Handler {
builder.addCode(` from `); builder.addCode(` from `);
if (q.from == null) { if (q.from == null) {
builder.addCode(" DUAL"); builder.addCode(" DUAL");
} else if (q.from instanceof Table) { } else if (q.from instanceof Table || q.from instanceof TableAlias) {
builder.addCode(q.from.serialize(handler)); builder.addCode(q.from.serialize(handler));
} else { } else {
builder.append(q.from.serialize(handler)); builder.append(q.from.serialize(handler));
@ -299,7 +305,7 @@ export class Handler {
const s = q.setD[i]; const s = q.setD[i];
qb.addCode(s[0].serialize(handler)); qb.addCode(s[0].serialize(handler));
qb.addCode(" = ("); qb.addCode(" = (");
if (s[1] instanceof Attribute) qb.addCode(s[1].serialize(handler)); if (s[1] instanceof Attribute || s[1] instanceof AttributeAlias) qb.addCode(s[1].serialize(handler));
else if (s[1] instanceof Modifier || s[1] instanceof selectQuery || s[1] instanceof Aggregation) { else if (s[1] instanceof Modifier || s[1] instanceof selectQuery || s[1] instanceof Aggregation) {
qb.append(s[1].serialize(handler)); qb.append(s[1].serialize(handler));
} else { } else {
@ -443,14 +449,15 @@ export class Handler {
return builder; return builder;
}, },
addPrimaryKey: (handler: Handler, table: Table) => { addPrimaryKey: (handler: Handler, table: Table) => {
let primaAttr = Object.entries(table.dbLangTableAttributes)
.filter(([n, attr]) => !!attr.ops.primaryKey);
const qb = new QueryBuilder(); const qb = new QueryBuilder();
if(primaAttr.length == 0) return qb;
qb.addCode("ALTER TABLE "); qb.addCode("ALTER TABLE ");
qb.addCode(table.serialize(handler)); qb.addCode(table.serialize(handler));
qb.addCode(" add PRIMARY KEY if not exists ("); qb.addCode(" add PRIMARY KEY if not exists (");
qb.addCodeCommaSeperated( qb.addCodeCommaSeperated(
Object.entries(table.dbLangTableAttributes) primaAttr.map(([n, attr]) => handler.builders.escapeID(n))
.filter(([n, attr]) => !!attr.ops.primaryKey)
.map(([n, attr]) => handler.builders.escapeID(n))
); );
qb.addCode(")"); qb.addCode(")");
return qb; return qb;
@ -550,7 +557,7 @@ export class Handler {
let sql = ""; let sql = "";
for (let i = 0; i < qb.list.length; i++) { for (let i = 0; i < qb.list.length; i++) {
const [inject, data] = qb.list[i]; const [inject, data] = qb.list[i];
if(inject)sql += handler.builders.escapeLiteral(data); if (inject) sql += handler.builders.escapeLiteral(data);
else sql += data; else sql += data;
} }
return curr.split(", ").join(",").startsWith(sql.split(", ").join(",")); return curr.split(", ").join(",").startsWith(sql.split(", ").join(","));
@ -664,7 +671,7 @@ export class Handler {
divide: joinArg("-/"), divide: joinArg("-/"),
not: (handler: Handler, a: allModifierInput[]): QueryBuilder => { not: (handler: Handler, a: allModifierInput[]): QueryBuilder => {
let e = a[0]; let e = a[0];
if (e instanceof Attribute) return new QueryBuilder([{ data: "not (" + e.toString(handler) + ")" }]) if (e instanceof Attribute || e instanceof AttributeAlias) 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) {
const builder = new QueryBuilder(); const builder = new QueryBuilder();
builder.addCode("not ("); builder.addCode("not (");
@ -680,14 +687,14 @@ export class Handler {
}, },
like: (handler: Handler, a: allModifierInput[]): QueryBuilder => { like: (handler: Handler, a: allModifierInput[]): QueryBuilder => {
const builder = new QueryBuilder(); const builder = new QueryBuilder();
if (a[0] instanceof Attribute) builder.addCode(a[0].toString()); if (a[0] instanceof Attribute || a[0] instanceof AttributeAlias) builder.addCode(a[0].toString());
else if (a[0] instanceof Modifier || a[0] instanceof selectQuery || a[0] instanceof Aggregation) { else if (a[0] instanceof Modifier || a[0] instanceof selectQuery || a[0] instanceof Aggregation) {
builder.append(a[0].serialize(handler)); builder.append(a[0].serialize(handler));
} else { } else {
builder.addInjection(a[0]); builder.addInjection(a[0]);
} }
builder.addCode(" LIKE "); builder.addCode(" LIKE ");
if (a[1] instanceof Attribute) builder.addCode(a[1].toString()); if (a[1] instanceof Attribute || a[1] instanceof AttributeAlias) builder.addCode(a[1].toString());
else if (a[1] instanceof Modifier || a[1] instanceof selectQuery || a[1] instanceof Aggregation) { else if (a[1] instanceof Modifier || a[1] instanceof selectQuery || a[1] instanceof Aggregation) {
builder.append(a[1].serialize(handler)); builder.append(a[1].serialize(handler));
} else { } else {
@ -700,7 +707,7 @@ export class Handler {
builder.addCode("CONCAT("); builder.addCode("CONCAT(");
for (let i = 0; i < a.length; i++) { for (let i = 0; i < a.length; i++) {
const e = a[i]; const e = a[i];
if (e instanceof Attribute) builder.addCode(e.toString()); if (e instanceof Attribute || e instanceof AttributeAlias) builder.addCode(e.toString());
else if (e instanceof Modifier || e instanceof selectQuery || e instanceof Aggregation) { else if (e instanceof Modifier || e instanceof selectQuery || e instanceof Aggregation) {
builder.append(e.serialize(handler)); builder.append(e.serialize(handler));
} else { } else {
@ -798,7 +805,7 @@ function joinArg(type: string) {
const builder = new QueryBuilder(); const builder = new QueryBuilder();
for (let i = 0; i < a.length; i++) { for (let i = 0; i < a.length; i++) {
const d = a[i]; const d = a[i];
if (d instanceof Attribute) builder.addCode(d.toString(handler)); if (d instanceof Attribute || d instanceof AttributeAlias) builder.addCode(d.toString(handler));
else if (d instanceof Modifier || d instanceof selectQuery || d instanceof Aggregation) { else if (d instanceof Modifier || d instanceof selectQuery || d instanceof Aggregation) {
builder.addCode("("); builder.addCode("(");
builder.append(d.serialize(handler)); builder.append(d.serialize(handler));

View file

@ -1,3 +1,4 @@
import { AttributeAlias } from "./alias";
import { Attribute, DB, Table } from "./db"; import { Attribute, DB, Table } from "./db";
import { BooleanModifier, Modifier } from "./dbStructure"; import { BooleanModifier, Modifier } from "./dbStructure";
import { Handler } from "./defaultHandler"; import { Handler } from "./defaultHandler";
@ -48,6 +49,7 @@ export class QueryBuilder {
this.list.push(...qb.list); this.list.push(...qb.list);
} }
appendEnding(qb: QueryBuilder) { appendEnding(qb: QueryBuilder) {
if(qb.isEmpty()) return;
this.append(qb); this.append(qb);
this.list.push([false, ";"]); this.list.push([false, ";"]);
} }
@ -72,8 +74,8 @@ export class selectQuery {
this.whereD = m; this.whereD = m;
return this; return this;
} }
groupByD: Attribute[] = []; groupByD: (Attribute | AttributeAlias)[] = [];
groupBy(a: Attribute[]) { groupBy(a: (Attribute | AttributeAlias)[]) {
this.groupByD = a; this.groupByD = a;
return this; return this;
} }

View file

@ -1,12 +1,13 @@
import { AttributeAlias, TableAlias } from "./alias";
import { Attribute, Table } from "./db"; import { Attribute, Table } from "./db";
import { Aggregation, BooleanModifier, Datatype, Joins, Modifier } from "./dbStructure"; import { Aggregation, BooleanModifier, Datatype, Joins, Modifier } from "./dbStructure";
import { QueryBuilder, selectQuery } from "./query"; import { QueryBuilder, selectQuery } from "./query";
export type primaryData = string | number | boolean | null; export type primaryData = string | number | boolean | null;
export type allModifierInput = primaryData | Modifier | selectQuery | Attribute | Aggregation; export type allModifierInput = primaryData | Modifier | selectQuery | Attribute | AttributeAlias | Aggregation;
export type selectElements = primaryData | Attribute | Aggregation | selectQuery export type selectElements = primaryData | Attribute | AttributeAlias | Aggregation | selectQuery
export type selectFromElements = Table | Joins | null; export type selectFromElements = TableAlias | Table | Joins | null;
export type joinElements = Table | Joins; export type joinElements = Table | Joins;
export type serializeReturn = [string, primaryData[]]; export type serializeReturn = [string, primaryData[]];